はじめに
Excelファイルに入力されたデータを抽出して色々処理する必要があったので、PythonでExcelファイルを操作できるモジュールopenpyxl
の使い方についての簡単なメモ
準備など
- 動作環境
- Python 3.6.1
- openpyxl 3.0.5
普通にpip
コマンドでインストールします
pip install openpyxl
データの読み書き
こういうExcelファイルがあったとします
とりあえず、入力されてるセルから適当な値を取り出してみます
import openpyxl as ex
wb = ex.load_workbook("./data.xlsx") # Excelファイル選択
ws = wb["Sheet1"] # シート名選択
read_value = ws["A2"].value # セル座標選択、値を取得
print(read_value)
田村 奈央
Sheet1
のA2
セルに入力されている田村 奈央
という値が出力されました
5行目、value = ws["A2"].value
のところをvalue = ws["A2"]
とすると
値ではなくCell
オブジェクトの取得になるので、print文で表示させたい時はフィールドであるvalue
を持ってきてください
次は書き込みをやってみます
wb = ex.load_workbook("./data.xlsx") # Excelファイル選択
read_value = wb["Sheet1"]["A2"].value # シート、セル座標選択、値を取得
wb["Sheet2"]["B1"] = read_value # 書き込み
wb.save("./data.xlsx") # 保存
上半分はさっきとほぼ同じです
まっさらなシート"Sheet2"を用意しておき、B1セルに書き込みます
最終行、save
メソッドで上書き保存するのを忘れずに
(この部分の処理が無いとExcelファイルに反映されません)
当然ですが、その部分にあった入力値は消えてしまいます。不安な方は別名で保存しておきましょう
行列番号でのセル座標指定
アドレスでのセル番地指定(先程までの座標指定方法)だと、loop処理などで扱いにくいケースが出てきます
そこで、行番号と列番号での座標指定を行ってみます
wb = ex.load_workbook("./data.xlsx")
ws = wb["Sheet1"]
read_value_01 = ws["A2"].value # セル番地指定
read_value_02 = ws.cell(2,1).value # 行列番号指定
print(read_value_01, read_value_02)
田村 奈央 田村 奈央
for
でインデックスを指定する時などはこっちの方が扱いやすい気がします
自分は行と列がいつもごっちゃになってしまうのでラッパーを作ったりしています
行と列共にインデックスは「1」からのスタートとなっているので注意
(「0」以下の値を指定するとERRORになる)
注意点
関数を入力しているセルの読み込み
先程と同じシートにおいて、
「年齢」列のデータの読み込みを行ってみます
wb = ex.load_workbook("./data.xlsx")
ws = wb["Sheet1"]
read_value = ws["E2"].value
print(read_value)
=DATEDIF(D2,$G$2,"Y")
表示されている38
という値を取ってきてほしいのに、数式を取得してしまいました
このように、関数によって値を算出しているセルの場合
算出された値ではなく、入力されている関数が読み込まれます
もし値そのものを読み込みたい場合は
load_workbook
メソッド内の引数data_only
の値をTrue
にしてExcelファイルをロードしておきましょう
wb = ex.load_workbook("./data.xlsx", data_only=True) # 表示されている値として取得
ws = wb["Sheet1"]
read_value = ws["E2"].value
print(read_value)
38
結合セルの扱い
Excelにはセル結合という忌まわしき機能が存在します
シートの見栄えは良くなるのですが、結合セルの値は左上部分の座標のみに記録されているため、データとして処理する際には困ります
具体例を見てみましょう
上述のようなシートにおいて、データを人数分出力するコードを書いてみます
wb = ex.load_workbook("./data.xlsx", data_only=True)
ws = wb["Sheet1"]
for row in range(2, 19+1):
for colmun in range(1, 5+1):
print(ws.cell(row, colmun).value, end=", ")
print() # 改行
男, 安井 人志, やすい ひとし, 1960-01-30 00:00:00, 61,
None, 中山 寿明, なかやま としあき, 1999-12-04 00:00:00, 21,
None, 岩田 一徳, いわた いっとく, 1945-06-28 00:00:00, 75,
None, 重松 真一, しげまつ しんいち, 1960-12-13 00:00:00, 60,
None, 高山 雅彦, たかやま まさひこ, 1982-11-27 00:00:00, 38,
None, 相田 幸平, あいだ こうへい, 1967-04-09 00:00:00, 53,
None, 三原 丈史, みはら たけし, 1974-03-31 00:00:00, 46,
None, 中岡 将也, なかおか まさや, 1976-02-25 00:00:00, 44,
None, 徳永 明慶, とくなが あきよし, 1978-11-22 00:00:00, 42,
女, 及川 えみ, おいかわ えみ, 1980-05-31 00:00:00, 40,
None, 小野寺 淳子, おのでら あつこ, 1944-04-14 00:00:00, 76,
None, 布川 怜奈, ふかわ れいな, 1961-08-04 00:00:00, 59,
None, 瀬戸 かおり, せと かおり, 1950-03-12 00:00:00, 70,
None, 長崎 路子, ながさき みちこ, 1974-03-08 00:00:00, 46,
None, 滝 奈央, たき なお, 1954-02-09 00:00:00, 67,
None, 小野 あおい, おの あおい, 1974-04-14 00:00:00, 46,
None, 竹下 恵梨香, たけした えりか, 1988-05-28 00:00:00, 32,
None, 本村 紗季, ほんむら さき, 1955-05-30 00:00:00, 65,
性別の出力に注目してみてください
値がある人とない人がいることがわかります
これは結合セルの左上部分以外の座標には、内部的に値が存在しないことによる現象です
結合セルを含んだシートを処理する場合は十分に気をつけてください
一番良いのは、結合セルを使わないことです
リンクなど
- openpyxl:公式ドキュメント
-
なんちゃって個人情報
- 本記事で使用したデータはこちらのサイトで自動生成しました