VBA
Kopiera, returnera och vidarebefordra matriser
Sök…
Kopiering av matriser
Du kan kopiera en VBA-matris till en matris av samma typ med =
operatören. Matriserna måste vara av samma typ annars kommer koden att kasta ett "Kan inte tilldela till array" kompilationsfel.
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
Källarrayen kan vara fixerad eller dynamisk, men destinationsgruppen måste vara dynamisk. Att försöka kopiera till en fast matris kommer att kasta ett kompilationsfel "Kan inte tilldela till array". All föregående data i den mottagande arrayen går förlorad och dess gränser och dimenioner ändras till samma som källarrayen.
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)
När kopian är gjord är de två matriserna separata i minnet, dvs de två variablerna är inte referenser till samma underliggande data, så ändringar gjorda i en matris visas inte i den andra.
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
Kopiera matriser av objekt
Med matriser av objekt kopieras referenser till dessa objekt, inte själva objekten. Om en förändring görs till ett objekt i en array verkar det också ändras i den andra arrayen - de båda hänvisar till samma objekt. Att ställa ett element till ett annat objekt i en array ställer dock inte in det objektet till det andra arrayet.
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
Varianter som innehåller en matris
Du kan också kopiera en matris till och från en variantvariabel. När du kopierar från en variant måste den innehålla en matris av samma typ som den mottagande matrisen, annars kommer det att kasta ett "typ misslyckande" runtime-fel.
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
Återvända matriser från funktioner
En funktion i en normal modul (men inte en klassmodul) kan returnera en matris genom att sätta ()
efter datatypen.
Function arrayOfPiDigits() As Long()
Dim outputArray(0 To 2) As Long
outputArray(0) = 3
outputArray(1) = 1
outputArray(2) = 4
arrayOfPiDigits = outputArray
End Function
Resultatet av funktionen kan sedan läggas in i en dynamisk grupp av samma typ eller en variant. Elementen kan också nås direkt genom att använda en andra uppsättning parenteser, men detta kommer att kalla funktionen varje gång, så det är bäst att lagra resultaten i en ny matris om du planerar att använda dem mer än en gång
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
Observera att det som returneras faktiskt är en kopia av matrisen i funktionen, inte en referens. Så om funktionen returnerar innehållet i en statisk matris kan dess data inte ändras med samtalsproceduren.
Skickar ut en matris via ett utgångsargument
Det är normalt bra kodningspraxis för en procedurs argument att vara ingångar och att mata ut via returvärdet. VBA-begränsningarna gör emellertid ibland nödvändigt för en procedur för att mata ut data via ett ByRef
argument.
Utmatning till en fast grupp
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
Ange en matris från en klassmetod
Ett utgångsargument kan också användas för att mata ut en matris från en metod / framsteg i en klassmodul
' 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
Vidarebefordra matriser till förfaranden
Matriser kan skickas till förlopp genom att sätta ()
efter namnet på matrisvariabeln.
Function countElements(ByRef arr() As Double) As Long
countElements = UBound(arr) - LBound(arr) + 1
End Function
Matriser måste skickas som referens. Om ingen passeringsmekanism specificeras, t.ex. myFunction(arr())
, kommer VBA att anta ByRef
standard, men det är bra kodningssätt att göra det uttryckligt. Att försöka skicka ett array efter värde, t.ex. myFunction(ByVal arr())
kommer att resultera i ett "Array-argument måste vara ByRef" -kompileringsfel (eller ett "Syntax-fel" -kompilationsfel om Auto Syntax Check
är inte markerat i VBE-alternativen) .
Om du skickar en referens innebär att alla ändringar i matrisen kommer att bevaras i samtalsprocessen.
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
Om du vill undvika att ändra den ursprungliga arrayen ska du vara noga med att skriva funktionen så att den inte ändrar några element.
Function doubleAndSum(ByRef arr() As Long)
doubleAndSum = arr(0) * 2 + arr(1) * 2
End Function
Skapa alternativt en fungerande kopia av matrisen och arbeta med kopian.
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