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 Sub

Bonjour 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 Sub

Bonjour 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.

18exemple.xlsm (22.66 Ko)

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 Sub

A+

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
    Next

a é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 Ind

La 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 Sub

Merci 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 If

Pour 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.

14exemple-1.zip (418.87 Ko)

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 fois

BsAlv,

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
          Next

Je 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
     Next

si 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

Rechercher des sujets similaires à "construction tableau ligne plutot que colonne"