今回はエクセルファイルのデータを読み出してみます。とは言え単純にシェルスクリプト、コマンドラインでは難しい感じがするので流行りのPythonを利用します。Pythonでエクセルデータを読み出して標準出力に出してしまえば後はいろいろ応用できるはずです。つまりエクセルの特定の場所のセルの値だけ読み出すことができれば何とかなるということです。全部Pythonで解決する方が処理速度的にもよいのですが、そこはPython関係の書籍やWebなどの情報におまかせすることにしましょう。
Windowsの情報はたくさん溢れていますので、ここは情報の少ないmacOSでやってみます。使用するライブラリやPythonのプログラムはWindowsでもmacOSでも変わりません。
なお、大前提としてPython 3以上がOSにインストールされているものとします。その上でopenpyxlライブラリをインストールします。

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

openpyxlライブラリのインストールは以下のコマンドを入力します。すでにインストールされている場合は図のような画面になります。

pip install openpyxl

無事にインストールできたら準備完了です。なお、動作するシェルはbash,zshいずれでも構いません。

エクセルファイルを用意

 まずはデータを読み出すためのエクセルファイルを用意しましょう。ここでは図のような簡単な表にしました。

 作成したらフォルダに保存します。ここではいつものようにデスクトップ上にあるsampleフォルダに入れておきます。保存するファイル名はBook1.xlsxとします。なお、このフォルダには実行するPythonのスクリプトも入ります。

セルの内容を読み出して表示

 まず基本的な特定のセルの内容を読み出してみます。プログラムはシンプルに以下の4行です。2行目の'Book1.xlsx'が読み出すエクセルファイル名になります。最後の行の'A1'が読み出すセルの位置になります。このファイルをExcelファイルと同じフォルダに入れておきます。ファイル名は自由ですが、ここではe1.pyとしました。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx')
ws = wb.active
print(ws['A1'].value)

 このPythonスクリプトを実行するには以下のようにします。入力する文字を少なくするため、カレントディレクトリに移動してから実行します。

 実行するとA1セルの内容である年度の文字が表示されます。なお、実行して結果が出るまでに30秒とか、かなり時間がかかることがあります。なお、2回目以降は高速に処理されます。

 セルの位置をA1やD51などのように指定するのはプログラムにとっては、あまり使い勝手のよいものではありません。どちらかというと左からのセルの位置、上からのセルの位置を指定する方が便利です。
 セルの位置を指定して読み出すにはws.cell(row=2, column=1)のようにします。rowは行数を、columnは列数を示します。row=2, column=1なら2019の値が読み出されます。
 以下のプログラムをe2.pyというファイル名で保存し実行すると以下のような結果になります。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx')
ws = wb.active
n = ws.cell(row=2, column=1)
print(n.value)

計算結果を表示

 エクセルでは様々な計算が行われ、その結果がセルに表示されます。用意したエクセルファイルでは合計の列、E2〜E7とB7,C7,D7がSUM関数によって計算した値になります。
 ここでE2のセルを読み出してみましょう。最初のスクリプトのA1の部分をE2に変更して実行します。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx')
ws = wb.active
print(ws['E2'].value)

 実行するとセルに表示されている数値の153ではなく計算式の=SUM(B2:D2)が表示されてしまいました。計算結果を得るにはload_workbook()でdata_only=Trueを指定する必要があります。つまり、以下のようにすると期待する合計値が表示されます。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx',data_only=True)
ws = wb.active
print(ws['E2'].value)

複数のセルの内容を表示

 ここまでは1つのセルの内容だけを表示しました。どのみちシェルスクリプトで制御するなら1つだけ読み出せれば十分です。ただし、実行速度は非常に遅いので場合によっては、読み出すデータの数によっては、スクリプト側でまとめて読み出さないと実用的ではないこともあります。

 まず、不連続なセルは以下のようにprint()で読み出すセルの位置を指定すればよいでしょう。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx',data_only=True)
ws = wb.active
print(ws['E2'].value)
print(ws['B7'].value)
print(ws['E7'].value)

改行ではなく,区切りにしたい場合は以下のように','をそれぞれ追加します。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx',data_only=True)
ws = wb.active
print(ws['E2'].value,',',ws['B7'].value,',',ws['E7'].value)

 不連続でなく連続してセルを読み出す場合は定番のforの繰り返し処理を利用します。Pythonの場合、for i in range(1,6)とすると1〜5までの繰り返しになります。
 以下のようにすると2行目の5つのセル(A2,B2,C2,D2,E2)の内容が読み出されます。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx',data_only=True)
ws = wb.active
for i in range(1,6):
  n = ws.cell(row=2, column=i)
  print(n.value)

 行の読み出しだから改行ではなく横1行にしたい場合もあります。rsコマンドが使えるなら(macOSではデフォルトで使えます)以下のように|(パイプ)を使ってrsコマンドにPythonの結果を渡します。

python e7.py | rs 

,区切りにしたい場合は以下のように指定します。

python e7.py | rs -C,

 コマンドでなくPythonで横1行にしたい場合は以下のようなプログラムになります。

import openpyxl
wb = openpyxl.load_workbook('Book1.xlsx',data_only=True)
ws = wb.active
for i in range(1,6):
  n = ws.cell(row=2, column=i)
  print(n.value,end=',')

 次回はシェルスクリプトと組み合わせて処理をしてみましょう。

著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。