Azure Functions + PythonでOpenpyxlを使う
Microsoft Azure の Azure Functions を Python で作成し、Openpyxlを使って Excelファイルの入出力をおこないます。
ストレージは Azure Blob Storage を使い、Python v12 SDKを使って操作します。
この記事の前提条件
- アクティブなサブスクリプションが含まれる Azureアカウント がある
- Azureに ストレージアカウント が作成済である
- ChromeBook で開発する
- ChromeBook には VSCode がインストールされている
- HttpトリガーのFunctionが作成済である
SDKを使用して Azure Blob Storage を操作する方法は、次の記事を参考にしてください。
パッケージのインストール
local.settings.jsonの編集
Pythonの外部ライブラリを使用するためlocal.settings.json
に"PYTHON_ENABLE_WORKER_EXTENSIONS": "1"
を追加します。
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "<Blob Storageへの接続文字列>",
"FUNCTIONS_WORKER_RUNTIME": "python",
"PYTHON_ENABLE_WORKER_EXTENSIONS": "1"
}
}
openpyxlのインストール
ローカル環境にopenpyxl
をインストールします。
VSCodeのターミナルで対象プロジェクトのディレクトリに行き、次のコマンドでインストールします。
pip install openpyxl
requirements.txtに追加
インストールした「openpyxl」を依存パッケージの一覧であるrequirements.txt
にも追記します。バージョンはローカル環境にインストールしたものに合わせます。
Azureにデプロイする際にシステムによってインストールされます。
azure-functions
azure-storage-blob
openpyxl == 3.0.9
Python関数の編集と実行
Httpトリガーで起動された関数が、Azure Blob Storage 上のExcelファイルを読み取り、既存シートの最下行のセルに値を書き込むというプログラムを書いていきます。Excelファイルが存在していなかった場合には、新たにファイルを作成して新しいシートを追加した上で、値を書き込みます。
プログラムの全体像
- Azure Blob Storage に接続し、BLOBを操作するために BlobClient オブジェクトへの参照を取得します
- 対象となるExcelファイルが存在している場合は、一旦ダウンロードして
openpyxl
で読み込みます - Excelファイルが存在しない場合には、新たに
openpyxl
のオブジェクトを用意します - 「datasheet」というシートの最下行のセルに値を書き込みます
- 一時ファイルを作成し、編集した
openpyxl
のオブジェクトをExcelファイルとして保存します - 保存した一時ファイルを Azure Blob Storage にアップロードします
import logging
import azure.functions as func
import os
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, __version__
from tempfile import NamedTemporaryFile
import openpyxl
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
# Blob Storage へ出力するファイルの準備
# 出力するExcelファイルは仮にsample.xlsxとします
connect_str = os.environ['AzureWebJobsStorage']
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
blob_client = blob_service_client.get_blob_client(container='container/sdk-sample', blob='sample.xlsx')
if blob_client.exists():
# ファイルが存在している場合はいったんダウンロードしてopenpyxlで読み込みます
with NamedTemporaryFile('wb',suffix='.xlsx') as xltmp:
xltmp.write(blob_client.download_blob().readall())
wb = openpyxl.load_workbook(xltmp.name)
# datasheetシートに書き込みます
ws = wb["datasheet"]
maxrow = ws.max_row
else:
# ファイルが存在しない場合はExcelブックのオブジェクトを作成します
wb = openpyxl.Workbook()
wb.create_sheet(title="datasheet")
ws = wb["datasheet"]
maxrow = 0
ws.cell(row=maxrow+1,column=1).value = "Hello"
ws.cell(row=maxrow+2,column=2).value = "world."
# 一時ファイルを作成しExcelブックとして保存します
with NamedTemporaryFile('wb',delete=False) as tmp:
wb.save(tmp.name)
# 一時ファイルをいったんクローズしたあと再度オープンし、Blob Storageにアップロードします
# その際、ファイルは上書きします
with open(tmp.name, "rb") as data:
blob_client.upload_blob(data,overwrite=True)
# 一時ファイルを削除します
os.remove(tmp.name)
return func.HttpResponse(f"ok.")
1.BlobClient オブジェクトへの参照を取得する
環境変数「AzureWebJobsStorage」から Azure Blob Storage への接続文字列を取得します。ローカルでの開発時にはlocal.settings.json
の値が参照され、Azure上でサービスを実行する場合には、Azure Functionsのアプリケーション設定に設定されている同キーの値が参照されます。
その接続文字列を使って Azure Storage リソースと BLOB コンテナーを操作を操作するためのBlobServiceClient
を用意し、さらにBLOB を操作するためのBlobClient
オブジェクトへの参照を取得します。
ここでは、予め Azure Blob Storage 上に、コンテナ「container」、ディレクトリ「sdk-sample」を作成しておくものとします。
BlobClient
オブジェクトのexists()
メソッドで、Blob Storage上に対象のExcelファイルが存在しているかの判定をします。
connect_str = os.environ['AzureWebJobsStorage']
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
blob_client = blob_service_client.get_blob_client(container='container/sdk-sample', blob='sample.xlsx')
if blob_client.exists():
2.Excelファイルが存在している場合は、一旦ダウンロードしてからopenpyxlで読む
Excelファイルが存在していた場合は、BlobClient
オブジェクトのdownload_blob()
メソッドを使って、BLOBをダウンロードしそれを一時ファイルに書き込みます。
openpyxl
で読み込めるようにするため、一時ファイルは拡張子として「.xlsx」を指定して作成します。
ファイルの新規作成時に「datasheet」というシートを作成してあるので、そのワークシートを指定してmax_row
でデータの入力されている最下行を取得しておきます。
with NamedTemporaryFile('wb',suffix='.xlsx') as xltmp:
xltmp.write(blob_client.download_blob().readall())
wb = openpyxl.load_workbook(xltmp.name)
ws = wb["datasheet"]
maxrow = ws.max_row
3.Excelファイルが存在しない場合は、openpyxlを用意する
Blob Storage上に対象のExcelファイルが存在していなかったらopenpyxl
で新たにワークブックとシートを作成します。
今回は、新しくワークブックを作成したときにデフォルトで作成されるシート「Sheet」は無視して、「datasheet」というシートを追加します。
wb = openpyxl.Workbook()
wb.create_sheet(title="datasheet")
ws = wb["datasheet"]
maxrow = 0
4.Excelを編集し、作成した一時ファイルに保存する
対象のシート最下行のセルに値を書き込みます。openpyxl
のsave()
メソッドはファイル名を指定する必要があるので、新たに一時ファイルを作成してその名前を渡します。
あとでアップロードするので自動的に削除はしないでおきます。
with NamedTemporaryFile('wb',delete=False) as tmp:
wb.save(tmp.name)
5.編集後のファイルをアップロードする
openpyxl
で保存した編集後のExcel一時ファイルを、再度オープンしてBlobClient
オブジェクトのupload_blob()
メソッドを使ってBLOBをアップロードします。
with open(tmp.name, "rb") as data:
blob_client.upload_blob(data,overwrite=True)
実行結果
関数を実行すると1度目の実行で Azure Blob Storage に sample.xlsx
が新規作成されます。2度目の実行で、1度目に作成した「datasheet」の最終行の次のセルから、同じ値が書き込まれます。
1度目の実行
2度目の実行
まとめ
本記事では Python で作成した Azure Functions で、Openpyxl を使って、Azure Blob StorageでExcelファイルを入出力する方法を紹介しました。
Blob Storage での入出力に気をつければ、あとはOpenpyxlの世界の話になるのでOpenpyxlでできることの範囲でExcelを操作できます。
Azure上でデータベースのデータをExcelに出力したり、Application InsightsのデータをExcelで加工することなどにも使えます。
'なんでもExcel'には賛否あると思いますが、Excelは非エンジニアでも使えるので、必要なデータをExcelに出力することで、部門間や役割を超えて、情報の共有がしやすくなるのではないかと思います。
参考
Discussion