OpenPyXl でチェックボックスを押したい

2022年12月15日 2023年11月8日
カテゴリ: プログラミング
Python Excel OpenPyXl

Python で Excel ファイルを扱う方法はいくつかありますが、その中でも OpenPyXl がメジャーなのかなと思っています。
OpenPyXl を使えば Excel ファイルを読み込んだり作成したり、大抵の操作はできます。
ただ、フォームコントロールの操作等、OpenPyXl では実現不可能な機能もあります。

今回、Excel ファイルを出力する機能がある Web アプリを制作していて DB の値によってチェックボックスをオンオフする必要があったのですが、OpenPyXl の正攻法では難しそうだったので色々検討してみました。

検討したこと

pywin32 を使う

pywin32 というライブラリを使用すればフォームコントロールの操作もできるようです。
ただ、残念なことに Windows 専用の様で Ubuntu 等の OS では導入できないみたいです。
(制作している Web アプリは OS が Ubuntu なので試してもいません・・・)

Windows 上で動かすシステムならこれで何とかなるかも。

Excel を扱うツールを作る

C# とかの MS 系の言語で Excel ファイルを扱うツールを用意して Web アプリから渡したデータを元に Excel を出力する、という方法を考えました。

問題点としては
・そもそも実現可能なのか
・C# の知見がほぼない
・チェックボックスを押すためだけにそこまで時間をかけたくない

といった感じです。

力技で乗り切る

OpenPyXl ではチェックボックス等を持った Excel ファイルを読み込むということ自体は可能です。
そして、出力する Excel にはチェックボックスが 8 個あり、データの内容によって複数選択もあり得ます。

そこで、予めチェックボックスを押しておいた Excel ファイルをすべてのパターンで用意しておけばよいのではと考えました。
8 個のチェックボックスのオンオフの組み合わせは 2 の 8 乗 (256 パターン) になります・・・。
イメージとしてはこんな感じ。

256 通りの Excel ファイルを用意して、データの内容によって使用する Excel ファイルを変えるということです。

まさに狂気・・・!

もしも、Excel の仕様が変わってチェックボックスが一つ増えたりすると、それだけで必要なファイル数は倍になります。

吐き気がしてきたのでこれも見送りました。

やっぱり、どうしても OpenPyXl でチェックボックスを押したい!

ということで OpenPyXl で何とかする方法を考えました。
なんてことはない、Excel の機能を利用すればよかったのです。

結論から言うと、チェックボックスをセルにリンクさせて、そのセルに値を入れるだけです。

まず、前提として出力する Excel ファイルの元となるテンプレを作成します。
それを OpenPyXl で読み込んで値を入力して新しいファイルを出力するという流れです。

テンプレートとなる Excel ファイルを用意する

まずは、[開発タブ] → [挿入] → [フォームコントロール] からチェックボックスを選択してシートに挿入します。

※ [開発タブ] がない場合は [リボンのユーザー設定] から追加します。
※ [ActiveX コントロール] はこの方法だと操作できません。

追加したチェックボックスを右クリック → [コントロールの書式設定] → [リンクするセル] にセルのアドレスを指定します。

この状態でチェックボックスを押すと・・・

リンクしたセルに 「TRUE」 と表示されますね。
この状態でチェックを外すと 「FALSE」 になります。

今度はセルの方に 「TRUE」 「FALSE」 または数値を入力してみましょう。

「TRUE」 または 0 以外の数値を入力するとチェック状態になります。
「FALSE」 または 0 を入力するとチェックは外れます。

OpenPyXl で Excel ファイルを読み込んで出力

Python のコードは次のような感じになります。

from openpyxl import load_workbook

wb = load_workbook("input.xlsx", keep_vba=True)

ws = wb["Sheet1"]

ws["B2"] = True
ws["B3"] = False
ws["B4"] = 1
ws["B5"] = 0

wb.save("output.xlsm")

OpenPyXl は入っていない場合は pip でインストールしましょう。

pip install openpyxl

ポイントとしては、Excel ファイルを読み込む際に load_workbook の引数に keep_vba=True を指定することと、出力するファイルの拡張子を xlsm にすることです。

出力したファイルを見てみると、ちゃんとチェックが入っていることが分かります。

リンクしたセルの値を隠したい場合は、リンクするセルを画面の端っこにしたり、フォントの色を白にしたり工夫してみてください。

関連の記事

【Django】CSS や JavaScript の変更が反映されないときの対処法

ExcelVBA で時間が正しく変換されない

Sphinxで作ったドキュメントの外部リンクを新しいタブで開く方法を考える

「GAKKOU」 問題を Python で解いてみよう