前回の記事では、テンプレートエンジンMiniTemplatorについての簡単な使い方を説明しました。
今回は前回より少し高度な使い方を説明していきたいと思います。
1.サブブロックの構築
MiniTemplatorではブロックの中に、更にブロックを構築することができます。
サブブロックを利用することで、
複雑なテンプレートも簡潔に書くことができます。
例えば前回でも使用したサンプルを拡張してみましょう。
前回ではExcelの表をそのままHTMLの表にするだけでしたが、
今回はこのExcelから項目の日付ごとに品物と金額の表を複数個作成するマクロを作成します。
以下がテンプレートです。(ソース1)
前回のテンプレートを拡張しています。
具体的には表から日付の項目を削除し、日付は見出しとして採用しています。
そして、表の中にあるItemsブロックを囲むように、
見出しの外側からVariationブロックを用意しています。
<head><title>買い物リスト</title></head><body>
<h1>6月支出まとめ</h1>
<!-- $BeginBlock Variation -->
<h2>${date}</h2>
<table border=”1″ bgcolor=”#eeffee”>
<tr>
<th>品物</th>
<th>金額</th>
</tr>
<!-- $BeginBlock Items -->
<tr>
<td>${name}</td>
<td>${price}</td>
</tr>
<!-- $EndBlock Items -->
</table>
<hr/>
<!-- $EndBlock Variation -->
</body>
</html>
ソース1:テンプレートサンプル
以下がVBAでの出力用のソースです。(ソース2)
このサンプルでは、前処理としてDictionaryオブジェクトを使用して、
表の中に登場する日付を調べて、
日付のリスト(DateList)を作成しています。
そして、表を先頭から末尾まで探索して、
対象の日付と一致している日付の項目のみをItemsブロックに追加します。
一致している項目を全て追加し終わってから、Variationブロックを追加します。
これを日付の数分繰り返します。
ここで注意するのが、ItemsブロックはVariationブロックよりも先に追加を行うことです。
Variationブロックを追加すると、それまで追加していたItemsブロックのデータは一旦クリアされます。
(SetVariableでセットした値についてはクリアされません)
先にサブブロックを追加してから、メインブロックの追加を行ってください。
Private Const START_CELL = “B5″Public Sub PushButton()
Dim i As Integer
Dim Cell As Range
Dim Temp As MiniTemplator
Dim Dic As Object
Dim DateList As Variant
Set Dic = CreateObject(“Scripting.Dictionary”)
Set Temp = New MiniTemplator
‘まず登場する日付のリストを作ります。
Set Cell = Range(START_CELL)
Do While Cell.Row <= ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
If Not Dic.Exists(Cell.Offset(0, 1).Value) Then
Dic.Add Cell.Offset(0, 1).Value, 1
End If
Set Cell = Cell.Offset(1, 0)
Loop
DateList = Dic.Keys
Temp.ReadTemplateFromFile ThisWorkbook.Path & “\template.html”
‘登場する日付の種類分だけ以下を繰り返します。
For i = 1 To Dic.Count
Set Cell = Range(START_CELL)
Temp.SetVariable “date”, DateList(i – 1)
Do While Cell.Row <= _
ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
‘日付が一致しているもののみサブブロックに追加します。
If StrComp(DateList(i – 1), Cell.Offset(0, 1)) = 0 Then
Temp.SetVariable “name”, Cell.Value
Temp.SetVariable “price”, Cell.Offset(0, 2).Value
Temp.AddBlock “Items”
End If
Set Cell = Cell.Offset(1, 0)
Loop
‘サブブロックを追加し終わってからブロックを追加します。
Temp.AddBlock “Variation”
Next i
Temp.GenerateOutputToFile ThisWorkbook.Path & “\output.html”
MsgBox “HTML生成完了”
End Sub
ソース2:VBAソースサンプル
出力のHTMLを確認すると、表が日付ごとにしっかり作成されています。(表1)
表1:出力サンプル
2.エスケープ処理
SetVariableメソッドでプレースホルダーに設定した値はエスケープ処理が行われません。
よって、htmlタグなどを変数に埋め込んだ場合、そのタグがそのままhtmlに反映されます。
それを防ぎたい場合はSetVariableEscメソッドを利用します。(ソース3)
このメソッドはエスケープ処理を行いますので、タグがhtmlに反映されることはありません。
以下の入出力サンプルで使用するマクロには、ソース2の品物の項目にSetVariableメソッドを、金額の項目にSetVariableEscメソッドを使用しています。
入力として、htmlタグを使用したデータを用意しました。(図2)
品物の項目ではタグが有効になっていますが、金額の項目では記述したタグがそのまま表示されています。(図3)
Temp.SetVariable “name”, Cell.Value
Temp.SetVariableEsc “price”, Cell.Offset(0, 2).Value
Temp.AddBlock “Items”
ソース3:SetVariableEsc使用サンプル
図2:htmlタグ入り入力サンプル
図3:出力サンプル(SetVariableEsc使用)
3.サブテンプレート
MiniTemplatorにはサブテンプレートをインクルードする機能が備わっています。
この機能を使うことで、テンプレートを複数のファイルに分けて記述することが可能になります。
以下はソース1を拡張して、サブテンプレートを使用した例になります。(ソース4)
また、サブテンプレートを以下のように記述します。(ソース5)
サブテンプレートのインクルードには<!-- $Include XXXX -->と記述する必要があります。
XXXXの内容はファイル名です。拡張子まで記述してください。
<head><title>買い物リスト</title></head><body>
<!-- $Include subTemplate.html -->
<h1>6月支出まとめ</h1>
<!-- $BeginBlock Variation -->
<h2>${date}</h2>
<table border=”1″ bgcolor=”#eeffee”>
<tr>
<th>品物</th>
<th>金額</th>
</tr>
<!-- $BeginBlock Items -->
<tr>
<td>${name}</td>
<td>${price}</td>
</tr>
<!-- $EndBlock Items -->
</table>
<hr/>
<!-- $EndBlock Variation -->
</body>
</html>
ソース4:テンプレートサンプル(サブテンプレート使用)
サブテンプレートです。<br/>
ここに切り分けた文章を記述します。<br/>
ソース5:サブテンプレート
VBAのソースにも修正が必要になります。
ReadTemplateFromFileメソッドを呼び出す前に、
MiniTemplatorオブジェクトのSubtemplateBasePathプロパティに、サブテンプレートのフォルダパスを設定して下さい。
この設定を行わないままReadTemplateFromFileメソッドを実行するとエラーになります。
Temp.ReadTemplateFromFile ThisWorkbook.Path & “\template.html”
ソース6:VBAソースサンプル(サブテンプレート使用部分)
以下が実行結果のサンプルになります。
サブテンプレートの中に記述した文章が、出力のhtmlにも記述されています。(図4)
図4:出力サンプル(サブテンプレート使用)