Excelで1セル内に複数の書式(フォント)が混在するようなものをPythonで扱いたい

# この記事の対象

タイトルにある「**1セル内に複数の書式が混在するようなもの**」とは、下図スクリーンショットの**A2**セルのようなものを想定しています。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/96294ea0-9d1a-3b5a-77da-1ad6cb3452a7.png)

そして、本記事でやりたいことは、以下の2つです。（できるとは言っていない）

1. 書式の違いを保持した状態でセルの値を<font color="Red">読み取りたい</font>（既存ファイルから）
2. 1つのセルに対して複数の書式が混在した値を<font color="Red">書き込みたい</font>（新規ファイルへ）

というわけで、簡単に調べてみました。

# 結論

1.<font color="Red">読み込み</font>は**難しく**、2.<font color="Red">書き込み</font>は**できそう**といった感じでした。また、読み込みに関しては、将来的にはできるようになるかもという状態でした。

（もし、読み込みの方法をご存知の方がいらっしゃいましたらご指摘ただければ幸いです。）

# 複数書式の考え方

調べた感じ、おそらく、1つのセルの中の値は、[プレーンテキスト](https://ja.wikipedia.org/wiki/プレーンテキスト)ではなく、[リッチテキスト](https://ja.wikipedia.org/wiki/Rich_Text_Format)で格納されているものと思われます。よって、Excelのリッチテキストに対応したPythonライブラリがあれば、やりたいことが叶いそうです。

# OpenPyXLの対応状況

xlsxファイルの読み書きをするライブラリで有名なの物の1つに、[OpenPyXL](https://openpyxl.readthedocs.io/)があります。しかし、2019/6/22現在、OpenPyXL（Version 2.6.2）はリッチテキストの読み書きには対応していなさそうです。（[Issue](https://bitbucket.org/openpyxl/openpyxl/issues/340/cell-styles-that-have-multiple-font)に理由等が記されています。（英語））

しかし、需要はあるようで、BitBucket上で議論はされています（[#224 Support of rich text in cells](https://bitbucket.org/openpyxl/openpyxl/pull-requests/224/)）。本プルリクエスト内のスレッドを読む感じですと、将来的には実装されるかもしれません。今後に期待。

このスレッド内でも言及されていますが、別ライブラリとして、[XlsxWriter](https://xlsxwriter.readthedocs.io/index.html)であれば、リッチテキストに対応しているみたいです。

# XlsxWriterでリッチテキストを扱う（書き込み限定）

XlsxWriterは、名前を見てもわかる通り、書き込みオンリーです。既存のファイルを読み込んだりはできません。

公式で、[リッチテキストを追加するサンプル](https://xlsxwriter.readthedocs.io/example_rich_strings.html)がありました。

それにならって、冒頭のスクショのようなセルを作りたければ、下記のようなコードとなります。コメントも併せてご覧ください。

```python
import xlsxwriter

## 準備
workbook = xlsxwriter.Workbook('TestFile2.xlsx') # 新規xlsxファイル作成
worksheet = workbook.add_worksheet()             # ワークシートの追加

## 書式の準備
red = workbook.add_format({'color': 'red'})                                     # 赤色
italic_underline = workbook.add_format({'italic': True, 'underline': True})     # 斜体と下線
bold = workbook.add_format({'bold': True})                                      # 太字
superscript = workbook.add_format({'font_script': 1})                           # 上付き文字（2にすると下付き文字）
superscript_purple = workbook.add_format({'font_script': 1, 'color': 'purple'}) # 紫色の上付き文字

## リッチテキストをA1セルに追加
worksheet.write_rich_string('A1', # セルを指定
                            'いろんな', # 基本的には、ひたすら引数に追加したい文字列を並べる
                            red, 'フォント', # 書式を設定したい場合は、書式オブジェクトを引数に加えると、直後の文字列のみその書式が適用される
                            '(', # 直前に書式オブジェクトが無い場合は、デフォルトの書式になる
                            italic_underline, '書式',
                            ')が',
                            bold, '混在',
                            'するセル',
                            superscript, '上付き',
                            superscript_purple, '文字')

## ファイルを閉じる
workbook.close()
```

上記のコードを実行すると、下図のようなxlsxファイルが出力されます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/3492b356-0438-079c-14fa-37942b3e1cf0.png)

worksheetオブジェクトに対して、`write_rich_string()`メソッドを呼ぶと、リッチテキストで値を書き込むことができます。

## 補足

### 設定できる書式の種類

workbookオブジェクトに対して、`add_format()`メソッドを呼ぶと、返り値としてFormatオブジェクトが返ってきますが、このFormatオブジェクトに設定できる書式は、[公式ドキュメントにいろいろ書かれています](https://xlsxwriter.readthedocs.io/format.html)ので、そちらをご覧ください。（英語）

### セル指定方法

上記コードでは、`write_rich_string()`メソッドの第1引数で`'A1'`というようなセル指定をしており、第2引数以降に、文字列や書式を設定しています。

代わりに、下記コードのように、行と列のインデックス番号で指定することもできます。第1引数は行番号（0始まり）、第2引数は列番号（0始まり）です。

```python
## リッチテキストをA1セルに追加
worksheet.write_rich_string(3,4, # この場合、E4セルを指定していることになる
                            'いろんな',
                            red, 'フォント',
                            '(',
                            italic_underline, '書式',
                            ')が',
                            bold, '混在',
                            'するセル',
                            superscript, '上付き',
                            superscript_purple, '文字')
```

この場合、第3引数以降が、設定したい文字列や書式になります。