久保、文章書きます

書きたいことを好き勝手書きます。備忘録的な感じです。

【Python】Excelのフォーマットを一括で整えるツールをGUIで作った

だいぶお久しぶりです。
生きてます。

今回はPythonのライブラリである「PySimpleGUI」というものの存在を知ったので使ってみました。

作るもの

せっかくなら今まで仕事をしてきて自動化できたら楽だなと思っていることを実現するためのツールを作成しようと思いました。
仕事上、大量のExcelファイルの受け渡しを行う機会がそれなりにあり、その度に1つ1つのファイルのフォーマットを確認することが時間の無駄なので自動化しようと思います。

  • 先頭シートをアクティブシートにする
  • 全シートのアクティブセルをA1にする
  • 全シートの表示倍率を100%にする

仕事上、上記の内容をフォルダ内のExcelに対して一括で設定できれば楽になると考えました。
また、「3のうち2つだけ設定したい」といったような場合も考慮し、GUIで対応する設定内容を選択できるようにしたいと思いました。



使用ライブラリ

・PySimpleGUI
 →簡単にGUI作れるライブラリ
github.com


・openpyxl
 →PythonExcelファイルを操作するためのライブラリ
github.com

ソースコード

import PySimpleGUI as psg
import os
import openpyxl

# レイアウト設定
layout = [
    [psg.Text("Excelファイルを一括更新する親フォルダを選択してください")],
    [psg.Text("フォルダ"), psg.InputText(key="folder"), psg.FolderBrowse()],
    [psg.Checkbox("アクティブシートを先頭シートにする", key="activeSheet")],
    [psg.Checkbox("全シートのアクティブセルをA1にする", key="activeCell")],
    [psg.Checkbox("全シートの表示倍率を100%にする", key="zoom100")],
    [psg.Button("実行", size=(7, 1), key="execution")],
    [psg.Button("終了", key="exit")],
]

window = psg.Window("Excelフォーマット一括設定", layout)

while True:
    event, value = window.read()
    # 実行ボタン押下時のイベントを定義
    if event == "execution":
        # 処理前にエラーチェックを実施
        # ERROR:対象フォルダが選択されていない場合
        if not value["folder"]:
            failMsg = "【ERROR】フォルダを選択してください"
            psg.popup(failMsg)
            continue

        # ERROR:対象フォルダが存在しない場合
        if not os.path.exists(value["folder"]):
            failMsg = "【ERROR】フォルダが存在しません"
            psg.popup(failMsg)
            continue

        # ERROR:対象がフォルダではない場合
        if not os.path.isdir(value["folder"]):
            failMsg = "【ERROR】フォルダを選択する必要があります"
            psg.popup(failMsg)
            continue

        # ERROR:処理内容のチェックボックスが1つも選択されていない場合
        if (
            value["activeSheet"] == False
            and value["activeSheet"] == False
            and value["zoom100"] == False
        ):
            failMsg = "【ERROR】処理内容を選んでください"
            psg.popup(failMsg)
            continue

        # 指定されたフォルダ内のファイル分だけ繰り返し
        for root, dirs, files in os.walk(value["folder"]):
            for file in files:
                ext = os.path.splitext(file)[1]
                ext = ext.lower()
                # 拡張子が.xlsxのファイルのみ処理対象とする
                if ".xlsx" in ext:
                    # 絶対パス組み立て
                    abs = value["folder"] + "/" + file
                    # 対象ファイル読み込み
                    wb = openpyxl.load_workbook(abs)

                    # 先頭シートをアクティブシートにする処理
                    if value["activeSheet"] == True:
                        # シートの選択状態を解除
                        for ws in wb.worksheets:
                            ws.sheet_view.tabSelected = False
                        wb.active = wb.worksheets[0]
                        # 保存
                        wb.save(abs)

                    # 全シートのアクティブセルをA1にする処理
                    if value["activeCell"] == True:
                        cell_no = "A1"
                        for ws in wb.worksheets:
                            sv = ws.sheet_view
                            sv.selection[0].activeCell = cell_no
                            sv.selection[0].sqref = cell_no
                            sv.selection[0].activeCellId = None
                        # 保存
                        wb.save(abs)

                    # 全シートの表示倍率を100%にする処理
                    if value["zoom100"] == True:
                        zoom_scale = 100
                        for ws in wb.worksheets:
                            sv = ws.sheet_view
                            sv.zoomScale = zoom_scale
                            sv.zoomScaleNormal = zoom_scale
                        # 保存
                        wb.save(abs)

        # 処理完了時の表出メッセージを組み立て
        exeMsgs = list()
        if value["activeSheet"] == True:
            exeMsgs.append("・アクティブシートを先頭シートにする")
        if value["activeCell"] == True:
            exeMsgs.append("・全シートのアクティブセルをA1にする")
        if value["zoom100"] == True:
            exeMsgs.append("・全シートの表示倍率を100%にする")

        compMsg = "以下の処理が完了しました"
        for exeMsg in exeMsgs:
            compMsg = compMsg + "\n" + exeMsg

        psg.popup(compMsg)
        break

    elif event is None:
        break

    if event == "exit":
        break

作ったもの

対象のフォルダを選択して、そのフォルダ内のExcelファイルに対してラジオボタンで選択した操作を行います。



以上のような設定がバラバラのシートを用意して、全てのラジオボックスにチェックを入れて実行すると。。



フォーマットが統一されました!!
(画像では分かりづらいですがSheet1がアクティブシートになった状態で保存されています。)




最後に

「PySimpleGUI」の簡単さに驚きました。
GUIの実装はかなり面倒なイメージがあったのですが、ほんの数行で書けてしまいました。

Excelのフォーマットは様々な人が関わっているプロジェクトでは必ずと言っていいほどバラバラになってしまいがちなので、このツールの

今後、時間があればexe化するところまでやってみたいと思いました。


おわり