【Python】openpyxl:基本的なエクセル操作方法を徹底解説

2020.11.08 /

【Python】openpyxl:基本的なエクセル操作方法を徹底解説

PythonではExcel操作できるライブラリがいくつもあります。
その中で本記事は、openpyxlでの基本的なエクセル操作を解説していきます。

本記事で基本的なExcelの操作方法は網羅していると思います。

昔はVBAでマクロを組んで、自動化を会社では行っていました。
ですが今ではほとんどPythonで組むようになりました。

私のようにPythonでExcel操作ができれば、わざわざVBAを覚えてマクロを組む必要はなくなります。

ぜひこの機会にVBAからPythonに切り替えて、VBAから卒業してみましょう!

VBAをPythonで使用したい場合は、win32comを使用してください。win32comの使用方法は以下記事をご参照ください。

openpyxlとは

openpyxlはExcel 2010以降のエクセルファイルxlsx/xlsm/xltx/xltm形式のエクセルファイルを操作できるライブラリのことです。

Excelが使用するOffice Open XML形式ファイルの読み書きを行います。

Excelはアプリケーションを通してエクセルファイルを読み書きしますが、openpyxlはOffice Open XMLで直接ファイルの読み書きをしますので、ファイルを開く必要がありません。
そのためMicrosoft Excelがパソコンにインストールされていなくてもエクセルの操作が可能となっています。

openpyxlはエクセルを操作する多くの機能があり、様々なことが可能になっています。

公式サイトは以下になります。

OpenPyXL公式サイト

本記事ではバージョン3.0.5(2020年11月時点の最新版)のopenpyxlモジュールを使用しています。

openpyxlでのエクセルファイル構成

エクセルはエクセルファイル本体であるスプレッドシート(ブック)、その中に複数あるシート、シートに無数にあるセルで構成されています。

これらをopenpyxlではオブジェクトとして扱います。

  • スプレッドシート(ブック):Workbookオブジェクト
  • シート:Worksheetオブジェクト
  • セル:Cellオブジェクト

openpyxlでは、これらオブジェクトを操作してエクセルを編集していきます。

openpyxlモジュールのインストール

openpyxlモジュールはpythonの標準モジュールではないので、pipで別途インストールする必要があります。

pip install openpyxl

またPythonプログラム中でopenpyxlを使う際には、必ずプログラムの先頭でインポートすることを忘れないでください。

import openpyxl

ワークブック:新規作成・既存のファイルを開く

エクセルを使うとき、まず最初に何をしますか?

最初は操作するブックを新規で作成するか、既存のブックを選んで開きますよね。
ブックの新規作成(Workbook()関数)と既存のブックを開く方法(load_workbook()関数)を解説します。

openpyxl:ブックの新規作成・既存ファイルを開く

新規でエクセルファイルを作成(Workbook()関数)

新規にExcelファイルを作成する場合は、Workbookオブジェクトを作成します。
Workbookオブジェクトの作成にはopenpyxl.Workbook()関数を使用します。

import openpyxl
wb = openpyxl.Workbook()

新規でエクセルを作成すると、そのエクセル内には自動的に「Sheet」という名前のワークシートが作成されます。

wb = openpyxl.Workbook()
wb.get_sheet_names()
# ['Sheet']

既存エクセルを開く(load_workbook()関数)

既存のエクセルファイルを開く場合は、openpyxl.load_workbook()関数を使用します。

引数には開きたいエクセルのパス+ファイル名をとり、そのエクセルファイルのWorkbookオブジェクトを返します。

import openpyxl
wb = openpyxl.load_workbook('office54.xlsx')

読み込んだブックに対して書き込みをしたくない場合は、引数にread_only = Trueを与えます。
この引数を与えることで、読み込み専用でブックを取得できます。

wb = openpyxl.load_workbook('office54.xlsx', read_only = True)

load_workbook()関数にはこれ以外にも指定できる引数があります。
必要に応じて使い分けましょう。

引数 データ型 説明
read_only Boolean デフォルト:False 読み取り専用で開く
keep_vba Boolean デフォルト:False 元ファイルのVBAを保存する場合はTrueにする
data_only Boolean デフォルト:False 数式で計算された値を取得する場合はTrueにする
keep_links Boolean デフォルト:True 外部ワークブックへのリンクを保持する

シート:Worksheetオブジェクトを取得(指定)する

次にエクセルファイル内のシートを操作するための準備について説明します。
シート(シート内のセル)を操作するには、Worksheetオブジェクトに対して操作する必要があるため、まずはWorksheetオブジェクトをWorkbookオブジェクトから取得する必要があります。

Worksheetオブジェクトを取得する方法には、

  • アクティブシートのWorksheetオブジェクトを取得
  • シート名からWorksheetオブジェクトを取得
  • シートのインデックスからWorksheetオブジェクトを取得

の3つの方法があります。

シートには、アクティブシート・シート名・インデックスの情報があり、それらを使ってWorksheetオブジェクトを取得しています。

openpyxl:Worksheetオブジェクトの取得

アクティブシートのWorksheetオブジェクト取得

エクセルのアクティブになっているWorksheetオブジェクトを取得するには、Workbookオブジェクトに対してactiveを使用します。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb.active

activeをWorkbookオブジェクトに使用することで、アクティブシートのWorksheetオブジェクトが返されます。

シート名からWorksheetオブジェクト取得

シート名からそのシートのWorksheetオブジェクトを取得する方法は以下になります。

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

またget_sheet_by_name()関数を使ってシート名からWorksheetオブジェクトを取得することができます。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb.get_sheet_by_name('Sheet1')

しかし廃止が予定されているのか、現在get_sheet_by_name()関数を使用すると以下の警告が表示されます。

DeprecationWarning: Call to deprecated function get_sheet_by_name (Use wb[sheetname]).

そのためシート名からWorksheetオブジェクトを取得する場合は、前述の方法がおすすめです。

シートのインデックスからWorksheetオブジェクト取得

エクセルのシートは左からインデックス番号が0、1と付いています。
そのインデックスを指定して、シートのWorksheetオブジェクトを取得します。

シートのインデックスからWorksheetオブジェクトを取得するには、worksheets[]をWorkbookオブジェクトに対して使用します。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb.worksheets[0]

シート:挿入、削除、名前の変更

エクセルファイル内にシートを新たに挿入・削除・名前の変更をする方法を説明します。
実際のExcelのシート上で右クリックした際に行える操作ですね。

openpyxl:シートの挿入・削除・名前の変更

シートの挿入:creat_sheet()メソッド

新規にシートを挿入するにはWorkbookオブジェクトに対してcreate_sheet()メソッドを使います。

wb = openpyxl.load_workbook('office54.xlsx')
print(wb.sheetnames)
# ['Sheet']

wb.create_sheet()
print(wb.sheetnames)
# ['Sheet', 'Sheet1']

sheet()メソッドに引数を与えない場合は、Sheet*という名前が付けられます。
シート名を指定したい場合は、引数にシート名を与えます。

wb = openpyxl.load_workbook('office54.xlsx')
print(wb.sheetnames)
# ['Sheet']

wb.create_sheet('OFFICE54')
print(wb.sheetnames)
# ['Sheet', 'OFFICE54']

またシートが挿入される位置は、デフォルトでは末尾です。
挿入される位置を変更したい場合は、引数のシート名の後に挿入したいインデックス番号を入れます。

wb = openpyxl.load_workbook('office54.xlsx')
print(wb.sheetnames)
# ['Sheet']

wb.create_sheet('OFFICE54')
print(wb.sheetnames)
# ['Sheet', 'OFFICE54']

wb.create_sheet('No.0', 0)
print(wb.sheetnames)
# ['No.0', 'Sheet', 'OFFICE54']

wb.create_sheet('No.1', 1)
print(wb.sheetnames)
# ['No.0', 'No.1', 'Sheet', 'OFFICE54']

シートの削除:remove()メソッド、del文

シートを削除する方法は2種類あります。

  • Workbookオブジェクトに対してremove()メソッドを用いる
  • del文でWorksheetオブジェクトを指定して削除する

以下のサンプルプログラムを見ていただいて、使い方を確認してください。

wb = openpyxl.load_workbook('office54.xlsx')
print(wb.sheetnames)
# ['Sheet']

wb.create_sheet('OFFICE54')
print(wb.sheetnames)
# ['Sheet', 'OFFICE54']

wb.create_sheet('No.0', 0)
print(wb.sheetnames)
# ['No.0', 'Sheet', 'OFFICE54']

wb.create_sheet('No.1', 1)
print(wb.sheetnames)
# ['No.0', 'No.1', 'Sheet', 'OFFICE54']

シート:シート名の変更

シート名を変更するには、Worksheetオブジェクトのtitle属性を変更します。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet1']
ws.title = "OFFICE54"

シート:コピー(copy_worksheet()メソッド)

シートのコピーにはWorkbookオブジェクトに対してcopy_worksheet()メソッドを用います。

copy_worksheet()の引数には、コピーしたいシートのWorksheetオブジェクトを与えます。

wb = openpyxl.load_workbook('office54.xlsx')
print(wb.sheetnames)
# ['Sheet']

wb.copy_worksheet(wb['Sheet'])
print(wb.sheetnames)
# ['Sheet', 'Sheet Copy']

コピーされたシート名は元のシート名にCopyが加えられた名前になります。

セル:Cellオブジェクトを取得する

WorkbookオブジェクトからWorksheetオブジェクトを取得できたら、セルを操作する準備に入れます。

セルを操作する場合は、操作したいセルのCellオブジェクトを取得して操作します。
Cellオブジェクトの取得方法は2つあります。

  • Worksheetオブジェクトに対してセル番地を指定して取得する
  • Worksheetオブジェクトにcell()メソッドを用いて取得する

また取得したCellオブジェクトのvalue属性にアクセスすることで、セルの中身を取得できます。

以下に示すエクセルファイルに対して、セル操作を行います。

openpyxl:セル操作の対象エクセル

セル番地を指定して取得

Worksheetオブジェクトに対して、セル番地を与えることで、Cellオブジェクトを取得することができます。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']
print(ws['A1'].value)
# 54

cell()メソッドを用いて取得

Worksheetオブジェクトにcell()メソッドを用いることで、Cellオブジェクトが取得できます。

cell()メソッドの引数には、セルの行番号と列番号を与えます。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']
print(ws.cell(1,1).value)

前述のセル番地でCellオブジェクトを取得する方が直感的に簡単です。

しかしcellメソッドは繰り返し処理で、列または行が変わる処理で威力を発揮します。

プログラムによってCellオブジェクトの取得方法は使い分けましょう。

セル:範囲の指定方法

Worksheetオブジェクトに対して、マクロのようにセル番地で範囲指定することが可能です。

for文で範囲指定されたCellオブジェクトを1つずつ取得して操作できます。

openpyxl:Cellの範囲指定

A1からD5までを範囲指定して、その値を出力してみます。

import openpyxl
wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']
cells = ws["A1:D5"]

for row in cells:
    for cell in row:
        print(cell.value, end=' ')
    print()

# A1 B1 C1 D1
# A2 B2 C2 D2
# A3 B3 C3 D3
# A4 B4 C4 D4
# A5 B5 C5 D5

セル:Cellオブジェクトから取得できる座標と値

Cellオブジェクトから以下表ように座標やセルの値をを取得することができます。

説明
Cell.column 列(横軸)の番号
Cell.row 行(縦軸)の番号
Cell.coordinate セル番地
Cell.value セルの値

行列の挿入・削除

行の挿入・削除

行の挿入は、Worksheetオブジェクトに対して、insert_rows()メソッドを用います。

行の削除は、Worksheetオブジェクトに対して、delete_rows()メソッドを用います。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']

# 2行目に行を挿入する
ws.insert_rows(2)

# 4行目に行を4行挿入する
ws.insert_rows(4, 4)

# 3行目を削除する
ws.delete_rows(3)

# 5行目から7行目までを削除する
ws.delete_rows(5, 7)

列の挿入・削除

列の挿入は、Worksheetオブジェクトに対して、insert_cols()メソッドを用います。

行の削除は、Worksheetオブジェクトに対して、delete_cols()メソッドを用います。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']

# 2列目に列を挿入する
ws.insert_cols(2)

# 4列目に列を4列挿入する
ws.insert_cols(4, 4)

# 3列目を削除する
ws.delete_cols(3)

# 5列目から7列目までを削除する
ws.delete_cols(5, 7)

列幅・行高の変更

Excelでは列や行をドラッグして上下左右にマウスを動かせば、列幅や行高の変更ができましたね。
Pythonでは、Workbookオブジェクトが持っているrow_dimensionsとcolumn_dimensionsの属性を使い、列幅や行高の調整を行います。

列幅の変更(column_dimensions)

列幅はWorksheetオブジェクトに対して、column_dimensionsを用います。

column_dimensionsに列番号を与え、width属性を変更することで列幅を変更できます。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']
ws.column_dimensions['A'].width = 25

行高の変更(row_dimensions)

行高はWorksheetオブジェクトに対して、row_dimensionsを用います。

row_dimensionsに行番号を与え、height属性を変更することで行高を変更できます。

wb = openpyxl.load_workbook('office54.xlsx')
ws = wb['Sheet']
ws.row_dimensions[3].height = 25

行ごと・列ごとにCellオブジェクトを取得する

行ごとにCellオブジェクトを取得

行ごとにCellオブジェクトを取得するには、Worksheetオブジェクトに対して取得したい「行数」を指定します。

row = ws[3]
print(row)
# (<Cell 'Sheet'.A3>,)
for cell in row:
	print(cell.value)

上記では1行のみを指定しましたが、複数行を指定することも可能です。

row = ws[1:3]
print(row)

列ごとにCellオブジェクトを取得

列ごとにCellオブジェクトを取得するには、Worksheetオブジェクトに対して取得したい「列数」を指定します。
行数とは異なり数値ではなく、アルファベットで指定します。

col = ws['C']
print(col)
for cell in col:
	print(cell.value)

上記では1列のみを指定しましたが、複数列を指定することも可能です。

col = ws[1:3]
print(col)

ワークブック:変更を保存(save()メソッド)

編集したエクセルを保存するにはsave()メソッドを使用します。

save()メソッドで保存しない限り、いくらopenpyxlでエクセルを編集しても記録は残りませんので、忘れずに編集後はsave()するようにしましょう。

save()メソッドには、ファイル名を渡すことで、その名前でエクセルを保存することができます。

wb.save('ファイル名.xlsx')

そのため、既存のエクセルから読み込んだファイルを編集して保存する際は、別名で保存することで元のファイルを変更することなく、変更後のエクセルを別名保存できます。

エクセル表のデザイン

エクセルはただ値を入力するだけでは完成とは言えませんよね。フォントのサイズや色を変えたり、セルに背景色をつけるなどして理解しやすく見やすい表を作る必要があります。

もちろんopenpyxlではそういったデザインを行うことができます。

書式設定や背景色の変更はopenpyxl.stylesを利用します。
openpyxl.stylesの使い方については以下記事をご参照ください。

連載記事

Pythonによるエクセル操作の記事を定期的にアップしております。
ぜひエクセル仕事の効率化のためにご参照ください。