Recherche base de données

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Aimedjie

XLDnaute Occasionnel
Bonjour,

J'aimerais savoir comment je peux programmer en VBA une fonction qui me permet d'inscrire une valeur en fonction de plusieurs critères.

Je m'explique :

D’abord, la fonction doit inscrire un taux uniquement pour les cellules où il y a un taux d’inscrit.

Ensuite, la fonction doit faire les étapes suivantes :

1) Dans la feuille « Calcul », si l’indice est 99999, le taux de la feuille doit être « S/O » et la fonction arrête.

2) Sinon, la fonction recherche la ligne correspondant aux critères suivants :

- L'année de la colonne A de la feuille « Taux » doit correspondre à l'année inscrite sur la ligne 1 de la feuille « Calcul ».
- L’indice de la colonne B de la feuille « Taux » doit correspondre à l’indice de la colonne A de la feuille « Calcul ».

3) S’il n’y aucune ligne dans la feuille « Taux » qui correspond aux critères de recherche, une fenêtre apparaît avec le texte : « Vous avez saisi un coût pour l’indice XXX qui n’existe pas pour l’année XXX. »

4) Si la ligne de la feuille « Taux » est identifiée, je veux que le taux affiché dans la feuille « Calcul » corresponde au taux général de cette ligne si la juridiction est provinciale ou au taux particulier si la juridiction est fédérale.

Je joins un fichier pour être plus clair.

Merci.
 

Pièces jointes

Re : Recherche base de données

Merci beaucoup Davidc57, mais je voulais obtenir une solution avec la programmation VBA. Par contre, ton fichier répondait bien à mon besoin.

jp14, j'ai testé ton fichier et le bouton ne fonctionne pas. Lorsque j'inscrit de nouveaux indices ou en enlève, rien ne se passe lorsque j'appuie sur le bouton.
 
Re : Recherche base de données

jp14, j'ai testé ton fichier et le bouton ne fonctionne pas. Lorsque j'inscrit de nouveaux indices ou en enlève, rien ne se passe lorsque j'appuie sur le bouton.

Il faut remplacer les taux de la feuille par 1( pas de valeur = 0).( D’abord, la fonction doit inscrire un taux uniquement pour les cellules où il y a un taux d’inscrit)

JP
 
Re : Recherche base de données

Il faut remplacer les taux de la feuille par 1( pas de valeur = 0).( D’abord, la fonction doit inscrire un taux uniquement pour les cellules où il y a un taux d’inscrit)

JP

Je me suis trompé dans mon explication. Je voulais plutôt dire où il y a un coût d'inscrit. Effectivement, la macro fonctionne.

Merci beaucoup.

Est-ce possible de modifier le fichier et d'insérer la fonction dans WorkSheet.Change plutôt que dans un bouton?
 
Re : Recherche base de données

Bonjour

Ci joint le fichier avec des commentaires et une macro simplifiée ( en partie)
Le nombre de colonnes n'a pas d'importance, ce qui permet d'ajouter des années.
Seule la cellule dont le montant est modifiée est prise en compte cela limite le temps de traitement.
La seule contrainte les "Coûts" doivent se trouver dans les colonnes avec une valeur numérique paire D F H J L .....

Pour bien comprendre le déroulement il faut mettre un point d'arrêt et suivre la macro avec F8 en vérifiant la valeur des variables.

A tester

JP
 

Pièces jointes

Re : Recherche base de données

Bonjour jp14,

Je viens d'insérer les macros dans mon fichier et tout fonctionne parfaitement, mais comme ma base de données contient plus de 4000 lignes et que je veux que la macro s'exécute sur tous les coûts de la ou les lignes modifiées dans la feuille "Calcul", la macro met du temps avant de terminer.

Voici ma programmation :

Private Sub Worksheet_Change(ByVal Target As Range)

'==========================================================================
'À faire à chaque fois qu'une donnée change dans la feuille.
'--------------------------------------------------------------------------
'booChangeActif : Variable qui est égale à "vrai" seulement si une autre fonction se déroule.
'inChange : Variable qui est égale à "vrai" seulement si la fonction Worksheet_Change
' se déroule.
'donnee : Cellules sélectionnées à analyser en loop.
'==========================================================================

Static inChange As Boolean
Dim donnee As Range

'S 'il y a une macro active, donc booChangeActif = true, alors la fonction
'Worksheet_Change() ne doit pas se dérouler.
If booChangeActif Or inChange Then
Exit Sub
End If
'Désactiver la fonction Worksheet_Change() pendant l'exécution de la présente macro.
inChange = True

For Each donnee In Target

'Inscrire le taux de l'indice lorsqu'il y a un coût d'inscrit.
If donnee.Row > 3 And _
donnee.Row < 11 Then '41 lignes dans mon fichier.

Call inscrireTaux(donnee)

End If

Next donnee

'Réactiveer la fonction WorkSheet_Change().
inChange = False

End Sub


Sub inscrireTaux(ByVal Target As Range)

'==========================================================================
'Inscrire le taux de l'indice.
'--------------------------------------------------------------------------
'==========================================================================

Dim cellZoneCoût As Range
Dim annee As Long
Dim ligne As Long

'Cette macro s'applique à toute les cellules de la zone "Zone"
For Each cellZoneCoût In Range("Zone") 'dans mon cas, la zone comprend 41 lignes et 8 colonnes.

'La macro ne s'applique que sur les lignes modifiées.
If cellZoneCoût.Row = Target.Row And _
Cells(cellZoneCoût.Row, Range("A1").Column).Value <> "" Then

'S'il n'y a aucun coût inscrit dans la zone "Zone", il n'y
'a aucun taux de l'indice.
If cellZoneCoût.Value = "" Then
Cells(cellZoneCoût.Row, _
cellZoneCoût.Column - 1).Value = ""

Else
'S'il s'agit de l'indice 99999, le taux est "S/O".
If Cells(cellZoneCoût.Row, _
Range("A1").Column).Value = 99999 Then
Cells(cellZoneCoût.Row, _
cellZoneCoût.Column - 1).Value = "S/O"

Else

'Sinon, la macro recherche d'abord l'année où le coût est inscrit.
annee = Year(Cells(Range("A1").Row + 1, _
cellZoneCoût.Column - 1).Value)

'Ensuite, elle recherche la ligne de la feuille "Taux" correspondant à l'année et
'l'indice recherché.
ligne = rechercheLigne("Taux", _
Array(annee, "A", _
Cells(cellZoneCoût.Row, _
Range("A1").Column).Value, _
"B"), 2, _
Range("A1").Row + 2)

'Avertir l'utilisateur de son erreur lorsqu'il inscrit des coûts dans
'un indice qui n'existe pas pour cette année.
If ligne = 0 Then

Call MsgBox("Vous avez saisi des coûts pour " _
& "l'indice " & Cells(cellZoneCoût.Row, _
Range("A1").Column).Value & vbCrLf _
& " alors que cet indice n'existe pas pour l'année " _
& annee & ".", vbInformation, "Indice inexistant")

Else

If Cells(cellZoneCoût.Row, _
Range("B1").Column).Value = _
"Provinciale" Then

Cells(cellZoneCoût.Row, _
cellZoneCoût.Column - 1).Value = _
sheets("Taux").Cells(ligne, _
Range("C1").Column).Value

Else

Cells(cellZoneCoût.Row, _
cellZoneCoût.Column - 1).Value = _
sheets("Taux").Cells(ligne, _
Range("D1").Column).Value

End If

End If

End If

End If

End If

Next cellZoneCoût
End Sub


Public Function rechercheLigne(ByVal feuilleRecherche As String, parametre As Variant, _
nbDonneeRecherche As Integer, ligneDepart As Long)

'==========================================================================
'Rechercher une ligne contenant un texte dans deux colonnes non adjacente.
'--------------------------------------------------------------------------
'feuilleRecherche : Feuille contenant les données à rechercher.
'parametre : Correspond aux données et la colonne recherchées.
'nbDonneeRecherche : Nombre de colonnes dans lesquelles il faut effectuer la recherche.
'ligneDepart : Première ligne de la recherche
'dataToRecherche : Représente la donnée créée à rechercher.
'dataCree : Représente les données créées parmi lesquelles la recherche s'effectue.
'noDonneeCree : Représente le numéro de l'information à insérer dans la donnée créée
' à rechercher.
'noDonneeRecherche : Représente le numéro de l'information à insérer dans les données
' créées parmi lesquelles la recherche s'effectue.
'indiceParametre : Représente le plus petit indice disponible pour la dimension
' indiquée du tableau Parametre.
'noLigneRecherche : Représente le numéro de la ligne recherchée.
'--------------------------------------------------------------------------
'==========================================================================

Dim dataToRecherche As String, dataCree As String
Dim noDonneeCree As Integer
Dim noDonneeRecherche As Long
Dim indiceParametre As Integer

'indiceParametre : Représente le plus petit indice disponible pour la dimension
' indiquée du tableau Parametre.
indiceParametre = LBound(parametre)

'Indiquer la feuille dans laquelle la recherche s'effectue.
With Sheets(feuilleRecherche)

'La ligne de départ doit nécessairement être inférieure à la dernière ligne de la
'feuilleRecherche où il y a des informations inscrites.
If ligneDepart <= .Range(parametre(indiceParametre + 1) & "65536").End(xlUp).Row Then

'S'il y plus d'une colonne, la macro assemble les données (concaténation).
If nbDonneeRecherche > 1 Then

'Création de la donnée recherchée en concaténant toutes les données à rechercher.
For noDonneeCree = 0 To nbDonneeRecherche * 2 - 1 Step 2
dataToRecherche = dataToRecherche & _
Trim(parametre(indiceParametre + noDonneeCree))
Next noDonneeCree

Else

'S'il y a une seule colonne, la donnée à rechercher correspond à la donnée de celle-ci.
dataToRecherche = Trim(parametre(indiceParametre))

End If

For noDonneeRecherche = .Range(parametre(indiceParametre + 1) & "65536").End(xlUp).Row To ligneDepart Step -1

dataCree = ""

If nbDonneeRecherche > 1 Then

For noDonneeCree = 0 To nbDonneeRecherche * 2 - 1 Step 2
dataCree = dataCree & _
Trim(.Range(parametre(indiceparmetre + 1 + _
noDonneeCree) & noDonneeRecherche))
Next noDonneeCree

Else

dataCree = dataCree & _
Trim(.Range(parametre(indiceParametre + 1) & _
noDonneeRecherche))

End If

If dataToRecherche = dataCree Then
rechercheLigne = noDonneeRecherche
Exit Function
End If

Next noDonneeRecherche

End If

rechercheLigne = 0

End With

End Function


Je sais que se n'est pas une partie de plaisir, mais je sens qu'on s'approche du but.

En bref, mes macros fonctionne à merveille, sauf qu'elle prenne énormément de temps. C'est pour cette raison que je voudrais limite les "For" puisqu'avec plus de 4000 lignes dans la feuille "Taux" et avec 41 lignes et 8 colonnes dans la zone "Zone", je vous assure que les "for" tournent longtemps.

Merci.
 
Re : Recherche base de données

Bonjour

Ci joint les modifications à apporter pour diminuer le temps de recherche


Fonction à utiliser
La méthode "find" étant une méthode du systéme est plus rapide qu'une boucle.
Code:
'---------------------------------------------------------------------------------------
' Procedure : chercheligne
' DateTime  : 22/03/2007 12:27
' Author    : jp14
' Pour      : http://www.excel-downloads
' Utilisation   :Recherche simple avec Find
'Sheets().Range(colonne1a & "65536").End(xlUp).Row
'lig = chercheligne("Feuil1", "Valeur", "A1", "A20")
'---------------------------------------------------------------------------------------
'
Function chercheligne(£feuille As String, £valeur As String, £col1d As String, £col1f As String)
Dim cel As Range
Set cel = Sheets(£feuille).Range(£col1d & ":" & £col1f).Find(What:=£valeur, LookIn:=xlValues, SearchOrder:=xlByRows)

If cel Is Nothing Then
    chercheligne = 0
Else
    chercheligne = cel.Row
End If
End Function

Il faut modifier l'appel de la fonction, cette méthode ne peut fonctionner que si les données sont triées.
Code:
        annee = Year(.Cells(1, col2 - 1).Value) ' on recherche l'année
' a rajouter
         dl1 = Sheets(nomfeuille2).Range("a65536").End(xlUp).Row ' on cherche la dernière ligne
        ' on recherche la ligne ou commence l'année
        lig = chercheligne(nomfeuille2, CStr(annee), "A" & lidep2-1, "A" & dl1)
        ' on a trouvé l'année on cherche à partir de celle ligne le code
       ' la recherche find commençant après la cellule indiquée voir aide vba
       'pour ne pas avoir de message d'erreur il ne faut pas utiliser la ligne 1 sauf pour le titre de la 
       ' colonne 
        lig = chercheligne(nomfeuille2, CStr(cellule.Value), "b" & lig-1, "b" & dl1)
'        
dl1 = lig ' cette ligne et à supprimer elle sert pour tester
        
 ' ligne suivante à supprimer  après les test     
        lig = rechercheligne(nomfeuille2, Array(annee, "a", cellule.Value, "b"), 2, lidep2)
' code à supprimer après les tests
        If lig <> dl1 Then
            Call MsgBox("Erreur les deux méthodes ne donnent pas le même résultat", vbCritical, Application.Name)
        Exit Sub
        End If


A tester

JP
 
Dernière édition:
Re : Recherche base de données

Bonjour

Ayant eu des problèmes avec "find" qui commence la recherche après la première cellule j'ai modifié, fait des tests et corrigé certains points, en particulier la procédure de recherche.

J'ai rajouté (cellule M1 un "timer") pour mesurer le temps pour les tests.

A tester

JP
 

Pièces jointes

Dernière édition:
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
5
Affichages
420
Retour