PythonでExcelのセルの値を参照するときの注意点

[Python for Windows Extensions(pywin32)](https://pypi.python.org/pypi/pywin32)を利用してPythonのプログラムを作ると、Excelの報告書とかで、こっちのファイルを少し変更して似たようなファイルを作成するとか、いくつかのファイルを一つのファイルにまとめる、とかやっていることは単純なんだけど面倒で、しかもまったく生産性がないような作業を自動化することができるようになります。

pywin32を使うと[ここ(Win32 API の利用方法)](https://msdn.microsoft.com/ja-jp/library/cc440903.aspx)に書いてあるAPIをPythonから呼び出せるようになります。Excelのセルの値を参照するときに、呼び出し方法で参照される値と型が変わります。サンプルのデータを以下の呼び出し方法で参照した場合に、どのような型で値を取得できるのかをまとめました。

- セルをstrに変換
- valueプロパティ
- value2プロパティ
- textプロパティ
- formulaプロパティ

![サンプルデータ.png](https://qiita-image-store.s3.amazonaws.com/0/145530/c0380718-1c91-de0c-fd2d-7f0a6967852c.png "サンプルデータ")

プログラムは[こちら](https://gist.github.com/kubotama/ffd2f287dced63d87e77292732ad957d)に置きました。

# 文字列

```
文字列 文字列
str: ABCDEFG <class 'str'>
value: ABCDEFG class 'str'>
value2: ABCDEFG <class 'str'>
text: ABCDEFG <class 'str'>
formula: ABCDEFG <class 'str'>
```

文字列が入っているセルを取得した結果は、どれでも変わらないです。

# 数値

数値の場合はセルに割り当てられている書式で結果が変わりますので書式ごとに確認します。

## 標準フォーマット

```
数字 標準
str: 123456789.0 <class 'str'>
value: 123456789.0 <class 'float'>
value2: 123456789.0 <class 'float'>
text: 123456789 <class 'str'>
formula: 123456789 <class 'str'>
```

strで変換する場合とvalue, value2プロパティは同じに見えますが型が違います。数値としての値が必要な場合にはvalueプロパティ、文字列が必要な場合にはtextプロパティがよさそうです。

## 数値フォーマットで桁区切りあり

```
数値 数値、桁区切り
str: 123456789.0 <class 'str'>
value: 123456789.0 <class 'float'>
value2: 123456789.0 <class 'float'>
text: 123,456,789  <class 'str'>
formula: 123456789 <class 'str'>
```

標準フォーマットと似ていますが、textプロパティだけ桁区切りのカンマが入っています。

# 通貨フォーマットで記号が￥、小数点以下0桁

```
数値 通貨、記号\、小数点0桁
str: 123456789 <class 'str'>
value: 123456789 <class 'decimal.Decimal'>
value2: 123456789.0 <class 'float'>
text: ¥123,456,789 <class 'str'>
formula: 123456789 <class 'str'>
```

通貨フォーマットの場合、valueプロパティはdecimal.Decimal型になります。textプロパティのみ、記号と桁区切りが入っています。

# 通貨フォーマットで記号が￥、小数点以下2桁

```
数値 通貨、記号\、小数点2桁
str: 123456789.12 <class 'str'>
value: 123456789.12 <class 'decimal.Decimal'>
value2: 123456789.12 <class 'float'>
text: ¥123,456,789.12 <class 'str'>
formula: 123456789.12 <class 'str'>
```

小数点の有無は関係ないようです。

## 会計フォーマットで記号が￥、小数点以下0桁

```
数値 会計、記号\、小数点0桁
str: 123456789 <class 'str'>
value: 123456789 <class 'decimal.Decimal'>
value2: 123456789.0 <class 'float'>
text:  ¥        123,456,789  <class 'str'>
formula: 123456789 <class 'str'>
```

通貨フォーマットとの違いはtextプロパティで記号と数値の間にスペースが入ります。スペースの数はセルの幅が反映されるようです。

## 会計フォーマットで記号が￥、小数点以下2桁

```
数値 会計、記号\、小数点2桁
str: 123456789.12 <class 'str'>
value: 123456789.12 <class 'decimal.Decimal'>
value2: 123456789.12 <class 'float'>
text:  ¥   123,456,789.12  <class 'str'>
formula: 123456789.12 <class 'str'>
```
会計フォーマットも小数点以下の有無は関係ないようです。

## パーセンテージで小数点以下2桁

```
数値 パーセンテージ、小数点以下2桁
str: 123456789.0 <class 'str'>
value: 123456789.0 <class 'float'>
value2: 123456789.0 <class 'float'>
text: 12345678900.00% <class 'str'>
formula: 123456789 <class 'str'>
```

# 日付

## グレゴリオ暦

```
日付 日付、グレゴリオ暦
str: 2017-10-02 00:00:00+00:00 <class 'str'>
value: 2017-10-02 00:00:00+00:00 <class 'pywintypes.datetime'>
value2: 43010.0 <class 'float'>
text: 2017/10/2 <class 'str'>
formula: 43010 <class 'str'>
```

valueプロパティは日付らしい型に変換されていますが、pywintypesモジュールはpywin32で提供されているようで詳しい情報が見当たらないのとタイムゾーンが正しくないため、利用するには一手間かかりそうです。textプロパティは書式でで指定されたフォーマットの文字列が取得できます。

## 和暦

```
日付 日付、和暦
str: 2017-10-02 00:00:00+00:00 <class 'str'>
value: 2017-10-02 00:00:00+00:00 <class 'pywintypes.datetime'>
value2: 43010.0 <class 'float'>
text: 平成29年10月2日 <class 'str'>
formula: 43010 <class 'str'>
```

textプロパティは元号が入っています。

# 時刻

```
時間 時刻
str: 0.4875 <class 'str'>
value: 0.4875 <class 'float'>
value2: 0.4875 <class 'float'>
text: 11:42:00 <class 'str'>
formula: 0.4875 <class 'str'>
```

時刻はvalueプロパティはシリアル値を取得します。textプロパティはセルに定義されているフォーマットの文字列を取得します。

# 式

C13のセルに=D13+E13という式が設定されています。

```
式 標準、=D13+E13
str: 579.0 <class 'str'>
value: 579.0 <class 'float'>
value2: 579.0 <class 'float'>
text: 579 <class 'str'>
formula: =D13+E13 <class 'str'>
```

formulaプロパティで設定されている式を取得できます。それ以外の方法では式の計算結果の値を取得します。

# まとめ

以上をまとめると、以下の通りです。

- 設定されている式を取得したければformulaプロパティ
- 見た目のままの文字列を取得したければtextプロパティ
- 値を取得したければvalueプロパティ

ただしvalueプロパティはフォーマットによって型が変わることに注意する必要がありそうです。また、プロパティを指定しないでセルのオブジェクトをstrで変換した場合にはvalueプロパティが利用されているようです。