【牌】PythonでExcel操作してみる@雑感

2020年7月28日

image

Pythonのopenpyxlで簡単にExcelファイルの操作ができます。以下の公式のチュートリアルを見れば一目です。

公式チュートリアル

実際に今回初めて触ったのですが、全機能は試してないものの、一通りやってみて、非常にしっかりしたライブラリだなという印象。

公式サンプルコード

一度でも、Excel VBAマクロとか触った事があるなら、とっつきにくいんではないでしょうか。Workbook・Worksheetの関係とか。

openpyxlは非常に有名なので、既に記事が沢山ありますが、自分なりの備忘録として。

(;^ω^)

対応してるファイル

対応しているファイル種類は、xlsx/xlsm/xltx/xltmの4種類。

これらはExcel2007から利用されてるタイプのもので、中身がXMLで作られたもの。以前の、xls(バイナリ形式)は非対応。

※Office Open XML Format

XLS形式(バイナリ)を扱いたい場合、どーしても、Excel本体+ライセンスが必要になってきます。

内部でExcelを起動してる訳で、処理速度や自動処理の安定信頼度からどうにも気になります。

これらの条件が合えば、PowerShell(というか.Net)とかでも操作ができますね。

パッケージ内容

以下の公式を見られるのが最も早い。非常に多岐に渡ってます。

openpyxl package

最も多用しそうなものははこんなかな。

セル操作openpyxl.cell.cell

ワークシートopenpyxl.worksheet

簡単に始めるならVS2019

image

語るまでも無い有名な開発環境ですが、10万円ソフトが無料で利用できるのは黙って見過ごす訳にもいきません。

(;^ω^)法人の方は有料ですよ

VisualStudio2019

image

インストールするだけで、全ての環境が整いますし、何よりも、デバッガが有益です。

過去に、.NetやVBなどで、VisualStudioを使った事があるなら、すぐ使いこなせるでしょう。

image

パッケージを追加する場合は、写真のここ(ソリューションエクスプローラー)から導入する事ができます。

名前付きセルからの読み込み

自前で作ってみたやつです。

名前付きセル(ローカル・グローバル)から、値をリストにして読み込むものです(単一セルだったら、非リスト)

結合セルだったら、読み飛ばします。

簡単ですよね。

Rython特有の省略コードにしてないのは、デバッガーで値が読めるようにするため。

def getNamedCells(_wb,_ws,_namedCell):
     “""
     指定のGlobal/Local名前付きセルから読み出す
     結合セルは無視

    Parameters
     ——–
     Wordbook
     WorkSheet(Mode:local named cells) or None
     name

    Returns
     ——–
     list:Cells
     “""
     _dn = None
     if _ws is not None:
         _ws_id = _wb.sheetnames.index(_ws.title)
         if _namedCell in _wb.defined_names.localnames(_ws_id):
             _dn = _wb.defined_names.get(_namedCell, _ws_id)
     elif _namedCell in _wb.defined_names:
         _dn = _wb.defined_names[_namedCell]
     if _dn is None:
         return None
     # get cells
     _ad = _dn.destinations
     _cells = []
     for _sheet_name, _coord in _ad:
         _ws = _wb[_sheet_name]
         _cells.append(_ws[_coord])
     # get values
     _ret = []
     for _row in _cells:
         if hasattr(_row, “__iter__"):
             for _aa in _row:
                 _v = []
                 for _col in _aa:
                     if not type(_col) is openpyxl.cell.MergedCell:
                         _v.append(_col.value)
                 _ret.append(_v)
         else:
             _ret = _row.value
     return _ret

数式を読んでしまう場合

最初に躓いたのが、これ。値のつもりが、数式になってしまっていたという。

これは、ワークブックを読む際に指定できます。

_wb=openpyxl.load_workbook(_file, data_only=True)

data_onlyを有効にしておけば良いですが、公式にも書かれてる通り、Excelファイルが最後に値を更新した状態という事になってます。

data_only (bool) – controls whether cells with formulae have either the formula (default) or the value stored the last time Excel read the sheet

つまり、ゴリゴリにVBAコーディングされて、再計算を無効にしてた場合とかは、何が帰るかわからないという事。

公式リファレンス(load_workbook)

他にもオプションが用意されてるのが分かります。

縦・横方向にセルを読んでいく

縦/Row・横/Column方向に一直線に読みたいなんて事、結構あるんじゃないでしょうか。

こんな感じで読むことができます。

openpyxlでは、セル番号が1からとなってますが、この例だと、Pythonリストの扱いなので0からとなるので注意。

for _i, _c in enumerate(list(_ws.rows)[0]):
         for _j, _v in enumerate(list(_ws.columns)[_c.column – 1]):

セルの背景色はどれ?

image

これも悩んだw

てっきり、fill.bgColor.rgbだと思いこんでましたが、見当違いの色しか入ってない・・。

実際は、fill.fgColor.rgbの方に入ってます。名前からして、文字色だと思うでしょ。

でも、そういや、同じレベルにfont.color.rgbってのがあるのよね。これが文字色。

但し、これは、fill.patternTypeが”solid”の場合のみで、他の値(パターンやブラシ等)に、bgColorも利用されてる。

FFFFFFFFで、16進の4バイト。頭はFF固定のようです。アルファ値とか指定できるんでしょうか。詳しくは調べてません。

LibreOffice CalcでもOKです

image

当たり前っちゃーそうですが、LibreOffice Calcで保存したxlsxでも、しっかり操作できてます。

オープンソースバンザイでございます。

(;^ω^)

暗号化パッケージpycryptodome関連のインストールで、若干戸惑った。

他の関連パッケージと定義が重複しているらしく、インストール順序に癖がある。正常に入っていると思っても、参照できない。

一旦、pycryptodome含め、pycryptoなどの古いものをuninstallしてから、単体でpycryptodomeを再インストールすると正常になりました。

しかし、Python・・・、コードが長くなると。

インデントだけでのスコープ管理に限界を感じてくる(かなりのストレス)んですが、皆さんどうなんでしょ・・ね。

(;´∀`)

80桁を超えないで書けというのは賛同ですが、コメントを丁寧に書くと、如何せんコード行数が増えてくる。

ネストが多重になってくると、もうそれは地獄。

確かに、短いコードなら手軽なんだけども。