PR

tkinterのfiledialogでExcelファイルを選択する方法|前回フォルダの記憶も実装【開発記②】

Python

NINJIN Mail制作記 第2回

スポンサーリンク

前回の課題:Excelの置き場所が固定される問題を解決する

こんにちは、ニンジンです🥕

この記事では、Python標準GUIライブラリ tkinterfiledialog を使って、任意のフォルダにあるExcelファイルを「ファイルを開く」画面から選べるようにする方法を解説します。さらに、config.json直前に開いたフォルダを記憶させて、次回はその場所を最初に開く機能も実装します。

第1回では、pandasでExcelの中身を読み込むところまで作りました。ただ前回のコードには「プログラムと同じフォルダにExcelを置かないと動かない」という制約がありました。実際の業務では、デスクトップや共有フォルダなど、ファイルの保存場所はさまざまです。この「たかが1クリック」を削るUXの工夫を、現役エンジニア目線でまとめます。

この記事で分かること

  • tkinter.filedialog.askopenfilename() でExcelファイルを選択するサンプルコード
  • root.withdraw() で余計な空ウィンドウを隠す理由
  • filetypes.xlsx だけに絞って誤操作を防ぐ方法
  • config.json に前回のフォルダパスを保存し、次回の初期表示にする実装
  • 設定ファイルにJSONを選ぶ理由と、初回起動時のエラー回避(os.path.expanduser("~")
第1回のコード。Excelファイルがプログラムと同じフォルダに固定されている状態

▲ 前回(第1回)のコードは、Excelの置き場所が固定だった

前回はファイルパスをコード内に直書きしていたため、Excelを別の場所に置くと動きませんでした。ここを「画面で選ぶ」方式に変えていきます。


スポンサーリンク

tkinterのfiledialogでExcelファイルを選択する【サンプルコード】

任意のフォルダからファイルを選べるようにするため、Python標準のGUIライブラリ tkinter に含まれる filedialog を使います。氏名・アドレス・会社名のデータは第1回と同じExcelファイルを使用します。

import pandas as pd
from tkinter import filedialog
import tkinter as tk
import os

def select_and_load_excel():
    # 1. 小さなメインウィンドウが裏で出ないように隠す
    root = tk.Tk()
    root.withdraw()

    # 2. ファイル選択ダイアログを表示
    # filetypesでExcelファイル(.xlsx)だけを表示するように制限
    file_path = filedialog.askopenfilename(
        title="Excelファイルを選択してください",
        filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")]
    )

    # 3. ファイルが選択されたかチェック
    if not file_path:
        print("ファイルが選択されませんでした。")
        return

    print(f"選択されたファイル: {file_path}")

    # 4. Excelを読み込んで表示
    try:
        df = pd.read_excel(file_path)
        
        # 1行ずつデータを取り出す
        for index, row in df.iterrows():
            name = row['氏名']
            email = row['アドレス']
            company = row['会社名']
            
            print(f"データ取得成功: {company} / {name} 様 ({email})")
            
    except Exception as e:
        print(f"エラーが発生しました: {e}")

# 実行
if __name__ == "__main__":
    select_and_load_excel()

VS Codeなどのエディターで実行すると、Windowsでおなじみの「ファイルを開く」画面が立ち上がります。対象のExcelファイルを選んで「開く」を押し、ターミナルにExcelのデータが出力されれば成功です。

filedialogで開いた「ファイルを開く」ダイアログと、実行後にターミナルへExcelのデータが出力された画面

▲ 「ファイルを開く」画面でExcelを選び、ターミナルにデータが出れば成功

Windows標準のファイル選択画面がそのまま使えます。選んだファイルのパスは file_path に入り、pd.read_excel() で読み込めます。

コードのポイント

  • root.withdraw():tkinterは本来ウィンドウを作るためのライブラリなので、これがないと空の小さなウィンドウが表示されます。それを隠すための処理です。
  • filetypes の指定:画像や音楽ファイルなど対象外のファイルを選べないように制限し、誤操作を防ぎます。

スポンサーリンク

直前に開いたフォルダを記憶する:config.jsonによる設定保存

毎回ファイル選択のたびに目的のフォルダを探すのは手間です。そこで、直前に選んだ場所を記憶し、次回はその場所を初期表示する機能を追加します。設定の保存には軽量で扱いやすい JSON形式 を使います。

仕組みのイメージ

  • 起動時:config.json があるか確認し、あれば前回使ったフォルダパスを読み込む
  • ファイル選択時:読み込んだパスを initialdir(初期フォルダ)として開く
  • 選択後:新しく選んだ場所を config.json に上書き保存する
import pandas as pd
from tkinter import filedialog
import tkinter as tk
import os
import json

# 設定ファイルの保存名
CONFIG_FILE = "config.json"

def load_last_path():
    """前回使用したフォルダパスを読み込む"""
    if os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, "r", encoding="utf-8") as f:
            config = json.load(f)
            return config.get("last_path", os.path.expanduser("~")) # なければホームディレクトリ
    return os.path.expanduser("~")

def save_last_path(file_path):
    """選択されたフォルダパスを保存する"""
    folder_path = os.path.dirname(file_path)
    with open(CONFIG_FILE, "w", encoding="utf-8") as f:
        json.dump({"last_path": folder_path}, f, ensure_ascii=False, indent=4)

def select_and_load_excel():
    root = tk.Tk()
    root.withdraw()

    # 前回のパスを取得
    initial_dir = load_last_path()

    file_path = filedialog.askopenfilename(
        title="Excelファイルを選択してください",
        initialdir=initial_dir,  # ここで前回の場所を指定!
        filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")]
    )

    if not file_path:
        print("ファイルが選択されませんでした。")
        return

    # 選択されたらパスを保存
    save_last_path(file_path)
    print(f"選択されたファイル: {file_path}")

    try:
        df = pd.read_excel(file_path)
        for index, row in df.iterrows():
            print(f"取得: {row['会社名']} {row['氏名']} 様")
            
    except Exception as e:
        print(f"エラー: {e}")

if __name__ == "__main__":
    select_and_load_excel()

実行すると前回開いたフォルダが最初に開き、ターミナルにExcelのデータが出力されます。スクリプトと同じフォルダに config.json が自動生成されていれば成功です(すでにある場合は、そのファイルから設定が読み込まれます)。

実行後、スクリプトと同じフォルダにconfig.jsonが自動生成され、中に前回のフォルダパスが保存されている画面

▲ スクリプトと同じ場所に config.json が生成される

config.json の中身は {{"last_path": "選んだフォルダ"}} という単純なJSONです。テキストエディタで開いて確認できます。

設計上の工夫点

  • 直前のフォルダを記憶する:毎回同じフォルダを探す手間を省き、操作回数を減らすため
  • 設定ファイルにJSONを採用:テキストエディタで中身を確認しやすく、Pythonの辞書型(dict)と同じ感覚で扱えるため
  • os.path.expanduser("~") を初期値に使用:初回起動時など設定ファイルが無い場合でも、エラーを出さずにホームディレクトリを開けるようにするため

ファイルの配置はどうなる?

プログラムを実行すると、以下のような構成になります。config.json は初回実行時に自動生成されます。

作業フォルダ/
 ├── mailer.py      (メインプログラム)
 ├── config.json    (前回パスを記憶しているファイル)
 └── client_list.xlsx

スポンサーリンク

まとめ:次回はGUIでメール本文を作成する

今回で、Excelファイルを柔軟な場所から選び、直前のフォルダを記憶する仕組みが整いました。次回は、GUI(操作画面)上でメール本文を作成するステップに進みます。ツールとしての見た目は、ここから整っていきます。

PR

今回紹介したコードを含む開発の詳細は、noteで販売しています。コードに関心がある方も、「コードは難しそう」と感じる方も、内容だけでも覗いてみてください。

次に読む記事


スポンサーリンク

よくある質問(tkinter filedialog・config.json)

Qfiledialog.askopenfilename() を実行すると、小さな空のウィンドウが一緒に出てしまいます

Atkinterは本来ウィンドウを作るライブラリなので、tk.Tk() で作った親ウィンドウが表示されます。root = tk.Tk() の直後に root.withdraw() を呼ぶと、この空ウィンドウを隠せます。

Qダイアログで「キャンセル」を押すとエラーになります

Aaskopenfilename() はキャンセル時に空文字(””)を返します。if not file_path: return のように、空かどうかを必ずチェックしてから読み込み処理へ進みます。

Qfiletypes を指定してもすべてのファイルが表示されます

Afiletypes=[(“Excel files”, “*.xlsx”), (“All files”, “*.*”)] のように「すべてのファイル」を含めていると、ユーザーが表示を切り替えられます。.xlsxだけに絞りたい場合は (“All files”, “*.*”) の行を外します。

Qconfig.json はどこに作られますか?別の場所に保存したいです

Aコードでは CONFIG_FILE = “config.json” と相対パスで指定しているため、スクリプトを実行したカレントディレクトリに作られます。場所を固定したい場合は os.path.join(os.path.dirname(__file__), “config.json”) のように、スクリプトと同じフォルダを明示します。

Q前回のフォルダを記憶しているはずなのに、初回だけホームフォルダが開きます

A初回は config.json がまだ無いため、load_last_path() が os.path.expanduser(“~”)(ホームディレクトリ)を返す設計です。一度ファイルを選ぶと config.json が生成され、次回からはそのフォルダが初期表示されます。


ニンジン🥕アイコン

Follow me on X

本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕

@ninjin_py_vba をフォロー

この記事が役に立ったら、シェアしてもらえると嬉しいです🥕

Xでポスト はてブ LINE Pocket

PROJECT LOG — SERIES INDEX
スポンサーリンク

シリーズ記事一覧

電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。


コメント