0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

複数ファイルに跨ってexcelファイルを検索したい

0
Posted at

背景

社内で利用してよさそうなツールがなかったためpythonでツールを自作。


import os
import warnings
import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import Scrollbar, Text


def generate_excel_columns(num_columns):
    """
    どこの列に記載されているか表示したいが、
    A列のような取得方法が不明であったためA列からXFD列分配列を生成
    """
    columns = []
    col = 0
    while len(columns) < num_columns:
        col_str = ""
        temp_col = col
        while temp_col >= 0:
            col_str = chr(temp_col % 26 + ord('A')) + col_str
            temp_col = temp_col // 26 - 1
        columns.append(col_str)
        col += 1
    return columns

def out_put_text_search(text, folders, files, result_text_widget):

    # エクセル出力用変数
    out_folder_name = []
    out_file_name = []
    out_keys = []
    out_colums = []
    out_rows = []
    out_display = []
    
    num_columns = 16384  # 生成する列数
    excel_columns = generate_excel_columns(num_columns)

    result_text_widget.insert(tk.END, f"検索対象ファイル\n")
    for index in range(len(folders)):
        if '~$' not in files[index] and ('.xlsx' in files[index] or '.xls' in files[index]):        
            file_path = os.path.join(folders[index], files[index])  

            #検索対象ファイルを表示
            result_text_widget.insert(tk.END, f"{files[index]}\n")
            
            try:
                if files[index].lower().endswith('.xlsx'):
                    df = pd.read_excel(file_path, sheet_name=None,header=None, engine='openpyxl')
                else:  # .xlsファイルの場合
                    df = pd.read_excel(file_path, sheet_name=None,header=None, engine='xlrd')                
                
                for key in df.keys(): #シートの名前
                    sheet_df = df[key]
                    if sheet_df is not None and not sheet_df.empty:
                        for colum in sheet_df.columns:
                            column_data = sheet_df[colum]
                            if column_data is not None:
                                for row in range(len(column_data)):
                                    cell_value = column_data.iloc[row]

                                    if text in str(cell_value):                                        
                                        temp_out_folder_name = ""
                                        temp_out_file_name = ""
                                        temp_out_keys = ""
                                        temp_out_colums = ""
                                        temp_out_rows = ""
                                        temp_out_display = ""

                                        try:
                                            temp_out_folder_name = folders[index]
                                            temp_out_file_name = files[index]
                                            temp_out_colums = excel_columns[colum]
                                            temp_out_keys = key
                                            temp_out_rows = str(row + 1)
                                            temp_out_display = str(cell_value)
                                        except Exception as e:
                                            try:
                                                temp_out_folder_name = folders[index]
                                                temp_out_file_name = files[index]
                                                temp_out_colums = colum
                                                temp_out_keys = key
                                                temp_out_rows = str(row + 2)
                                                temp_out_display = str(cell_value)
                                            except Exception as e:
                                                result_text_widget.insert(tk.END, f"検索エラー: {str(e)}\n")
                                        
                                        out_folder_name.append(temp_out_folder_name)
                                        out_file_name.append(temp_out_file_name)
                                        out_keys.append(temp_out_keys)
                                        out_colums.append(temp_out_colums)
                                        out_rows.append(temp_out_rows)
                                        out_display.append(temp_out_display)
                                        
            except Exception as e:
                result_text_widget.insert(tk.END, f"ファイル読み込みエラー ({files[index]}): {str(e)}\n")
                continue

    # エクセルファイル出力用辞書
    data = {
        'フォルダ名':out_folder_name,
        'ファイル名': out_file_name,
        'シート名': out_keys,
        '': out_colums,
        '': out_rows,
        '表示名': out_display
    }

    # データフレームを作成
    out_df = pd.DataFrame(data)
    
    file_path = os.getcwd() + f'/result_{text}.xlsx'
    #書き込み
    try:
        out_df.to_excel(file_path, index=False, engine='openpyxl')
        result_text_widget.insert(tk.END, '検索結果が Excel ファイル result.xlsx に保存されました。\n')
        messagebox.showinfo("成功", "検索結果が保存されました。")
        return file_path 
    except Exception as e:
        result_text_widget.insert(tk.END, f"異常終了:{str(e)}\n")
        messagebox.showerror("エラー", f"ファイル書き込みエラー: {str(e)}")
        return None

def browse_folder(entry):
    folder_path = filedialog.askdirectory()
    if folder_path:
        entry.delete(0, tk.END)
        entry.insert(0, folder_path)

def start_search(text_entry, folder_entry, result_text_widget):
    text = text_entry.get()
    folder_path = folder_entry.get()

    if not text or not folder_path:
        messagebox.showerror("エラー", "検索文字列とフォルダパスを入力してください。")
        return

    if os.path.isdir(folder_path):

        result_text_widget.delete(1.0, tk.END)  # 既存の結果を消去

        excel_folders = []
        excel_files = []  # フォルダパスとファイル名を格納するリスト
        for root, _, files in os.walk(folder_path):  # 再帰的にフォルダを探索
            for file in files:
                if file.lower().endswith(".xlsx") or file.lower().endswith(".xls"):  # .xlsx,xlsファイルをチェック
                    excel_folders.append(root)
                    excel_files.append(file)

        output_file = out_put_text_search(text, excel_folders, excel_files, result_text_widget)

        if output_file:
            # 既存のボタンを削除して、新しいボタンを作成
            for widget in open_button_frame.winfo_children():
                widget.destroy()

            open_button = tk.Button(open_button_frame, text=f"検索結果を開く ({text})", command=lambda: open_excel(output_file))
            open_button.pack(pady=5)
    else:
        messagebox.showerror("エラー", "指定されたパスはディレクトリではありません。")

def open_excel(file_path):
    #ファイルを開く
    if os.name == 'nt':
        os.startfile(file_path)
    else:
        messagebox.showerror("エラー", "windows以外はサポートしてないよ。")


warnings.filterwarnings("ignore")

# GUIの設定
root = tk.Tk()
root.title("Excelファイル検索ツール")

# ウィンドウサイズ
root.geometry("600x400")

# 検索文字列入力
tk.Label(root, text="検索したい文字列:").pack(pady=5)
text_entry = tk.Entry(root, width=50)
text_entry.pack(pady=5)

# フォルダパス入力
tk.Label(root, text="検索対象フォルダ:").pack(pady=5)
folder_entry = tk.Entry(root, width=50)
folder_entry.pack(pady=5)
folder_browse_button = tk.Button(root, text="フォルダ選択", command=lambda: browse_folder(folder_entry))
folder_browse_button.pack(pady=5)

# 結果表示用のテキストウィジェット
result_text_widget = Text(root, height=10, width=150)
result_text_widget.pack(pady=10)

result_text_widget.insert(tk.END, f"指定したフォルダ配下の全てのxlsx/xlsファイルが対象\n")
result_text_widget.insert(tk.END, f"フォルダ、ファイルの件数が多い場合実行時間が長くなるよ")

# スクロールバー追加
scrollbar = Scrollbar(root, command=result_text_widget.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
result_text_widget.config(yscrollcommand=scrollbar.set)

# 検索ボタン
search_button = tk.Button(root, text="検索", command=lambda: start_search(text_entry, folder_entry, result_text_widget))
search_button.pack(pady=10)

# 結果を開くボタン用のフレーム
open_button_frame = tk.Frame(root)
open_button_frame.pack(pady=0)

# メインループ
root.mainloop()

結果

image.png

image.png

課題

  • 実行速度が遅い
    各ファイルの各シートの行列分ループしてればそら遅いですよね
    現状利用するのに困らないので時間が空いた時にでも検討したい
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?