アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

ReDimで配列サイズを再定義するための6つの掟

キャッチーなタイトルにしようとして失敗した感


PHPなんかに慣れちゃうと正直めちゃくちゃめんどくさく感じてくるVBAの配列。
中でも一番つらいのがReDim周辺。

特にシビアな処理でもない限り
「大き目のサイズを最初に指定しておけばいいか…」とかやっちゃうことも多いのでは(自分だけ?)

そんな自分のためにもReDimについてまとめなおしてみました。

ReDimの掟その1:最初にサイズ指定してしまうと使えない

最初はサイズ指定は空にしておきます。

Dim lList() As Long

Variantで定義するのもアリ。

Dim vList As Variant

ReDimの掟その2:でもサイズは指定しないと使えない

ここでReDimの出番。
ReDimせずに使おうとするとエラーになります。

Dim lList() As Long
'lList(0) = 1 // これはエラーになる
ReDim lList(0 To 1)
lList(0) = 1 'これはエラーにならない

ReDimの掟その3:ReDimなら何度でも再定義できる

Dim lList() As Long
ReDim lList(1)
ReDim lList(2)
ReDim lList(3)

ReDimの掟その4:「ReDim Preserve」にしないと中身は消える

Dim lList() As Long
ReDim lList(2)
lList(0) = 1
ReDim lList(3) '「lList(0)」にセットした値が消える
lList(0) = 1
ReDim Preserve lList(4) '「lList(0)」にセットした値が消えない

正直、ReDim Preserveだけ覚えときゃいいのでは? とも思いますが、
ReDim単独も、中身をクリアしたいときなんかにたまには便利です。たまには。

ReDimの掟その5:「ReDim Preserve」では「最後の次元の最大値」しか変えられない

一番めんどくさいのがコレ。
最小値を引き上げたいということはそうそうないのでともかくとして、
二次元配列の一次元目を変更することができないのが残念。
色々と工夫してやる必要が出てくる場合もあります。
<追記>コメント欄で工夫の例をいただいておりますのでご参照ください!</追記>

Dim lList() As Long
ReDim Preserve lList(0 To 3) '最初の定義:もちろんOK
ReDim Preserve lList(0 To 2) '最大値を引き下げる:OK
ReDim Preserve lList(1 To 2) '最小値を引き上げる:NG(エラーになる!)
Dim lList() As Long
ReDim Preserve lList(1, 1) '最初の定義:もちろんOK
ReDim Preserve lList(1, 2) '最後の次元の最大値を引き上げる:OK
ReDim Preserve lList(2, 2) '最初の次元の最大値を引き上げる:NG(エラーになる!)
ReDim Preserve lList(2, 2, 2) '次元を増やす:NG(エラーになる!)

ReDimの掟その6:LBoundとUBoundが必須

がっつり配列を扱うときに多用することになるのがLBoundとUBound(特にUBound)。
LBoundは「配列が何番から始まっているか」
UBoundは「配列が何番まであるか」
が分かります。

まず、一次元配列の場合はこちら。
配列のサイズを変えたりしつつ試してみてください。

Dim lList(1 To 2) As Long
Debug.Print LBound(lList) '「1」
Debug.Print UBound(lList) '「2」

二次元配列の場合がこちら。
各関数の第2引数に「何次元目か」を渡すことで、その次元についての情報が得られます。
(省略した場合は一次元目)

Dim lList(3 To 4, 5 To 7) As Long
Debug.Print LBound(lList) '「3」
Debug.Print UBound(lList) '「4」
Debug.Print LBound(lList, 1) '「3」
Debug.Print UBound(lList, 1) '「4」
Debug.Print LBound(lList, 2) '「5」
Debug.Print UBound(lList, 2) '「7」

この2つの関数を駆使することで、
「配列サイズを1つ増やす(減らす)」などの処理ができるようになります。

簡単なサンプルプログラムを置いておきます。
フィボナッチ数列(※)を作るプログラムで、
配列サイズを増やす、前の要素にアクセスする、など色々やっていますので
参考になればと思います。

※最初の二項が1で、第三項以降の項がすべて直前の二項の和になっている数列。
 つまり、1, 1, 2, 3, 5, 8, 13, ... という数列

Public Sub Fibonacci()
    Dim lNum() As Long '数列が入る配列
    Dim i As Long      'カウンタ用変数

    '最初の二項をセット
    ReDim lNum(1) 'lNum(0 To 1)と同義
    lNum(0) = 1
    lNum(1) = 1

    '数列の作成
    '100を超えたらやめる
    Do While True
        'lNumの最大値を今の最大値+1にする
        ReDim Preserve lNum(UBound(lNum) + 1)

        'lNumの最終項=ひとつ前の項+ふたつ前の項
        lNum(UBound(lNum)) = lNum(UBound(lNum) - 1) + lNum(UBound(lNum) - 2)

        'lNumの最終項が100をこえている場合は終了する
        If lNum(UBound(lNum)) > 100 Then
            Exit Do
        End If
    Loop

    '数列の表示
    For i = LBound(lNum) To UBound(lNum) 'iはlNumの初項から最終項まで
        Debug.Print lNum(i)
    Next
End Sub