ExcelシートからQRコードを大量生成する

Python

Excel(MS-Office)には2013あたりから標準でバーコードを作成するライブラリがあります。このライブラリでシートに入力された値をQRコードにできます。さわったことがあるかたはご存じかと思いますが、このバーコード作成ライブラリ(Microsoft bar code control)はイマイチ使い勝手がよろしくないのです。

VBAには荷が重いQRコード作成

少量を作る場合なら、このライブラリでも問題にはなりません。が、大量に必要な場合間違いなく心が折れます。VBAでループを使って生成することも可能かと思われますが、何しろ出力がシート上のコントロールというトンデモ仕様なので、取りまわしがすこぶる悪いです。何よりShapeをはじめとした、セル外に存在する物体が私は大嫌いです。

そもそも大量にQRコードが必要な場面というのが、ニッチな気もしないでもないですが、CordovaなどでQRコードを読み取るスマホアプリを簡単に作成できるご時世ですので、例えば職場の備品管理で、備品に貼ったQRコードをスマホでバンバン読んでいくだけで、どれがあってどれがないというのが一覧になる、なんてのはそんなに難しいことをしなくても実現できます。PCに外付けでリーダーを取り付ければExcel-VBAで処理することも容易です。

実際、私も似たようなことをやろうとして「ExcelでQRコード作成問題」にぶち当たったわけです。

Pythonには余裕のQRコード作成

さて、どうしようかということでPythonにQRコードを扱うモジュールがないわけがないと調べてみると、当然あるわけで、じゃあ、ExcelシートをPythonでQRコードにしちゃえば良くね?となり、今回のツールが完成しました。

QRコードを作成するWEBサービスは多々ありますが、大量生成は想定されていません。本ツールはExcelをベースにすることで、管理番号などを連番で大量にQRコードにしたい場合、オートフィル、コピペ、関数といったExcel上の機能を総動員して簡単に作成できます。すでに管理台帳がExcelで整備されていれば、そのデータを丸ごと流用できます。

Python標準モジュール以外に、Excelファイルの扱いは神ツールOpenPyXLで、QRコード生成にはqrcodeモジュール、画像処理はpillowモジュールを使っています。

使用方法

1.このページ下部「アプリを入手する」からzipファイルをダウンロードします。
展開すると次のようなアプリ実行ファイルとExcelファイルがあります。

Excelファイルはこのアプリ専用にデザインされているので、セルの追加削除等をしないでください。Excelファイルには次のようなシートがあります。

2.データを入力します。

  • コード列にはQRコードに変換する文字列(重複不可、途中に空白行不可、必須)
  • 名称列には任意の識別名(30文字以下、省略化)

あらかじめ次のようなデータが入力されているので、そのままお試しいただけます。名称はオプション設定(後述)により、出力画像に表示したりファイル名にしたりできます。

実際に使用するときは、これを書き換えてお使いください。

3.Excelファイルを保存終了してアプリにドラッグ&ドロップします。
Windowsからセキュリティの警告がでることがありますが、自己責任で実行許可してください。

一瞬DOS窓が表示されますが、こいつの仕業です。データ数により時間がかかることがあります。


4.処理した結果がフォルダとして出力されます。

フォルダの中身はシートへ入力したデータをQRコード画像へ変換したPNGファイルになっています。

画像は用途に応じてご自由にお使いください。
※ファイル名に禁則文字が含まれている場合は_(アンダーバー)に置き換わっています。

オプション設定

シートのオプション設定により出力するQRコードにさまざまな効果を適用できます。

オプション設定の意味は次の通りです。

オプション設定値説明既定値
名称表示する or しないQRコードの左上に名称列の値を表示するかしない
文字サイズ数値名称表示の文字のサイズ14
フォントパス文字列名称表示の文字のフォントファイルのパスmeiryo.ttc
前景色セル色(RGB)QRコードのドット部分の色0,0,0
背景色セル色(RGB)QRコードの背景の色255,255,255
余白サイズ数値QRコードの枠部分の太さ4
ファイル名名称 or コードファイル名をコードにするか名称にするか名称

だいたいは見たままなのでわかるかと思われますが、色変更は(あまりオススメしませんが)方法が特殊なので補足します。

通常のメニューからセル色を変更すると色は相対的に設定されます。詳細は省略しますがExcelが色をテーマで管理して一括変更を可能にするために、色そのものではなく色のインデックスがつけられているだけの状態です。これだとPythonで色として取得することが(たぶん)できないので絶対値で指定する必要があります。

セルの書式設定 → 塗りつぶし → その他の色 → ユーザー設定タブ とすると次のような設定画面になります。

ここで、カラーモデルをRGBにしてそれぞれ数値で設定するか、カラーピッカーで選んで前景色、背景色の設定セルを塗りつぶしてください。

オプションを適用して出力したQRコード画像のサンプルは次のようになります。

左から
「名称表示する・他デフォルト」
「名称表示する・文字サイズ増・余白サイズ増・前景色変更」
「名称表示しない・前景色変更・背景色変更」
となっております。

枠の太さ(余白サイズ)はQRコードに収めるデータのサイズによって設定通りにならない場合があります。QRコードがデータを表現できないサイズになると余白側へ拡張されます。

ソースコード

スクリプトは次の通りです。得体の知れないサイトの実行ファイルなんて使えねーというかたはソースコードをコピペしてpyファイルにしてご利用ください。

import re
import os
import sys
import qrcode
import openpyxl as excel
from PIL import ImageFont, ImageDraw, ImageColor

try:
    excel_file_path = sys.argv[1]
    wb = excel.open(excel_file_path, data_only=True)
    ws = wb.active

    # シートの設定値取得
    name_visible = ws['c2'].value == 'する'
    file_name_is_code = ws['c13'].value == 'コード'
    font_size = ws['c4'].value if type(ws['c4'].value) is int else 14
    qr_border = ws['c11'].value if type(ws['c11'].value) is int else 4
    font_path = ws['d4'].value if os.path.exists(ws['d4'].value) \
        else r'C:\Windows\Fonts\meiryo.ttc'

    # 色はRGBで設定している場合のみ有効
    qr_fc = ws['c7'].fill.fgColor
    qr_bc = ws['c9'].fill.fgColor

    if qr_fc.type == 'rgb':
        fill_color = ImageColor.getcolor('#' + qr_fc.rgb[2:], 'RGB')
    else:
        fill_color = 'black'

    if qr_bc.type == 'rgb':
        back_color = ImageColor.getcolor('#' + qr_bc.rgb[2:], 'RGB')
    else:
        back_color = 'white'

    font = ImageFont.truetype(font_path, font_size)

    p = sys.executable if getattr(sys, 'frozen', False) else __file__
    cd = os.path.dirname(os.path.abspath(p))

    dst_dir = os.path.join(cd, 'qr_code_result')

    if not os.path.exists(dst_dir):
        os.mkdir(dst_dir)

    # QRコード生成保存
    for row in ws.iter_rows(min_row=2):
        if row[0].value is None:
            break
        code_str = str(row[0].value)
        name = row[1].value
        qr = qrcode.QRCode(border=qr_border)
        qr.add_data(code_str)
        qr.make()
        img = qr.make_image(fill_color=fill_color, back_color=back_color)

        if name_visible and name is not None:
            draw = ImageDraw.Draw(img)
            draw.text((10, 10), str(name)[:30], font=font, fill=fill_color)

        if file_name_is_code:
            s = code_str
        else:
            s = name

        fn = re.sub(r'[\\/:*?"<>|]+', '_', s)
        img.save(os.path.join(dst_dir, fn + '.png'), 'PNG')

except:
    print('エラーのため中断しました。')
    input()

エラーは握り潰すので、必要に応じてエラーハンドラーを追加してください。

アプリを入手する

このアプリに含まれるOpenPyXLモジュールはデフォルトではXMLの脆弱性を利用した攻撃を防ぐことはできません。信頼できないExcelファイルを処理しないでください。

利用上のご注意

  • ダウンロードしたファイルを利用したことにより生じた結果については、利用者ご自身に責任を負っていただきます。
  • ご利用前に使用方法をご確認ください。
  • 当方は成果物の正確性について最善を尽くしますが保証はいたしません。
  • Windows11 Microsoft365 環境でのみ動作確認済み。

Downloadボタンを押下した時点で注意事項に同意したものとみなします。

qr_code_generator.zip

おわり。