VBA - Perdu dans une boucle de tableau à deux dim

Bonjour.

J'essaie désespérément de comprendre pourquoi je reçois le message "L'indice n'appartient pas à la sélection".

J'ai beau avoir lu le tuto de SilkyRoad et celui consacré à la représentation graphique des tableaux, je peine à comprendre:

  • Si le chiffre marqué dans les parenthèses désigne la dimension ou l'indice,
  • Pourquoi on stipule Redim Preserve (1 to 2, 1 to i) : que veut dire ce 1 to 2 je croyais qu'on redimensionnait seulement la dernière dimension.
  • Et à propos du Option Base 0 : cela suppose bien qu'on commence avec l'indice 0, c'est bien ça?

Enfin pour mon code ci dessus (qui cherche des cellules colorées et enregistre dans un tableau les données sur la ligne de ces cellules colorées), ai-je raison de considérer que mon For Each Cell 'puis Next Cell fournit une loop suffisante pour alimenter mon tableau?

Je croyais avoir dépassé mes difficultés d'abstraction, cependant là j'aurais vraiment besoin d'un coup de pouce.

Merci d'avance.

Private Sub CommandButton2_Click()

Dim cell As Range
Dim N As Integer
Dim i As Integer
Dim TblRecap() As Variant

i = 0
    For N = 1 To 10
            For Each cell In Sheets("0" & N).Range("I3:I299")                               'Parcours les feuilles 01 à 10
                    If cell.Interior.COLOR = RGB(174, 240, 194) Then                        'Si une cellule de couleur...
                                            TblRecap(0, i) = Range("B" & cell.Row).Value        'Alimentation des colonnes
                                            TblRecap(1, i) = Range("E" & cell.Row).Value
                                            TblRecap(2, i) = Range("I" & cell.Row).Value
                                            Debug.Print TblRecap(1, i)
                            i = i + 1: ReDim Preserve TblRecap(1 To 2, 1 To i)
                    End If
            Next cell
    Next N
End Sub

Bonsoir,

personnellement j'aurais mis le ReDim Preserve TblRecap(1 To 2, 1 To i)

juste après le "then" et surtout j'aurais mis un "i+1" afin de rester sur une écriture 1to 1 à la première boucle à la place de 1 to 0 !

En effet, vous déclarez le tableau sans "dimension", ensuite vous essayez d'y "entrer" des données et après vous le redimensionnez, c'est "un peu à l'envers", non ?

Pas essayé...

@ bientôt

LouReeD

Bonjour,

Essaie ainsi et médite...

Cdlt.

Private Sub XXX()
Dim ws As Worksheet
Dim Cell As Range, rng As Range
Dim I As Long, lRow As Long, k As Long
Dim Arr() As Variant

    For I = 1 To 10
        Set ws = Worksheets("O" & I)
        With ws
            Set rng = .Range("I3:I299")
            For Each Cell In rng
                lRow = Cell.Row
                If Cell.Interior.Color = RGB(174, 240, 194) Then
                    '3 lignes * k colonnes
                    ReDim Preserve Arr(3, k + 1)
                    Arr(0, k) = .Cells(lRow, 2).Value
                    Arr(1, k) = .Cells(lRow, 5).Value
                    Arr(2, k) = .Cells(lRow, 11).Value
                    k = k + 1
                End If
            Next Cell
        End With
    Next I
    'Restitution dans une nouvelle feuille...
    'x lignes * 3 colonnes
    ActiveWorkbook.Worksheets.Add
    Cells(3, 1).Resize(UBound(Arr, 2), 2).Value = Application.Transpose(Arr)

End Sub

Bonsoir Jean-Eric

à voir le code et mon message je me dis :"je commence à progresser", non ?

@ bientôt pour d'autre leçon !

LouReeD

Bonjour,

puisque tu connais ton nombre de lignes pourquoi faire un Redim à chaque fois ? C'est une (grosse) perte de temps.

Dimensionne-le au maximum, et fait un seul Redim Preserve à la fin quand tu connais le besoin exact.

Ensuite ça m'étonnerait que "O" & I te donne "10" pour I=10, ça sera plutôt "010"

Format(I,"00")

eric

Vous êtes trop sympa!

Merci, j’essai tout ça la semaine pro chaîne et vous laisse une trace de ma monté en sagesse.

Bonjour tout le monde.

@Jean-Eric: merci pour ce code c'est parfait.

@ Eriiic & Lou Reed: c'est dans un tuto que j'ai appris à déclarer un tableau vide (dynamique) et à le dimensionner à chaque attribution de valeur. De cette manière la procédure se charge en temps réel de dimensionner un tableau adapté là où de viser gros pour espérer que tout rentre, risque sur de nombreuses données de manquer de place.

@Eriiic : merci pour le format(i,"00"). Super utile pour mes programmes.

Private Sub CommandButton2_Click()

Dim ws As Worksheet
Dim Cell As Range, rng As Range
Dim i As Long, lRow As Long, k As Long
Dim alpha As String
Dim Arr() As Variant

'Enregistrement des noms de feuilles suos deux chiffres

    For i = 1 To 12
        alpha = Format(i, "00")
        Debug.Print alpha
        Set ws = Worksheets(alpha)
        With ws
            Set rng = .Range("I3:I299")
            For Each Cell In rng
                lRow = Cell.Row
                If Cell.Interior.COLOR = RGB(174, 240, 194) Then
                    '3 lignes * k colonnes
                    ReDim Preserve Arr(3, k+1)
                    Arr(0, k) = .Cells(lRow, 2).Value
                    Arr(1, k) = .Cells(lRow, 5).Value
                    Arr(2, k)= .Cells(lRow, 11).Value
                    k = k + 1
                End If
            Next Cell
        End With
    Next i
    'Restitution dans une nouvelle feuille...
    'x lignes * 3 colonnes
    ActiveWorkbook.Worksheets.Add
    Cells(3, 1).Resize(UBound(Arr, 2), 2).Value = Application.Transpose(Arr)

End Sub

Bonsoir

Vous :

Private Sub CommandButton2_Click()

Dim cell As Range

Dim N As Integer

Dim i As Integer

Dim TblRecap() As Variant

i = 0

For N = 1 To 10

For Each cell In Sheets("0" & N).Range("I3:I299") 'Parcours les feuilles 01 à 10

If cell.Interior.COLOR = RGB(174, 240, 194) Then 'Si une cellule de couleur...

TblRecap(0, i) = Range("B" & cell.Row).Value 'Alimentation des colonnes

TblRecap(1, i) = Range("E" & cell.Row).Value

TblRecap(2, i) = Range("I" & cell.Row).Value

Debug.Print TblRecap(1, i)

i = i + 1: ReDim Preserve TblRecap(1 To 2, 1 To i)

End If

Next cell

Next N

End Sub

Moi :

Bonsoir,

personnellement j'aurais mis le ReDim Preserve TblRecap(1 To 2, 1 To i)

juste après le "then" et surtout j'aurais mis un "i+1" afin de rester sur une écriture 1to 1 à la première boucle à la place de 1 to 0 !

Jean-Eric :

par Jean-Eric » 23 mars 2018, 19:28

Bonjour,

Essaie ainsi et médite...

Cdlt.

Code : Tout sélectionner

Private Sub XXX()

Dim ws As Worksheet

Dim Cell As Range, rng As Range

Dim I As Long, lRow As Long, k As Long

Dim Arr() As Variant

For I = 1 To 10

Set ws = Worksheets("O" & I)

With ws

Set rng = .Range("I3:I299")

For Each Cell In rng

lRow = Cell.Row

If Cell.Interior.Color = RGB(174, 240, 194) Then

'3 lignes * k colonnes

ReDim Preserve Arr(3, k + 1)

Arr(0, k) = .Cells(lRow, 2).Value

Arr(1, k) = .Cells(lRow, 5).Value

Arr(2, k) = .Cells(lRow, 11).Value

k = k + 1

End If

Next Cell

End With

Next I

'Restitution dans une nouvelle feuille...

'x lignes * 3 colonnes

ActiveWorkbook.Worksheets.Add

Cells(3, 1).Resize(UBound(Arr, 2), 2).Value = Application.Transpose(Arr)

End Sub

Vous :

@ Eriiic & Lou Reed: c'est dans un tuto que j'ai appris à déclarer un tableau vide (dynamique) et à le dimensionner à chaque attribution de valeur. De cette manière la procédure se charge en temps réel de dimensionner un tableau adapté là où de viser gros pour espérer que tout rentre, risque sur de nombreuses données de manquer de place.

Donc moi ce soir :

oui je connais redim preserve, mais dans votre premier code vous attribuez une valeur à un tableau non dimensionné, puis vous le redimensionnez...

Quand vous dites :

pourquoi je reçois le message "L'indice n'appartient pas à la sélection".

moi je vous suggérais de redimensionner le tableau puis après mettre la valeur, ce qu'à fait Jean-Eric :

ReDim Preserve Arr(3, k + 1)

Arr(0, k) = .Cells(lRow, 2).Value

Arr(1, k) = .Cells(lRow, 5).Value

Arr(2, k) = .Cells(lRow, 11).Value

k = k + 1

il y a même le +1, non pas avec le i mais avec le k, mais l'idée était là !

Donc merci @ vous de m'expliquer mais je crois bien que j'avais compris !

et oui le Dim TblRecap() As Variant, dimensionne le tableau en variant (d'ailleurs qu'elle est l'utilité car variant est d'office, non ?)

mais ne lui donne aucune taille ni index !

du coup quand vous faites :

                                            TblRecap(0, i) = Range("B" & cell.Row).Value        'Alimentation des colonnes
                                            TblRecap(1, i) = Range("E" & cell.Row).Value
                                            TblRecap(2, i) = Range("I" & cell.Row).Value
                                            Debug.Print TblRecap(1, i)
                            i = i + 1: ReDim Preserve TblRecap(1 To 2, 1 To i)

vous essayez d'attribuer des valeur à des index de tableau qui n'existe pas du coup vous avez le message d'erreur "l'indice n'appartient pas à la sélection"

Perso c'est à ceci que j'ai répondu... Excusez moi du peu, mais quand je dis :"je pense que c'est l'inverse" cela veut dire que c'est l'inverse !

@ bientôt

LouReeD

Bonjour,

à mon tour

là où de viser gros pour espérer que tout rentre, risque sur de nombreuses données de manquer de place.

Il ne s'agit pas de viser gros, tu connais ton nombre de lignes : 3 à 299. 297 lignes c'est peanuts.

Redim Preserve est consommateur de ressources, autant limiter quand on peut. Surtout si ça simplifie le code en plus.

eric

Bonjour Messieurs,

je m'incline.

Celui qui apprend fonde ses certitudes seulement sur ce qu'il connait.

Donc j'ai encore beaucoup à apprendre et vous remercie d'ailleurs pour vos contributions sur ce poste qui me servira de référence dorénavant.

Merci.

Bonsoirs,

rassurez vous si je puis dire, j'en ai encore (énormément ) à apprendre !

Bon courage pour la suite.

@ bientôt (sur le forum)

LouReeD

Rechercher des sujets similaires à "vba perdu boucle tableau deux dim"