openpyxlをうす〜く理解しよう~その1/3（値編）

# はじめに
なんやかんや言ってもエクセルを使う場面って多い。
そして、見せる資料としても、チェックする資料としても活躍の場が多い。
なので、エクセルに書き込んで、体裁を整えるためのチートとして活用していただければ！
と思ったけど、なかなか深い。うん、深い。
なので、うす〜く、さらっとopenpyxlを理解したいと思います。

ざっぱに、今回の内容はこんな感じ
1. ファイルの読み込みから保存
1. openpyxlでエクセルを操作するための準備
1. セルの値の取得
1. 行番号とカラムの取得
1. いったん、ここいらで中締め


まずはここまで。


# 環境
MacBookAir 2020 M1
python=3.10.8
openpyxl=3.1.2
インストールは`pip install openpyxl`で！
あんまり関係ないわな。

# openpyxl
言わずと知れたopenpyxlのドキュメントがこちら。正直、よくわからん。マジでわからん。
なので僕なりに整理した順に追っていく。

https://openpyxl.readthedocs.io/en/stable/index.html

# ファイルの読み込みから保存
面倒なんで、シートの読み取りもしくはシートの作成、保存までやちゃいましょう。
<br>
<br>
- 既存のエクセルファイルを読み取って、既存のシートの読み込み
```Python
import openpyxl

workbook = openpyxl.load_file('ファイル名')
worksheet = workbook['Sheet1']

workbook.save('ファイルパス')
```
<br>
<br>

- 新しくopenpyxlのインスタンスを作って、新しいシートの作成
```Python
from openpyxl import Workbook

workbook = Workbook()
worksheet = workbook.create_sheet('created_sheet', 0)

workbook.save('ファイルパス')
```
`create_sheet`の引数の０は0番目の順番の位置にシートを作る。だからなくてもOK。
<br>
<br>

この辺はチュートリアルに書いてある
https://openpyxl.readthedocs.io/en/stable/tutorial.html

<br>
<br>

---
---

# openpyxlでエクセルを操作するための準備
<br>
こんなエクセルを作りました。ファイル名は`test.xlsx`、シート名は`Sheet1`

![スクリーンショット 2024-04-16 18.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655320/98631935-94e4-40d6-f72d-9e959c9e6062.png)

こいつを操作というか、読み取ることから確認していきましょうね。
<br>

### まずは読み込み

```python
import openpyxl

workbook = openpyxl.load_file('./test.xlsx')
worksheet = workbook['Sheet1']
```

<br>

### シートのの行列数の取得方法
- 行数の取得
```python
max_row = worksheet.max_row
print(max_row)
```
出力は`4`
worksheetにmax_rowを渡してあげると入力されたセル数が取れる。こうなるとcolumn側もわかるよね。

- 列数の取得
```python
max_col = worksheet.max_column
print(max_col)
```
出力は`4`
はい、想像つきましたね。はい。
あ、縦横で入力セル数を変えればよかった。

ではどんどんいきます。

<br>
<br>


# セルの値の取得
### エクセル座標とindex座標
エクセルの座標で指示する方法と、リストのようにインデックスで指定する方法があります。
<br>

- エクセル座標の指定方法

```python
print(worksheet['A1'])
print(worksheet['A1'].value)
```

出力は
```
<Cell 'Sheet1'.A1>
1-1
```
わかりますねー。
`worksheet['A1']`でセルのインスタンスが取れて、それに`value`を渡すと中の値が取れます。
<br>
<br>

- インデックスで指定する方法
```python
print(worksheet.cell(row=1, column=1))
print(worksheet.cell(row=1, column=1).value)
```
出力は全く同じ。つまり、どっちの方法でもOK。
```
<Cell 'Sheet1'.A1>
1-1
```
<br>
<br>


### じゃ、行ごと、列ごとの取得は？
<br>

- 列の取得
```python
print(worksheet['A'])
```
出力
```
(<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.A2>, <Cell 'Sheet1'.A3>, <Cell 'Sheet1'.A4>)
```
タブルで全てのセルが帰ってきます。for文で回してあげれば値も取得できますね。
ですが、`worksheet['A'].value`はだめ。タプルに`value`は使えませんよとエラーが返ってきます。
**ちなみに`worksheet.cell(column=1)`をしてもrowの値がないぞとエラーが出ます。**

<br>
<br>

- 行の取得
```python
print(worksheet[1])
```
出力
```
(<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.B1>, <Cell 'Sheet1'.C1>, <Cell 'Sheet1'.D1>)
```
はい、行ごと取れましたね。
これも列ごとと同じパターンの模様。

---
---

# じゃ、ここからセルに入力していこう


### 値を入力
値の入力はこのあたりに書いてある。一括でデータを入れるなら便利。一個ずつ入れる方法もある。
https://openpyxl.readthedocs.io/en/stable/worksheet_tables.html

ここで、理解しておきたい内容だけを公式から抜粋して解説。シンプルにいきましょう。
```python
# ライブラリのインポート
from openpyxl import Workbook

# openpyxlのインスタンスを作って、シートを作って
wb = Workbook()
ws = wb.active

# データをリストで作る
data = [
    ['Apples', 10000, 5000, 8000, 6000],
    ['Pears',   2000, 3000, 4000, 5000],
    ['Bananas', 6000, 6000, 6500, 6000],
    ['Oranges',  500,  300,  200,  700],
]

# シートにアペンドしていけば上から順に入力されていくので、最初にカラム名を挿入して
ws.append(["Fruit", "2011", "2012", "2013", "2014"])

# リストで作ったデータを1行ずつアペンドして入力していく
for row in data:
    ws.append(row)

# 保存
wb.save("table.xlsx")
```
データを作って、行ごとアペンドしてあげれば入力可能。

<br>
<br>


### 特定のセルへの値の入力
もう、大丈夫ですよね。こんな感じ。
```python
worksheet.cell(row=1, column=2) = 5
```

```python
worksheet['A2'] = 5
```
<br>
<br>


### 入力文字のタイプの判別
```python
worksheet.cell(row=1, column=2).data_type
```
`s`
stringの意味かな？
<br>
<br>

```python
worksheet.cell(row=2, column=2).data_type
```
`n`
numberの意味かな？Pythonなんだからintのiとかfloatのfで出てくれればいいのに。
あ、一文字じゃなくてもいいよね。
<br>
<br>

そして気になるTRUE/FALSE

```python
worksheet.cell(row=2, column=4).data_type
```
`b`
`boolen`の`b`かな
<br>
<br>


# 行番号とカラムの取得
### カラムのアルファベットの取得（B1のBを取得）
```python
worksheet.cell(row=2, column=2).column_letter
```
`B`
2列目はB
### カラムのインデックスの取得（B2のセル）
```python
worksheet.cell(row=2, column=2).col_idx
```
`2`
2番目のカラム

<br>

この書き方もできますね。

```python
worksheet['B'][0].col_idex
```
`2`
出力は同じ。


---
# いったん、ここいらで中締め
長くなりそうなんで、ここでいったんシメます。
ここまでできれば値は自由に入れ替えできそうです。
次回は見やすくするために色をつけていきましょうかね。