Sélection d'une colonne à partir d'une variable
Bonjour à tous,
J'essaie d'écrire une macro VBA pour calculer le max d'une variable à partir de la fonction Application.WorksheetFunction.MaxIfs
J'ai un tableau avec les colonnes Référence, Itération. J'ai nommé deux variables : numeroColonneRef et numeroColonneIteration.
Dans un premier temps je fais une boucle For :
For j = 1 To derniereColonne (je calcule la derniere colonne dans mon code)
If Worksheets("DataBase").Cells(1, j) = "Itération" Then
numeroColonneIteration = j
End If
If Worksheets("DataBase").Cells(1, j) = "Référence" Then
numeroColonneRefExterne = j
End If
Next
Je fais cette boucle pour avoir des colonnes qui peuvent bouger et donc avoir une macro qui s'adapte malgré le déplacement des colonnes.
IterationMaxJalon = Application.WorksheetFunction.MaxIfs(Range(Columns(numeroColonneIteration)), Range(Columns(numeroColonneRefExterne)), Worksheets("Database").Cells(i, numeroColonneRefExterne))
Pour chaque ligne de mon tableau je voudrais calculer le max de l'itération pour une référence donnée.
Par exemple, si j'ai trois lignes dans mon tableau avec une référence A et respectivement 1, 2 et 3 dans la colonne itération, je souhaiterais que IterationMaxJalon = 3.
Lorsque je fais tourner mon code, j'ai l'erreur suivante : La méthode Range de l'objet Global a échoué. J'imagine que j'ai mal écris Range(Columns(i)) mais je ne vois pas ce qui bloque.
Pouvez vous m'aider s'il vous plaît ?
Bonjour Exia, bonjour le forum,
Désolé mais j'ai du mal avec les variables trop longues... Essaie comme ça :
Dim O As Worksheet
Dim DC As Integer
Dim J As Integer
Dim NC As Integer
Dim NCRE As Integer
Set O = Worksheets("DataBase")
DC = O.Cells(1, Application.Columns.Count).End(xlToLeft).Column
For J = 1 To DC
If O.Cells(1, J) = "Itération" Then NC = J
If O.Cells(1, J) = "Référence" Then NCRE = J
Next
MsgBox "Itération : " & NC & ", Référence : " & NCRE
IterationMaxJalon = Application.WorksheetFunction.MaxIfs(O.Range(O.Cells(1, NC), O.Cells(1, NCRE)).EntireColumn, O.Cells(i, numeroColonneRefExterne))Sub Documents_Uniques()
Worksheets("Database").Activate
'Identification des documents uniques et remplissage de l'onglet Database Unity
For i = 2 To 16
For k = 1 To derniereLigneJalon
Select Case Worksheets("Database").Cells(i, numeroColonneJalon).Value
Case Worksheets("Liste Jalon").Cells(k, 1).Value
IterationMaxJalon = Application.WorksheetFunction.MaxIfs(Range(Columns(numeroColonneIteration), Columns(numeroColonneIteration)), Range(Columns(numeroColonneRefExterne), Columns(numeroColonneRefExterne)), Worksheets("Database").Cells(i, numeroColonneRefExterne))
If Worksheets("Database").Cells(i, numeroColonneIteration) = IterationMaxJalon Then
Worksheets("Database_Unity").Cells(i, numeroColonneIDUnity) = Worksheets("Database").Cells(i, numeroColonneID)
End If
End Select
Next
Next
End SubJ'ai réussi à corriger mon code en adaptant la formule Columns, je n'avais pas assez d'arguments. J'ai testé et cela semble bien fonctionné. Néanmoins je rencontre un soucis esthétique... Lorsque la condition est vraie, il va copier la référence d'un onglet dans un autre. Sauf que lorsque la condition n'est pas satisfaite, il passe à la ligne suivante et donc quand il va copier la référence lorsque la condition sera vraie, j'aurai des lignes vides dans mon nouvel onglet...
Par exemple, si la condition est vraie des lignes 1 à 5 et puis 10 à 15 dans l'onglet A; il va copier la référence sur les lignes 1 à 5 et 10 à 15 de l'onglet B
Comment faire pour que ça copier à la suite dans l'onglet B s'il vous plaît ?
Merci d'avance.
Bonjour Exia,
Sans le code complet où l'on sait ce que valent les variables, on ne peut pas t'aider. L'idéal serait ton fichier ou un fichier exemple anonymisé basé sur ton fichier original.
Bonjour,
Je comprends, mais j"ai fini par trouver la solution à mon problème en cherchant sur internet une macro pour supprimer les lignes vides. Ce n'est peut être pas le plus optimisé mais ça fait le travail. Par contre j'ai une autre question à laquelle je n'ai pas encore trouvé de réponse...
For i = 5 To derniereLigne
For k = 2 To derniereLigne2
If Worksheets("Extraction").Cells(i, numeroColonneID_1) = Worksheets("Database").Cells(k, numeroColonneID) Then
Exit For
End If
derniereLigne = derniereLigne + 1
Worksheets("Database").Cells(derniereLigne, numeroColonneID) = Worksheets("Extraction PJL").Cells(i, numeroColonneID_1)
Next
NextLorsque je fais du pas à pas, je constate que lorsqu'il sort de la deuxieme boucle for, k n'est ensuite plus incrémenté... or ce n'est pas ce que je voulais faire. Si la condition est vraie, j'aimerai qu'il passe au i et k suivant...
Pouvez vous m'aidez svp ?
Salut,
Ha le fameux Exit For...
Si tu fais un Exit For comme son nom l'indique tu sort de la boucle que tu sois à 2, 3, ou 15 tu sort sans vérifier les suivants.
Il faut éviter autant que faire ce peut ce type de programmation, et préférer des Select Case ou Bloc If. Et comme le dit si bien @ThauThème sans fichier exemple...
Bonjour,
Je vous ai mis un fichier mais je ne vois pas en quoi ça va aider... le code complet ne contient pas plus que ce que j'ai mis dans mon message, si ce n'est les déclarations de variables et les comptages de lignes / colonnes.
Dans le cas d'un select case, mon problème reste le même, comment passer aux itérations suivantes si le cas est vrai ? Etant donné qu'il n'y a qu'une condition, ça ne semble pas utile de faire un select case...
Bonjour le fil, bonjour le forum,
Exia, tu ne vois peut-être pas en quoi ça peut aider, mais ça nous permet tout simplement de tester sans avoir a recréer ton environnement.
Ton code me paraît correct mais il y a une erreur de variable :
For j = 1 To derniereColonne
If Worksheets("DataBase").Cells(1, j) = "ID" Then
numeroColonneID = j
End If
Next
For j = 1 To derniereColonne
If Worksheets("Extraction").Cells(4, j) = "ID" Then
numeroColonneID2 = j
End If
NextLa deuxième boucle devrait avoir comme variable derniereColonne2. Ça arrive avec des noms de variable peu explicites...
Une autre proposition :
Sub NouveauxDocs()
Dim OD As Worksheet 'déclare la variable OD (Onglet Database)
Dim OE As Worksheet 'déclare la variable OE (Onglet Extraction)
Dim CIDD As Integer 'déclare la variable CIDD (Colonne ID Database)
Dim CIDE As Integer 'déclare la variable CIDE (Colonne ID Extraction))
Dim DLE As Long 'déclare la variable DLE (Dernière Ligne Extraction)
Dim I As Long 'déclare la variable I (Incrément)
Dim R As Range 'déclare la variable R (Recherche)
Dim DEST As Range 'déclare la variable DEST (cellule de DESTination)
Set OD = Worksheets("DataBase") 'définit l'onglet OD
Set OE = Worksheets("Extraction") 'définit l'onglet OE
CIDD = OD.Rows(1).Find("ID", , xlValues, xlWhole).Column 'définit la colonne CIDD contenant ID dans la lignne 1 de l'onglet Database
CIDE = OE.Rows(4).Find("ID", , xlValues, xlWhole).Column 'définit la colonne CIDE contenant ID dans la ligne 4 de l'onglet Extraction
DLE = OE.Cells(Application.Rows.Count, CIDE).End(xlUp).Row 'définit la dernière ligbne éditée DLE de la colonne CIDE de l'onglet Extraction
For I = 5 To DLE 'boucle sur toutes les lignes éditées I de l'onglet Extraction (en partant de la cinquième)
'définit la recherche R (recherche la valeur entière de la cellule ligne I colonne CIDE
'de l'onglet Extraction dans la colonne CIDD de l'onglet DataBase
Set R = OD.Columns(CIDD).Find(OE.Cells(I, CIDE), , xlValues, xlWhole)
If R Is Nothing Then 'condition : si aucune occurrence trouvée
'définit la cellule de destination DEST (première cellule vide de la colonne CIDD de l'onglet DataBase)
Set DEST = OD.Cells(Application.Rows.Count, CIDD).End(xlUp).Offset(1, 0)
OE.Cells(I, CIDE).Copy DEST 'copie la cellule ligne I colonne CIDE de l'onglet Extraction et la colle dans DEST
End If 'fin de la condition
Next I 'prochaine ligne de la boucle
End SubOk, je comprends.
Je vais essayer d'insérer le code chez moi et reprendre avec mes variables pour tester.
Néanmoins, étant donné que mon code semble correct pourquoi ça ne fonctionne pas ?
Autre question, lorsque je ne trouve pas la valeur, je la copie dans l'onglet où elle n'existe pas. Si en plus, je souhaite copier les données des autres colonnes associées à cette valeur comment puis je faire s'il vous plaît ?
Tel un bon débutant, j'ai rajouté des Worksheets.cells = worksheets.cells mais cela prends énormément de temps.... J'ai un tableau de plus de 20 000 lignes.
Peut-on faire plus rapide? Je joindrais un fichier exemple quand j'aurai accès à Excel [ne réponds plus].
Merci d'avance.
Re,
Si tu ne lis pas les réponses on ne s'en sortira pas... Pourquoi ça ne fonctionne pas ? Parce que mauvaise variable dans la boucle 2.
Sinon, toujours la même réponse... Le fichier qui va bien et des explications claires basées sur ce fichier...
J'ai lu les réponses. L'erreur de variable vient du fait que j'ai anonymisé mes variables pour donner un fichier exemple. J'ai testé mon code en corrigeant cette erreur et le résultat escompté n'est pas le bon. Voir le fichier joint exemple. Comme indiqué dans les messages précédents, le exit for est le problème... soit mal placé soit ce n'est pas la bonne instruction.
Le fichier exemple 2 c'est la même chose sauf que j'ai complété les lignes pour avoir du concret. Ce que je souhaite faire, c'est qu'une fois que la macro a identifié les ID qui ne sont pas extraction et les a collés dans Database, je souhaiterai importer les données de ces lignes dans Database. J'aimerai le faire en deux macro séparés car le fichier de base a plus de 20K lignes.
Est ce que les explications sont claires ? :)
Merci d'avance.
Re,
Tu n'as même pas daigné jeter un coup d'œil au code que je t'avais proposé. Ou, en tous cas, tu n'as fait aucun commentaire... Désolé mais devant tant de désinvolture, je passe la main...
Bonjour,
J'ai écris, précédemment, que je devais reprendre ton code pour me l'approprier. Tu as du mal avec les variables longues, moi je n'y comprends rien avec des variables en deux lettres.
Qui plus est, je suis venu parce que j'avais un problème et essayé de comprendre pourquoi mon code n'était pas bon et tu ne m'as pas non plus répondu, sauf me dire qu'une variable est mal nommée et pourtant malgré correction ça ne fonctionne toujours pas.
Bilan, certes j'ai une alternative et je t'ai remercié mais je n'ai toujours pas compris mon erreur et c'est ce que je cherche à comprendre.
Je ne comprends pas cette réaction mais bon, pas de problème, je vais attendre l'aide d'une autre personne qui voudra bien m'aider à comprendre pourquoi mon code ne fait pas ce que je demande.
Bonjour le fil, bonjour le forum,
Tu as raison Exia, ton cod, même avec la variable renommée, ne fonctionne toujours pas. Pourquoi ? Je t'avoue que je ne sais pas. Comme tu utilises une méthode qui ne me convient pas, je t'ai proposé une autre solution. Je comprends aussi que cette proposition ne te convienne pas non plus mais je ne peux plus rien pour toi.
Sache quand même que VBE (l'éditeur de VBA) propose une option Rechercher/Remplacer ([CTRL]+[H]) qui en quelques clics te permet de remplacer les noms des variables...
Bonne chance.
Bonjour,
Merci pour ton retour. J'ai récupéré ton code et je l'ai fait fonctionner. Cela marche très bien et réalise ce que je veux. Je l'ai donc gardé vu qu'il est mieux que le mien. Merci pour ton aide.
J'aurai besoin d'aide pour ajouter des lignes de codes supplémentaires. Le fichier est joint pour avoir le contexte.
En plus de copier, l'ID d'un onglet à un autre lorsqu'il n'y est pas, je souhaite copier les données des autres colonnes.
Est ce qu'il est possible d'introduire une deuxième boucle comme ci-dessous ?
For I = 5 To DLE 'boucle sur toutes les lignes éditées I de l'onglet Extraction (en partant de la cinquième)
'définit la recherche R (recherche la valeur entière de la cellule ligne I colonne CIDE
'de l'onglet Extraction dans la colonne CIDD de l'onglet DataBase
Set R = OD.Columns(CIDD).Find(OE.Cells(I, CIDE), , xlValues, xlWhole)
If R Is Nothing Then 'condition : si aucune occurrence trouvée
'définit la cellule de destination DEST (première cellule vide de la colonne CIDD de l'onglet DataBase)
For J = 1 to DerniereColonneExtraction
Set DEST = OD.Cells(Application.Rows.Count, J).End(xlUp).Offset(1, 0)
OE.Cells(I, J).Copy DEST 'copie la cellule ligne I colonne CIDE de l'onglet Extraction et la colle dans DEST
Next J
End If 'fin de la condition
Next I 'prochaine ligne de la boucle
Bonjour Exia, bonjour le forum,
Désolé pour le retard mais je suis peu disponible en ce moment.
Essaie comme ça (3 changements notés "<------ ICI", dans la code)Sub NouveauxDocs()
Dim OD As Worksheet 'déclare la variable OD (Onglet Database)
Dim OE As Worksheet 'déclare la variable OE (Onglet Extraction)
Dim CIDD As Integer 'déclare la variable CIDD (Colonne ID Database)
Dim CIDE As Integer 'déclare la variable CIDE (Colonne ID Extraction))
Dim DLE As Long 'déclare la variable DLE (Dernière Ligne Extraction)
Dim DCE As Integer 'déclare la variable DCE (Dernière Colonne Extactoin)
Dim I As Long 'déclare la variable I (Incrément)
Dim R As Range 'déclare la variable R (Recherche)
Dim DEST As Range 'déclare la variable DEST (cellule de DESTination) <------------- ICI
Set OD = Worksheets("DataBase") 'définit l'onglet OD
Set OE = Worksheets("Extraction") 'définit l'onglet OE
CIDD = OD.Rows(1).Find("ID", , xlValues, xlWhole).Column 'définit la colonne CIDD contenant ID dans la lignne 1 de l'onglet Database
CIDE = OE.Rows(4).Find("ID", , xlValues, xlWhole).Column 'définit la colonne CIDE contenant ID dans la ligne 4 de l'onglet Extraction
DLE = OE.Cells(Application.Rows.Count, CIDE).End(xlUp).Row 'définit la dernière ligbne éditée DLE de la colonne CIDE de l'onglet Extraction
DCE = OE.Cells(4, Application.Columns.Count).End(xlToLeft).Column 'définit la dernière colonne éditée DCE de la ligne 4 de l'onglet Extraction <------------- ICI
For I = 5 To DLE 'boucle sur toutes les lignes éditées I de l'onglet Extraction (en partant de la cinquième)
'définit la recherche R (recherche la valeur entière de la cellule ligne I colonne CIDE
'de l'onglet Extraction dans la colonne CIDD de l'onglet DataBase
Set R = OD.Columns(CIDD).Find(OE.Cells(I, CIDE), , xlValues, xlWhole)
If R Is Nothing Then 'condition : si aucune occurrence trouvée
'définit la cellule de destination DEST (première cellule vide de la colonne CIDD de l'onglet DataBase)
Set DEST = OD.Cells(Application.Rows.Count, CIDD).End(xlUp).Offset(1, 0)
OE.Range(OE.Cells(I, CIDE), OE.Cells(I, DCE)).Copy DEST 'copie la plage ligne I colonne CIDE à colonne DLE de l'onglet Extraction et la colle dans DEST <------------- ICI
End If 'fin de la condition
Next I 'prochaine ligne de la boucle
End SubBonjour,
Je suis désolé pour le délai de réponse, j'étais sur un autre projet et je n'ai pas eu le temps de regarder ce code. Je te remercie pour ton aide.
Je vais tester ce que ça donne et je te fais un retour dans les prochains jours.
Merci !