【プログラミング】PythonでExcelのセルの値を取得する方法

Excel

前回の記事でPythonでExcelのシートを取得してセルの値を取得しました。

https://doku-pro.com/?p=493

セルの値を取得することに関してほとんど詳しく触れませんでしたが、Excelを操作するときの必須の技術なので、本記事で詳しく紹介させていただきます。

・本記事では、Pythonからエクセルのセルの値を自由に弄る術を身につけることができます
PythonからExcelを操作する基本の部分を習得している方向けの記事です。

OpenPyXLでExcelを操作する下準備

前回の記事で、PythonからExcelを想いのままに操るのためには「OpenPyXL」というモジュールが必要であることを紹介しました。前回のように「都道府県ランキング」のExcelシートを用いて解説します。
一緒に進めたい方は、下からダウンロードしてください。

前の記事のように、上のファイルを今から作るPythonファイルと同じ階層(カレントディレクトリ)に配置してください。
次に、Pythonファイルに次のコードを記述してください。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

ここまでは、コチラの記事で紹介しているので割愛します。

PythonでExcelのセルの値を取得

Excelのセルを取得する方法は以下の通りです。

  1. sheet[‘A1’]を使う
  2. sheet.cell(row=1, column=1)を使う
  3. list(sheet.columns)[1]を使う
  4. list(sheet.rows)[1]を使う

例えば、次のコードを書いて実行してみてください。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

print(sheet['A1'].value)

すると、A1のセルに格納された、「住みたい県ランキング」という文字列が表示されたと思います。

それでは詳しくみていきましょう。

sheet[‘A1’]でセルの値を取得

>>> sheet['A1']
<Cell ‘Sheet1’.A1>#sheet[‘A1’]で返されるオブジェクト

上のように、sheet[‘A1’]は、<Cell ‘Sheet1’.A1>というCellオブジェクトを返します。Cellオブジェクトにはvaluerowcolumncoordinateという属性があり、ドットで属性値を続けることで、それぞれに対応した値を取得することができます。

「何を言っているかわからない」と言わずに、次のようなコードを書いてみてください。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

print(sheet['A1']) #A1セルのCellオブジェクトを返す
print(sheet['A1'].value) #A1セルの値を返す
print(sheet['A1'].row) #A1セルの行番号を返す
print(sheet['A1'].column) #A1セルの列番号を返す
print(sheet['A1'].coordinate) #A1セルの場所、つまりA1を返す

rowとは行列の行のことであり、columnは行列の列のことです。横方向が行で、縦方向が列です。これはよくこんがらがってしまいますね。
参考:ひと目でわかる行列(Row ・ Column)の方向の覚え方

上のコードの実行結果は次のようになります。

pythonでExcelのセルの値を取得
上記コードの実行結果です

つまり、valueはセルの中身の値、rowはセルが何行目にあるか、columnはセルが何列目にあるか、coordinateはセルが何行何列目にあるかを取得します。

また、この方法では、複数のセルを取得することもできます。

sheet['A3':'D49']

とすると、A1セルからD49セルまでの値をタプルとして取得することができます。
参考:【python】リスト、タプル、辞書にデータを格納
タプルとして複数の値が格納されているので、「sheet[‘A3′:’D49’].value」としても値を取得できません。for文でループを作ってやる必要があります。
参考:【for文】Pythonの繰り返し処理を実践してみた

例えば、次のようなコードを実行してみてください。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

many_values = sheet['A3':'D49']
for i in many_values:
	print(i[0].value, i[1].value, i[2].value, i[3].value)

すると、エクセルシートのランキングに関する値が全て取得できます。

excelの全てのセル値を同時に取得
上記のコードの実行結果です
タプルとしてセルの値が取得される
for文を回すイメージです

cell()メソッドでセルの値を取得

まずはcell()メソッドでどのような値が返されるのか確かめてみましょう。

>>> sheet.cell(row=1, column=1)
<Cell 'Sheet1'.A1>

こうしてみると、先ほどのSheet[‘A1’]で取得できる値と等しいことが分かったと思います。
基本的に使い方は先ほどのものと同じです。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

print(sheet.cell(row=1, column=1)) #A1セルのCellオブジェクトを返す
print(sheet.cell(row=1, column=1).value) #A1セルの値を返す
print(sheet.cell(row=1, column=1).row) #A1セルの行番号を返す
print(sheet.cell(row=1, column=1).column) #A1セルの列番号を返す
print(sheet.cell(row=1, column=1).coordinate) #A1セルの場所、つまりA1を返す

value属性でセルの値、row, column, coordinate属性でセルの情報を取得できます。
先ほどと異なるのは、セルの指定の仕方です。Sheet[‘A1’]では、一つの値でセルを指定しています。しかしcell(row=1, column=1)では、行と列それぞれを指定することで、二つの値から一つのセルを指定しています。

このメリットは、次のコードを実行していただければ一目瞭然でしょう。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

for i in range(1, 50):    #iが1~49までの間for文を繰り返す
    print(sheet.cell(row=i,column=1).value) #i行、1列(iは1から49まで変化)のセルの値を表示

すると、Excelの一行目の値が全て表示されます。

pythonでExcelのセルの値を取得
一行目の値がすべて表示されます。

つまり、for文との相性が非常に良いことが分かると思います。

sheet.columnsかsheet.rowsでセル値を取得

最後に、sheet.columnsを使えば行のセルを、右から左まで全部取得でき、sheet.rowsを使えば列のセルを上から下まで全部取得できます。
ただし、sheet.columnとsheet.rowsはジェネレーターオブジェクトであり、これまでと扱い方を少し変えなければなりません。いったいどういうことでしょうか?

>>> sheet.columns
<generator object Worksheet._cells_by_col at 0x122fc7d00> #列を基準としたジェネレーターオブジェクトですよ、という意味

例えば、sheet.columnsには、ジェネレーターオブジェクトとして、シートの情報が全て格納されています。これを、なじみのある方法で扱うには、リスト化するかタプル化するかしてやればよいので、list(sheet.columns)とするかtuple(sheet.columns)とします。

list(sheet.solumns)とすれば、二重のリストが生成されます。

pythonにおけるエクセルのセルのリスト化
二重のリストとになります。

また、tuple(sheet.columns)とすれば二重のタプルが生成されます。

それではサンプルのコードを見て理解を深めましょう。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

ranking = list(sheet.columns) #rankingという変数にリスト化されたExcelデータを格納

print(ranking[0]) #1列目のすべてのセルオブジェクトを上から下まで取得したものを表示
print(ranking[1][1]) #二重のリストなので特定のセルを取得するには[][]が必要

for i in ranking[1]: #2列目のセル情報を上から下まで一つずつ表示
    print(i.value)

リストのn番目の要素にアクセスするためにはリストに続けて[n-1]を付け足す必要がありました。

参考:【python】リスト、タプル、辞書にデータを格納

sheet.rowsの場合も扱いかたは同じです。単純に、横方向のセルを取得するようになる、という違いだけです。

おわりに

いかがでしたでしょうか?PythonでExcelを操作するためには、セルの値を駆使する必要があります。よって、以下にセルを取得するかが重要となってきます。

最後に、Excelのランキングシートを用いて、それぞれの県のランキングの浮き沈みについて出力するプログラムを書いてみました。

import openpyxl

wb = openpyxl.load_workbook('住みたい都道府県ランキング.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

many_values = sheet['A3':'D49']
for i in many_values:
	if i[1].value - i[0].value > 0:
		print(i[2].value,'は、昨年よりも',abs(i[1].value - i[0].value),'位ランキングが上がりました')
	elif i[1].value - i[0].value == 0:
		print(i[2].value,'は昨年と同順位です')
	else:
		print(i[2].value,'は昨年よりも',abs(i[1].value - i[0].value),'位ランキングが下がりました')

すると、出力は次のようになります。

pythonでExcelを操作
出力はこのようになります

ここまでできるようになると、さらに応用させられそうで、ワクワクしてきますね。
OpenPyXLモジュールでは、Excelのグラフを作ってしまったりと、できることは本当にたくさんあります。これからも紹介してまいりたいと思います。どうぞよろしくお願いします。

最後に、この記事を書くにあたって参考にした、大変すばらしい書籍を案内させていただきます。

退屈なことはPythonにやらせよう 第二版