記事ID: 110
タイトル: 【VBA】XMLファイルをExcelに読み込み・生成する方法(コピペOK)
カテゴリ: 外部連携
一次キーワード: VBA XML 読み込み 作成
想定読者: 他システムとXML形式でデータをやり取りする必要がある実務担当者(VBA初心者〜初級者)
検索意図: VBAでXMLファイルをExcelに読み込む方法、ExcelのデータからXMLファイルを生成する方法を知りたい
読者の悩み(1文): 他システムから出力されたXMLをExcelに取り込みたい、またはExcelのデータをXMLで出力したいが、やり方が分からない。
読了後にできること(1文): MSXML2.DOMDocument60を使って、XMLファイルの読み込み・解析・生成がVBAでできるようになる。
前提条件:
- Excel版: Excel 2016以降 / Microsoft 365
- OS: Windows 10/11
- 保存形式: .xlsm(マクロ有効ブック)
- 貼り付け場所: 標準モジュール
- 実行方法: マクロ実行(Alt+F8)
更新日: 2026-03-18
—
この記事でわかること
- XMLファイルをVBAで読み込んでExcelシートに一覧表として展開できる
- ExcelのデータからXMLファイルを自動生成できる
- MSXML2.DOMDocument60の基本的な使い方(Load / Save / getElementsByTagName)が分かる
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
どんな場面で使う?
- 他部門のシステムから出力されたXMLファイルを自動でExcelに取り込みたいとき
- Excelの一覧データをXML形式で他システムに渡したいとき
- XMLの特定タグだけ抽出してExcelの表に展開したいとき
- 毎日定時で出力されるXMLファイルを朝イチで自動取込する仕組みを作りたいとき
—
完成イメージ(Before / After)
Before(XMLファイルの中身):
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product id="P001">
<name>ボールペン</name>
<price>150</price>
<stock>200</stock>
</product>
<product id="P002">
<name>ノート</name>
<price>300</price>
<stock>150</stock>
</product>
<product id="P003">
<name>消しゴム</name>
<price>80</price>
<stock>500</stock>
</product>
</products>
After(Excelシートに展開):
| A列(商品ID) | B列(商品名) | C列(価格) | D列(在庫) |
|---|---|---|---|
| P001 | ボールペン | 150 | 200 |
| P002 | ノート | 300 | 150 |
| P003 | 消しゴム | 80 | 500 |
XMLファイルを指定して実行するだけで、タグの中身がセルに一覧表として展開される。逆に、Excelの一覧表からXMLファイルを自動生成することもできる。
—
自分も以前、他部門のシステムからXML形式で出力されるデータを毎回手作業でExcelに転記していた。タグの中身を1つずつコピーしてセルに貼る作業が正直めんどくさかった。VBAでXML読み込みを自動化してからは、ファイルを指定して実行するだけで一覧表が完成するようになった。同じようにXMLの手作業転記で時間を溶かしている人が、この記事でサクッと自動化できればうれしい。
テキストファイルの取り込みが初めてなら、まず テキストファイル(txt/log)をExcelに取り込む方法 で基本を押さえておくとスムーズに進められる。
—
実行前の準備
バックアップを取る
実務版コードはXMLファイルを新規生成する(既存ファイルは上書きされる)。実行前に元データのコピーを別フォルダに保存しておく。
サンプルXMLファイルを用意する
読み込みテスト用に、以下のXMLをメモ帳で作成して保存する。
- メモ帳を開く
- 上の「Before」のXMLコードをコピペする
- 「ファイル」→「名前を付けて保存」
- ファイル名:
products.xml - 文字コード: UTF-8(メモ帳の場合「エンコード」で選択)
- 保存先:
C:\Test\products.xml(任意のフォルダでOK)
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
- コード内の
xmlPathを実際のXMLファイルのパスに書き換える Alt + F8→ マクロ名を選んで「実行」
コードの先頭に
Option Explicitを入れておくと、変数名のタイプミスをVBAが検出してくれる。標準モジュールの1行目に書いておくのがおすすめ。
—
コード(最小版)– XMLファイルをExcelに読み込む
サンプルXMLファイル(products.xml)を読み込んで、アクティブシートに一覧表として展開する。まずはこれで動きを確認する。
Option Explicit
'============================================================
' ■ XMLファイルをExcelに読み込む(最小版)
' → 指定したXMLファイルを解析し、シートに一覧表として展開
'============================================================
Sub ImportXML()
'--- ★書き換えポイント: XMLファイルのパス ---
Dim xmlPath As String
xmlPath = "C:\Test\products.xml"
'--- XMLオブジェクトを生成
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
'--- 同期読み込みに設定(重要: これがないとデータが空になる)
xmlDoc.Async = False
'--- XMLファイルを読み込む
If xmlDoc.Load(xmlPath) = False Then
MsgBox "XMLの読み込みに失敗しました。" & vbCrLf & _
xmlDoc.parseError.reason, vbExclamation
Exit Sub
End If
'--- product要素を全て取得
Dim products As Object
Set products = xmlDoc.getElementsByTagName("product")
If products.Length = 0 Then
MsgBox "product要素が見つかりませんでした。", vbExclamation
Exit Sub
End If
'--- ヘッダーを書き込む
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Cells(1, 1).Value = "商品ID"
ws.Cells(1, 2).Value = "商品名"
ws.Cells(1, 3).Value = "価格"
ws.Cells(1, 4).Value = "在庫"
'--- データを書き込む
Dim i As Long
Dim node As Object
For i = 0 To products.Length - 1
Set node = products.Item(i)
ws.Cells(i + 2, 1).Value = node.getAttribute("id")
ws.Cells(i + 2, 2).Value = node.selectSingleNode("name").Text
ws.Cells(i + 2, 3).Value = node.selectSingleNode("price").Text
ws.Cells(i + 2, 4).Value = node.selectSingleNode("stock").Text
Next i
MsgBox products.Length & " 件の商品データを読み込みました。", vbInformation
Set xmlDoc = Nothing
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
xmlPath |
XMLファイルのフルパス | C:\Test\products.xml |
getElementsByTagName("product") |
取得する要素のタグ名 | "product" |
getAttribute("id") |
取得する属性名 | "id" |
selectSingleNode("name") 等 |
取得する子要素のタグ名 | "name", "price", "stock" |
ポイント: xmlDoc.Async = False を忘れると、読み込みが完了する前にデータを取得しようとして空になる。これが最もハマりやすいポイント。
最小版ではselectSingleNodeの結果がNothingの場合(子要素が存在しない場合)にエラーになる。サンプルXMLで動作確認したら、実務版に進むとよい。
読み込む前にファイルの存在を確認したい場合は ファイルやフォルダの存在を確認してから処理する方法 を参照。
—
コード(実務版)– エラー処理付きXML読み込み+XML生成
実務では「読み込み」と「生成」の両方が必要になることが多い。このコードは以下の2つのマクロを含む。
- ImportXMLEx: エラー処理・ファイル存在チェック付きのXML読み込み
- ExportToXML: ExcelのデータからXMLファイルをUTF-8で生成
この方法を覚えてからは、他システムから毎日出力されるXMLファイルを朝イチで自動取込するマクロを組んで、始業前にデータが揃うようにしている。チームからも「朝来たらデータが入ってるの助かる」と言われるようになった。
※ XMLファイルの生成時、指定パスに既存ファイルがある場合は上書きされます。実行前にバックアップを取ってください。
Option Explicit
'============================================================
' ■ XMLファイルをExcelに読み込む(実務版・エラー処理付き)
' → ファイル存在チェック・エラー処理・処理件数の表示
'============================================================
Sub ImportXMLEx()
'--- ★書き換えポイント ---
Dim xmlPath As String
xmlPath = "C:\Test\products.xml"
Dim startRow As Long
startRow = 2 '← データの開始行(1行目はヘッダー)
'--- ★ここまで ---
'--- ファイルの存在チェック(ここが追加)
If Dir(xmlPath) = "" Then
MsgBox "XMLファイルが見つかりません。" & vbCrLf & _
xmlPath, vbExclamation
Exit Sub
End If
'--- XMLオブジェクトを生成
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.Async = False
xmlDoc.ValidateOnParse = False '← DTD検証をスキップ(高速化)
'--- XMLファイルを読み込む
If xmlDoc.Load(xmlPath) = False Then
MsgBox "XMLの解析に失敗しました。" & vbCrLf & _
"行: " & xmlDoc.parseError.Line & vbCrLf & _
"理由: " & xmlDoc.parseError.reason, vbExclamation
Exit Sub
End If
'--- product要素を取得
Dim products As Object
Set products = xmlDoc.getElementsByTagName("product")
If products.Length = 0 Then
MsgBox "product要素が見つかりませんでした。", vbExclamation
Exit Sub
End If
'--- シートの準備
Dim ws As Worksheet
Set ws = ActiveSheet
'--- ヘッダーを書き込む
ws.Cells(1, 1).Value = "商品ID"
ws.Cells(1, 2).Value = "商品名"
ws.Cells(1, 3).Value = "価格"
ws.Cells(1, 4).Value = "在庫"
'--- データを書き込む(エラー処理付き)(ここが追加)
Dim i As Long
Dim node As Object
Dim errCount As Long
errCount = 0
For i = 0 To products.Length - 1
Set node = products.Item(i)
On Error Resume Next
ws.Cells(i + startRow, 1).Value = node.getAttribute("id")
ws.Cells(i + startRow, 2).Value = node.selectSingleNode("name").Text
ws.Cells(i + startRow, 3).Value = CLng(node.selectSingleNode("price").Text)
ws.Cells(i + startRow, 4).Value = CLng(node.selectSingleNode("stock").Text)
If Err.Number <> 0 Then
errCount = errCount + 1
ws.Cells(i + startRow, 1).Value = "(読み取りエラー: 行 " & i + 1 & ")"
Err.Clear
End If
On Error GoTo 0
Next i
'--- 結果表示
Dim msg As String
msg = products.Length & " 件の商品データを読み込みました。"
If errCount > 0 Then
msg = msg & vbCrLf & errCount & " 件でエラーが発生しました(該当行を確認してください)。"
End If
MsgBox msg, vbInformation
Set xmlDoc = Nothing
End Sub
'============================================================
' ■ ExcelデータからXMLファイルを生成(実務版)
' → アクティブシートのA〜D列のデータをXML形式で保存
' → A列: 商品ID、B列: 商品名、C列: 価格、D列: 在庫
' → ADODB.StreamでUTF-8(BOM付き)保存
'============================================================
Sub ExportToXML()
'--- ★書き換えポイント ---
Dim outputPath As String
outputPath = "C:\Test\products_output.xml"
Dim startRow As Long
startRow = 2 '← データの開始行(1行目はヘッダー)
Dim idCol As Long
idCol = 1 '← 商品IDの列(A列=1)
Dim nameCol As Long
nameCol = 2 '← 商品名の列(B列=2)
Dim priceCol As Long
priceCol = 3 '← 価格の列(C列=3)
Dim stockCol As Long
stockCol = 4 '← 在庫の列(D列=4)
'--- ★ここまで ---
Dim ws As Worksheet
Set ws = ActiveSheet
'--- 最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, idCol).End(xlUp).Row
If lastRow < startRow Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- XMLオブジェクトを生成
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
'--- XML宣言を追加
Dim pi As Object
Set pi = xmlDoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8""")
xmlDoc.appendChild pi
'--- ルート要素を作成
Dim root As Object
Set root = xmlDoc.createElement("products")
xmlDoc.appendChild root
'--- データ行をループしてXML要素を作成
Dim r As Long
Dim productNode As Object
Dim childNode As Object
Dim textNode As Object
Dim processCount As Long
processCount = 0
For r = startRow To lastRow
'--- product要素を作成
Set productNode = xmlDoc.createElement("product")
'--- id属性を設定
productNode.setAttribute "id", CStr(ws.Cells(r, idCol).Value)
'--- name子要素
Set childNode = xmlDoc.createElement("name")
Set textNode = xmlDoc.createTextNode(CStr(ws.Cells(r, nameCol).Value))
childNode.appendChild textNode
productNode.appendChild childNode
'--- price子要素
Set childNode = xmlDoc.createElement("price")
Set textNode = xmlDoc.createTextNode(CStr(ws.Cells(r, priceCol).Value))
childNode.appendChild textNode
productNode.appendChild childNode
'--- stock子要素
Set childNode = xmlDoc.createElement("stock")
Set textNode = xmlDoc.createTextNode(CStr(ws.Cells(r, stockCol).Value))
childNode.appendChild textNode
productNode.appendChild childNode
'--- ルートに追加
root.appendChild productNode
processCount = processCount + 1
Next r
'--- UTF-8で保存(ADODB.Streamを使用)(ここが追加)
Dim stream As Object
Set stream = CreateObject("ADODB.Stream")
stream.Type = 2 '← adTypeText
stream.Charset = "UTF-8"
stream.Open
stream.WriteText xmlDoc.XML
stream.SaveToFile outputPath, 2 '← 2 = adSaveCreateOverWrite
stream.Close
MsgBox processCount & " 件の商品データをXMLに出力しました。" & vbCrLf & _
outputPath, vbInformation
Set stream = Nothing
Set xmlDoc = Nothing
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
xmlPath |
読み込むXMLファイルのパス | C:\Test\products.xml |
outputPath |
出力するXMLファイルのパス | C:\Test\products_output.xml |
startRow |
データの開始行 | 2(1行目はヘッダー) |
各列番号(idCol等) |
データの列位置 | A〜D列(1〜4) |
シート構成の例
| A列(商品ID) | B列(商品名) | C列(価格) | D列(在庫) |
|---|---|---|---|
| P001 | ボールペン | 150 | 200 |
| P002 | ノート | 300 | 150 |
| P003 | 消しゴム | 80 | 500 |
XML処理の実行結果をログに残したい場合は マクロの実行ログをファイルに自動記録する方法 を参照。
—
よくある落とし穴5選
1. Async = False を設定し忘れてデータが空になる
原因: DOMDocument60のAsync既定値はTrue(非同期読み込み)。非同期だと、Loadが完了する前に次の行が実行されるため、データが空のまま処理が進む。
対策: Load前に必ず xmlDoc.Async = False を設定する。
' NG: Asyncを設定し忘れ → データが空
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.Load "C:\Test\products.xml" '← 非同期で読み込み開始
Debug.Print xmlDoc.getElementsByTagName("product").Length '← 0になる
' OK: Async = False を設定
xmlDoc.Async = False
xmlDoc.Load "C:\Test\products.xml"
Debug.Print xmlDoc.getElementsByTagName("product").Length '← 正しい件数
2. XMLのエンコーディング宣言と実際の保存形式が不一致で文字化けする
自分もこれで1時間溶かした。XMLファイルの先頭に encoding="UTF-8" と書いてあるのに、実際にはShift-JISで保存されていた。Loadは通るのに日本語が全部文字化けしていて、原因に気づくまでコードばかり疑ってしまった。
原因: XML宣言のencoding属性と、ファイルの実際のエンコーディングが一致していない。
対策: メモ帳で保存する際に文字コードを「UTF-8」に指定する。XML宣言の encoding="UTF-8" と保存形式を必ず一致させる。
3. 名前空間付きのXMLでgetElementsByTagNameが0件になる
原因: XMLに xmlns="http://example.com" のような既定の名前空間(デフォルト名前空間)が設定されている場合、getElementsByTagNameでは要素を取得できない。名前空間は「XMLの要素がどの定義に属するか」を示す仕組みで、業務システムが出力するXMLに付いていることが多い。
対策: selectNodesとXPathを使い、setPropertyで名前空間のプレフィックスを指定する。
' 名前空間付きXMLの場合の対処法
xmlDoc.setProperty "SelectionLanguage", "XPath"
xmlDoc.setProperty "SelectionNamespaces", "xmlns:ns='http://example.com'"
' nsプレフィックスを付けてselectNodesで取得
Dim nodes As Object
Set nodes = xmlDoc.selectNodes("//ns:product")
Debug.Print nodes.Length '← 正しい件数が取得できる
4. Saveで保存するとUTF-16になり、他システムで文字化けする
原因: DOMDocument60の .Save メソッドは、XML宣言に encoding="UTF-8" と書いてあっても、実際にはUTF-16で保存することがある。UTF-16のXMLを受け取るシステム側で文字化けやパースエラーが発生する。
対策: 実務版コードのように、ADODB.Streamを使って明示的にUTF-8で保存する。
' NG: xmlDoc.Save でUTF-16になる場合がある
xmlDoc.Save "C:\Test\output.xml"
' OK: ADODB.StreamでUTF-8を明示
Dim stream As Object
Set stream = CreateObject("ADODB.Stream")
stream.Type = 2
stream.Charset = "UTF-8"
stream.Open
stream.WriteText xmlDoc.XML
stream.SaveToFile "C:\Test\output.xml", 2
stream.Close
5. parseErrorを確認せず、読み込み失敗の原因が分からない
原因: LoadメソッドはXML解析に失敗するとFalseを返すだけで、VBAのランタイムエラーは発生しない。戻り値を無視すると、なぜ失敗したか分からないまま止まる。
対策: Loadの戻り値をチェックし、Falseなら xmlDoc.parseError.reason(理由)と xmlDoc.parseError.Line(エラー行)を表示する。
If xmlDoc.Load(xmlPath) = False Then
MsgBox "XMLの解析に失敗しました。" & vbCrLf & _
"行: " & xmlDoc.parseError.Line & vbCrLf & _
"理由: " & xmlDoc.parseError.reason, vbExclamation
Exit Sub
End If
—
VBAでXMLの読み込みデータが空になるときの対処法
「XML.Loadを実行したのにデータが空になる」という場合、原因は Async = False の設定漏れだ。DOMDocument60の既定値はTrue(非同期)なので、Loadが完了する前に次の処理が動いてしまう。Load前に必ず xmlDoc.Async = False を入れる。
VBAでXMLの日本語が文字化けするときの対処法
「XMLを読み込んだら日本語が化ける」という場合、原因はXML宣言のencoding属性と実際のファイルのエンコーディングが不一致だ。encoding=UTF-8と宣言しているならファイルもUTF-8で保存する。メモ帳で保存する際にエンコードをUTF-8に指定すれば解決する。
FAQ
Q1: 参照設定は必要?
不要。CreateObject("MSXML2.DOMDocument.6.0") でレイトバインディングすれば参照設定なしで動く。ただし、VBEで入力補完(IntelliSense)を使いたい場合は、VBEメニュー「ツール」→「参照設定」→「Microsoft XML, v6.0」にチェックを入れるとよい。
Q2: XMLの特定の要素だけ読み込みたい場合は?
selectNodes でXPath式を使えば特定の要素だけ抽出できる。
' 全商品の名前だけ取得
Dim nameNodes As Object
Set nameNodes = xmlDoc.selectNodes("//product/name")
Dim i As Long
For i = 0 To nameNodes.Length - 1
Debug.Print nameNodes.Item(i).Text
Next i
XPathでは条件指定もできる。例えば //product[price>=200] で価格200以上の商品だけ取得できる。
Q3: 大きなXMLファイル(数万行)でも処理できる?
DOMDocument60はファイル全体をメモリに読み込む方式のため、数十MBを超えるXMLではメモリ不足になる可能性がある。一般的な業務データ(数千〜数万行程度)であれば問題ない。
Q4: CSVとXMLのどちらで出力すべき?
データが単純な表形式(行と列だけ)ならCSVが軽量で扱いやすい。階層構造があるデータ(入れ子のカテゴリ、属性付きデータ等)はXMLが向いている。CSVの取り込みは CSVファイルをExcelに正しく取り込む方法 を参照。
Q5: 生成したXMLのBOM(バイトオーダーマーク)が問題になる場合は?
ADODB.StreamでUTF-8保存すると、ファイル先頭にBOM(3バイトの識別子)が付く。一部のシステムではBOM付きUTF-8を正しく処理できない場合がある。BOMなしで保存するには、一度バイナリとして読み直してBOM部分をスキップして書き出す方法がある。
' BOMなしUTF-8で保存する方法
Dim stmUTF8 As Object
Set stmUTF8 = CreateObject("ADODB.Stream")
stmUTF8.Type = 2
stmUTF8.Charset = "UTF-8"
stmUTF8.Open
stmUTF8.WriteText xmlDoc.XML
'--- バイナリモードで読み直し、BOM(先頭3バイト)をスキップ
stmUTF8.Position = 0
stmUTF8.Type = 1 '← adTypeBinary
stmUTF8.Position = 3 '← BOMの3バイトをスキップ
Dim binData() As Byte
binData = stmUTF8.Read
'--- BOMなしで書き出し
Dim stmOut As Object
Set stmOut = CreateObject("ADODB.Stream")
stmOut.Type = 1
stmOut.Open
stmOut.Write binData
stmOut.SaveToFile outputPath, 2
stmOut.Close
stmUTF8.Close
—
まとめ
- XML読み込み:
MSXML2.DOMDocument.6.0の Load → getElementsByTagName でデータ取得 → セルに書き込み - XML生成: createElement / createTextNode でツリー構築 → ADODB.Stream で UTF-8 保存
- 必須設定:
Async = False(同期読み込み)を忘れない - エンコーディング: XML宣言の encoding と実際の保存形式を一致させる
- エラー確認: parseError で読み込み失敗の原因を必ず確認する
関連記事
- テキストファイル(txt/log)をExcelに取り込む方法 — テキスト系ファイル取り込みの基本
- CSVファイルをExcelに正しく取り込む方法 — CSV取り込みとの使い分け
- ファイルやフォルダの存在を確認してから処理する方法 — 読み込み前の安全チェック
- マクロの実行ログをファイルに自動記録する方法 — XML処理のログ出力
- ExcelデータをCSVファイルに書き出す方法 — XMLではなくCSVで出力したい場合
—
次にやりたくなること
- CSVファイルをExcelに正しく取り込む方法: XMLだけでなくCSVファイルの取り込みも自動化したい場合。CSV vs XML の使い分けが分かる
- マクロの実行ログをファイルに自動記録する方法: XML読み込み・生成の処理結果をログファイルに残して、いつ・何件処理したかを記録したい場合
- JSONデータをExcelに読み込み・書き出しする方法: XML以外にJSON形式のデータ連携も必要な場合。XMLとJSONの使い分けが分かる


コメント