Mettre boucle for dans condition if VBA [Fermé]

Signaler
-
Messages postés
1682
Date d'inscription
mardi 12 juillet 2011
Statut
Membre
Dernière intervention
20 juillet 2012
-
Bonjour,

Je voudrais savoir s'il était possible de mettre un boucle for dans une condition if, par exemple:

if UBound(tab_bd)>0 and
for c=0 to UBound(tab_bd)
cells(tab_bd(c),6)=cells(tab_bd(0),6)
cells(tab_bd(c),7)=cells(tab_bd(0),7)
cells(tab_bd(c),8)=cells(tab_bd(0),8)
then
msgbox("ok")
end if

Pour l'instant ça ne marche pas...
Merci d'avance à ceux qui pourront m'éclairer sur ce point.

16 réponses

Bonjour,
On ne vout pas trop ce que tu cherches à faire ..
Essaie ça :

dim bTrouvé as boolean ;
bTrouvé = false ;

if UBound(tab_bd)>0 then
for c=0 to UBound(tab_bd)
if cells(tab_bd(c),6)=cells(tab_bd(0),6) and
cells(tab_bd(c),7)=cells(tab_bd(0),7) and
cells(tab_bd(c),8)=cells(tab_bd(0),8) then
bTrouvé = true ;
exit for ;
next ;
end if ;
if bTrouvé then msgbox("OK") ;

cdlt
Je ne pense pas que cette solution convienne à mon cas, car pour moi il faut que tous les bTrouvé soient true pour afficher la message box. Ici j'ai l'impression qu'il suffit que le dernier b trouvé soit true pour que ça marche.
Dis moi si j'ai mal compris ton code.

Merci
Oui, tu l'as mal compris, regarde bien les And dans la condition du If.
Il faut que les 3 conditions soient réalisées pour que bTrouvé passe à True

cdlt
Oui mais il faut que les 3 conditions soient respectés pour chaque "c". Est-ce le cas ici ? Ou il suffit que les 3 conditions soient respectés pour le dernier c et bTrouvé=true dans ce cas?
Le exit for ne me fait-il pas sortir de la boucle et dans ce cas s'arrête au premier cas trouvé? Si oui, comment faire pour vérifier tous les "c" et si c'est true pour tous les cas alors afficher la message box?

Please help, c'est vraiment urgent...
Regarde bien les "and". Il faut que les 3 conditions soient respectées.
Si c'est le cas, tu sors de la boucle avec ton indicateur à True.
Sinon, tu boucles sur tout ton tableau jusqu'à ce que tu trouves.
A la fin, si tu n'as rien trouvé, ton flag est resté à false et tu n'affiches pas le message.
Tu fais des tests, au moins ? Où c'est juste pour nous occuper ?
Mille excuses, il manquait un endif aprè la sortie forcée de boucle. Je la refais.

dim bTrouvé as boolean ;
bTrouvé = false ;

if UBound(tab_bd)>0 then
for c=0 to UBound(tab_bd)
if cells(tab_bd(c),6)=cells(tab_bd(0),6) and _
cells(tab_bd(c),7)=cells(tab_bd(0),7) and _
cells(tab_bd(c),8)=cells(tab_bd(0),8) then
bTrouvé = true ;
exit for ;
endif ;
next ;
end if ;

if bTrouvé then msgbox("OK") ;
Merci de ton aide Titi-21. Mais ma question est la suivante, dans le cas où UBound(tab_bd)=2: imaginons que pour c=0, la condition soit vérifié, pour c=1 également mais que pour c=2 elle ne le soit pas.
Il faudrait dans ce cas que la msgbox ne s'affiche pas, or d'après le programme ci-dessus j'ai l'impression qu'elle va s'afficher...
Pourrais-tu m'éclairer sur ce point?
Après test, ça fait bien ce que j'ai dit. Quelqu'un à une solution pour que la message box s'affiche uniquement si la condition est vérifié pour tous les "c"?
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Bonjour Jack et Titi-21

Jack vous n'expliquez pas assez ce que vous attendez. De ce fait Titi-21 vous a fourni un code qui marche mais ne correspond pas a ce que vous attendiez.

Ci-dessous un exmple de code qui affiche le message si toutes les verifs sont vrai.

Dim pTrouvé As Boolean
pTrouvé = False
    
  If UBound(tab_bd) > 0 Then
    For c = 0 To UBound(tab_bd)
      If Cells(tab_bd(c), 6) = Cells(tab_bd(0), 6) And _
          Cells(tab_bd(c), 7) = Cells(tab_bd(0), 7) And _
          Cells(tab_bd(c), 8) = Cells(tab_bd(0), 8) Then
      Else
        'si un seul pas trouvé
        pTrouvé = True
      End If
    Next c
  End If

  'Message si pas pastrouve
  If Not pTrouvé Then
    MsgBox ("OK")
  End If


Bonne suite
Bonjour f894009,

Merci de ton aide et désolé pour mon imprécision. Toutefois, ne manquerait-il pas un morceau dans ton code après le then?
Je crois que je viens de comprendre, quand on ne met rien après le then, il ne se passe rien et c'est exactement ce que tu recherches ici. C'est bien cela?
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Re,
Non, mais cela peut ce modifier comme cela:

Dim pTrouvé As Boolean

pTrouvé = False
    
  If UBound(tab_bd) > 0 Then
    For c = 0 To UBound(tab_bd)
      If Not (Cells(tab_bd(c), 6) = Cells(tab_bd(0), 6) And _
          Cells(tab_bd(c), 7) = Cells(tab_bd(0), 7) And _
          Cells(tab_bd(c), 8) = Cells(tab_bd(0), 8)) Then
        'si un seul pas trouvé
        pTrouvé = True
      End If
    Next c
  End If
  'Message si pas pastrouve
  If Not pTrouvé Then
    MsgBox ("OK")
  End If


Bon courage
Messages postés
1682
Date d'inscription
mardi 12 juillet 2011
Statut
Membre
Dernière intervention
20 juillet 2012
293
salut

le premier if ne sert à rien puisque cette condition est testé par la boucle
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Bonjour vordano,
Si il sert, parce que Jack utilise des tests UBound(tab_bd) a differentes valeurs pour faire ou ne pas faire des morceaux de code dans sa programmation (mais vous ne pouviez pas le savoir).
Messages postés
1682
Date d'inscription
mardi 12 juillet 2011
Statut
Membre
Dernière intervention
20 juillet 2012
293
ah d'ac

et j'espère qu'il n'y à pas de 0 dans son tab_bd(c) parce que je ne crois pas que microsoft ai modifié son vba pour accepter les f0, g0, h0
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Re,
Jack met des numeros de ligne d' une feuille excel dans son tableau. Merci pour le exit for, mais j'attendais de savoir la suite pour lui ecrire.

Bye
Encore une question: pour optimiser le programme, ne pourrait-on pas mettre un exit for après le pTrouvé=TRUE?
Parce que dans mon cas il suffit qu'un des "c" ne respecte pas la condition pour ne pas afficher le message.
Messages postés
1682
Date d'inscription
mardi 12 juillet 2011
Statut
Membre
Dernière intervention
20 juillet 2012
293
on peux mettre un exit oui

ou utiliser un while avec toutes tes conditions
Merci Vordano et f894009 de votre aide précieuse. Par contre chose étrange, j'ai adapté le code à une autre application que l'affichage de la message box et ça ne fait pas vraiment ce que je veux...
Voir fichier joint, ça sera plus clair: http://cjoint.com/?3GjsC0LB4Rq

Je ne comprends pas pourquoi pour les lignes 12 à 14 j'obtiens cela dans les lignes surlignés... normalement je devrais être dans le cas où pFind = True ici et donc juste afficher les numéros de lignes ayant le même "CatName" et "Name".

Si vous pouviez m'éclairez là-dessus je vous serai vraiment reconnaissant, parce que je commence vraiment à avoir retourner la question dans tous les sens sans avoir la moindre idée d'où ça vient.

Merci d'avance
PS: n'accordez pas d'importance au code mis en commentaire
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Re,

pour le if not(, c'est pour tous les objets du test ou que les deux premiers?????
Tous les objets du test, si par tous les objets vous entendez les égalités séparées par les And
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Bonjour,
Il faut modifier ce que vous avez fait, une ( apres le Not et une ) juste apres le dernier, avant Then.

Votre test ElseIf UBound(tab_bd) > 0 And pFind = True Then ne sera jamais vrai.

Code modifie (j'ai enleve le code en commentaire)

Sub Completor()

  Dim Wbk As Workbook
  Dim cell As Range
  Dim plage As Range
  Dim line_insertion As Integer
  Dim tab_bd
  Dim msg As String
  Dim msg2 As String
  Dim pFind As Boolean
  
  
'Definition of "plage": plage is the group that contain all the elements of the column "Name"
  Set Wbk = Workbooks("Test nutrition.xls")
  Set plage = Wbk.Worksheets("Structure").Range("F3:" & Range("F3").End(xlDown).Address)
  
'We activate the worksheet where we work
  Wbk.Worksheets("Structure").Activate
    
  'Now we looking for the case where only "CatName" and "Name" corresponding
  For j = 3 To Cells(3, 6).End(xlDown).Row
    line_insertion = 0
    pFind = False
    If Cells(j, 36) = 0 Then
      ReDim tab_bd(0)
      For Each cell In plage
        If j <> cell.Row And cell.Offset(0, 30) <> 0 Then
          If (Cells(j, 6).Value = cell.Value) And (Cells(j, 5).Value = cell.Offset(0, -1).Value) Then
            ReDim Preserve tab_bd(line_insertion)
            tab_bd(line_insertion) = cell.Row
            line_insertion = line_insertion + 1
          Else
            Cells(j, 30).Value = "No equivalent record was found"
          End If
        End If
      Next cell


      If UBound(tab_bd) = 0 And line_insertion = 1 Then
        Range(Cells(j, 30), Cells(j, 38)).Value = Range(Cells(tab_bd(0), 6).Offset(0, 24), Cells(tab_bd(0), 6).Offset(0, 32)).Value
      ElseIf UBound(tab_bd) > 0 Then
        For c = 0 To UBound(tab_bd)
          If Not ((Cells(tab_bd(c), 30).Value = Cells(tab_bd(0), 30).Value) And _
            (Cells(tab_bd(c), 31).Value = Cells(tab_bd(0), 31).Value) And _
            (Cells(tab_bd(c), 32).Value = Cells(tab_bd(0), 32).Value) And _
            (Cells(tab_bd(c), 33).Value = Cells(tab_bd(0), 33).Value) And _
            (Cells(tab_bd(c), 34).Value = Cells(tab_bd(0), 34).Value) And _
            (Cells(tab_bd(c), 35).Value = Cells(tab_bd(0), 35).Value) And _
            (Cells(tab_bd(c), 36).Value = Cells(tab_bd(0), 36).Value) And _
            (Cells(tab_bd(c), 37).Value = Cells(tab_bd(0), 37).Value) And _
            (Cells(tab_bd(c), 38).Value = Cells(tab_bd(0), 38).Value)) Then
            'si un seul pas trouvé
            pFind = True
            Exit For
          End If
            'MsgBox (pFind)
        Next c
        'Trouve
        If Not pFind Then
          Range(Cells(j, 30), Cells(j, 38)).Value = Range(Cells(tab_bd(0), 30), Cells(tab_bd(0), 38)).Value
        Else
          'Message si pas trouve
          For y = 0 To UBound(tab_bd)
            msg2 = msg2 & tab_bd(y) & ", "
          Next y
          Cells(j, 30).Value = msg2
        End If
      End If
      msg2 = ""
    End If
  Next j
End Sub


A vous de tester et rendez nous compte
Merci pour les parenthèse je ne connaissais pas la syntaxe du if not. Concernant mon else if, j'ai compris qu'il ne le voyait pas car la condition du dessus l'englobe déjà, merci de me l'avoir fait remarquer, à croire que parfois quand on est plongé dans le code on rate des choses essentielles.
ça marche parfaitement, même avec le morceau de code qui était mis en commentaire, merci beaucoup! Par contre, il y a un dernier point que je n'arrive pas résoudre, voir image: http://cjoint.com/?3GkkGMGPlqn
C'est ce que j'obtiens lorsque je lance le code entier (avec celui mis précédemment en commentaire). ça fonctionne très bien sauf qu'il me détecte à la ligne 13, la ligne 14 comme correspondant à ce que je recherche, i.e avec les valeurs nutritionnelles remplies. Logique vu que cette ligne s'est remplie durant l'exécution du code... Mais ce qu'il faudrait c'est qu'il ne tienne compte que des lignes remplies avant l'exécution du code.
Comment pourrait-on programmer cela? En gros, comment ne considérez que l'instant t-1 pour la recherche des données?
ça ne marchera que dans le fichier test. A terme, les lignes à remplir ne serons pas forcément les dernières...
N'y a-t-il pas un autre moyen?
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Re,
Je reflichis a la question.

A+
Messages postés
15740
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
24 avril 2021
1 483
Re,
Mettre en memoire les lignes qui auront ete ecrites apres la ligne de code:
If Not pFind Then

et tester apres le:
For j = 3 To Cells(3, 6).End(xlDown).Row
que j n'est pas deja dans les numeros de lignes deja traitees.

Pour la memoire je vous laisse le choix.

A plus
Finalement je m'en suis sortit plus simplement en utilisant des colorIndex. En effet, j'ai colorié les cellules que j'ai déjà examiné comme ça elles sont reconnaissables, puis lors des tests je rajoute la condition qu'elles ne doivent pas être coloré. Ensuite une simple boucle en fin de programme pour décoloré toutes les cellules que l'on a précédemment colorées.
Voilà, mon programme est maintenant finit et fonctionnel.
Merci à vous pour l'aide précieuse que vous m'avez fourni, j'ai vraiment appris pas mal de chose en programmation VBA.

A+

Sub Completor()

Dim Wbk As Workbook
Dim cell As Range
Dim plage As Range
Dim line_insertion As Integer
Dim tab_bd
Dim msg As String
Dim msg2 As String
Dim pFind As Boolean


'Definition of "plage": plage is the group that contain all the elements of the column "Name"
Set Wbk = Workbooks("Test nutrition.xls")
Set plage = Wbk.Worksheets("Structure").Range("F3:" & Range("F3").End(xlDown).Address)

'We activate the worksheet where we work
Wbk.Worksheets("Structure").Activate

'For each element record we test if the cell AJ is empty
For i = 3 To Cells(3, 6).End(xlDown).Row
If Cells(i, 36).Value = "" Then
Cells(i, 36).Interior.ColorIndex = 29
End If
line_insertion = 0
If Cells(i, 36) = 0 Then
ReDim tab_bd(0) 'tab_bd is dynamic table, here we initialize it size at 0 element
'If AJ isn't empty we do nothing, but if is empty then we "scan" each other record
For Each cell In plage
'For all other records with cell AJ not empty, we look if we have the same "CatName", "Name", "Name2"
If i <> cell.Row And cell.Offset(0, 30) <> 0 And cell.Offset(0, 30).Interior.ColorIndex <> 29 Then
'If it's the case then
If (Cells(i, 6).Value = cell.Value) And (Cells(i, 5).Value = cell.Offset(0, -1).Value) And (Cells(i, 7).Value = cell.Offset(0, 1).Value) Then
ReDim Preserve tab_bd(line_insertion) 'We resize the tab_bd according to the value of line_insertion
tab_bd(line_insertion) = cell.Row 'We save the row of the record as the "line_insertion" element of tab_bd
line_insertion = line_insertion + 1 'We increment by one line_insertion, like that the next row will be the next element in tab_bd
Else
Cells(i, 30).Value = "No equivalent record was found"
End If
End If
Next cell

'If tab_bd contain only one element, we copy nutrition values of corresponding record
If UBound(tab_bd) = 0 And line_insertion = 1 Then
Range(Cells(i, 30), Cells(i, 38)).Value = Range(Cells(tab_bd(0), 30), Cells(tab_bd(0), 38)).Value
'Else we display a messsage with the different row numbers of record correponding
ElseIf UBound(tab_bd) > 0 Then
For Z = 0 To UBound(tab_bd)
msg = msg & tab_bd(Z) & ", "
Next Z
Cells(i, 30).Value = "Non-unique nutrition numbers in lines " & Left(msg, Len(msg) - 2)
End If
End If
msg = ""
Next i

'Now we looking for the case where only "CatName" and "Name" corresponding
For j = 3 To Cells(3, 6).End(xlDown).Row
line_insertion = 0
pFind = False
If Cells(j, 36) = 0 And (Cells(j, 30).Value = "" Or Cells(j, 30).Value = "No equivalent record was found") Then
ReDim tab_bd(0)
For Each cell In plage
If j <> cell.Row And cell.Offset(0, 30) <> 0 And cell.Offset(0, 30).Interior.ColorIndex <> 29 Then
If (Cells(j, 6).Value = cell.Value) And (Cells(j, 5).Value = cell.Offset(0, -1).Value) Then
ReDim Preserve tab_bd(line_insertion)
tab_bd(line_insertion) = cell.Row
line_insertion = line_insertion + 1
Else
Cells(j, 30).Value = "No equivalent record was found"
End If
End If
Next cell


If UBound(tab_bd) = 0 And line_insertion = 1 Then
Range(Cells(j, 30), Cells(j, 38)).Value = Range(Cells(tab_bd(0), 6).Offset(0, 24), Cells(tab_bd(0), 6).Offset(0, 32)).Value
ElseIf UBound(tab_bd) > 0 Then
For c = 0 To UBound(tab_bd)
If Not ((Cells(tab_bd(c), 30).Value = Cells(tab_bd(0), 30).Value) And _
(Cells(tab_bd(c), 31).Value = Cells(tab_bd(0), 31).Value) And _
(Cells(tab_bd(c), 32).Value = Cells(tab_bd(0), 32).Value) And _
(Cells(tab_bd(c), 33).Value = Cells(tab_bd(0), 33).Value) And _
(Cells(tab_bd(c), 34).Value = Cells(tab_bd(0), 34).Value) And _
(Cells(tab_bd(c), 35).Value = Cells(tab_bd(0), 35).Value) And _
(Cells(tab_bd(c), 36).Value = Cells(tab_bd(0), 36).Value) And _
(Cells(tab_bd(c), 37).Value = Cells(tab_bd(0), 37).Value) And _
(Cells(tab_bd(c), 38).Value = Cells(tab_bd(0), 38).Value)) Then
'If only one record hasn't the same nutrition values than the first one selected then pFind = True
pFind = True
Exit For
End If
Next c

'If pFind = False then we copy the nutrition value from the first row selected (pFind = False significate that nutrition values are the same for all records selected)
If Not pFind Then
Range(Cells(j, 30), Cells(j, 38)).Value = Range(Cells(tab_bd(0), 30), Cells(tab_bd(0), 38)).Value
'Else we display a messsage with the different row numbers of record correponding
Else
For y = 0 To UBound(tab_bd)
msg2 = msg2 & tab_bd(y) & ", "
Next y
Cells(j, 30).Value = "Non-unique nutrition numbers in lines " & Left(msg2, Len(msg2) - 2)
End If
End If
msg2 = ""
End If
Next j

For k = 3 To Cells(3, 6).End(xlDown).Row
If Cells(k, 36).Interior.ColorIndex = 29 Then
Cells(k, 36).Interior.ColorIndex = xlColorIndexNone
End If
Next k

End Sub


PS: Je ne sais pas comment mettre le topic en "résolu", j'ai l'impression que lorsque j'exécute CCleaner je n'ai plus la possibilité de le faire.
Messages postés
1682
Date d'inscription
mardi 12 juillet 2011
Statut
Membre
Dernière intervention
20 juillet 2012
293
pour clore il faut être connecté et cliquer sur le lien au dessus de ton premier post (qui est le sujet)