t-hom’s diary

主にVBAネタを扱っているブログです。

VBAで、C言語のprintfのように\nと%sをサポートする関数を作る。

今回はVBAC言語のprintfもどきをやってみたいと思う。

※ちなみに\は円マークである。環境によってはバックスラッシュに見えるかと思うが、間違えてスラッシュにならないよう注意。

C言語を知らない方向けに

Cのprintf命令は、print formattedから名前がつけられており、その名の通りフォーマットして出力される。
たとえば\nは改行に、%sは第二引数以降の文字列に置換される。

Cのprintfは以下のように使う。

char	str1[] = "Unknown";
char	str2[] = "thom";
printf("はじめまして%sさん。\n私は%sと申します。\n\nどうぞよろしくお願いいたします。", str1, str2);

すると、次のように出力される。

はじめましてUnkownさん。
私はthomと申します。

どうぞよろしくお願いいたします。

これをVBで普通にやろうとすると、こう書く必要がある。

MsgBox "はじめまして" & str1 & "さん。" & vbNewLine & _
    "私は" & str2 & "と申します。" & vbNewLine & vbNewLine & _
    "どうぞよろしくお願いいたします。"

まあ、実にVBらしいコードで別に嫌いではないけれど、文字列の処理が多くなってくると面倒くさい。そこで今回はCのようにフォーマットできるFunctionプロシージャを作成してみた。

仕様

  • 出力するのではなく、あくまで文字列を返すだけ。
  • サポートするのは\nと%sだけ。%dや%5.1fなどの細かい指定はやらない。
  • エスケープをサポートしない。(特定用途のみ)

実装

実際のコードはこちら。

Public Function CStyle(ByVal st As String, ParamArray args() As Variant) As String
    st = Replace(st, "\n", vbNewLine)
    Dim s() As String: s = Split(st, "%s")
    If (UBound(args) + 1) <> UBound(s) Then
        Err.Raise 1000, "CStyle", "CStyle関数:" & _
            "%sの数と引数の数が一致していません。"
        CStyle = st
        Exit Function
    End If
    
    Dim buf As String: buf = s(0)
    Dim i As Integer
    For i = 0 To UBound(args)
        buf = buf & args(i) & s(i + 1)
    Next i
    
    CStyle = buf
End Function

そして、上のコードを利用したサンプル

Sub Sample()
    Dim str1: str1 = "Unknown"
    Dim str2: str2 = "thom"
    MsgBox CStyle("はじめまして%sさん。\n私は%sと申します。\n\nどうぞよろしくお願いいたします。", str1, str2)
End Sub

少しスッキリ書けるようになる。ただし、わかりやすいかどうかと言えば、C言語風のフォーマットになれているかどうかによる。英文の中に現れると少しややこしく見えるかもしれない。

"Hello, %s.\nMy name is %s.\nNice to meet you.", str1, str2

それと、前述したようにエスケープはサポートしていない。
エスケープとは、\nそのものを出力したいときにCなら\\nと書けば良いが、この関数では\と改行に変換されてしまう。
これを回避するには、\nを%sとしておいて、第二引数以降に"\n"を渡してやれば良い。
次がそのサンプルである。

MsgBox CStyle("%sと%sの出力テスト", "\n", "%s")

Cの場合は他にも\tでタブ文字、\"でダブルクォートを出力する機能がある。
この関数を改良すれば似たようなことが出来るので興味がある方は試してみてほしい。

\"は困難だが、\qを""に置換する等は簡単にできる。
たとえば次のコードはダブルクォートの数が多くて分かりづらい。

Sub WQuoteTest()
    str1 = "Sample"
    MsgBox """ダブルクォートで囲むテストです。""" & _
        vbNewLine & """" & str1 & """" & vbNewLine & _
        """""ダブルクォート2個ずつで囲むテストです。"""""
End Sub

このように書けたら。。

Sub WQuoteTest()
    str1 = "Sample"
    MsgBox CStyle("\qダブルクォートで囲むテストです。\q\n" & _
        "\q%s\q\n" & _
        "\q\qダブルクォート2個ずつで囲むテストです。\q\q", str1)
End Sub

。。相変わらず分かりづらいが、多少ダブルクォートがカウントしやすい気がする。


このように、実務でVBAしか触らない場合でも他の言語から得た知識がヒントになる場合があるので、レベルアップを目指したい方は色々やってみると良いと思う。

やさしいC 第4版 (「やさしい」シリーズ)

やさしいC 第4版 (「やさしい」シリーズ)

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。