凡人も語りたい

VBAに関すことや日々考えている事柄について投稿しようと思っています。

ExcelVBAの一工夫:配列の繰り返し処理について

どうも、こんぺです。
今回、VBAの配列について小技とも言えないような「ちょっとした一工夫」をご紹介します

配列の繰り返し処理について

VBAにおける配列の使い方や書き方は様々なサイトで取り扱われていると思われますので、割愛させていただきます。
配列と繰り返し処理の組み合わせ技は強力ですが、慣れないうちは、

  • Do Loopの終わりがわかりにくい
  • For Next は繰り返し処理後イテレーター変数は「繰り返した回数+1」になっている
  • カウンタ変数をカウントアップ(ダウン)するタイミングがいまいちわからない

とロジックエラーが起きやすい部分でもあると思います。
しかし、ちょっとしたひと工夫で「一気にわかりやすいコードに変わった」経験をしたのでご紹介します。

テストコード

  1. 1~20までの整数rndをランダムで決め、
  2. 1~rnd まで順に2乗し、配列に格納、
  3. 最後に配列の内容をイミディエイトウィンドウに表示

という処理をしています。

Sub test()
'cnt(=ループ処理の回数)を1~20までの整数からランダムで選出
    Dim rnd As Long
    rnd = Int(WorksheetFunction.RandBetween(1, 20))
'カウンタ変数とDoLoopを用いた動的配列の処理
    Dim arr() As String
    Dim cnt As Long
    Dim i As Long
    Do
        cnt = cnt + 1
        ReDim Preserve arr(1 To cnt) As String
        arr(cnt) = Str(cnt ^ 2)
    Loop Until cnt = rnd
'配列内数値の確認
    Debug.Print "要素数:" & cnt, Join(arr, ",")
End Sub

解説

今回の工夫した箇所は以下の部分

    Do
        cnt = cnt + 1
        ReDim Preserve arr(1 To cnt) As String
        繰り返し行いたい処理
    Loop Until cnt = 繰り返したい回数

非常に短いですが、工夫としては

  • 処理の「前」にカウンタ変数をカウントアップする
  • 配列に動的配列を用いる
  • 「ReDim Preserve」で処理結果を格納する要素を直前に「追加」する
  • 素数は「必ず『1』から要素が始まる」ようにする
  • 条件分岐に「Until」を使う

といったことが挙げられます。

これにより

  1. 「配列の要素数が足りない」というエラーを除去できる
  2. ループを抜けたタイミングは「カウンタ変数=繰り返し処理回数」でわかりやすく、繰り返し処理後のロジックエラーを起こしにくい
  3. 素数が「1」から始めることでめインデックス「0」を考慮しなくてよいため、後々Rangeに転記しやすい

など、「後々エラーの原因になりやすいポイント」を未然に解消してくれます。

おわりに

簡単ではございますが、「コーディングにおける一工夫」をご紹介させていただきました。
この書き方のアイディアを知るまで、私は「処理後にカウントアップ」していました。そのため、繰り返し処理後にロジックエラーを起こして予期しない動作になることが度々あり、「エラー回避するためのコード」を頭をひねって追加していました。しかし、この一工夫でその労力は「ほぼ0」になりました…
業務効率だけではなく、リーダブルコーディングで「コーディング効率」も上げていかねば…と思った次第です。


最後にお詫びです
以前、VBA勉強会に登壇させていただいたときに行ったリファクタリングをしたコードをすっかりアップし忘れていました。
しかし、動作確認をしたところバグが見つかってしまったので修正したのちアップします(;´・ω・)