Construction tableau ligne après ligne plutôt que colonne après colonne
Bonjour à tous,
Je suis un utilisateur VBA débutant et cela fait quatre jours que je bute sur un problème.
J'utilise des variables tableau interdépendantes.
Ma première variable tableau, tableau(I, 0), récupère des données dans un onglet Excel nommé "Exercice" (tableau(I, 0) = Sheets("Exercice").Range("A" & I + 1) )
Ma deuxième variable tableau, tableau(I, 1), est égal à 1 si tableau(I - 1, 0) est > 7 et si tableau(I - 1, 2) est = 2
Ma troisième variable tableau, tableau(I, 2), est égal à 2 si tableau(I, 0) est > 8
Mon problème, c'est que la deuxième variable ne fonctionne pas puisque VBA construit d'abord mon premier tableau, puis mon deuxième et enfin mon troisième. Comme s'il construisait colonne après colonne.
Au stade de tableau(I, 1), VBA n'a aucune information sur la valeur de tableau(I, 2).
Sur le tableur Excel, je ne rencontre pas ce problème, puisque le tableur construit ligne après ligne. Je peux très bien construire ma cellule B2 en fonction de la cellule C1. Pas dans mon code VBA.
J'espère avoir été clair.
Qu'est-ce que je n'ai pas compris ? Comment faire pour que mes variables tableau se comportent comme dans un tableur Excel ?
Merci de votre aide.
P.S. : merci de ne pas me donner l'astuce de remplacer dans ma deuxième variable tableau(I - 1, 2) par tableau(I-1, 0) est > 8. Vous n'avez compris, ce n'est pas ce que je recherche.
Sub Exemple()
'Déclarations
Dim tableau()
Dim derniereLigne As Integer
Dim I As Integer
derniereLigne = Sheets("Exercice").Cells(Rows.Count, 1).End(xlUp).Row 'Dernière ligne de la base de données
ReDim tableau(derniereLigne - 1, 2) 'Redimensionnement
For I = 0 To derniereLigne - 1
tableau(I, 0) = Sheets("Exercice").Range("A" & I + 1) 'Enregistrement des valeurs dans le tableau 7, 8, 9 , 8, 7
Next
For I = 1 To derniereLigne - 1
If tableau(I - 1, 0) > 7 And tableau(I - 1, 2) = 2 Then
tableau(I, 1) = 1
End If
Next
For I = 0 To derniereLigne - 1
If tableau(I, 0) > 8 Then
tableau(I, 2) = 2
End If
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("S" & I + 1) = tableau(I, 0)
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("T" & I + 1) = tableau(I, 1)
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("U" & I + 1) = tableau(I, 2)
Next
End SubBonjour Fab7627
Vous devriez en apprendre beaucoup sur le site de notre regretté BOISGONTIER
http://boisgontierj.free.fr/pages_site/tableaux.htm
A+
Bonsoir Bruno,
En effet, j'ai passé une partie de mon après-midi sur ce site sans trouver mon bonheur.
J'avoue que je n'ai pas compris comment remplir mon tableau ARRAY avec des if… Then…
N'importe quoi !
Je me suis emmêlé les pinceaux avec mes For… Next.
Merci d'avoir éclairé ma lanterne sur cette grossière erreur de débutant (c'est ironique !).
Bonsoir Fab7627
N'hésitez pas à reposter le code corrigé, ce sera également une solution pour ceux qui passeraient par ici
Vous avez raison ...
Sub Exemple()
'Déclarations
Dim tableau()
Dim derniereLigne As Integer
Dim I As Integer
derniereLigne = Sheets("Exercice").Cells(Rows.Count, 1).End(xlUp).Row 'Dernière ligne de la base de données
ReDim tableau(derniereLigne - 1, 3) 'Redimensionnement
For I = 0 To derniereLigne - 1
tableau(I, 0) = Sheets("Exercice").Range("A" & I + 1) 'Enregistrement des valeurs dans le tableau 7, 8, 9 , 8, 7
Next
For I = 1 To derniereLigne - 1
If tableau(I - 1, 0) > 7 And tableau(I - 1, 2) = 2 Then
tableau(I, 1) = 1
End If
If tableau(I, 0) > 8 Then
tableau(I, 2) = 2
End If
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("S" & I + 1) = tableau(I, 0)
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("T" & I + 1) = tableau(I, 1)
Next
For I = 0 To derniereLigne - 1
Sheets("Exercice").Range("U" & I + 1) = tableau(I, 2)
Next
End SubBonjour Fab7627,
Et j'ai bien fait, je ne comprend pas votre façon de gérer le tableau
on en fait pas du tout comme ça, sinon ça sert à rien ou pas grand chose !
Pourriez-vous poster votre fichier, qu'on vous donne la vrai bonne solution
A+
Merci, j'attends vos corrections avec impatience.
Re,
Voici
On remplit une variable Array simplement en donnant la plage de cellules
Sub Exemple_BrunoM45()
Dim dLig As Long, Ind As Long
Dim Tabl0 As Variant, Tabl1 As Variant
' Avec l'objet conteneur
With Sheets("Exercice")
' Dernière ligne remplie de la colonne voulue
dLig = .Cells(Rows.Count, 1).End(xlUp).Row
' On remplit le 1er tablo des valeurs
Tabl0 = .Range("A1:A" & dLig).Value
' On dimensionne le tableau 2 multi-dimensions
ReDim Tabl1(3, UBound(Tabl0))
' On passe en revue chaque élément
For Ind = 1 To UBound(Tabl0)
' On effectue les traitments souhaités
Tabl1(0, Ind) = Tabl0(Ind, 1)
If Tabl0(Ind, 1) > 8 Then
Tabl1(2, Ind) = 2
ElseIf Tabl0(Ind, 1) > 7 And Tabl1(2, Ind - 1) = 2 Then
Tabl1(1, Ind) = 1
End If
Next Ind
' On restitue le résultat en redimensionnant la plage comme souhaitée
.Range("S1").Resize(Ind, 3).Value = Application.Transpose(Tabl1)
End With
End SubA+
Merci pour votre code.
Mais à vrai dire j'ai du mal à voir son apport d'efficacité par rapport au mien.
Je note surtout que la partie de mon code :
For I = 1 To derniereLigne - 1
If tableau(I - 1, 0) > 7 And tableau(I - 1, 2) = 2 Then
tableau(I, 1) = 1
End If
If tableau(I, 0) > 8 Then
tableau(I, 2) = 2
End If
Nexta été modifié par :
If Tabl0(Ind, 1) > 8 Then
Tabl1(2, Ind) = 2
ElseIf Tabl0(Ind, 1) > 7 And Tabl1(2, Ind - 1) = 2 Then
Tabl1(1, Ind) = 1
End If
Next IndLa pertinence de ces différences ne me saute pas aux yeux et j'ai du mal à voir les défauts de ma manière de faire.
Votre code fonctionne, mais le mien aussi. Et votre "ElseIf" me perturbe.
Je vous trouve un peu sévère quand vous me dites que mon code "ne sert à rien ou pas grand-chose". A priori, Il semble logique ; il produit le résultat attendu ; et il n'est pas si gourmand que ça en écriture.
Mais ce n'est que l'avis d'un profane, et peut-être que dans quelque temps je vais me rendre compte de l'impasse ou j'étais.
Re,
Je vous trouve un peu sévère quand vous me dites que mon code "ne sert à rien ou pas grand-chose". A priori, Il semble logique ; il produit le résultat attendu ; et il n'est pas si gourmand que ça en écriture.
J'entendais par là que faire 3 boucles pour remplir un tableau n'est pas approprié...
Faites le test sur à minima sur 15000 lignes et je pense que là, vous comprendrez
Maintenant faites comme bon vous semble, perso je m'en fou, c'était juste pour vous dire comment on pratique normalement.
Vous parlez de la vitesse d'exécution ?
bonjour,
un alternatif, la vitesse pour 15.000 lignes? immédiatement (0.2s, 10% pour ce boucle, 90% pour écrire le tableau vers la feuille)
Sub Example_BsAlv()
Dim Tabl0, Tabl1
't = Timer
With Sheets("Exercice")
Tabl0 = .Range("A1:A" & .Range("A" & Rows.Count).End(xlUp).Row).Value ' matrice initiale
Tabl1 = Tabl0 'copie
ReDim Preserve Tabl1(1 To UBound(Tabl0), 1 To 3) 'ajuster les dimensions
For I = 1 To UBound(Tabl1) 'boucle
If Tabl1(I, 1) > 8 Then
Tabl1(I, 3) = 2 'cette ligne
If I < UBound(Tabl1) Then 'et pour la ligne suivante, si ce n'est pas la dernière
If Tabl1(I + 1, 1) > 7 Then Tabl1(I + 1, 2) = 1
End If
End If
Next
.Range("S1").Resize(UBound(Tabl1), UBound(Tabl1, 2)).Value = Tabl1
End With
'MsgBox Timer - t
End SubMerci BsAlv,
Moi j'ai supprimé le "ElseIf" de Bruno. Je veux que l'écriture d'une colonne se fasse selon certaines conditions mais je ne veux pas que l'écriture d'une colonne se fasse exclusivement si les conditions d'une autre colonne ne sont pas remplies.
J'espère que je suis clair, ça l'est à peine pour moi. Le "ElseIf" me gênait, instinctivement quoi.
Cela donne ceci :
Tabl1(0, Ind) = Tabl0(Ind, 1)
If Tabl0(Ind, 1) > 7 And Tabl1(2, Ind - 1) = 2 Then
Tabl1(1, Ind) = 1
End If
If Tabl0(Ind, 1) > 8 Then
Tabl1(2, Ind) = 2
End IfPour info, la vitesse d'exécution du code de Bruno, pour 15000 lignes et avec ma petite modification, est plus de 50 fois plus rapide que la vitesse d'exécution de mon code. Quand même.
re,
il faut minimaliser les interactions avec la feuille, donc écrire ce tableau en une fois vers la feuille.
Votre macro a besoin de 0.25 sec, celles de Bruno et moi 0.1 sec (à peine plus grand que le marge d'erreur de ce chronomètre). Le résultat de vous et moi est égal, les cellules jaune de Bruno sont différent.
Impressionnant.
Hâte d'adapter mon code source à cette nouvelle (pour moi) manière de faire.
Merci BsAlv et merci Bruno.
re,
comme vous êtes débutant, c'est peut-être mieux d'utiliser cette méthode (formule ici dessous avec ubound et lbound) pour comprendre comment transférer une matrice vers une feuille. Votre matrice est base 0 (lbound=0), la mienne est base 1 (lbound=1), c'est pourquoi, vous devez ajouter 1.
La même chose pour l'autre dimension, donc lbound(tableau,1) est la même chose que lbound(tableau) = 0 et lbound(tableau,2) est pour vous ici aussi 0, mais ce n'est pas toujours comme-ca.
exemple une matrice 3D
Dim Arr(-1 to 100, -10 to 5, -365 to 20), bizarre mais possible
Sheets("Exercice").Range("S2").Resize(UBound(tableau) - LBound(tableau) + 1, UBound(tableau, 2) - LBound(tableau, 2) + 1).Value = tableau 'ecrire en une foisBsAlv,
Il y a un truc que je ne comprends pas dans votre code.
For I = 1 To UBound(Tabl1) 'boucle
If Tabl1(I, 1) > 8 Then
Tabl1(I, 3) = 2 'cette ligne
If I < UBound(Tabl1) Then Tabl1(I + 1, 2) = 1
End If
NextJe croyais que pour un "If", il devait suivre obligatoirement un "End If".
Vous, vous utilisez deux "If" pour un seul "End If".
Comment ça s'fait que cela fonctionne ?
Moi, si j'enlève un "End If", ça marche plus.
For I = 1 To derniereLigne - 1
If tableau(I - 1, 0) > 7 And tableau(I - 1, 2) = 2 Then
tableau(I, 1) = 1
End If
If tableau(I, 0) > 8 Then
tableau(I, 2) = 2
End If
Nextsi ce "IF" est très simple et on continue dans la même ligne, le "Endif" n'est plus nécessaire
donc c'est
If I < UBound(Tabl1) Then Tabl1(I + 1, 2) = 1
ou
If I < UBound(Tabl1) Then
Tabl1(I + 1, 2) = 1
endif
Moi, j'utilise ce Add-in pour intendre mes macros, alors cela se voit très vide, s'il me manque quelque part un "Endif" ou un "Next" ou ... n'importe .
https://forum.excel-pratique.com/astuces/intend-macros-texte-en-retrait-171805