これまでの記事で、「特殊文字のエスケープ」「タグで囲む」「属性の追加」といった、HTML生成のための部品となる関数を個別に作成してきました。
今回はその集大成として、これらの部品をすべて内包し、引数の与え方によって様々なパターンのHTML要素を1つで生成できる「万能関数」の作り方を解説します。この関数の鍵となるのが、VBAのOptional
引数です。
完成したVBAコード(全ヘルパー関数+万能関数)
まず、今回の主役であるGenerateHtmlElement
関数と、それが内部で利用する3つのヘルパー関数、そして実行デモを含む全コードを掲載します。
' =================================================================
' === ヘルパー関数群 (これまでの記事で作成) ===
' =================================================================
' 関数1:HTMLの特殊文字をエスケープ処理する
Function EncodeToHtml(ByVal inputText As String) As String
Dim dom As Object
Set dom = CreateObject("MSXML2.DOMDocument.6.0")
dom.LoadXML "<temp />"
dom.FirstChild.Text = inputText
EncodeToHtml = Replace(dom.FirstChild.FirstChild.xml, vbCrLf, "<br />")
Set dom = Nothing
End Function
' 関数2:指定したタグ名で文字列を囲む
Function WrapWithTag(ByVal tagName As String, ByVal content As String) As String
WrapWithTag = "<" & tagName & ">" & content & "</" & tagName & ">"
End Function
' 関数3:HTML要素の文字列に属性を追加する
Function AddAttribute(ByVal elementString As String, ByVal attrName As String, ByVal attrValue As String) As String
Dim dom As Object
Set dom = CreateObject("MSXML2.DOMDocument.6.0")
dom.LoadXML elementString
dom.FirstChild.setAttribute attrName, attrValue
AddAttribute = dom.FirstChild.xml
Set dom = Nothing
End Function
' =================================================================
' === 万能HTML生成関数 (今回のメイン) ===
' =================================================================
Function GenerateHtmlElement(ByVal content As String, _
Optional ByVal tagName As Variant, _
Optional ByVal attributes As Variant) As String
Dim htmlString As String
Dim i As Long
' 1. まずはコンテンツをHTMLエスケープ
htmlString = EncodeToHtml(content)
' 2. (もしあれば) タグで囲む
If IsMissing(tagName) = False Then
htmlString = WrapWithTag(CStr(tagName), htmlString)
' 3. (もしあれば) 属性をループで追加
If IsMissing(attributes) = False Then
For i = 0 To UBound(attributes)
htmlString = AddAttribute(htmlString, CStr(attributes(i)(0)), CStr(attributes(i)(1)))
Next i
End If
End If
' 完成したHTML文字列を返す
GenerateHtmlElement = htmlString
End Function
' =================================================================
' === 実行デモ ===
' =================================================================
Sub Demo_GenerateHtml()
' パターン1: テキストのエスケープのみ
Range("C2").Value = GenerateHtmlElement("Excel & VBA > HTML")
' パターン2: テキストをdivタグで囲む
Range("C3").Value = GenerateHtmlElement("Excel & VBA > HTML", "div")
' パターン3: テキストをdivタグで囲み、さらに複数の属性を付与
Range("C4").Value = GenerateHtmlElement("Excel & VBA > HTML", "div", Array(Array("id", "main-box"), Array("class", "content body")))
MsgBox "HTML生成が完了しました。"
End Sub
コードのポイント解説
① Optional引数とIsMissing関数
Function GenerateHtmlElement(ByVal content As String, _
Optional ByVal tagName As Variant, _
Optional ByVal attributes As Variant) As String
この関数の柔軟性を実現しているのが**Optional
キーワードです。引数の前にOptional
を付けると、その引数は「省略可能」**になります。
Optional
な引数が、関数呼び出し時に実際に指定されたかどうかは**IsMissing()
**関数で判定します。
If IsMissing(tagName) = False Then
' tagNameが指定された場合の処理
End If
このように、IsMissing()
を使って処理を分岐させることで、引数の数に応じて関数の振る舞いを変えることができます。
② 属性を配列で渡すテクニック
Array(Array("id", "main-box"), Array("class", "content body"))
複数の属性(id
とclass
など)を一度に渡すため、**「配列の中に配列を入れる」**という構造(二次元配列やジャグ配列とも呼ばれます)を利用しています。
- 外側の
Array
: 属性全体のリスト - 内側の
Array
: 一つの属性の「名前」と「値」のペア
VBAコード側では、この構造をFor
ループで処理します。
For i = 0 To UBound(attributes)
' attributes(i)(0) で属性名、attributes(i)(1) で属性値を取得
htmlString = AddAttribute(htmlString, CStr(attributes(i)(0)), CStr(attributes(i)(1)))
Next i
これにより、いくつでも属性を柔軟に追加できるようになっています。
③ これまでの関数の集大成
このGenerateHtmlElement
関数は、それ自体が複雑な処理を行うのではなく、これまで作ってきた専門的なヘルパー関数(EncodeToHtml
, WrapWithTag
, AddAttribute
)を、**適切な順序で呼び出す「司令塔」**の役割を果たしています。
- まず、必ず
EncodeToHtml
を実行して入力を安全にする。 - もし
tagName
があれば、WrapWithTag
を呼び出す。 - もし
attributes
があれば、AddAttribute
をループで呼び出す。
このように、機能を部品化(関数化)し、それらをまとめる上位の関数を作ることで、コード全体が非常に整理され、理解しやすくなります。
まとめ
Optional
引数を活用することで、一つの関数に複数の機能を持たせ、様々な状況に対応できる、柔軟で使い勝手の良い「万能関数」を作成することができます。
また、小さな専門関数を組み合わせてより大きな機能を実現するアプローチは、VBAプログラミングにおける可読性やメンテナンス性を向上させるための非常に重要な設計思想です。