XLOOKUP相当
XLOOKUPの強みは「検索列と戻り列を自由に指定」「見つからないときの値を簡単に設定」「縦横どちらも対応」。VBAでも同じ発想で、最短の呼び出しから辞書・Find・自作関数まで用途別に使い分けられます。
前提と選び方
- 環境の前提:
- XLOOKUPをそのまま呼ぶ: Excel 365 / 2021 以降。
- それ以前のExcel: 辞書・Find・Evaluate(INDEX/MATCH)で代替。
- 使い分けの目安:
- 最短で書きたい: WorksheetFunction.XLookup。
- 大量データで爆速+柔軟: Dictionary(O(1)検索)。
- 部分一致や複雑な条件: Range.Find。
- 数式で一括生成→値化: EvaluateでINDEX/MATCH。
最短テンプレ:WorksheetFunction.XLookup
Sub XLookup_Basic()
Dim key As Variant, lookArray As Range, returnArray As Range, result As Variant
key = Range("A2").Value
Set lookArray = Range("D2:D1000") '検索対象の列(1列でOK)
Set returnArray = Range("F2:F1000") '戻り値列(同じ行数)
result = Application.WorksheetFunction.XLookup(key, lookArray, returnArray, "") '未一致は空文字
Range("B2").Value = result
End Sub
VB- ポイント:
- 検索列と戻り列を別々に指定できる。
- 未一致時の値(第4引数)を与えれば、エラー処理不要。
- 複数列返しも可能(戻り範囲を複数列にすると配列返却)。セルへ出すときは範囲に一括代入。
Sub XLookup_MultiReturn()
Dim res As Variant
res = Application.WorksheetFunction.XLookup( _
Range("A2").Value, Range("D2:D1000"), Range("F2:G1000"), Array("", ""), False)
Range("B2:C2").Value = res '2列分を一気に貼り付け
End Sub
VB大量データ定番:DictionaryでXLOOKUP相当
Sub XLookup_Dictionary()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
'キー列→戻り列(複数可)を辞書化
Dim map As Object: Set map = CreateObject("Scripting.Dictionary")
Dim m As Range: Set m = Worksheets("Master").Range("A2:C500000") 'A:キー B,C:戻り
Dim data As Variant: data = m.Value
Dim i As Long, k As String
For i = 1 To UBound(data, 1)
k = CStr(data(i, 1))
'戻り複数を配列で保持
map(k) = Array(data(i, 2), data(i, 3))
Next
'明細側で照合(A:キー → B,Cを埋める)
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Dim out As Range: Set out = Range("A2:C" & last)
Dim v As Variant: v = out.Value
For i = 1 To UBound(v, 1)
k = CStr(v(i, 1))
If map.Exists(k) Then
v(i, 2) = map(k)(0)
v(i, 3) = map(k)(1)
Else
v(i, 2) = "": v(i, 3) = ""
End If
Next
out.Value = v
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
VB- メリット:
- 高速: 10万〜数百万行でも安定。
- 柔軟: キー・戻り列の位置に制約なし。複数列返却も簡単。
- コツ:
- キー型の統一: CStrで文字列化して登録・照合。
- 配列一括: 読み込み・書き戻しは範囲の配列で。
条件が自由:Range.FindでXLOOKUP相当
Sub XLookup_Find()
Dim key As String: key = Range("A2").Value
Dim col As Range: Set col = Range("D2:D100000") '検索対象
Dim f As Range
Set f = col.Find(What:=key, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False)
If Not f Is Nothing Then
Range("B2").Value = f.Offset(0, 2).Value 'D→Fへ(+2列)
Else
Range("B2").Value = ""
End If
End Sub
VB- メリット:
- 部分一致(xlPart)や大文字小文字、検索方向など柔軟。
- 注意:
- 一件ずつの検索は大量処理に不向き。大量は辞書で。
数式一括生成:EvaluateでINDEX/MATCH(互換性重視)
Sub XLookup_Like_IndexMatch()
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
With Range("B2:B" & last)
.Formula = "=IFERROR(INDEX($F$2:$F$100000, MATCH(A2, $D$2:$D$100000, 0)), """")"
.Value = .Value '値化して再計算負荷ゼロに
End With
End Sub
VB- メリット:
- 古いExcelでも動く。 XLOOKUPが使えない環境の安定策。
- コツ:
- 計算モードを手動にして最後に1回再計算すると体感が軽い。
自作関数:XLOOKUP風UDF(学習用・互換用)
Function XLOOKUP_VBA(ByVal key As Variant, look As Range, ret As Range, Optional notFound As Variant = "")
Dim i As Long, n As Long
n = look.Rows.Count
If ret.Rows.Count <> n Then
XLOOKUP_VBA = CVErr(xlErrRef)
Exit Function
End If
For i = 1 To n
If key = look.Cells(i, 1).Value Then
XLOOKUP_VBA = ret.Cells(i, 1).Value
Exit Function
End If
Next
XLOOKUP_VBA = notFound
End Function
VB- 使い方例:
- シートで
=XLOOKUP_VBA(A2, D2:D1000, F2:F1000, "")
- シートで
- 注意:
- 基本は「完全一致・単一列返し」。部分一致や複数列返しは拡張が必要。
- 速度は辞書>UDF。業務では辞書の方が安定。
まとめの使い分け
- Excel 365/2021: WorksheetFunction.XLookupを最短で。未一致の第4引数を活用。
- 旧環境・大量データ: 辞書+配列一括が鉄板。
- 柔軟検索: Findでピンポイント。複数候補はFindNextで列挙。
- 式で一括+値化: INDEX/MATCHをEvaluateで埋めて最後に値化。
落とし穴と対策
- ラベル:キー型の不一致
- 数値と文字列の「00123/123」問題。キーは CStr で統一。
- ラベル:検索範囲と戻り範囲の長さ不一致
- XLOOKUPも辞書も「同じ行数」が前提。UDFではRefエラー返すなど検知。
- ラベル:大量データのセル個別アクセス
- 遅い。必ず配列で処理して一括書き戻し。
- ラベル:再計算やイベントの暴発
- 処理前に ScreenUpdating/EnableEvents/Calculation を一時停止→最後に復帰。
