t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

VBA 数値をふりがなに変換するマクロ

今回のマクロは、数値をふりがなに変換するマクロの紹介。
例えば1なら「いち」、290なら「に / ひゃく / きゅう / じゅう」という具合だ。

これの何が難しいかというと、単純に数値の読み「1~9」と位の読み「じゅう・ひゃく・せん」を組み合わせればできるというものでもないってところ。

たとえば8は「はち」。
800は?

はちひゃくと呼んでも意味は伝わるけど、普通は「は / ゃく」だ。
2000は、「に / せん」。
3000は?

「さん & ぜん」と読む。

色々整理したところ、例外も含めた規則が分かってきたのでコードに落とし込んでみた。

規則

  • 1の位は普通に読む。
  • 1の位以外の位に「1」が出てきたら「いち」は読まずに位だけを読む。
  • ある位に「0」が出てきたら、読まずに次の位に移る。
  • 百の位が3の場合、位は「びゃく」と読む
  • 百の位が6の場合、6は「ろっ」と読み、位は「ぴゃく」と読む。
  • 百の位が8の場合、8は「はっ」と読み、位は「ぴゃく」と読む。
  • 千の位が3の場合、位は「ぜん」と読む。
  • 千の位が8の場合、8は「はっ」と読む。
  • 万より上の位は普通。ただし一万を超える値において千の位に「1」が来た場合、「いっ」と読んでも良い。

コード

出力シートのオブジェクト名はOutputSheetに変更したうえで、標準モジュールに次のコードを書いて実行する。

Option Explicit
Sub NumberToPronounciation()
    Dim numWord: numWord = Split("ぜろ いち に さん よん ご ろく なな はち きゅう")
    
    Dim i
    For i = 0 To 9999
        Dim numAsText: numAsText = Format(i, "0000")
        Dim thousandsPlace: thousandsPlace = Int(Mid(numAsText, 1, 1))
        Dim hundredsPlace: hundredsPlace = Int(Mid(numAsText, 2, 1))
        Dim tensPlace: tensPlace = Int(Mid(numAsText, 3, 1))
        Dim onesPlace: onesPlace = Int(Mid(numAsText, 4, 1))
        
        Dim c As Collection: Set c = New Collection
        Select Case thousandsPlace
        Case 0
            'Do nothing
        Case 1
            c.Add "せん"
        Case 3
            c.Add "さん"
            c.Add "ぜん"
        Case 8
            c.Add "はっ"
            c.Add "せん"
        Case Else
            c.Add numWord(thousandsPlace)
            c.Add "せん"
        End Select
        
        Select Case hundredsPlace
        Case 0
            'Do nothing
        Case 1
            c.Add "ひゃく"
        Case 3
            c.Add "さん"
            c.Add "びゃく"
        Case 6
            c.Add "ろっ"
            c.Add "ぴゃく"
        Case 8
            c.Add "はっ"
            c.Add "ぴゃく"
        Case Else
            c.Add numWord(hundredsPlace)
            c.Add "ひゃく"
        End Select

        Select Case tensPlace
        Case 0
            'Do nothing
        Case 1
            c.Add "じゅう"
        Case Else
            c.Add numWord(tensPlace)
            c.Add "じゅう"
        End Select
        
        Select Case onesPlace
        Case 0
            If c.Count = 0 Then
                c.Add "ぜろ"
            End If
        Case Else
            c.Add numWord(onesPlace)
        End Select
        
        Dim result As String: result = ""
        Dim j
        For j = 1 To c.Count
            result = result & c(j)
        Next
        OutputSheet.Cells(i + 1, 1).Value = i
        OutputSheet.Cells(i + 1, 2).Value = result
    Next
End Sub

実行結果

こんな感じで出力される。
f:id:t-hom:20191013215453p:plain
※ブログ用に画像加工で横に並べてますが出力はA列とB列だけです。

実際にやりたかったこと

実際にやりたいのは、Raspberry Piを使った数値の音声読み上げである。1.wav~9.wav, jyu.wav, hyaku.wav, sen.wavのように予め発話用のwavファイルを用意しておき、それらを組み合わせて数値を発音させる。

「体重データをもとに、必要エネルギーを計算します。あなたの体重は」
「はち」
「じゅう」
「よん」
「てん」
「に」
「キロです。」
「1カ月あたり1キロやせたい場合、本日の摂取エネルギーの上限は」
「に」
「せん」
「さん」
「びゃく」
「ろく」
「じゅう」
「なな」
「キロカロリーです。」

そんなことしなくてもLinuxにはフリーの音声合成もあるので、リアルタイムで数字そのまま読み上げさせることもできるんだけど、どうにも声が気に入らないし、購入済のVOICEROIDで作ったwavファイルと連続で読み上げさせるので、数値だけ別の声というのも違和感がある。それで検討した結果、wav組み合わせ方式を採用することにした。

一応、得意なVBAでの検証が済んだのでこのあとPythonコードに翻訳し、「いち」や「に」等の出力の代わりに「1.wav」「2.wav」を再生するように改変して出来上がりの予定。

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