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 ce1 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