【ExcelVBA】Excelを使ってXMLを作る

# VBAを使ってxmlを作る方法

## 環境
* Windows10 Pro(x64)
* Excel 2016

## 手順
1. Excel起動 -> 開発 -> Visual Basic -> Visual Basic for Applications を起動する
1. ツール(T) -> 参照設定(R) を押して参照設定ウィンドウを開く[^1]
1. 「Microsoft XML, v6.0」にチェックを入れてOKボタンを押す
1. 挿入(I) -> 標準モジュール(M)を押す


参考：[ VBA ] xml ファイルを作成する ( MSXML2.DOMDocument60 )
http://hensa40.cutegirl.jp/archives/4975


# XML Schema定義 (XSD)を使ってxmlを作る

VBAを組む必要なくエクセル上でXMLのデータを扱えるので試す分にはこっちの方が楽。
ただし、以下の点に注意。

1. エクスポートしたxmlファイルに名前空間(ns1:)が表示される
1. リスト内のリストは表現できない[^2]

## 環境
* Windows10 Pro(x64)
* Vual Studio Community 2019(XSD作成のため)
* Excel 2016

## 手順

1. ひな形となる XML ファイルを事前につくる
1. ひな形から、XML スキーマファイル(*.xsd)をつくる
1. エクセルのワークシートのセルに XML の要素を対応付ける
1. エクセル上でデータを作成する
1. 編集したデータを XML ファイルとして出力する

参考：Excel 2010 を使って XML ファイルを編集する
https://qiita.com/go_astrayer/items/70dc67f6a4468d26794b

## スキーマの名前空間について
秀丸などのテキストエディタを使って不要な名前を置換すればいいのでそこまで問題ないと思う。
詳しく知りたい人は、スキーマファイルの宣言を調べてみてください。

スキーマ宣言
http://www.mitchy-world.jp/xml/xmlschema/step02.htm

<!-- 

```vb:XmlMakeSample.bas

Sub XmlMakeSample()
 Dim xmlDoc As MSXML2.DOMDocument60 'XMLドキュメント
 Dim xmlPI As IXMLDOMProcessingInstruction 'XML宣言
 Dim node As IXMLDOMNode '要素
 Dim rootNode As IXMLDOMNode 'root要素
 Dim custNode As IXMLDOMNode 'customer要素
 Dim attr As MSXML2.IXMLDOMAttribute '属性

 Set xmlDoc = New MSXML2.DOMDocument60 'XMLドキュメントを作成。

 'XML宣言(文字コードにはUTF-8を指定)
 Set xmlPI = xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8"""))

 '要素<Root>を追加
 Set rootNode = xmlDoc.appendChild(xmlDoc.createNode(NODE_ELEMENT, "Root", ""))

 '要素<Customer>を追加
 Set custNode = rootNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "Customer", ""))

 'Customer要素にid属性を追加
 Set attr = custNode.Attributes.setNamedItem(xmlDoc.createNode(NODE_ATTRIBUTE, "id", ""))
 attr.NodeValue = "1"

 '要素（名前）を追加
 Set node = custNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "名前", ""))
 node.Text = "ビッグジョン"

 '要素（住所）を追加
 Set node = custNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "住所", ""))
 node.Text = "メキシコシティ"

 '要素（電話）を追加
 Set node = custNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "電話", ""))
 node.Text = "0000-0000-0000"

 'XMLドキュメントの出力
 xmlDoc.Save ("sample.xml")
End Sub
```

# STEP1

とりあえずはまず作ってみる。
例としてこんなのが作りたい。

```xml:hobby.xml
<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="http://www.xxxx.yyyyy.com" name="human" userName="DEFAULT" password="hush" tenant="DEFAULT">
 <addHobbyModel>
 <HobbyModelName>機関車プラレール</vehicleModelName>
 <make>山田金属加工</make>
 <Vendor>ダカラ・トミー</Vendor>
 <modelCode>PLA-RAIL</modelCode>
 </addHobbyModel>

 以下 addHobbyModel が沢山

</service>
```
要素は後々エクセルから引っ張ってくるのでまずはこの形のXMLを作る事を目標とする

```vb:XmlMakeSample.bas

Sub XmlMakeSample()
 Dim xmlDoc As MSXML2.DOMDocument60 'XMLドキュメント
 Dim xmlPI As IXMLDOMProcessingInstruction 'XML宣言
 Dim node As IXMLDOMNode '要素
 Dim serviceNode As IXMLDOMNode 'service要素
 Dim hobbyNode As IXMLDOMNode 'addHobbyModel要素
 Dim attr As MSXML2.IXMLDOMAttribute '属性

 'XMLドキュメントを作成
 Set xmlDoc = New MSXML2.DOMDocument60

 'XML宣言(文字コードにはUTF-8を指定)
 Set xmlPI = xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8"""))

 '要素<service>を追加
 Set serviceNode = xmlDoc.appendChild(xmlDoc.createNode(NODE_ELEMENT, "service", "http://www.xxxx.yyyyy.com"))

 'service要素にid属性を追加
 Set attr = serviceNode.Attributes.setNamedItem(xmlDoc.createNode(NODE_ATTRIBUTE, "tenant", ""))
 attr.NodeValue = "DEFAULT"
 Set attr = serviceNode.Attributes.setNamedItem(xmlDoc.createNode(NODE_ATTRIBUTE, "password", ""))
 attr.NodeValue = "hush"
 Set attr = serviceNode.Attributes.setNamedItem(xmlDoc.createNode(NODE_ATTRIBUTE, "userName", ""))
 attr.NodeValue = "DEFAULT"
 Set attr = serviceNode.Attributes.setNamedItem(xmlDoc.createNode(NODE_ATTRIBUTE, "name", ""))
 attr.NodeValue = "human"

 '要素<addHobbyModel>を追加
 Set hobbyNode = serviceNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "addHobbyModel", ""))

 '要素を追加
 Set node = hobbyNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "HobbyModelName", ""))
 node.Text = "機関車プラレール"
 Set node = hobbyNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "make", ""))
 node.Text = "山田金属加工"
 Set node = hobbyNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "Vendor", ""))
 node.Text = "ダカラ・トミー"
 Set node = hobbyNode.appendChild(xmlDoc.createNode(NODE_ELEMENT, "modelCode", ""))
 node.Text = "PLA-RAIL"

 'XMLドキュメントの出力
 xmlDoc.Save ("sample.xml")
End Sub
```

## 結果

```xml
<?xml version="1.0" encoding="UTF-8"?>
<service name="human" userName="DEFAULT" tenant="DEFAULT" password="hush" xmlns="http://www.xxxx.yyyyy.com">
 <addHobbyModel xmlns="">
 <HobbyModelName>機関車プラレール</HobbyModelName>
 <make>山田金属加工</make>
 <Vendor>ダカラ・トミー</Vendor>
 <modelCode>PLA-RAIL</modelCode>
 </addHobbyModel>
</service>
```

とりあえず今日はここまで

-->

[^1]: 参照設定がグレーアウトになっている人は裏でマクロが動いている可能性がある
[^2]: エクセルの仕様で出来ない様になっているようだ。しかしリスト内リストが使えないのは本当に痛い