J'essayais de savoir comment déclarer un tableau à 2 dimensions, mais tous les exemples que j'ai trouvés jusqu'à présent sont déclarés avec des entiers définis. J'essaie de créer un programme qui utilisera deux matrices à 2 dimensions, puis effectuera des opérations simples sur ces tableaux (comme la recherche de différence ou pourcentage). Les tableaux sont renseignés par des chiffres dans des feuilles Excel (un ensemble de numéros est sur la feuille1 et un autre ensemble est sur la feuille2, les deux ensembles ont le même nombre de lignes et de colonnes).
Puisque je ne sais pas combien de lignes ou de colonnes Il y a j'allais utiliser des variables. p> Lorsque je tente d'exécuter cette erreur, je reçois une erreur de compilation à la Merci, P> Jesse Smothermon P> P> DIM S2ARRAY (TOTALROWOW, TOTALCOL) < / code> disant qu'une expression constante est requise. La même erreur se produit si je le change en Dim S2array (1 à TOTALROWOW, 1 à TOTALCOL) CODE>. Puisque je ne sais pas ce que sont les dimensions de l'issue go, je ne peux pas le déclarer comme Dim S2array (1, 1) code> Parce que je vais obtenir une exception hors limites. < / p>
4 Réponses :
Vous avez besoin Comme d'autres ont souligné, votre problème réel serait mieux résolu avec des gammes. Vous pouvez essayer quelque chose comme ceci: p> redim code>:
Merci, il semble que cela fonctionne mais je ne peux pas vraiment dire parce que je ne peux pas vraiment voir ce qui est là. Savez-vous comment imprimer les valeurs dans des cellules? Voici ce que j'ai jusqu'à présent: activeworkbook.sheets (FirsteheetName) .Copie avant: = actifworkbook.sheets (FirstSheetName) pour IROW = 1 à TOTALROW pour ICOL = 1 à TOTALCOL ActiveHeet.cells (IROW, ICOL) = Anglais ) Next ICOL Next Irow, mais cela ne produit rien
@Jesse Essayez mon édition, des trucs si dans le code dans une feuille de calcul vide et frappez F5!
@David a une sorte d'erreur étrange. Ma grille de test passe de 1 à 324, les dimensions étant 9 par 36 (avec la deuxième grille passant de 324 à 1). Je change votre code strictement pour adapter mon code pour que rien ne soit majeur, à l'exception des noms. Jusqu'à présent, il semble simplement copier ma première grille sur, puis dispose d'une boîte de message indiquant "Impossible d'effectuer l'opération demandée". Merci
@Jesse Eh bien, je ne peux pas deviner quelle raison cela doit être quelque chose de mal dans votre code. Quoi qu'il en soit, vous devriez le faire @ Idevelop's Way, ce sera beaucoup plus facile et plus rapide!
@Jesse pour ce que ça vaut la peine, j'ai mis à jour ma réponse pour inclure une version de plage basée sur une plage.
J'ai compris ce que le problème était ... Quand je remplissais les matrices, je viens d'utiliser des "cellules" au lieu de "ActiveHeet.cells". Je suppose que lorsque vous utilisez simplement des cellules, il regarde la feuille où se trouve le bouton macro.
Savez-vous comment imprimer les valeurs dans des cellules? Er, tu faisais. Vous avez vu le code qui remplit une variante de tableau à 2 dimensions comme Varx - Plage.Value? Si vous pouvez définir une plage de mêmes dimensions, Plage.Value = VararrayX remplit votre plage * dans un «hit à la feuille» au lieu de plusieurs centaines d'opérations d'écriture à la cellule distinctes. Je verrai si je peux poster un code de chaudière, j'ai écrit que cela encapsule le processus ...
En fait, je n'utiliserais aucun redim, ni une boucle pour transférer des données de la feuille à la tablette: ou même p> Et c'est tout, votre tableau est rempli beaucoup plus vite puis avec une boucle, pas de redim. p> p>
+1 C'est une meilleure façon de le faire, je suis d'accord. Je viens de traiter naïvement l'erreur de syntaxe.
C'est la meilleure façon, il convient de souligner que l'instruction DIM utilise une variante par défaut.
Je ne sais pas quelles sont les dimensions avant que la macro commence à courir. Merci d'avoir répondu
Testé-le sur le mien et cela a au moins fait la même chose que Redim et cela semblait plus rapide. Question rapide, pourrais-je utiliser cette région en courant pour remplir un espace spécifique avec un tableau? Cela pourrait donc ressembler à une plage ("A2"). CurrentRégion = Artwo où Artwo est un tableau. Merci
Je lis un peu plus sur CurrentRégion, ai-je raison de mettre en évidence la région ou stocke-t-il des valeurs dans la matrice (utilisée ici d'un tableau 2 dimensions)?
CurrentRegion étend la plage jusqu'à ce qu'il trouve une ligne vide et une colonne vide. C'est le signe "=" qui attribue les valeurs de la plage dans la matrice.
@idevlop Une fois que j'ai défini les valeurs dans les matrices, comment puis-je effectuer des opérations sur eux? Voici donc que S2ARRAY a un ensemble de valeurs, S3ARRAY a un autre ensemble et répondeur sera la différence entre ces tableaux. S2ARRAY et S3ARRAY sont situés dans différentes feuilles Excel. J'ai essayé de faire de réponse = S2ARRAY - S3ARRAY, mais obtenez une inadéquation de type. Merci
Pour cela, vous devrez utiliser une double boucle imbriquée, comme dans votre poste d'origine. Pas de raccourcis ici, hélas.
Désolé que cela ne soit pas sous la forme appropriée ... mais voici mon code pour essayer de soustraire les valeurs dans un tableau d'un autre. Pour Irow = 1 à TOTALROW pour ICOL = 1 à TOTALCOL répondeur (IROW, ICOL) = S2ARRAY (IROW, ICOL) - S3ARRAY (IROW, ICOL) Next ICOL Next Irwow Heworray a des valeurs vides tout au long. Pouvez-vous dire ce qui ne va pas avec ça? Merci
Pour cet exemple, vous devrez créer votre propre type, ce qui serait un tableau. Ensuite, vous créez un plus grand tableau quels éléments sont de type que vous venez de créer.
Pour exécuter mon exemple, vous devrez remplir des colonnes A strong> et B fort> dans feuille1 forte> avec certaines valeurs. Ensuite, courez Test () Strong>. Il lira la première Testé dans Excel 2007. P> Option Explicit
Private Type SmallArr
Elt() As Variant
End Type
Sub test()
Dim x As Long, max_row As Long, y As Long
'' Define big array as an array of small arrays
Dim BigArr() As SmallArr
y = 2
ReDim Preserve BigArr(0 To y)
For x = 0 To y
ReDim Preserve BigArr(x).Elt(0 To 1)
'' Take some test values
BigArr(x).Elt(0) = Cells(x + 1, 1).Value
BigArr(x).Elt(1) = Cells(x + 1, 2).Value
Next x
'' Write what has been read
Debug.Print "BigArr size = " & UBound(BigArr) + 1
For x = 0 To UBound(BigArr)
Debug.Print BigArr(x).Elt(0) & " | " & BigArr(x).Elt(1)
Next x
'' Get the number of the last not empty row
max_row = Range("A" & Rows.Count).End(xlUp).Row
'' Change the size of the big array
ReDim Preserve BigArr(0 To max_row)
Debug.Print "new size of BigArr with old data = " & UBound(BigArr)
'' Check haven't we lost any data
For x = 0 To y
Debug.Print BigArr(x).Elt(0) & " | " & BigArr(x).Elt(1)
Next x
For x = y To max_row
'' We have to change the size of each Elt,
'' because there are some new for,
'' which the size has not been set, yet.
ReDim Preserve BigArr(x).Elt(0 To 1)
'' Take some test values
BigArr(x).Elt(0) = Cells(x + 1, 1).Value
BigArr(x).Elt(1) = Cells(x + 1, 2).Value
Next x
'' Check what we have read
Debug.Print "BigArr size = " & UBound(BigArr) + 1
For x = 0 To UBound(BigArr)
Debug.Print BigArr(x).Elt(0) & " | " & BigArr(x).Elt(1)
Next x
End Sub
Voici Un tableau VBA générique pour fonction Range strong> qui écrit un tableau à la feuille dans un « hit » à la feuille. Ceci est beaucoup em> plus vite que l'écriture des données dans la feuille une cellule à la fois dans les boucles pour les lignes et colonnes ... Cependant, il y a un peu de ménage à faire, comme vous devez spécifier la taille de la cible gamme correctement cette apparence « d'entretien » comme beaucoup de travail et il est probablement assez lent. mais ce code est « last mile » pour écrire à la feuille, et tout em> est plus rapide que d'écrire à la feuille de calcul. Ou du moins, beaucoup plus vite que c'est effectivement instantanée, par rapport à une lecture ou d'écriture à la feuille de calcul, même en VBA, et vous devez faire tout ce que vous pouvez éventuellement dans le code avant de frapper la feuille. P> composante majeure de c'est-piégeage d'erreur que je voyais tourner partout. Je déteste le codage répétitif: Je l'ai codé tout ici, et - espérons-le - vous ne devez écrire à nouveau p> Array pour Range 'Une VBA fonction strong> <. p> Private Function ArrayDimensions(arr As Variant) As Integer
'-----------------------------------------------------------------
' will return:
' -1 if not an array
' 0 if an un-dimmed array
' 1 or more indicating the number of dimensions of a dimmed array
'-----------------------------------------------------------------
' Retrieved from Chris Rae's VBA Code Archive - http://chrisrae.com/vba
' Code written by Chris Rae, 25/5/00
' Originally published by R. B. Smissaert.
' Additional credits to Bob Phillips, Rick Rothstein, and Thomas Eyde on VB2TheMax
Dim ptr As Long
Dim vType As Integer
Const VT_BYREF = &H4000&
'get the real VarType of the argument
'this is similar to VarType(), but returns also the VT_BYREF bit
CopyMemory vType, arr, 2
'exit if not an array
If (vType And vbArray) = 0 Then
ArrayDimensions = -1
Exit Function
End If
'get the address of the SAFEARRAY descriptor
'this is stored in the second half of the
'Variant parameter that has received the array
CopyMemory ptr, ByVal VarPtr(arr) + 8, 4
'see whether the routine was passed a Variant
'that contains an array, rather than directly an array
'in the former case ptr already points to the SA structure.
'Thanks to Monte Hansen for this fix
If (vType And VT_BYREF) Then
' ptr is a pointer to a pointer
CopyMemory ptr, ByVal ptr, 4
End If
'get the address of the SAFEARRAY structure
'this is stored in the descriptor
'get the first word of the SAFEARRAY structure
'which holds the number of dimensions
'...but first check that saAddr is non-zero, otherwise
'this routine bombs when the array is uninitialized
If ptr Then
CopyMemory ArrayDimensions, ByVal ptr, 2
End If
End Function
+1 pour dire "Vous devriez faire tout ce que vous pouvez faire tout ce que vous pouvez faire de la feuille" et +1 pour avoir le post le plus méga-ginormous que j'ai jamais vu sur. au moins dans la section VBA.
@idevlop ... Yep, Tout ce que ces trucs b>. En partie, c'est VBA ne pas être une langue concise; Surtout, nous ne passions pas de paramètres à une fonction bien définie écrite par un développeur, nous interagissons avec une interface utilisateur - une grille pouvant contenir tout type de données et toutes sortes d'erreurs - qui exigent un codage défensif étendu.
@Nile: Je plaisantais. Je ne vois pas vraiment la valeur ajoutée par rapport à la "solution d'une ligne" J'ai donné Stackoverflow.com/a/5252452/78522 a>
@idevlop - Si vous ne le faites jamais une fois une fois, la valeur ajoutée est négative. Si vous développez plus d'une centaine d'outils tactiques par an, de jeter des données dans des plages partout et partout, et vous devez les supporter B> la valeur du code avec la résilience intégrée est considérable. La plus importante métrique de productivité pour un développeur tactique n'est pas une sortie de ligne, c'est la charge de travail continue par ligne de code.
Utilisez des tableaux de variante selon la réponse d'Idevlop. Ils ont été faits pour des gammes dans Excel.