PythonでExcelの値を取得する方法
お久しぶりです。EFです。
今回はPythonでExcelのデータを取得する方法をまとめておきます。
値を取得できると、そこから別フォーマットに変換できたりします。
pywin32とは
pywin32はCOMオブジェクトを介してExcelを操作できるモジュールです。
使い方
# -*- coding: utf-8 -*- import os import win32com.client as win32 # Excelファイルは以下の想定です # A B # ┌───────────────┬───────────────┐ # │ 名前 │ 値 │ # 1行目 # ├───────────────┼───────────────┤ # │ アイテム1 │ 100 │ # 2行目 # ├───────────────┼───────────────┤ # │ アイテム2 │ 200 │ # 3行目 # ├───────────────┼───────────────┤ # │ アイテム3 │ 300 │ # 4行目 # ~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~ # │ アイテム999 │ 99900 │ # 1000行目 # ├───────────────┼───────────────┤ # │ アイテム1000 │ 100000 │ # 1001行目 # └───────────────────────────────┘ try: # COMを利用してExcelに接続 app = win32.Dispatch("Excel.Application") # エクセルファイルを開く path = os.path.abspath("./test.xlsx") book = app.Workbooks.Open(path) # シートを取得 # book.Worksheets("シート1") のように文字列でも取得可能. sheet = book.Worksheets(1) # セルを取得 wk = sheet.UsedRange # 使用範囲を取得 columns = wk.Columns.Count # 行数 rows = wk.Rows.Count # 列数 for y in range(1,rows+1): # セルは1から始まるので注意 for x in range(1,columns+1): # セルは1から始まるので注意 # セルから値を取得 print(sheet.Cells(y, x).Value) finally: # ブックを閉じ、COMを終了させる book.Close(SaveChanges=False) app.Quit() del app
これで値は取得できます。
ですが、上記のコードを実行すると非常に時間がかかることがわかります。このままではダメなので高速化を行います。
高速化
for文で表示しているところを計測します。処理のばらつきを考慮し、3回行った平均にします。
# 3回の平均を計測 N = 3 times = [] for idx in range(N): start = time.perf_counter() for y in range(1,rows+1): for x in range(1,columns+1): print(sheet.Cells(y, x).Value) times.append(time.perf_counter() - start) print("time {:.7f} sec".format(sum(times)/len(times))) #秒
結果は 6.5105476秒 でした。
遅い原因はCells関数が現在のプロセスからExcelのプロセス(EXCEL.EXE)にアクセスし、大量のオーバーヘッドを発生をさせているためです。
なのでCells関数を使わない方法でアクセスします。
cells = wk.Value for y in range(0,rows): for x in range(0,columns): print(cells[y][x])
wk.ValueはExcelのプロセスからシートのデータを取得しています。
なので、それをローカルのメモリにコピーすることで高速に値を取得できます。
こちらも同じように3回の平均を計測したところ、0.1483422秒 でした。
速度が97.7%早くなり、高速化に成功しました。
最後に
お手軽にExcelの値を取得することができました。
あとはstructモジュールを使用すれば、バイナリデータも作成できます。
また、.xlsxはバイナリデータなので中間ファイルを吐き出せばテキストベースで管理できます。