マスタが外部ファイル
「商品マスタや社員マスタが別ブックに保存されていて、明細ブックから参照したい」——そんな場面で役立つのが 外部ファイルを開いて辞書化→JOIN のテンプレです。初心者でも壊れないように、最短のVLOOKUP版、堅牢な辞書版、見出し名対応版を用意しました。
基本の考え方
- 外部ファイルを開く:
Workbooks.Openで読み取り専用で開く - マスタ範囲を配列に読み込む:
Range("A1").CurrentRegion.Value - 辞書に格納: キー→レコードを作る
- JOIN: 明細に付与して一括書き戻し
- 最後に閉じる:
wb.Close SaveChanges:=False
最短テンプレ:外部ファイルを開いてVLOOKUP
Sub JoinMaster_VLookup_External()
'明細: このブックのSheet("明細") A=コード, B=数量
'外部マスタ: "C:\Data\商品マスタ.xlsx" のSheet("マスタ") A=コード, B=名称, C=単価
Dim wsD As Worksheet: Set wsD = Worksheets("明細")
Dim lastD As Long: lastD = wsD.Cells(wsD.Rows.Count, "A").End(xlUp).Row
'外部ファイルを開く(読み取り専用)
Dim wbM As Workbook: Set wbM = Workbooks.Open("C:\Data\商品マスタ.xlsx", ReadOnly:=True)
Dim wsM As Worksheet: Set wsM = wbM.Worksheets("マスタ")
Dim rgM As Range: Set rgM = wsM.Range("A1").CurrentRegion
'名称・単価をVLOOKUPで付与
wsD.Range("C1:D1").Value = Array("名称", "単価")
With wsD.Range("C2:C" & lastD)
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,'" & wbM.Name & "'!" & rgM.Address(True, True, xlA1, True) & ",2,FALSE),""#N/A"")"
.Value = .Value
End With
With wsD.Range("D2:D" & lastD)
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,'" & wbM.Name & "'!" & rgM.Address(True, True, xlA1, True) & ",3,FALSE),0)"
.Value = .Value
End With
'外部ファイルを閉じる
wbM.Close SaveChanges:=False
End Sub
VB- ポイント
- 外部ファイルを開いて範囲を参照。
- 式は値化して軽く運用。
- 閉じるときは
SaveChanges:=Falseで安全。
爆速テンプレ:外部ファイルを辞書化してJOIN
Sub JoinMaster_Dictionary_External()
'明細: このブックのSheet("明細") A=コード, B=数量
'外部マスタ: "C:\Data\商品マスタ.xlsx" のSheet("マスタ") A=コード, B=名称, C=単価
Dim wsD As Worksheet: Set wsD = Worksheets("明細")
Dim rgD As Range: Set rgD = wsD.Range("A1").CurrentRegion
Dim vD As Variant: vD = rgD.Value
'外部ファイルを開く
Dim wbM As Workbook: Set wbM = Workbooks.Open("C:\Data\商品マスタ.xlsx", ReadOnly:=True)
Dim wsM As Worksheet: Set wsM = wbM.Worksheets("マスタ")
Dim vM As Variant: vM = wsM.Range("A1").CurrentRegion.Value
'辞書作成(コード→(名称,単価))
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim i As Long, key As String
For i = 2 To UBound(vM, 1)
key = UCase$(Trim$(CStr(vM(i, 1))))
dict(key) = Array(CStr(vM(i, 2)), Val(vM(i, 3)))
Next
'出力配列(明細+名称+単価)
Dim out() As Variant: ReDim out(1 To UBound(vD, 1), 1 To UBound(vD, 2) + 2)
Dim c As Long: For c = 1 To UBound(vD, 2): out(1, c) = vD(1, c): Next
out(1, UBound(vD, 2) + 1) = "名称": out(1, UBound(vD, 2) + 2) = "単価"
Dim r As Long
For r = 2 To UBound(vD, 1)
For c = 1 To UBound(vD, 2): out(r, c) = vD(r, c): Next
key = UCase$(Trim$(CStr(vD(r, 1))))
If dict.Exists(key) Then
out(r, UBound(vD, 2) + 1) = dict(key)(0)
out(r, UBound(vD, 2) + 2) = dict(key)(1)
Else
out(r, UBound(vD, 2) + 1) = "#N/A"
out(r, UBound(vD, 2) + 2) = 0
End If
Next
rgD.Resize(UBound(out, 1), UBound(out, 2)).Value = out
'外部ファイルを閉じる
wbM.Close SaveChanges:=False
End Sub
VB- ポイント
- 外部マスタを配列→辞書化してJOIN。
- セル往復ゼロで高速。
- 未一致は「#N/A」や0で補完。
見出し名で安全にJOIN(列順変更に強い)
Sub JoinMaster_ByHeaders_External()
'明細: このブックのSheet("明細") A=コード, B=数量
'外部マスタ: "C:\Data\商品マスタ.xlsx" のSheet("マスタ") A=コード, B=名称, C=単価
Dim wsD As Worksheet: Set wsD = Worksheets("明細")
Dim rgD As Range: Set rgD = wsD.Range("A1").CurrentRegion
Dim vD As Variant: vD = rgD.Value
'外部ファイルを開く
Dim wbM As Workbook: Set wbM = Workbooks.Open("C:\Data\商品マスタ.xlsx", ReadOnly:=True)
Dim wsM As Worksheet: Set wsM = wbM.Worksheets("マスタ")
Dim rgM As Range: Set rgM = wsM.Range("A1").CurrentRegion
Dim vM As Variant: vM = rgM.Value
'見出し列特定
Dim cKeyM As Long: cKeyM = FindHeader(rgM.Rows(1), "コード")
Dim cNameM As Long: cNameM = FindHeader(rgM.Rows(1), "名称")
Dim cPriceM As Long: cPriceM = FindHeader(rgM.Rows(1), "単価")
'辞書作成(コード→(名称,単価))
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim i As Long, key As String
For i = 2 To UBound(vM, 1)
key = UCase$(Trim$(CStr(vM(i, cKeyM))))
dict(key) = Array(CStr(vM(i, cNameM)), Val(vM(i, cPriceM)))
Next
'出力配列(明細+名称+単価)
Dim out() As Variant: ReDim out(1 To UBound(vD, 1), 1 To UBound(vD, 2) + 2)
Dim c As Long: For c = 1 To UBound(vD, 2): out(1, c) = vD(1, c): Next
out(1, UBound(vD, 2) + 1) = "名称": out(1, UBound(vD, 2) + 2) = "単価"
Dim r As Long
For r = 2 To UBound(vD, 1)
For c = 1 To UBound(vD, 2): out(r, c) = vD(r, c): Next
key = UCase$(Trim$(CStr(vD(r, 1))))
If dict.Exists(key) Then
out(r, UBound(vD, 2) + 1) = dict(key)(0)
out(r, UBound(vD, 2) + 2) = dict(key)(1)
Else
out(r, UBound(vD, 2) + 1) = "#N/A"
out(r, UBound(vD, 2) + 2) = 0
End If
Next
'書き戻し
rgD.Resize(UBound(out, 1), UBound(out, 2)).Value = out
'外部ファイルを閉じる
wbM.Close SaveChanges:=False
End Sub
VB初心者向け解説
- 外部ファイルを開く:
Workbooks.Open("パス", ReadOnly:=True)で安全に開く。 - 見出し名で列特定:
FindHeader関数を使うと列順が変わっても壊れない。 - 辞書に格納: キー(コード)を正規化して「名称・単価」を保存。
- JOIN処理: 明細のコードをキーにして辞書から名称・単価を付与。
- 未一致補完: 辞書にないコードは「#N/A」「0」で埋める。
- 閉じる:
wbM.Close SaveChanges:=Falseで外部ファイルを閉じる。
例題で練習
'例1:外部マスタをVLOOKUPでJOIN
Sub Example_External_VLookup()
JoinMaster_VLookup_External
End Sub
'例2:外部マスタを辞書化して高速JOIN
Sub Example_External_Dict()
JoinMaster_Dictionary_External
End Sub
'例3:見出し名で安全にJOIN(列順変更に強い)
Sub Example_External_ByHeaders()
JoinMaster_ByHeaders_External
End Sub
VB