1. はじめに
Excel/VBA の文字列の書式指定関数といえば WorksheetFunction.Text
関数や Format
関数がありますが、これらはいずれも変換対象となる文字列をひとつしか指定できません。
私は書式指定する際は複数の文字列を書式変換しつつ結合・埋込することが多く、いちいち &
でつなぐのが煩わしく感じるうえにコードも見づらくなるので、printf
のような関数を Windows の VBA 環境で使えたら楽なのにな~と思うことがけっこうあります。
2. 環境
私の環境は次のとおりです。
- OS : Windows 10
- Office : Excel 2016
3. 書式を指定して出力する方法
3.1. WorksheetFunction.Text を使う
Excel で書式指定するといえばこれです。この関数の弱いところが、冒頭でふれた、引数が2つ固定という点です。複数個カンマ区切りで表記したい数値がある場合は =TEXT(4001, "#,###")&TEXT(1234, "#,###")
のように &
でつながなくてはなりません。
また、 printf
とは引数の並び順が逆で、個人的には割とよく間違えます。あと printf("%7d", 1200)
とか printf("%7.3f", 125.05)
などが VBA でどう書けば楽かがわからない。
3.2. Format を使う
WorksheetFunction.Text
と Format
の違いが正直よくわかりません。受取る引数の並び順、指定できる引数が2つ固定など基本同じ関数だと考えてもいいんでしょうかね?
3.3. MSYS/MinGW の printf を使う
MSYSやMINGWのprintfを WSH 経由でむりやり呼出すことができます。こちらで紹介されているコードを拝借しました。
Public Function Sprintf(ByVal format_ As String, ParamArray args() As Variant) As String
Dim wsh As Object
Dim wsh_exec As Object
Dim result As String
Dim params As String
Dim arg As Variant
For Each arg In args
params = params & " " & CStr(arg)
Next arg
Set wsh = CreateObject("WScript.Shell")
Set wsh_exec = wsh.Exec("C:\tools\msys64\mingw64\bin\printf " & format_ & " " & params)
Do While wsh_exec.Status = 0
DoEvents
Loop
Sprintf = wsh_exec.StdOut.ReadAll
Set wsh_exec = Nothing: Set wsh = Nothing
End Function
エスケープシーケンスを使用して改行やタブを表現できますが、実行するたびに、画面上に一瞬DOS窓が表示されてしまいます。
3.4. .NET Framework の StringBuilder を使う
最近の Windows ならほぼ間違いなく入っている(と思う) .NET Framework に、 COM として呼出せる System.Text.StringBuilder
クラスがあります。通常は文字列の連結に用いられるクラスですが、このクラスには書式指定しつつ文字列を結合する AppendFormat
というメソッドがあります。このメソッドを文字列の結合ではなく、書式設定のために使ってしまおうというわけです。
Microsoft のリファレンス を見るとオーバーロードがたくさんあります。こちらで VBA での StringBuilder
のラッパを公開されていますが、このうちの AppendFormat_4
を利用すれば、結合する引数の数にかからわず統一的にあつかえるので楽そうですね。
' System.Text.StringBuilder AppendFormat_4(string format, Params System.Object[] args)
Dim str_builder As Object: Set str_builder = CreateObject("System.Text.StringBuilder")
Debug.Print str_builder.AppendFormat_4("{0}の最強の具は{1}である。", Array("おにぎり","筋子")).ToString
' => "おにぎりの最強の具は筋子である。"
StringBuilder
を利用すれば、こちらの関連項目に貼られているリンク先にあるような豊富な種類の書式が指定できるようになります。
3.5. その他
VBA printf
などで Google 検索をかけてみると、こちらでも自作の printf
を公開されていますし、スタックオーバーフローでも質問が上がっています。やっぱりある程度の需要はあるんでしょうかね。
あとは自作という手もありますが…。
4. おわりに
多彩な書式を利用しつつ printf
的に複数個の引数を渡すなら、 StringBuilder
がよさそうです。
私がしょっちゅう使うのは =TEXT(505001, "#,###")
(→ 505,001
) のような数値のカンマ区切りや、 =TEXT(12345, "00000000")
のゼロ埋桁指定、 =TEXT(42865, "ggge年m月n日")
(→ 平成29年5月10日
) といった日付の書式指定(特に和暦表記)なので、普通に printf
を使っても指定できない書式なんですよね。おとなしく Format
を使っておきましょうかね…。