Excel VBA 逆引き集 | 差分高速テンプレ

Excel VBA
スポンサーリンク

差分高速テンプレ

「差分を取りたいけど、行数が多くて遅い…」そんなときに役立つのが高速差分テンプレです。初心者でも安心して使えるように、配列+辞書を使った効率的なコード例をかみ砕いて説明します。


高速化の基本テクニック

  • 画面更新停止: Application.ScreenUpdating = False
  • イベント停止: Application.EnableEvents = False
  • 計算停止: Application.Calculation = xlCalculationManual
    → 終了時に必ず元に戻す。
  • 配列に読み込む: Range.Valueを配列に入れて一括処理。セルを1つずつ読むより数十倍速い。
  • 辞書で突合: Scripting.Dictionaryを使ってキー存在判定を一瞬で行う。

差分高速テンプレ(基本版)

「SheetA」と「SheetB」を比較して、新規・削除・変更を別シートに出力します。

Option Explicit

Sub FastDiffTemplate()
    ' 高速化ON
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Dim wsA As Worksheet: Set wsA = Worksheets("SheetA")
    Dim wsB As Worksheet: Set wsB = Worksheets("SheetB")
    Dim vA As Variant: vA = wsA.Range("A1").CurrentRegion.Value
    Dim vB As Variant: vB = wsB.Range("A1").CurrentRegion.Value

    ' 辞書にBのキーを登録
    Dim dictB As Object: Set dictB = CreateObject("Scripting.Dictionary")
    Dim i As Long, k As String
    For i = 2 To UBound(vB, 1)
        k = UCase$(Trim$(CStr(vB(i, 1)))) 'コード列
        If Len(k) > 0 Then dictB(k) = i
    Next

    ' 出力シート
    Dim wsNew As Worksheet: Set wsNew = Worksheets("新規")
    Dim wsDel As Worksheet: Set wsDel = Worksheets("削除")
    Dim wsChg As Worksheet: Set wsChg = Worksheets("変更")
    wsNew.Cells.Clear: wsDel.Cells.Clear: wsChg.Cells.Clear
    wsNew.Range("A1:C1").Value = Array("コード", "名称(B)", "単価(B)")
    wsDel.Range("A1:C1").Value = Array("コード", "名称(A)", "単価(A)")
    wsChg.Range("A1:E1").Value = Array("コード", "項目", "A値", "B値", "差分")

    Dim rNew As Long: rNew = 2
    Dim rDel As Long: rDel = 2
    Dim rChg As Long: rChg = 2

    ' A基準で削除・変更
    Dim setA As Object: Set setA = CreateObject("Scripting.Dictionary")
    For i = 2 To UBound(vA, 1)
        k = UCase$(Trim$(CStr(vA(i, 1))))
        If Len(k) = 0 Then GoTo contA
        setA(k) = True

        If dictB.Exists(k) Then
            Dim rb As Long: rb = dictB(k)
            ' 名称比較
            If CStr(vA(i, 2)) <> CStr(vB(rb, 2)) Then
                wsChg.Cells(rChg, 1).Value = vA(i, 1)
                wsChg.Cells(rChg, 2).Value = "名称"
                wsChg.Cells(rChg, 3).Value = vA(i, 2)
                wsChg.Cells(rChg, 4).Value = vB(rb, 2)
                rChg = rChg + 1
            End If
            ' 単価比較
            Dim aPrice As Double: aPrice = CDbl(Val(vA(i, 3)))
            Dim bPrice As Double: bPrice = CDbl(Val(vB(rb, 3)))
            If aPrice <> bPrice Then
                wsChg.Cells(rChg, 1).Value = vA(i, 1)
                wsChg.Cells(rChg, 2).Value = "単価"
                wsChg.Cells(rChg, 3).Value = aPrice
                wsChg.Cells(rChg, 4).Value = bPrice
                wsChg.Cells(rChg, 5).Value = bPrice - aPrice
                rChg = rChg + 1
            End If
        Else
            wsDel.Cells(rDel, 1).Value = vA(i, 1)
            wsDel.Cells(rDel, 2).Value = vA(i, 2)
            wsDel.Cells(rDel, 3).Value = vA(i, 3)
            rDel = rDel + 1
        End If
contA:
    Next

    ' Bのみ(新規)
    Dim j As Long
    For j = 2 To UBound(vB, 1)
        k = UCase$(Trim$(CStr(vB(j, 1))))
        If Len(k) > 0 And Not setA.Exists(k) Then
            wsNew.Cells(rNew, 1).Value = vB(j, 1)
            wsNew.Cells(rNew, 2).Value = vB(j, 2)
            wsNew.Cells(rNew, 3).Value = vB(j, 3)
            rNew = rNew + 1
        End If
    Next

    ' 整形
    wsNew.Columns.AutoFit: wsDel.Columns.AutoFit: wsChg.Columns.AutoFit

    ' 高速化OFF
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True

    MsgBox "差分完了: 新規=" & rNew - 2 & " 削除=" & rDel - 2 & " 変更=" & rChg - 2
End Sub
VB

例題で練習

'例1:シートAとBを比較して差分を高速に出力
Sub Example_FastDiff()
    FastDiffTemplate
End Sub
VB

初心者向けポイント

  • 配列に読み込む: Range.Valueで一気に配列化 → セルを1つずつ読むより圧倒的に速い。
  • 辞書で突合: キー存在判定が一瞬。Existsで新規・削除を簡単に判定。
  • 差分シート: 新規・削除・変更を別シートに出すと分かりやすい。
  • 数値差分: 単価などは差分(新−旧)を出すと便利。

実務の落とし穴と対策

  • キー表記揺れで誤判定Trim+UCaseで正規化。
  • 列順変更で壊れる → 見出し名から列番号を取得する関数を追加すると安心。
  • 大量行で遅い → 配列+辞書+高速化ON/OFFで解決。
タイトルとURLをコピーしました