LoginSignup
6
8

More than 5 years have passed since last update.

[Excel/VBA] 文字列の書式指定出力・埋込

Last updated at Posted at 2017-05-11

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.TextFormat の違いが正直よくわかりません。受取る引数の並び順、指定できる引数が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 を使っておきましょうかね…。

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8