Python で Excel の数式を追加する、または読み取る

Excel の数式はデータ処理の核心的なツールです。単純な足し算や引き算から複雑な論理判定に至るまで、基礎の構文を習得することは、効率的な作業の出発点です。例えば、SUM 関数を使って迅速に合計を求めたり、IF 関数を使って条件判定を行ったりすることができます。数式を使ってデータを計算することで、手作業による計算の誤り率を減らすことができます。本文では、Python を使って Excel に様々な数式/関数を追加する方法、または Excel の数式を読み取る方法について紹介します。
* [Python を使ってExcelに数式/関数を追加する](#python-を使ってexcelに数式関数を追加する)
* [PythonでExcelの数式/関数を読む]()

## Excel ファイルを処理するための Python ライブラリ
Python アプリケーションで Excel ドキュメントを操作するには、[**Spire.XLS for Python**](https://www.e-iceblue.com/Introduce/xls-for-python.html) ライブラリが必要です。以下の pip コマンドを使って直接インストールすることができます。
```
pip install Spire.XLS
```
また、以下のリンクから製品パッケージをダウンロードし、ローカルパスからインストールすることもできます。

https://www.e-iceblue.com/Download/Spire-XLS-Python.html


## Python を使ってExcelに数式/関数を追加する
Spire.XLS for Python は、Excel ワークシートの特定のセルに数式を追加するための **`Worksheet.Range[].Formula`** プロパティを提供しています。これは、SUM、AVERAGE、COUNT、IF などの多くの一般的な数式や、日付と時刻の数式、数学および三角関数などを追加することをサポートしています。

手順は以下の通りです：
1. Excel ワークブックを作成します。
1. **`Workbook.Worksheets[sheetIndex]`** プロパティを通じて指定されたワークシートを取得します。
1. **`Worksheet.Range[rowIndex, columnIndex].Text`** および **`Worksheet.Range[rowIndex, columnIndex].NumberValue`** プロパティを通じて、指定されたセルにテキストと数値データを追加します。
1. **`Worksheet.Range[rowIndex, columnIndex].Formula`** プロパティを介して、指定されたセルに数式を追加します。
1. 結果のファイルを保存します

Python のコード：
```python
from spire.xls import *
from spire.xls.common import *

# ワークブックを作成する
workbook = Workbook()

# 最初のワークシートを取得する
sheet = workbook.Worksheets[0]

# 2 つの変数を定義する
currentRow = 1
currentFormula = ""

# セルにテキストを追加し、セルのスタイルを設定する
sheet.Range[currentRow, 1].Text = "テストデータ："
sheet.Range[currentRow, 1].Style.Font.IsBold = True
sheet.Range[currentRow, 1].Style.KnownColor = ExcelColors.PaleBlue
sheet.Range[currentRow, 1].Style.Borders[BordersLineType.EdgeBottom].LineStyle = LineStyleType.Medium
currentRow += 1

# セルにデータを追加する
sheet.Range[currentRow, 1].NumberValue = 1.5
sheet.Range[currentRow, 2].NumberValue = 7
sheet.Range[currentRow, 3].NumberValue = 3.4
sheet.Range[currentRow, 4].NumberValue = 9
sheet.Range[currentRow, 5].NumberValue = 6.6
sheet.Range[currentRow, 6].NumberValue = 8
currentRow += 2

# セルにテキストを追加し、セルのスタイルを設定する
sheet.Range[currentRow, 1].Text = "数式"
sheet.Range[currentRow, 2].Text = "計算結果"
sheet.Range[currentRow, 1, currentRow, 2].Style.Font.IsBold = True
sheet.Range[currentRow, 1, currentRow, 2].Style.KnownColor = ExcelColors.PaleBlue
sheet.Range[currentRow, 1, currentRow, 2].Style.Borders[BordersLineType.EdgeBottom].LineStyle = LineStyleType.Medium
currentRow += 1

# 式を追加する
currentFormula = "=1+2+3+4+5-6-7+8-9"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

currentFormula = "=33*3/4-2+10"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# セル参照を追加する
currentFormula = "=Sheet1!$B$2"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 一連の値の平均を計算するために、AVERAGE 関数を追加する
currentFormula = "=AVERAGE(Sheet1!$D$2:F$2)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 一連の値を合計するために、SUM 関数を追加する
currentFormula = "=SUM(18,29)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 指定された条件に基づいて判断を行い、異なる結果を返すために、IF 関数を追加する。
currentFormula = "=IF(4,2,2)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値を含むセルの数をカウントするために、COUNT 関数を追加する
currentFormula = "=COUNT(3,5,8,10,2,34)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# データリストまたはデータベースにおけるカテゴリ別の集計のために、SUBTOTAL 関数を追加する
currentFormula = "=SUBTOTAL(3,Sheet1!A2:F2)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 現在の日付を返すために、NOW関数を追加する
currentFormula = "=NOW()"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
sheet.Range[currentRow, 2].Style.NumberFormat = "yyyy-MM-DD"
currentRow += 1

# 時刻値から秒を抽出するために、SECOND関数を追加する
currentFormula = "=SECOND(0.503)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 時刻値から分を抽出するために、MINUTE関数を追加する
currentFormula = "=MINUTE(0.78125)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 日付値から月の情報を抽出するために、MONTH関数を追加する
currentFormula = "=MONTH(9)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 日付値から特定の日の情報を抽出するために、DAY関数を追加する
currentFormula = "=DAY(10)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 時、分、秒をそれぞれ指定して標準化された時刻形式を作成するために、TIME関数を追加する
currentFormula = "=TIME(4,5,7)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 指定された年、月、日に基づいて日付を構築するためのDATE関数を追加します
currentFormula = "=DATE(6,4,2)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 0 以上 1 未満のランダムな小数を生成するために、RAND 関数を追加します
currentFormula = "=RAND()"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 時刻値から時を抽出するために、HOUR関数を追加する
currentFormula = "=HOUR(0.5)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 2つの数を除算した余りを返すために、MOD関数を追加する
currentFormula = "=MOD(5,3)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 日付に対応する週番号を返すために、WEEKNUM 関数を追加します
currentFormula = "=WEEKDAY(3)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 与えられた日付から対応する年を抽出するために、YEAR関数を追加する
currentFormula = "=YEAR(23)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 与えられた論理値を反転させるために、NOT関数を追加する
currentFormula = "=NOT(true)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 複数の条件に対して論理和演算を行うために、OR関数を追加します（この関数は、与えられた条件のうち少なくとも1つがTRUEの場合にTRUEを返し、すべての条件がFALSEの場合にのみFALSEを返します）
currentFormula = "=OR(true)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 複数の条件に対して論理積演算を行うために、AND関数を追加します（AND関数は、指定されたすべての条件がTRUEの場合にのみTRUEを返し、いずれかの条件がFALSEの場合は常にFALSEを返します）
currentFormula = "=AND(TRUE)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値のテキスト形式を数値型に変換するためのVALUE関数を追加する
currentFormula = "=VALUE(30)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# テキスト文字列の文字数を返すために、LEN 関数を追加する
currentFormula = "=LEN(\"world\")"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# テキスト文字列の指定された開始位置から指定された長さの文字を抽出するために、MID関数を追加します
currentFormula = "=MID(\"world\",4,2)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 値を指定された桁数で四捨五入するために、ROUND関数を追加する
currentFormula = "=ROUND(7,3)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 値の正負を判定し、その符号に対応する値を返すために、SIGN関数を追加する
currentFormula = "=SIGN(4)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 値を切り捨てて最も近い整数にするために、INT関数を追加します。つまり、値の小数部分を取り除き、その値以下の最大の整数を返します
currentFormula = "=INT(200)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値の絶対値を返すために、ABS 関数を追加します。つまり、数値の正負に関係なく、その数値の符号を取り除き、数値の大きさのみを残します
currentFormula = "=ABS(-1.21)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値の自然対数を計算するために、LN関数を追加する。 
currentFormula = "=LN(15)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 自然定数e（約2.71828）の指定された累乗を計算するために、EXP関数を追加する
currentFormula = "=EXP(20)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# ある数の算術平方根を計算するために、SQRT関数を追加する
currentFormula = "=SQRT(40)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数学定数π（円周率）の近似値を返すために、PI関数を追加する
currentFormula = "=PI()"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 角度の余弦値を計算するために、COS関数を追加する
currentFormula = "=COS(9)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 与えられた角度の正弦値を計算するために、SIN関数を追加する
currentFormula = "=SIN(45)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値のセットの中から最大値を返すために、MAX 関数を追加する
currentFormula = "=MAX(10,30)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 数値の集合の中から最小値を返すために、MIN関数を追加する
currentFormula = "=MIN(5,7)"
sheet.Range[currentRow, 1].Text = "'" + currentFormula
sheet.Range[currentRow, 2].Formula = currentFormula
currentRow += 1

# 列幅を設定する
sheet.SetColumnWidth(1, 32)
sheet.SetColumnWidth(2, 16)
sheet.SetColumnWidth(3, 16)

# スタイルを適用する
style = workbook.Styles.Add("Style")
style.HorizontalAlignment = HorizontalAlignType.Left
sheet.ApplyStyle(style)

# 生成された文書を保存する
workbook.SaveToFile("ExcelFormula.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

結果を生成しています：
![ExcelFormula.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/e5d1f3db-74d0-4d89-84cf-b1764f1f01d9.png)




## Python でExcelの数式/関数を読む
ワークシート内のすべてのセルを反復処理し、**`Cell.HasFormula`** プロパティを使って数式を含むセルを見つけ、その後 **`CellRange.Formula`** プロパティを呼び出してセル内の数式を取得することができます。

手順は以下の通りです：
1. Excel ファイルを読み込みます。
1. **`Workbook.Worksheets[sheetIndex]`** プロパティを介して指定されたワークシートを取得します。
1. **`Worksheet.AllocatedRange`** プロパティを介してワークシート内の使用されている範囲を取得します。
1. 空のリストを作成します。
1. 使用されている範囲内のすべてのセルを繰り返し処理します。
1. **`Cell.HasFormula`** プロパティを使用して数式を含むセルを見つけます。
1. **`CellRange.RangeAddressLocal`** および **`CellRange.Formula`** プロパティを使用してセル名と数式を取得します。
1. 抽出した内容をリストに追加し、その後 txt ファイルに書き込みます。

Python のコード：
```python
from spire.xls import *
from spire.xls.common import *

# Excel 文書を読み込む
workbook = Workbook()
workbook.LoadFromFile("ExcelFormula.xlsx")

# 最初のワークシートを取得する
sheet = workbook.Worksheets[0]

# ワークシートの使用範囲を取得する
usedRange = sheet.AllocatedRange

# リストを作成する
list = []

# ワークシートの使用範囲内のセルを一つずつ処理する
for cell in usedRange:
    # セルに式があるかどうかをチェックする
    if(cell.HasFormula):
        # セルの名前を取得する
        cellName = cell.RangeAddressLocal
        # 式を取得する
        formula = cell.Formula
        # セルの名前と式をリストに追加する
        list.append(cellName + " 公式：" + formula)

# テキスト（.txt）ファイルをインポートする
with open("ReadFormula.txt", "w", encoding = "utf-8") as text_file:
    for item in list:
        text_file.write(item + "\n")

workbook.Dispose()
```

出力：
![ReadFormula.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/d5c2fbd1-7497-4701-b39c-0b420ba4ece1.png)

* * *

上記の例を通じて、開発者はプログラム内で Excel ファイルに数式を簡単に追加し、読み取ることができ、データ処理や分析に関連する開発作業に大きな利便性をもたらします。単純な数学の数式であれ、複雑な関数式であれ、Spire.XLS for Python ライブラリは良好にサポートします。

> Python で Excel ファイルに対する他の操作については、以下の例を参考にできます：

https://www.e-iceblue.com/Tutorials/Python/Spire.XLS-for-Python/Program-Guide/Spire.XLS-for-Python-Program-Guide-Content.html