差分高速テンプレ
「差分を取りたいけど、行数が多くて遅い…」そんなときに役立つのが高速差分テンプレです。初心者でも安心して使えるように、配列+辞書を使った効率的なコード例をかみ砕いて説明します。
高速化の基本テクニック
- 画面更新停止:
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で解決。
