サーチ…


配列のコピー

=演算子を使用して、VBA配列を同じ型の配列にコピーできます。配列は同じ型でなければなりません。さもなければ、コードは "配列に代入できません"というコンパイルエラーをスローします。

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

ソース配列は固定または動的にできますが、宛先配列は動的でなければなりません。固定配列にコピーしようとすると、 "Can not assign to array"コンパイルエラーがスローされます。受信配列内の既存データはすべて失われ、その範囲と次元は送信元配列と同じに変更されます。

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)

コピーが作成されると、2つの配列はメモリ内で別々のものになります。つまり、2つの変数は同じ基礎データへの参照ではないため、一方の配列の変更は他方の配列には表示されません。

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

オブジェクトの配列のコピー

オブジェクトの配列では、それらのオブジェクトへの参照がコピーされ、オブジェクト自体はコピーされません。 1つの配列内のオブジェクトに変更が加えられた場合、その変更は他の配列でも変更されているように見えます - 両方とも同じオブジェクトを参照しています。ただし、要素を1つの配列内の別のオブジェクトに設定しても、それを他の配列に設定することはできません。

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

配列を含むバリアント

バリアント変数との間で配列をコピーすることもできます。バリアントからコピーするときは、受信配列と同じ型の配列を含む必要があります。それ以外の場合は、「型の不一致」ランタイムエラーが発生します。

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

関数から配列を返す

通常のモジュール(クラスモジュールではない)の関数は、データ型の後に()を置くことによって配列を返すことができます。

Function arrayOfPiDigits() As Long()
    Dim outputArray(0 To 2) As Long
    
    outputArray(0) = 3
    outputArray(1) = 1
    outputArray(2) = 4

    arrayOfPiDigits = outputArray
End Function

関数の結果は、同じ型またはバリアントの動的配列に格納することができます。要素には、第2のブラケットセットを使用して直接アクセスすることもできますが、これは毎回関数を呼び出すため、複数回使用する予定がある場合は結果を新しい配列に格納することをお勧めします

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

返されるのは、実際には関数内の配列のコピーであり、参照ではありません。関数が静的配列の内容を返す場合、そのデータは呼び出し側のプロシージャによって変更できません。

出力引数による配列の出力

プロシージャの引数が入力であり、戻り値を介して出力されるのは、通常は良いコーディング方法です。しかし、VBAの制限により、プロシージャがByRef引数を介してデータを出力する必要がByRefます。

固定配列への出力

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

クラスメソッドからの配列の出力

出力引数は、クラスモジュールのメソッド/プロシージャから配列を出力するためにも使用できます

' 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

プロジェクトへの配列の受け渡し

配列変数の名前の後ろに()置くことによって、配列を手続きに渡すことができます。

Function countElements(ByRef arr() As Double) As Long
    countElements = UBound(arr) - LBound(arr) + 1
End Function

配列参照渡しする必要あります。渡すメカニズムが指定されていない場合、たとえばmyFunction(arr())場合、VBAはデフォルトでByRefを引き受けますが、明示的にするのは良いコーディング方法です。たとえば、 myFunction(ByVal arr())配列を値渡しで渡すと、「配列引数はByRefでなければなりません」コンパイルエラー(VBEオプションでAuto Syntax Checkがチェックされていないと「構文エラー」コンパイルエラー) 。

参照渡しとは、配列への変更が呼び出し手順で保持されることを意味します。

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

元の配列を変更しないようにするには、要素を変更しないように関数を記述するように注意してください。

Function doubleAndSum(ByRef arr() As Long)
    doubleAndSum = arr(0) * 2 + arr(1) * 2
End Function

あるいは、配列の作業コピーを作成し、そのコピーで作業してください。

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


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow