web-dev-qa-db-ja.com

VBA(Excel)ループなしで配列全体を初期化する

私はVBAにかなり慣れていないので、これは簡単な質問かもしれませんが、ここに行きます。

VBAで配列全体を初期化したいmyArray、たとえば整数の場合。私は次のような簡単な初期化によってこれを行うことができることを知っています:

Dim myArray
myArray = Array(1, 2, 4, 8)

しかし、配列が大きい場合、これは面倒であり、すべての要素を同じ値に初期化したいと思います。理想的には次のようなものです:

myArray(:) = 0

私はそれを試しましたが、コンパイラは不満を言いました。それからmyArray() = 0を試してみましたが、それについても文句を言いました。

誰もこれを行う方法を説明できますか、ループなし?可能であれば、1つのステートメントでそれを行いたいです。

明確化

配列のすべての要素を初期値に初期化します。たとえば、300個の整数のDim myArray(300) As Integer配列がある場合、300個の要素すべてが同じ初期値(たとえば、13)を保持します。

詳細説明

私は この回答 を見つけました。これは、次のような変数でこれを行うことができると述べています。

Dim x As Double: x = 0

おそらく、構文をわずかに更新して配列に適用できるようにする方法はありますか?

35
user1205577

少なくとも1ベースの1Dまたは2Dバリアント配列が必要な場合、これは簡単です。

Sub StuffVArr()
    Dim v() As Variant
    Dim q() As Variant
    v = Evaluate("=IF(ISERROR(A1:K1), 13, 13)")
    q = Evaluate("=IF(ISERROR(A1:G48), 13, 13)")
End Sub

バイト配列も悪くありません:

Private Declare Sub FillMemory Lib "kernel32" Alias "RtlFillMemory" _
        (dest As Any, ByVal size As Long, ByVal fill As Byte)

Sub StuffBArr()
    Dim i(0 To 39) As Byte
    Dim j(1 To 2, 5 To 29, 2 To 6) As Byte
    FillMemory i(0), 40, 13
    FillMemory j(1, 5, 2), 2 * 25 * 5, 13
End Sub

同じメソッドを使用して他の数値データ型の配列を埋めることができますが、単一の繰り返しバイトで表現できる値のみに制限されます。

Sub StuffNArrs()
    Dim i(0 To 4) As Long
    Dim j(0 To 4) As Integer
    Dim u(0 To 4) As Currency
    Dim f(0 To 4) As Single
    Dim g(0 To 4) As Double

    FillMemory i(0), 5 * LenB(i(0)), &HFF 'gives -1
    FillMemory i(0), 5 * LenB(i(0)), &H80 'gives -2139062144
    FillMemory i(0), 5 * LenB(i(0)), &H7F 'gives 2139062143

    FillMemory j(0), 5 * LenB(j(0)), &HFF 'gives -1

    FillMemory u(0), 5 * LenB(u(0)), &HFF 'gives -0.0001

    FillMemory f(0), 5 * LenB(f(0)), &HFF 'gives -1.#QNAN
    FillMemory f(0), 5 * LenB(f(0)), &H80 'gives -1.18e-38
    FillMemory f(0), 5 * LenB(f(0)), &H7F 'gives 3.40e+38

    FillMemory g(0), 5 * LenB(g(0)), &HFF 'gives -1.#QNAN
End Sub

他の状況でループを回避したい場合は、さらに複雑になります。配列が50K以上のエントリでない限り、実際に価値はありません。ループで各値を設定するだけで、高速になります、十分に、以前の回答 で説明しました。

26
Chel

次元を指定して配列を初期化できます。例えば

Dim myArray(10) As Integer
Dim myArray(1 to 10) As Integer

配列を使用していて、これが初めての場合は、Chip Pearsonの WEBSITE にアクセスすることをお勧めします。

これは何に初期化されますか?たとえば、配列全体を13に初期化する場合はどうなりますか?

13要素の配列を初期化する場合、2つの方法で行うことができます

Dim myArray(12) As Integer
Dim myArray(1 to 13) As Integer

最初は、配列の下限が0で始まるため、配列に13個の要素を格納できます。例えば

myArray(0) = 1
myArray(1) = 2
'
'
'
myArray(12) = 13

2番目の例では、1として下限を指定しているため、配列は1で始まり、13個の値を再び格納できます。

myArray(1) = 1
myArray(2) = 2
'
'
'
myArray(13) = 13

上記のメソッドのいずれかを使用して配列を初期化すると、配列の各要素の値は0と等しくなります。確認するには、このコードを試してください。

Sub Sample()
    Dim myArray(12) As Integer
    Dim i As Integer

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

または

Sub Sample()
    Dim myArray(1 to 13) As Integer
    Dim i As Integer

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

コメントからのフォローアップ

したがって、この例ではすべての値が13になります。したがって、配列Dim myArray(300)As Integerがある場合、300個の要素すべてに値13が保持されます。

私が言ったように、私の知る限り、あなたが望むものを達成する直接的な方法はありません。これは、ワークシート関数Reptを使用して13の繰り返し文字列を作成する1つの方法です。その文字列を取得したら、","を区切り文字として使用してSPLITを使用できます。ただし、これによりバリアント配列が作成されますが、計算で使用できることに注意してください。

また、次の例ではmyArrayが実際に最後の空の301値を保持することに注意してください-この値を追加で初期化するか、sNum操作の前のSplitから最後の「、」を削除することで、それを考慮する必要があります。

Sub Sample()
    Dim sNum As String
    Dim i As Integer
    Dim myArray

    '~~> Create a string with 13 three hundred times separated by comma
    '~~> 13,13,13,13...13,13 (300 times)
    sNum = WorksheetFunction.Rept("13,", 300)
    sNum = Left(sNum, Len(sNum) - 1)

    myArray = Split(sNum, ",")

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

計算でバリアント配列を使用する

Sub Sample()
    Dim sNum As String
    Dim i As Integer
    Dim myArray

    '~~> Create a string with 13 three hundred times separated by comma
    sNum = WorksheetFunction.Rept("13,", 300)
    sNum = Left(sNum, Len(sNum) - 1)

    myArray = Split(sNum, ",")

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print Val(myArray(i)) + Val(myArray(i))
    Next i
End Sub
10
Siddharth Rout

配列のすべての要素を初期値に初期化します。たとえば、配列300整数のDim myArray(300)As Integerがある場合、300個の要素すべてが同じ初期値(たとえば、13番)を保持します。

誰でもこれを行う方法を説明できますか?ループなし?可能であれば、1つのステートメントでそれを行いたいです。

私は何に勝ちますか?

Sub SuperTest()
   Dim myArray
   myArray = Application.Transpose([index(Row(1:300),)-index(Row(1:300),)+13])
End Sub
4
tbur

この関数は、tburとFilipeの応答を組み合わせたサイズと初期値の変数で機能します。

Function ArrayIniValue(iSize As Integer, iValue As Integer)
Dim sIndex As String
sIndex = "INDEX(Row(1:" & iSize & "),)"
ArrayIniValue = Evaluate("=Transpose(" & sIndex & "-" & sIndex & "+" & iValue & ")")
End Function

このように呼ばれます:

myArray = ArrayIniValue(350, 13)
1
EEM

VBAの場合、2行で初期化する必要があります。

Sub TestArray()

Dim myArray
myArray = Array(1, 2, 4, 8)

End Sub
0
Santosh

関数に@rdhs回答を配置する派手な方法:

Function arrayZero(size As Integer)
  arrayZero = Evaluate("=IF(ISERROR(Transpose(A1:A" & size & ")), 0, 0)")
End Function

そして、次のように使用します:

myArray = arrayZero(15)
0
Filipe

配列の要素全体に値を割り当てるために使用できる1つの方法は、データを未使用のワークシートに配置し、ワークシートから配列に値を読み戻すことです。たとえば、123の値を5x5配列の要素全体に割り当てたいです。このようなタスクを実装する1行のコードを次に示します。

ReDim MyArray(1 To 5, 1 To 5): Range("A1:E5") = 123: MyArray = Range("A1:E5")

少し遅いですが、うまく動作します。配列宣言を削除することもできます。

Range("A1:E5") = 123: MyArray = Range("A1:E5")

実際、いくつかの要素の値を簡単に変更できます。たとえば、要素MyArray(1,1)、MyArray(1,5)、MyArray(3,3)、MyArray(5,1)、およびMyArray(5,5)の値を789に変更するとします。 、コードは次のようになります

Range("A1:E5") = 123: Range("A1,E1,C3,A5,E5") = 789: MyArray = Range("A1:E5")