Excel VBA | ByRef(参照渡し)を積極活用した実例

Excel VBA VBA
スポンサーリンク

ここでは 「ByRef を活かしつつ、高速化(配列 × Dictionary)」を組み合わせた実務レベルの VBA サンプル を提示します。
Excel の 大量データ処理・検索・置換・集計などに使える構成 にしてあります。


高速化(配列 × Dictionary)× ByRef 実務サンプル

目的

  • 大量データを Range → 配列 → Dictionary → 配列 → Range の流れで高速処理
  • ByRef で「データ編集結果」を呼び出し元に渡す
  • 再利用しやすいテンプレ構造

サンプル内容

以下 3 点の高速処理をまとめた業務実例:

  1. 配列でシート全体を読み込み高速処理
  2. Dictionary による高速検索・重複排除・集計
  3. ByRef で結果配列や集計情報を返す

実務テンプレ構成

  • Main:全体の流れ
  • LoadData (配列読み込み)
  • ProcessData (Dictionary 処理)
  • WriteData (書き戻し)

コード(そのまま Excel VBA へ貼って動作OK)

Option Explicit

Sub Main_高速処理_ByRef()
    On Error GoTo ERR_HANDLER

    Dim arrData As Variant
    Dim dictResult As Object
    Dim arrOutput As Variant

    Dim lastRow As Long
    lastRow = Cells(Rows.Count, "A").End(xlUp).Row

    '---------------------------
    ' ① データ読込(配列)
    '---------------------------
    Call LoadData(arrData, lastRow)

    '---------------------------
    ' ② 高速処理(Dictionary)
    '---------------------------
    Call ProcessData(arrData, dictResult, arrOutput)

    '---------------------------
    ' ③ 出力(配列 → Range)
    '---------------------------
    Call WriteData(arrOutput, "D2")

    MsgBox "処理完了", vbInformation
    Exit Sub

ERR_HANDLER:
    MsgBox "エラー発生:" & Err.Description, vbCritical
End Sub

'===============================================
' ★① 読み込み:ByRef で配列を構築して返す
'===============================================
Private Sub LoadData(ByRef arr As Variant, ByVal lastRow As Long)
    ' A列〜C列を一括で配列化
    arr = Range("A2:C" & lastRow).Value
End Sub

'===============================================
' ★② 高速処理:Dictionary を ByRef で返す
'===============================================
Private Sub ProcessData( _
        ByRef arrIn As Variant, _
        ByRef dictOut As Object, _
        ByRef arrOut As Variant)

    Dim i As Long
    Dim key As String
    Dim tmp As Variant

    Set dictOut = CreateObject("Scripting.Dictionary")

    '------------------------------------------
    ' 例:A列「商品名」で集計(合計数量を Dictionary でまとめる)
    '------------------------------------------
    For i = 1 To UBound(arrIn, 1)
        key = CStr(arrIn(i, 1))     '商品名
        tmp = arrIn(i, 3)           '数量(例)

        If dictOut.Exists(key) Then
            dictOut(key) = dictOut(key) + tmp
        Else
            dictOut.Add key, tmp
        End If
    Next i

    '------------------------------------------
    ' Dictionary → 2次元配列へ変換(書き出し用)
    '------------------------------------------
    Dim r As Long: r = 1
    ReDim arrOut(1 To dictOut.Count, 1 To 2)

    Dim k As Variant
    For Each k In dictOut.Keys
        arrOut(r, 1) = k
        arrOut(r, 2) = dictOut(k)
        r = r + 1
    Next k
End Sub

'===============================================
' ★③ 書き戻し:ByRef 配列を指定セルへ配置
'===============================================
Private Sub WriteData(ByRef arr As Variant, ByVal startCell As String)
    Range(startCell).Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
End Sub
VB

使い方

入力データ(例)

A〜C列に以下のようなデータを置いてください:

A:商品名B:担当者C:数量
りんご佐藤10
みかん鈴木5
りんご高橋7
バナナ田中12

出力内容(D列以降)

D2: 商品名
E2: 合計数量

例:

商品名合計
りんご17
みかん5
バナナ12

なぜ高速なの?

  • Range へ何度もアクセスすると 遅い
  • まとめて配列にすると 数万行でも一瞬
  • Dictionary により
    • 重複排除
    • 高速検索
    • 高速集計
      が可能

ByRef を使っている箇所

プロシージャByRef で返すもの役割
LoadDataarr(配列)生データを配列化
ProcessDatadictOut(Dictionary)arrOut(出力用配列)高速検索・集計
WriteDataarr(出力配列)書き戻し

ByRef にしていることで
「複数の巨大データ構造(配列・Dictionary)を効率的に渡し続ける」
ことができます。


このテンプレートは実務でどう使う?

  • 売上データの集計
  • ログファイルの読み込みと重複排除
  • マスタ突合(検索)
  • CSV 読み込み後の高速加工
  • 伝票番号のユニーク化
  • 文字列 → コード変換テーブルによるマッピング

などに即利用できます。

タイトルとURLをコピーしました