条件
- 配列 A から配列 B へ値を詰めたい。
- どちらの配列も、要素数とインデックスの開始番号が不明
- エラーが発生しないようにしたい。
- Step は 1 ずつ増える。
ポイント
- ループしない方の配列のインデックス開始番号を予め取得し、インクリメントを自分で行う。
- ループしている配列の現在のループ回数を、ループしない配列の要素数と比較することでインデックス外へのアクセスを防止する。
VBA コード
Option Explicit
Public Sub Test()
Dim values As Variant: values = Array(1, 1, 1) ' インデックスは 0 〜 2
Dim sames As Variant: sames = Array(2, 2, 2) ' インデックスは 1 〜 3
ReDim Preserve sames(1 To UBound(sames) + 1)
Dim longs As Variant: longs = Array(4, 4, 4, 4, 4) ' インデックスは 2 〜 6
ReDim Preserve longs(1 To UBound(longs) + 2)
Dim shorts As Variant: shorts = Array(3, 3) ' インデックスは 3 〜 4
ReDim Preserve shorts(3 To UBound(shorts) + 3)
Dim i As Long
' インデックスのズレを意識しなくてよいように、
' ループしない配列の開始位置を予め取得し、自前でインクリメントをする。
Dim samesIndex As Long: samesIndex = LBound(sames)
For i = LBound(values) To UBound(values)
sames(samesIndex) = values(i)
samesIndex = samesIndex + 1
Next i
Debug.Print ArrayToString(sames)
' ループしない配列のほうが長い場合は問題は発生しない。
Dim longsIndex As Long: longsIndex = LBound(longs)
For i = LBound(values) To UBound(values)
longs(longsIndex) = values(i)
longsIndex = longsIndex + 1
Next i
Debug.Print ArrayToString(longs)
' ループしない配列の方が短い場合は、
' インデックス外へのアクセスが発生し、エラーとなる。
' よって、ループ回数が配列要素数を超えていないかを判定することで予防する。
Dim shortsIndex As Long: shortsIndex = LBound(shorts)
Dim shortsCount As Long: shortsCount = UBound(shorts) - LBound(shorts) + 1
Dim valuesNow As Long
For i = LBound(values) To UBound(values)
' ループしている配列の現在のループ回数が
' ループしない配列の要素数を上回った時にループを抜け
' エラーを回避する
valuesNow = i - LBound(values) + 1
If valuesNow > shortsCount Then: Exit For
shorts(shortsIndex) = values(i)
shortsIndex = shortsIndex + 1
Next i
Debug.Print ArrayToString(shorts)
End Sub
Public Function ArrayToString(ByVal values As Variant)
Dim s As String
Dim v As Variant
For Each v In values
s = s & v & ", "
Next v
ArrayToString = s
End Function
確認
1, 1, 1, 1, 1, 1, 4, 4, 1, 1,
おわりに
Range.Value クラスを書いている時、配列の操作が大変です><。よく混乱いたしますので、今回まとめました♪
次のページが参考になりました!ありがとう存じます!
以上です。
