【Python】ExcelのセリフシートをWordの縦書き台本に変換する

# 1.やりたいこと
こんな感じでExcelに書かれたセリフシートを、Wordの縦書き台本に変換します。



| ＜キャラクター紹介＞| |
|:-:|:-:|
| 自己紹介|はじめまして！　オレは猫だ！　よろしくな。<br>えっ名前？　まだ無いんだ、すまない|
| 朝のあいさつ| おはよう！　今日も元気そうだな        |
| 昼のあいさつ| ふぁ～　ちょっと眠いな|
|夜のあいさつ|疲れた～！　今日はもう終わりにしよう。また明日な！|


# 2.準備
縦書きの収録台本として、今回は配布されている「[映画用脚本・シナリオ・ワード・テンプレート](http://deerstudio.jp/inc/downloads/film-and-video/script-microsoft-word-template.html)」を利用します。
テンプレートを開き、中の文章を全部クリアした後docx形式で保存し直します。
このテンプレートにはスタイルが複数種類登録されていて、今回は「台詞」と「柱・シーン」というスタイルを利用することにします。

### importするライブラリ
またExcelの読み込みにPythonのopenpyxlを、Wordの読み書きにdocxを使うので、必要に応じてpip installします。
文字列置換も利用するのでimportは下記の3つになります。

```python
import openpyxl
import docx
import re
```

### Wordのリスト番号を拡張する
Wordのリスト書式で丸囲い数字を使う場合、①～⑳までしか対応していません。
代替として、行頭に丸囲い数字を入れる関数toCircledを作り、行頭に追加することにします。
ベースは[こちら](https://qiita.com/taqm/items/144d707caedd69070970)を参考にしました。
これで1～50までは丸囲い数字のリスト風に番号を出力することができます。


```python
#=========================================================================================
# 数字を丸囲い数字に変換
#=========================================================================================
def toCircled(num):

    if num <= 0 or num > 50:
        #1～50以上は丸囲い数字がないので文字列にして戻す  
        return str(num)

    if num <= 20:
        return chr(ord('①') + num -1)
    
    if num <= 35:
        return chr(ord('㉑') + num -21)

    if num <= 50:
        return chr(ord('㊱') + num -36)
```

### 一部文字の変換
また不等号記号は縦書きに対応していないため、山括弧に変換します。

```python
#=========================================================================================
# 大なり小なりを山括弧に変換
#=========================================================================================
def repSign(str):
    str = str.replace("＜","〈")
    str = str.replace("＞","〉")
    return str

```

# 3.処理

主な処理を書いていきます。
FILENAMEにはExcelのファイル名を、WORD_TEMPLATEにはテンプレートのdocxファイルが指定されています。
表で言う左の部分を太字、右の台詞は装飾なしで書き出します。

```python
    #ベースとなるセリフシートを読み込み
    wb = openpyxl.load_workbook(FILENAME)

    #ワークシートの分だけ処理する
    for ws in wb.worksheets:

        #テンプレートのWordファイル読み込み
        doc = docx.Document(WORD_TEMPLATE)
        num = 1

        #1行目から5行目までを処理してみる
        for r in range(1,5):

            if ws.cell(r,1).value == None:
                continue

            #2列目にセリフがある場合
            if ws.cell(r,2).value != None:

                #項目部分は太字
                p = doc.add_paragraph()
                style = p.add_run(toCircled(num) + " " + repSign(ws.cell(r,1).value))
                style.bold = True
                style.font.name = "ＭＳ 明朝"
                p.style = "台詞"
                

                #採番をインクリメント
                num += 1

                #セリフを挿入
                p = doc.add_paragraph()

                #行末の句読点を削除し、鍵括弧で挟んで挿入する
                style = p.add_run("　「" + re.sub('。$','',repSign(ws.cell(r,2).value)) +"」")
                style.font.name = "ＭＳ 明朝"
                p.style = "台詞"

                p = doc.add_paragraph()
                p.style = "台詞"                
                

            #セリフがない場合は柱として扱う
            else:
                #doc.add_page_break()
                p = doc.add_paragraph(repSign(ws.cell(r,1).value),style="柱・シーン")

                #採番をリセット
                num = 1


        #ワークシート名で台本を保存
        doc.save(ws.title + '.docx')

```

# 4.補足
インデントなどは個々人で使いやすい設定があると思うので、テンプレートのスタイルを変更することをおすすめします。
また表紙などに横書きのものを入れたい場合、Word内で1x1の表を作り、そこにテキストを挿入する方法が簡単です。
（docxではテキストボックスを取得できないようです）
表にテキストを挿入する注意点として、fontで日本語フォントを指定するだけでは反映されないことがあります。
その際は「[Python-docxで日本語フォントを使いたい](https://qiita.com/shrimp-f/items/893adf2768fb62d584e2)」を参考にしてみてください。