Excelの表データを、WebページやHTMLメールで表示するための<table>
タグに変換したい、というニーズは非常に多くあります。しかし、For
ループで"<tr>"
や"<td>"
といったタグを文字列として連結していく方法は、コードが煩雑になりがちで、ミスも発生しやすくなります。
この記事では、MSXML2.DOMDocument
オブジェクトを利用して、XMLの親子関係を組み立てるようにHTMLのテーブル構造をプログラムで構築し、最終的にHTML文字列として出力する、よりスマートで信頼性の高いカスタム関数を解説します。
完成したVBA関数と実行デモ
まず、Excelのセル範囲を引数として受け取り、HTMLの<table>
文字列を返すメインの関数(RangeToHtmlTable
)と、それを使って実際にHTMLファイルを作成するデモプロシージャです。
' メインの関数: RangeオブジェクトをHTMLのTable文字列に変換する
Function RangeToHtmlTable(ByVal sourceRange As Range) As String
' 変数を宣言
Dim dom As Object
Dim tableNode As Object
Dim rowNode As Object
Dim cellNode As Object
Dim rowNum As Long
Dim colNum As Long
' XMLドキュメントオブジェクトを生成
Set dom = CreateObject("MSXML2.DOMDocument.6.0")
' 1. 最初に<table>のルート要素だけを作成
dom.LoadXML "<table border='1' style='border-collapse: collapse;' />"
Set tableNode = dom.FirstChild
' 2. Excelの範囲を1行ずつループ
For rowNum = 1 To sourceRange.Rows.Count
' <tr>要素(行)を作成し、<table>の子として追加
Set rowNode = tableNode.appendChild(dom.CreateElement("tr"))
' 3. 行の中のセルを1列ずつループ
For colNum = 1 To sourceRange.Columns.Count
' 4. 1行目なら<th>、2行目以降なら<td>要素を作成
Set cellNode = dom.CreateElement(IIf(rowNum = 1, "th", "td"))
' 5. セルの表示内容をテキストとして設定
cellNode.Text = sourceRange.Cells(rowNum, colNum).Text
' 6. 作成したセル(th/td)を行(tr)の子として追加
rowNode.appendChild cellNode
Next colNum
Next rowNum
' 7. 完成したtable要素のHTML文字列を返す
RangeToHtmlTable = tableNode.xml
' オブジェクトを解放
Set cellNode = Nothing
Set rowNode = Nothing
Set tableNode = Nothing
Set dom = Nothing
End Function
' 実行デモ: 上記の関数を使い、HTMLファイルを作成する
Sub Demo_CreateTableFile()
Dim targetRange As Range
Dim htmlContent As String
Dim streamObj As Object
Dim outputFilePath As String
' HTMLに変換したいExcelの範囲
Set targetRange = ThisWorkbook.Worksheets("Sheet1").Range("A1:D6")
' 関数を呼び出して、HTMLのtable文字列を取得
htmlContent = RangeToHtmlTable(targetRange)
' ADODB.Streamを使ってHTMLファイルとして書き出す
outputFilePath = ThisWorkbook.Path & "\TableReport.html"
Set streamObj = CreateObject("ADODB.Stream")
With streamObj
.Type = 2
.Charset = "UTF-8"
.Open
.WriteText "<html><head><meta charset='UTF-8'><title>データ表</title></head><body>"
.WriteText "<h1>Excelからのエクスポートデータ</h1>"
.WriteText htmlContent ' ←ここで関数が返したtable文字列を書き込む
.WriteText "</body></html>"
.SaveToFile outputFilePath, 2
.Close
End With
Set streamObj = Nothing
MsgBox "HTMLテーブルファイルの作成が完了しました。"
End Sub
コードのポイント解説
① DOMでテーブルの骨格を作成
dom.LoadXML "<table border='1' style='...' />"
Set tableNode = dom.FirstChild
まず、LoadXML
を使って、HTMLの<table>
タグだけを持つDOMオブジェクトをメモリ上に作成します。これが、これから組み立てるすべての行(<tr>
)とセル(<td>
)を格納する、大元の親となります。
② 行(tr)とセル(th/td)の動的生成
入れ子にしたFor
ループでExcelのセル範囲を一行ずつ、一セルずつ処理していきます。 その中で最も重要なのが、セル要素(<th>
または<td>
)を作成する以下の部分です。
Set cellNode = dom.CreateElement(IIf(rowNum = 1, "th", "td"))
ここでは**IIf
関数(即時If関数)というVBAの便利な機能を使っています。 IIf(条件式, 真の場合の値, 偽の場合の値)
という構文で、もし現在の行番号(rowNum
)が1、つまりヘッダー行であれば要素名を"th"
**に、**それ以外の行であれば"td"
**にする、という条件分岐を一行で実現しています。
③ セル内容の転記とツリーの構築
cellNode.Text = sourceRange.Cells(rowNum, colNum).Text
rowNode.appendChild cellNode
.Text
プロパティ: セルの値を取得する際、.Value
ではなく.Text
プロパティを使っています。これにより、日付や通貨、パーセンテージなど、Excelシート上で表示されている書式をそのまま文字列として取得できます。.appendChild
: 作成したセル要素(cellNode
)を、現在処理している行要素(rowNode
)の子として追加します。この「子として追加」を繰り返すことで、XML/HTMLの階層構造(ツリー)が正確に組み立てられます。
④ 完成したHTMLの取得
RangeToHtmlTable = tableNode.xml
すべてのループが完了すると、tableNode
オブジェクトは、入れ子になった<tr>
や<td>
をすべて含む、完全なテーブルの構造体になっています。その.xml
プロパティを取得することで、<table>...</table>
という、ひとかたまりのHTML文字列として取り出すことができます。
まとめ
文字列連結でHTMLを組み立てる代わりに、MSXML2.DOMDocument
オブジェクトを使って構造的に(ツリーとして)HTMLを構築する方法は、以下のような大きなメリットがあります。
- タグの閉じ忘れなどの構文エラーが原理的に発生しない。
- コードの親子関係が、HTMLの階層構造と一致するため、ロジックが分かりやすい。
- 複雑な構造でも、
appendChild
を繰り返すことで確実に対応できる。
このRangeToHtmlTable
関数は、ExcelデータをWebページなどで活用したい場合に非常に役立つ、強力なツールとなります。