概要
Wordで教材を作るために、大量のテキストにルビを振りたい(ふりがなを設定したい)。しかし、Wordのルビ機能は貧弱なためほぼ手作業になり時間がかかる。そこで、ChatGPTとWord VBAを使って、ルビ振りの半自動化を目指した。
成果
- ChatGPTでそこそこの精度でルビを振ることができた
- Wordの機能を使ったふりがな設定はほぼ自動化できた
要約
- Wordでのルビ振りは精度が低く、一括処理が難しい
- ChatGPTなら自然なルビ振りが一括でできる
- Wordに貼り付けたChatGPTの出力から、自動でルビ設定するVBAのコードを書いた
背景
Wordのルビ振りにはいくつかの問題点があり、とても時間がかかる。教材作成のため数千字にルビを振る必要があり、時間を短縮したかった。
やったこと
1. 文章を用意する
あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。
2. ChatGPTでルビを振る
ChatGPTにルビを振るように指示し、文章を入力した。
今回はChatGPT 4を使ったが、ChatGPT 3.5でもおそらくそんなに変わらないと思う。プロンプトは次のようにした。
入力された文章に対して、 #青空文庫形式 でルビを振ってください。
熟語には、 #熟語のルビの例 のようにまとめてルビを振ってください。
送り仮名がある場合は、 #送り仮名のある場合の例 のように、漢字部分のみにルビを振るようにしてください。
#注意事項 を守って出力してください。
#青空文庫形式
|漢字《かんじ》
#熟語のルビの例
- 「初夏」→「|初夏《しょか》」
#送り仮名のある場合の例
- 「越えて」→「|越《こ》えて」
#注意事項
- すべての漢字に対してルビを振る。
- ひらがな、カタカナ、アルファベットにはルビを振らない。
- 可能であれば、意味の解釈が必要な部分では最も一般的な読み方を選ぶ。
- ルビ付きの文章のみを出力する。
- ルビを追加する以外の改変はしない。
- 読みが分からず、どうしてもルビを振れないときはそのままにしてよい。
あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。
あの|イーハトーヴォ《イーハトーヴォ》のすきとおった|風《かぜ》、|夏《なつ》でも|底《そこ》に|冷《つめ》たさをもつ|青《あお》いそら、うつくしい|森《もり》で|飾《かざ》られたモリーオ|市《し》、|郊外《こうがい》のぎらぎらひかる|草《くさ》の|波《なみ》。
「イーハトーヴォ」が漢字の熟語としてルビを振られてしまっているが、気にしないこととする。どうせルビに正解があるとは限らないので、最終的には人がチェックし、気に入らない部分は直すことになる。ここでは95%程度が自動で処理されれば御の字と考えてスルーする。
3. Wordに貼り付ける
ChatGPTで出力されたルビ付きのテキストをWordに貼り付ける。このように、Wordのテキストにルビを設定するわけではないので、教材づくりのプロセスは少し変える必要があった。
4. VBAでルビを設定する
貼り付けた青空文庫形式のルビ付きテキストをもとに、Wordのルビ機能でルビを設定する。文書全体を見て、青空文庫形式のルビを見つけたら、それをもとにルビを設定するコードを書いた(ChatGPTが)。
Sub ApplyRubyToAll()
Dim regex As Object
Dim matches As Object
Dim match As Variant
Dim rubyText As String
Dim mainText As String
Dim startPos As Long, endPos As Long
' 正規表現オブジェクトの作成
Set regex = CreateObject("VBScript.RegExp")
With regex
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = "|(.*?)《(.*?)》" ' 青空文庫形式のルビを探す正規表現
End With
' ドキュメント内の全てのテキストに対してルビを適用
For i = ActiveDocument.Paragraphs.Count To 1 Step -1
Set para = ActiveDocument.Paragraphs(i)
If regex.Test(para.Range.Text) Then
Set matches = regex.Execute(para.Range.Text)
' 最後のマッチから処理を開始
For j = matches.Count - 1 To 0 Step -1
Set match = matches(j)
mainText = match.SubMatches(0) ' ルビを振る対象のテキスト
rubyText = match.SubMatches(1) ' ルビのテキスト
startPos = match.FirstIndex + 1
endPos = startPos + Len(match.Value) - 1
' ルビのテキストを含む範囲を選択
With para.Range
.Start = startPos - 1
.End = endPos
.Text = mainText ' ルビ記号とルビテキストを主テキストで置換
.PhoneticGuide Text:=rubyText ', Alignment:=wdPhoneticGuideAlignmentOneTwoOne, Raise:=10, FontSize:=5, FontName:="BIZ UDPゴシック"
End With
Next j
End If
Next i
End Sub
今後の課題
残る問題はいろいろあるが、手動よりはだいぶましな結果になった。
問題点
- まれに本文が改変されることがある
- カタカナにルビが振られることがある
- 生成AIを利用している(私の所属では使用が面倒)
記事を書いている中で、Yahoo! JAPANがルビ振りAPIを提供していることを知った。これを使ったほうがいい気がする。
続編