openpyxlを使う

なにやら大量のエクセルシートから特定データを抜き出して、別のシートにせよという面倒くさいタスク。
対象シートはいわゆるエクセル方眼紙になっていて、どのセルに目的のデータがあるかは一定していない。
頼りになるのは、特定の文字列("氏名"とか"申請者"とか)の右隣りのセルのデータがあるってことだけ。
そんなのになんでエクセル使うんだ。まったく。手でやってるとほんとに気が狂いそうなのでpythonにやらせる。

openpyxlをインストール

pipで一発。パッケージシステムバンザイ。

$ pip install openpyxl

シートの種類を判別する

シートをながめていると、どうやら特定文字列のすぐ右のセルにデータがあるシートと、右下(つまり、隣のカラムで、1つ下のrow番号)にデータがあるシートがある。セル結合はタヒね。表計算ソフトを表計算以外の目的につかってるやつもタヒね。
どこかで判定できるかなーとながめていると最初の5行目までのところにタイトルがあるのでそこで判定できそう。そのrowも1つめだったり、4つめだったりする。フリーダムすぎる。

ってことで判定ルーチンはこんな感じ

for row in sheet.iter_rows('A{}:A{}'.format(sheet.min_row,6)):
    for col in sheet.iter_cols(min_col-1,max_col=1):
        for cell in row:
           cv = cell.value
           if(re.search(r'(文字列|文字列)',str(cv))):
              sheet_type = 1              # タイプ1
      else:
              sheet_type = 2               # タイプ2
          else:
            continue
          break
       else:
          continue
       break

最初の6row目までにre.searchで指定した文字列が現れたらsheet_typeに1をいれてループを抜ける。
pythonだと多重ループを一発で抜けられないので、forにelseをいれてcontinueやbreakを書く。Cに慣れてるとちょっとん〜と思うところ。

でもって、スクリプトの最初の方にオフセット値を配列で設定しておく。

offset_name = ["1":0 , "2":1}

目的のデータを検索する

これはすべてのデータを舐めるしかない。rowとcolumnでループ。でもって、このスクリプトを書いていて、上記の特定文字列が複数あることに気づく。むきー。複数出てくるのは後ろの方で、目的データは最初の40行くらいなので、その範囲で検索する。最初に見つけたらbreakすればいいんでしょうけど、多重ループの抜け方が上記みたいに面倒なので簡単に済ませてしまいました。

for row in sheet.iter_rows('A{},H{}'.format(sheet.min_row,40)):
    for col in row:
        for cell in row:
            cv = cell.value
            if(re.search(r'(氏名|申込者|担当者)',str(cv))):
                name = sheet.cell(row=cell.row+offset_name[sheet_type],column=cell.col_idx+offset_name[sheet_type]).value

print(name)

ってな具合でなんとかなりました。実際には4〜5このデータを同時に検索して抽出しているので、検索するところとかoffsetの配列とかはもっと複雑です。それに対象となるエクセルワークブックも複数のシートで構成されていて、最初のシートにデータがはいっているとは限らなかったり、シート名ではデータかどうか判断できなかったりしたのでいろいろ駆使して解決しています。

で、感想としてはみんなタヒねってことですかね。再利用することを考えないで電子データに保存するのは全然意味がない。紙に鉛筆で書いて管理するのとなんにも変わらない。整理されてないデータはデータじゃなくて、ただのゴミかそれ以下だってことですね。

いかん。イラッとする作業で発言が過激になってる。