VBA
Copia, restituisce e passa array
Ricerca…
Copia di array
È possibile copiare un array VBA in un array dello stesso tipo usando l'operatore =
. Gli array devono essere dello stesso tipo, altrimenti il codice genererà un errore di compilazione "Can not assign to array".
Dim source(0 to 2) As Long
Dim destinationLong() As Long
Dim destinationDouble() As Double
destinationLong = source ' copies contents of source into destinationLong
destinationDouble = source ' does not compile
L'array sorgente può essere fisso o dinamico, ma l'array di destinazione deve essere dinamico. Cercando di copiare su un array fisso si genera un errore di compilazione "Can not assign to array". Tutti i dati preesistenti nell'array di ricezione vengono persi e i relativi limiti e dimensioni vengono modificati allo stesso array di origine.
Dim source() As Long
ReDim source(0 To 2)
Dim fixed(0 To 2) As Long
Dim dynamic() As Long
fixed = source ' does not compile
dynamic = source ' does compile
Dim dynamic2() As Long
ReDim dynamic2(0 to 6, 3 to 99)
dynamic2 = source ' dynamic2 now has dimension (0 to 2)
Una volta eseguita la copia, i due array sono separati in memoria, ovvero le due variabili non sono riferimenti agli stessi dati sottostanti, quindi le modifiche apportate a un array non vengono visualizzate nell'altro.
Dim source(0 To 2) As Long
Dim destination() As Long
source(0) = 3
source(1) = 1
source(2) = 4
destination = source
destination(0) = 2
Debug.Print source(0); source(1); source(2) ' outputs: 3 1 4
Debug.Print destination(0); destination(1); destination(2) ' outputs: 2 1 4
Copia di matrici di oggetti
Con le matrici di oggetti vengono copiati i riferimenti a quegli oggetti, non gli oggetti stessi. Se viene apportata una modifica a un oggetto in una matrice, sembrerà che sia stata modificata nell'altra matrice: entrambi fanno riferimento allo stesso oggetto. Tuttavia, l'impostazione di un elemento su un oggetto diverso in un array non lo imposterà sull'altro array.
Dim source(0 To 2) As Range
Dim destination() As Range
Set source(0) = Range("A1"): source(0).Value = 3
Set source(1) = Range("A2"): source(1).Value = 1
Set source(2) = Range("A3"): source(2).Value = 4
destination = source
Set destination(0) = Range("A4") 'reference changed in destination but not source
destination(0).Value = 2 'affects an object only in destination
destination(1).Value = 5 'affects an object in both source and destination
Debug.Print source(0); source(1); source(2) ' outputs 3 5 4
Debug.Print destination(0); destination(1); destination(2) ' outputs 2 5 4
Varianti contenenti una matrice
È anche possibile copiare un array in e da una variabile variante. Quando si copia da una variante, deve contenere una matrice dello stesso tipo dell'array ricevente, altrimenti genererà un errore di runtime "Tipo non corrispondente".
Dim var As Variant
Dim source(0 To 2) As Range
Dim destination() As Range
var = source
destination = var
var = 5
destination = var ' throws runtime error
Restituzione di matrici da funzioni
Una funzione in un modulo normale (ma non in un modulo di classe) può restituire un array inserendo ()
dopo il tipo di dati.
Function arrayOfPiDigits() As Long()
Dim outputArray(0 To 2) As Long
outputArray(0) = 3
outputArray(1) = 1
outputArray(2) = 4
arrayOfPiDigits = outputArray
End Function
Il risultato della funzione può quindi essere inserito in una matrice dinamica dello stesso tipo o di una variante. È anche possibile accedere agli elementi direttamente utilizzando una seconda serie di parentesi, tuttavia questa funzione chiamerà la funzione ogni volta, quindi è meglio memorizzare i risultati in una nuova matrice se si prevede di utilizzarli più di una volta
Sub arrayExample()
Dim destination() As Long
Dim var As Variant
destination = arrayOfPiDigits()
var = arrayOfPiDigits
Debug.Print destination(0) ' outputs 3
Debug.Print var(1) ' outputs 1
Debug.Print arrayOfPiDigits()(2) ' outputs 4
End Sub
Si noti che ciò che viene restituito è in realtà una copia dell'array all'interno della funzione, non un riferimento. Quindi se la funzione restituisce il contenuto di una matrice statica, i suoi dati non possono essere modificati dalla procedura chiamante.
Emissione di una matrice tramite un argomento di output
Normalmente è buona pratica di codifica che gli argomenti di una procedura siano input e output tramite il valore di ritorno. Tuttavia, le limitazioni di VBA talvolta rendono necessaria una procedura per l'output di dati tramite un argomento ByRef
.
Emissione su una matrice fissa
Sub threePiDigits(ByRef destination() As Long)
destination(0) = 3
destination(1) = 1
destination(2) = 4
End Sub
Sub printPiDigits()
Dim digits(0 To 2) As Long
threePiDigits digits
Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub
Emissione di una matrice da un metodo di classe
Un argomento di output può anche essere utilizzato per generare un array da un metodo / procedimento in un modulo di classe
' Class Module 'MathConstants'
Sub threePiDigits(ByRef destination() As Long)
ReDim destination(0 To 2)
destination(0) = 3
destination(1) = 1
destination(2) = 4
End Sub
' Standard Code Module
Sub printPiDigits()
Dim digits() As Long
Dim mathConsts As New MathConstants
mathConsts.threePiDigits digits
Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub
Passare gli array alle procedure
Le matrici possono essere passate alle procedure mettendo ()
dopo il nome della variabile di matrice.
Function countElements(ByRef arr() As Double) As Long
countElements = UBound(arr) - LBound(arr) + 1
End Function
Le matrici devono essere passate per riferimento. Se non viene specificato alcun meccanismo di passaggio, ad esempio myFunction(arr())
, VBA assumerà ByRef
per impostazione predefinita, tuttavia è buona pratica di codifica renderlo esplicito. Provando a passare un array in base al valore, ad esempio myFunction(ByVal arr())
comporterà un errore di compilazione "Argomento array deve essere ByRef" (o un errore di compilazione "Errore di sintassi" se Auto Syntax Check
non è selezionato nelle opzioni VBE) .
Passare per riferimento significa che eventuali modifiche alla matrice verranno mantenute nella procedura di chiamata.
Sub testArrayPassing()
Dim source(0 To 1) As Long
source(0) = 3
source(1) = 1
Debug.Print doubleAndSum(source) ' outputs 8
Debug.Print source(0); source(1) ' outputs 6 2
End Sub
Function doubleAndSum(ByRef arr() As Long)
arr(0) = arr(0) * 2
arr(1) = arr(1) * 2
doubleAndSum = arr(0) + arr(1)
End Function
Se vuoi evitare di cambiare la matrice originale, fai attenzione a scrivere la funzione in modo che non cambi alcun elemento.
Function doubleAndSum(ByRef arr() As Long)
doubleAndSum = arr(0) * 2 + arr(1) * 2
End Function
In alternativa, crea una copia funzionante della matrice e lavora con la copia.
Function doubleAndSum(ByRef arr() As Long)
Dim copyOfArr() As Long
copyOfArr = arr
copyOfArr(0) = copyOfArr(0) * 2
copyOfArr(1) = copyOfArr(1) * 2
doubleAndSum = copyOfArr(0) + copyOfArr(1)
End Function