Pythonまとめ(openpyxlライブラリ)

エクセル操作(openpyxl)

openpyxlライブラリを使うとエクセルファイルの操作が行える。注意点としてこのライブラリは数式の計算はできない。なのでopenpyxlでデータを更新したとしても、その計算結果をopenpyxlで取得することはできない。それにはopenpyxlでデータの更新だけ行い、再計算はExcelに委ねる。なお、Excelは最後の計算結果を保存しているため、最後にファイルを保存したときの計算結果は取得できる。

本稿では既存のエクセルファイルを単純に読み書きするための操作を中心に記載しており、条件付き書式やビュー、テーブル、チャートなどの項目については記載していない。

クラス構造

openpyxlでは主にWorkbook、Worksheet、Cellの3つのクラスを扱う。エクセルファイルがWorkbook、シートがWorksheet、セルがCellに対応している。

Workbook

エクセルファイルに相当するのがWorkbookである。ファイルをオープンすれば作成される。なお、openpyxlで開いたエクセルをそのまま保存すると一部データが失われることがあるため、別名で保存するが、保存しないで閉じること。

>>> excel = openpyxl.load_workbook(file, data_only=True)
>>> type(excel)
<class 'openpyxl.workbook.workbook.Workbook'>

既存のエクセルファイルを開くのではなく、新規に作成するのであれば新規オブジェクトを作成するだけでよい。そうすれば1つのシートを持つWorkbookが作成される。

>>> wb = openpyxl.Workbook()
>>> type( wb )
<class 'openpyxl.workbook.workbook.Workbook'>

Workbookの作成・保存

openpyxl.load_workbook関数でエクセルファイルを開き、Workbookオブジェクトを得られる。load_workbookでは引数で以下のオプションを指定できる。

オプション意味デフォルト値
fileエクセルファイルのパス
read_only読み込み専用で開くFalse
keep_vbaVBAマクロを保持するFalse
data_onlyセルの値として、数式は最後の計算結果を使用するFalse
keep_links他のエクセルへのリンクを保持するTrue
rich_textセルのリッチテキスト情報を保持するFalse

保存するにはWorkbook.saveメソッドを使う。繰り返しとなるがopenpyxlではデータが失われることがあるため別名保存を基本としたほうが良い。

分類項目サンプルコード実行サンプル
保存Workbookを保存wb.save(r'C:\Users\...')-

Workbookの操作

Workbookはファイル全体で共通な情報やワークシートの情報を保持しており、それらを追加や削除するメソッドも提供している。

分類項目サンプルコード実行サンプル
シート関連シート名の一覧を取得wb.sheetnames['Sheet1', 'Sheet2']
シートの一覧を取得wb.worksheets[<Worksheet "Sheet1">,<Worksheet "Sheet2">]
シート名でシートを取得wb[ 'Sheet1' ]<Worksheet "Sheet1">
アクティブなシートを取得wb.active<Worksheet "Sheet1">
シートをアクティブにするwb.active = wb["Sheet2"]戻り値なし
シートを追加wb.create_sheet( 'Sheet3', 0 )
# 2つめの引数は追加する位置

wb.sheetnames
<Worksheet "Sheet3">

['Sheet3', 'Sheet1', 'Sheet2']
シートを削除wb.remove( excel["Sheet2"] )
wb.sheetnames

['Sheet3', 'Sheet1']
シートのインデックスを取得wb.index( excel['Sheet1'] )1
シートを移動wb.move_sheet('Sheet1', -1)
wb.sheetnames

['Sheet1', 'Sheet3']
名前関連名前の一覧を取得wb.defined_names.keys()['Name1', 'Name2']
名前が参照する範囲を取得wb.defined_names['Name1'].value'Sheet1!$A$11'

Worksheet

Worksheetではシート個別の情報やシート内のセルを取得するためのメソッドが提供される。

セルアクセス

分類項目サンプルコード実行サンプル
セル関連セルを取得1ws['A1']<Cell 'Sheet3'.A1>
セルを取得2ws.cell(row=1,column=1)
# 番号は1から始まる
<Cell 'Sheet3'.A1>
セルに値を設定して取得ws.cell(row=2,column=1,value='test')<Cell 'Sheet3'.A2>
結合されたセルの一覧を取得ws.merged_cells<MultiCellRange [A11:C11 D11:E13]>
行・列関連有効な範囲のセルを取得ws.rows # 行単位の操作用
ws.columns # 列単位の操作用

※データのない範囲のセルはこれでは取得できない
generator object
空行を追加ws.insert_rows( 2, 3) # 2行目の上に空行を3行追加-
行を削除ws.delete_rows( 2, 3) # 2行目から3行を削除-
空の列を追加ws.insert_cols( 2, 3) # 2列目の左に列を3列追加-
列を削除ws.delete_cols( 2, 3) # 2列目から3列を削除-
範囲操作指定範囲のセルを取得# 以下はどちらもC1:D5を取得する。並びが行基準か列基準かの違いのみ
ws.iter_rows(min_row=1, max_row=5, min_col=3, max_col=4)
ws.iter_cols(min_row=1, max_row=5, min_col=3, max_col=4)
generator object
指定範囲のセルの値を取得# 以下はどちらもC1:D5を取得する。並びが行基準か列基準かの違いのみ
ws.iter_rows(min_row=1, max_row=5, min_col=3, max_col=4, values_only=True)
ws.iter_cols(min_row=1, max_row=5, min_col=3, max_col=4, values_only=True)
generator object

Cell

Cellではそのセルの座標や値に関する情報を取得できる。

分類項目サンプルコード実行サンプル
値関連セルの値を取得cell.value
2023-08-11
戻り値はstr,int,float,datetime,time,bool,Noneのいずれか
セルに値を設定cell.value = 'newvalue'-
セルの値の種別cell.data_typen : 数字(または空)
s : 文字列
b : 論理値
f : 数式
e : エラーコード
座標関連セルの座標を取得cell.coordinateC3
セルの行番号、列番号を取得cell.row
cell.column
3
3
セルの列名を取得cell.column_letterC
その他シートを取得cell.parent<Worksheet "Sheet1">
相対位置にあるセルを取得cell.offset(2,3)
# 今のセルから2行下、3行右のセル
<Cell 'Sheet1'.E5>
コメントを取得cell.commentComment型

ユーティリティ

エクセル操作に役立つユーティリティも用意されている。以下のソッドはいずれもopenpyxl.utils.cellモジュールにありインポートが必要である。

項目サンプル実行例
セル範囲文字列をバウンダリを表すタプルに変換range_boundaries('A3')
range_boundaries('A3:C5')

(1, 3, 1, 3)
(1, 3, 3, 5)
# min_col、max_col、min_row、max_rowの順
セル範囲文字列をセル座標のタプルに変換
cols_from_range('A1:B3')


rows_from_range('A1:B3')

# ジェネレータが得られる。以下は出力例
('A1', 'A2', 'A3')
('B1', 'B2', 'B3')

('A1', 'B1')
('A2', 'B2')
('A3', 'B3')
セル参照文字列をタプルに変換range_to_tuple('sheet1!A3:C5')('sheet1', (1, 3, 3, 5))
列番号の変換get_column_letter(3)'C'
列名の変換column_index_from_string('C')3
列範囲の変換get_column_interval(3,5)
get_column_interval('G','I')
['C', 'D', 'E']
['G', 'H', 'I']

サンプル

いくつかエクセル操作のサンプルを示す。

単純なデータの読み込み

フラグdate_only=Falsedate_only=True
サンプルimport openpyxl

excel = openpyxl.load_workbook( r"C:\Users\...." )
print( excel['Sheet1']['C1'].value )
import openpyxl

excel = openpyxl.load_workbook(r"C:\Users\....", data_only=True )
print( excel['Sheet1']['C1'].value )
実行結果=A1+B15

指定範囲の参照

import openpyxl 

wb = openpyxl.load_workbook(file)
ws =wb['Sheet1']

for row in ws.iter_rows(1,3,1,3):
    for cell in row:
        print( cell.value, end="")
    print()
A1B1C1
A2B2C2
A3B3C3

全データの処理

import openpyxl

wb = openpyxl.load_workbook(file)
ws = wb['Sheet1']

for rowvalues in ws.values:
    print( rowvalues )
(1, None, None, None, None)
(None, 2, None, None, None)
(None, None, 3, None, None)
(None, None, None, 4, None)
(None, None, None, None, 5)

空白セルのvalueにはNoneが入っている。Noneを手軽に空文字列にしたいならcell.value or ''でできる。ただし、これは論理値Falseが入っているときも空文字になるため、論理値が入っていない前提のときに使うか、cell.value if cell.value is not None else ''のようちゃんとチェックする。

様々なデータのタイプ

B4,C4には数式が入っており、D4は文字列#N/Aが入っている

import openpyxl

wb = openpyxl.load_workbook(file)
ws = wb['Sheet1']

for row in ws:
    for cell in row:
        print(f"{cell.value} {type(cell.value).__name__} {cell.data_type}")
    print()
項目data_only=Falsedata_only=True
数値2 int n
1.5 float n
3.112 float n
2 int n
1.5 float n
3.112 float n
日時2023-08-11 00:00:00 datetime d
2023-08-11 12:50:00 datetime d
12:50:00 time d
2023-08-11 00:00:00 datetime d
2023-08-11 12:50:00 datetime d
12:50:00 time d
論理/空白True bool b
False bool b
None NoneType n
True bool b
False bool b
None NoneType n
数式/エラー=MATCH("5",B1:D1) str f
=NA str f
N/A str e
N/A str e
NAME? str e
N/A str e

エラーは単なる文字列であり、data_typeではエラーの文字列と一致しているか見ているだけなので、D4の文字列#N/Aもエラーとして判定される。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です