見出し画像

[Python]zipファイル作成ツール

久しぶりにnote書きます。今年の目標書いて以来だ。。(汗)

ノンプロ研というコミュニティで主にプログラミング等の勉強をしています。普段はPythonを使って業務自動化、データ加工とか、スクレイピングをやったりしています。
今回は、Pythonで普段の業務をちょっとだけ楽にできるツールを作りました。以下の処理をPythonで実現しています。

  • zipファイル生成

  • 今日の日付が入ったファイル名にする

  • ファイルサイズ取得

  • フォルダにあるファイル一覧を取得

  • 取得した文字列情報をクリップボードにコピー

  • 取得した文字列情報をテキストファイルに書き込み

  • GUIで処理の分岐を制御

そもそもの始まりは

仕事で社外にファイルを転送するという業務が週に1回程度あります。諸事情によりファイル転送システムを使う関係で、ちょっとだけ面倒な作業があります。

  1. 転送するファイルは1つのzipファイルにまとめる

  2. 転送するファイルは台帳管理していて、台帳にzipファイル名を記載する

  3. 転送先にメールで、zipファイル名、ファイルサイズ、zip前のファイル一覧を連絡する

どれも大した作業ではないのですが、地味に面倒です。特に3番目のファイルサイズとzip前のファイル一覧を取るのがちょっとだけ面倒です。
(ファイル数が多い場合はコマンドプロンプトで一覧を取得してました)

ということで、地味に面倒な作業だけPythonで自動化してみました。

ツール概要

ツールでやらせたことは以下です。

  1. (事前準備)データ格納用フォルダに転送したいファイルを格納する

  2. スクリプトを実行してGUI起動

  3. 業務名(zipファイル名のヘッダになる)をボタンで選択

  4. zipファイル作成

  5. zipファイル名、ファイル名+ファイルサイズ、中身のファイル名一覧をGUI上に表示

  6. 上記の情報をクリップボードにコピーするボタンをGUIに配置

  7. 上記の情報をテキストファイルに出力

自動化したのはここまでです。以下の理由で、台帳への記入やメール作成は自動化していません。

  • 台帳はSharePointで共有されていて複数人で触るので、自動化のハードルが若干高い

  • メールは定形の内容に加えてコメントや連絡事項を記載しているので自動化のメリットが少ない
    (この作業が1日に何回もあるなら考えますが、週1なので。。)

ツールの動作

実際にサンプルファイルで実行してみた結果です。

1. データ格納用フォルダに転送したいファイルを格納する

ここは事前準備で、人がやる作業です。
Pythonスクリプトがあるフォルダに「data」という名前のフォルダを作成します。(1回やっておけばOK)

スクリプトがあるフォルダ

「data」フォルダにzip化したいファイルを格納します。

dataフォルダ

2. Pythonスクリプトを実行してGUIを起動

Pythonスクリプトを実行します。私はPythonファイルを関連付けでダブルクリック実行できるようにしているので、「zip変換.py」アイコンをダブルクリックするだけで実行できます。

スクリプト実行

(参考)ダブルクリック実行のやり方はこちら。

3. GUIが起動するので、Product名を選択するとzipファイルを生成する

GUI起動

zipファイルは書式が決まっていて、このProduct名は、zipファイルのヘッダになります。「ProductA」や「ProductB」のボタンをポチッと押すとzipファイルができます。

以下、生成された結果です。「Product名_doc_日付.zip」というのがzipファイル名です。

生成結果

zipファイルの中身を見ると、ちゃんと元のファイルが格納されています。

4. 変換結果がGUIで表示される

ここまではWindowsの標準機能で実現できます。ここからがちょっと面倒な作業だったファイル名等のコピペを効率化する機能です。

変換結果

Copyボタンを押すと、ボタンの左にある文字列がクリップボードにコピーされます。これを台帳やメールにぺたぺた貼り付けます。これが今回一番やりたかったことですね。

5. ファイル名等の情報をテキストファイルに出力

上のGUIでコピペしておけばよいのですが、うっかり右上の✕を押して閉じてしまうとコピーできなくなるので、念の為にoutput.txtというテキストファイルにも出力しておきます。中身はこんな感じ。

output.txtの中身

GUIに表示されていたものと同じ内容です。
なお、入力ファイル名一覧の前にスペースが空いているのは、メールに貼り付ける時に都合がよいからです。自分で作るツールなので、こんな感じで自由にカスタマイズできます。

ソースコード

ソースコードを貼っておきます。

import os
import datetime
import shutil
import pyperclip
import PySimpleGUI as sg

# カテゴリ一覧設定
PRODUCTS = ('ProductA', 'ProductB') # Product名はここで設定

# カテゴリ(ファイルヘッダ)選択のボタン配置
layout = [
    [sg.Text('Select product')], # テキストフィールド
    [sg.Button(p) for p in PRODUCTS] # Product名のボタン配置
]
window = sg.Window('zip変換', layout) #GUI作成

while True: # GUIのイベント待ち
    event, _ = window.read() # 何か押された
    
    if event == None: # Window右上の✕が押された場合
        break # 何もせずにClose
        
    if event in PRODUCTS:
        # 出力ファイル名設定
        output_file_name = f"{event}_doc_{datetime.date.today().strftime('%y%m%d')}"
        # 圧縮
        shutil.make_archive(output_file_name, format='zip', root_dir='data')
        break
        
window.close()

if event: # zip変換GUIで×を押した場合(event==None)は何もせずに終了

    # ファイル名取得
    output_zip_file_name = f'{output_file_name}.zip'
    output_file_size = f'{output_zip_file_name} ({os.path.getsize(output_zip_file_name)}byte)'
    input_files = '\n'.join([f'  {s}' for s in os.listdir('./data')])

    # 念のため結果をファイル出力
    with open('output.txt', 'w') as f:
        f.write('出力ファイル\n')
        f.write(output_zip_file_name)
        f.write('\n\n出力ファイル+容量\n')
        f.write(output_file_size)
        f.write('\n\n入力ファイル一覧\n')
        f.write(input_files)

    # 結果表示(GUI)
    L1 = [[sg.Text(f'{output_zip_file_name}'), sg.Button('Copy', key='outputfilename')]]
    L2 = [[sg.Text(f'{output_file_size}'), sg.Button('Copy', key='outputfilesize')]]
    L3 = [[sg.Text(f'{input_files}'), sg.Button('Copy', key='inputfilename')]]
    layout = [
        [sg.Frame('出力ファイル', L1, title_color = 'yellow')],
        [sg.Frame('出力ファイル+容量', L2, title_color = 'yellow')],
        [sg.Frame('入力ファイル一覧', L3, title_color = 'yellow')]
    ]
    window = sg.Window('zip変換結果', layout)

    while True:
        event, _ = window.read()

        if event == None:
            break

        if event == 'outputfilename':
            pyperclip.copy(output_zip_file_name) # クリップボードにコピー

        if event == 'outputfilesize':
            pyperclip.copy(output_file_size) # クリップボードにコピー

        if event == 'inputfilename':
            pyperclip.copy(input_files) # クリップボードにコピー

    window.close()

必要なモジュール

5つのモジュールをインポートしています。「pyperclip」「PySimpleGUI」はサードパーティ製のモジュールなので、あらかじめインストールしておく必要があります。
pyperclipはクリップボードを扱うモジュールで、PySimpleGUIはGUIを作るためのモジュールです。

# Windowsの場合
pip install pyperclip
pip install PySimpleGUI

 # macOS / Linuxの場合
pip3 install pyperclip
pip3 install PySimpleGUI

コードの主要部分の解説

GUIを作成するのに少しコードが長くなりましたが、主要な処理は以下で実現しています。

まず、出力ファイル名の設定です。出力ファイルは「Product名_doc_作成日.zip」にするという決まりがあります。Product名はGUIでボタンを押すとeventという変数に格納されます。日付は、datetimeモジュールのstrftimeメソッドで今日の日付を文字列化しています。2022年3月29日であれば220329になります。

output_file_name = f"{event}_doc_{datetime.date.today().strftime('%y%m%d')}"


zipファイル作成は標準でインストールされているshutilモジュールのmake_archiveメソッドを使いました。指定したフォルダ以下のファイルをまとめてzip化してくれます。

shutil.make_archive(output_file_name, format='zip', root_dir='data')

ファイルサイズは、osモジュールのos.path.getsizeメソッドで取得できます。

os.path.getsize(output_zip_file_name)

dataフォルダのファイル名一覧は、osモジュールのlistdirメソッドでリストを取得し、リスト内包表記とjoinメソッドを使って文字列型で一覧にしています。

input_files = '\n'.join([f'  {s}' for s in os.listdir('./data')])

GUIを作るモジュールのPySimpleGUIについては今回は詳しく書きませんが、以下に参考記事をまとめています。

まとめ

今回は、普段の作業を自動化し、GUIで制御するちょっとしたデスクトップアプリを作ってみました。これで微妙に面倒な作業が自動化できます。Pythonは万能なので、大抵のことはPythonで完結するのがいいところです。あらかじめモジュールが用意されており、どの処理も簡単なコードで実現できます。

Pythonって聞くと、大抵の人はガチなプログラマーが開発で使うとか、データサイエンスだのAIだのをイメージしますが、実は簡単なコードで普段の業務をちょっと自動化できるお手軽なプログラミング言語でもあるのです。
興味がある方はぜひ学んでみてください。

ちなみに、今回のツールの機能はノンプロ研タカハシさん著の通称ノンプロPython本にも載っていますので、Pythonを1から学びたい人はおすすめです。(PySimpleGUIは載ってないのであしからず)

こちらはノンプロ研のPython初心者講座です。コミュニティ連携型で、一緒に学ぶ人がいたり、講座以外のことをslackで質問できたりするので、書籍や動画での独学が苦手な方にオススメです!


以上です。コードと説明を書いてたら長くなってしまいました。。
最後まで読んでいただき、ありがとうございました。

最後まで読んで頂き、ありがとうございました。