【Excel VBA】HTMLを自在に生成する「万能関数」の作り方 (Optional引数)

これまでの記事で、「特殊文字のエスケープ」「タグで囲む」「属性の追加」といった、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"))

複数の属性(idclassなど)を一度に渡すため、**「配列の中に配列を入れる」**という構造(二次元配列やジャグ配列とも呼ばれます)を利用しています。

  • 外側の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)を、**適切な順序で呼び出す「司令塔」**の役割を果たしています。

  1. まず、必ずEncodeToHtmlを実行して入力を安全にする。
  2. もしtagNameがあれば、WrapWithTagを呼び出す。
  3. もしattributesがあれば、AddAttributeをループで呼び出す。

このように、機能を部品化(関数化)し、それらをまとめる上位の関数を作ることで、コード全体が非常に整理され、理解しやすくなります。


まとめ

Optional引数を活用することで、一つの関数に複数の機能を持たせ、様々な状況に対応できる、柔軟で使い勝手の良い「万能関数」を作成することができます。

また、小さな専門関数を組み合わせてより大きな機能を実現するアプローチは、VBAプログラミングにおける可読性やメンテナンス性を向上させるための非常に重要な設計思想です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次