web-dev-qa-db-fra.com

Excel VBA: plage de tableaux en une étape

Je sais que vous pouvez facilement prendre une plage de cellules et les insérer dans un tableau de variants, mais je souhaite travailler avec un tableau de chaînes (car il s'agit d'un tableau à une dimension et utilise moins de mémoire qu'un tableau de variants).

Est-il possible de convertir automatiquement une plage en tableau de chaînes?

En ce moment, j'utilise une fonction qui prend la plage et enregistre les valeurs dans un tableau variant, puis convertit le tableau variant en tableau de chaînes. Cela fonctionne bien, mais je cherche un moyen de passer directement de la plage au tableau de chaînes. Toute aide serait grandement appréciée.

Function RangeToArray(ByVal my_range As Range) As String()

Dim vArray As Variant
Dim sArray() As String
Dim i As Long

vArray = my_range.Value
ReDim sArray(1 To UBound(vArray))

For i = 1 To UBound(vArray)
    sArray(i) = vArray(i, 1)
Next

RangeToArray = sArray()

End Function 

UPDATE: On dirait qu'il n'y a aucun moyen de sauter l'étape consistant à jeter les données dans un tableau variable avant de le convertir en tableau de chaînes à une dimension. Une honte si c'est vrai (même si cela ne prend pas beaucoup d'effort, j'aime ultra-optimiser alors j'espérais qu'il y avait un moyen de sauter cette étape). Je vais fermer la question dans quelques jours si aucune solution ne se présente. Merci pour les commentaires utiles, les gars!

UPDATE2: La réponse va à Simon qui a fait de gros efforts (tout le monde l’a fait) et qui a tout à fait souligné qu’il était en effet impossible de passer d’un rang à l’autre. Merci tout le monde.

20
aevanko

Que diriez-vous...

Public Function RangeToStringArray(theRange As Excel.Range) As String()

    ' Get values into a variant array
    Dim variantValues As Variant
    variantValues = theRange.Value

    ' Set up a string array for them
    Dim stringValues() As String
    ReDim stringValues(1 To UBound(variantValues, 1), 1 To UBound(variantValues, 2))

    ' Put them in there!
    Dim columnCounter As Long, rowCounter As Long
    For rowCounter = UBound(variantValues, 1) To 1 Step -1
       For columnCounter = UBound(variantValues, 2) To 1 Step -1
           stringValues(rowCounter, columnCounter) = CStr(variantValues(rowCounter, columnCounter))
       Next columnCounter
    Next rowCounter

    ' Return the string array
    RangeToStringArray = stringValues

End Function
10
Simon Cowen

En fait, vous pouvez aller directement d'une plage à un tableau en utilisant les fonctions Split, Join et un délimiteur ne figurant pas dans le texte.

En supposant que vous ayez déjà attribué une plage de valeurs 1D en tant que SrcRange

Dim Array() As String: Array = Split(Join(Application.Transpose(SrcRange), "#"), "#")
5
Tragamor
Function RangeToStringArray(myRange as range) as String()

    ReDim strArray(myRange.Cells.Count - 1) As String
    Dim idx As Long
    Dim c As Range
    For Each c In myRange
        strArray(idx) = c.Text
        idx = idx + 1
    Next c

    RangeToStringArray = strArray
End Function
2
J.A. Daling

Si cela ne vous dérange pas de modifier le contenu du presse-papiers, alors:

  1. COPIER la plage dans le presse-papiers avec la méthode Copy:

    MyTargetRange.Copy
    
  2. Copiez le contenu du presse-papiers dans une variable chaîne (recherchez sur ce site ou ailleurs des fonctions permettant de transférer des chaînes vers/depuis le presse-papiers).

  3. SPLIT la chaîne dans un tableau variant:

    MyStringArray = Split(MyClipboardText, vbCrLf)
    
  4. FACULTATIF: le tableau comportera un élément vide supplémentaire car il y aura toujours un retour supplémentaire (vbCrLf) à la fin du texte que vous venez de copier dans le Presse-papiers. Pour supprimer simplement redimensionner le tableau:

    Redim Preserve MyStringArray(Ubound(MyStringArray) - 1)
    

Très simple et rapide !!!

Les inconvénients sont que le Presse-papiers peut changer lorsque vous vous y attendez le moins (lors d'un nouveau calcul) et qu'il ne produit que des tableaux de chaînes (pas de Doubles ni d'autres types de valeurs numériques).

Cela serait extrêmement utile si vous travaillez avec beaucoup de fonctions répétitives (des milliers) qui utilisent les mêmes données (des milliers de points de données). La première fois que votre fonction est appelée, effectuez tous les calculs intermédiaires sur les plages de données dont vous avez besoin, mais enregistrez les résultats dans des variables statiques. Enregistrez également une copie de chaîne de vos plages d’entrée via le presse-papiers. À chaque appel suivant de votre fonction, convertissez les plages de saisie en texte, à nouveau via le Presse-papiers, et comparez-les avec la copie enregistrée. S'ils sont identiques, vous pourrez peut-être éviter des calculs préliminaires.

1
Shawn Pauliszyn

Les plages nommées utilisées dans VBA sont déjà des tableaux. Alors commencez par créer une plage nommée, puis faites référence à cette plage et supprimez-la. Par exemple:

ThisWorkbook.Names.Add Name:="test_array", RefersTo:=Sheet1.Range("A4:B10")
a = Sheet1.Range("test_array")
ThisWorkbook.Names("test_array").Delete
0
tim goodwin