CSV/Excel の行フィルターGUIツールをつくってみた
ども、平社員リョーマです。
最近ますますサックは元気いっぱい。
こないだ散歩中に、パラコードで手作りしたロングリードをつけて走らせてたら、
勢いあまりすぎて ロープじゃなくて金具のほうがボキッ… と折れてしまいました(´;ω;`)
数時間かけて編んだやつが、一瞬でただのヒモに…。
「市販のちゃんとしたやつ買うか… いや、また手作りするか…」と悩みつつ、
とりあえず今日はワンコではなく、人間用の作業効率化ツールの話を。
何を作ったか(ざっくり)
お店やECの仕事をしていると、定期的にやってくるのが
- このカテゴリーの商品だけ一括で抜き出したい
- このブランド群だけ別ファイルに分けたい
- 一部の商品説明だけ手作業で直して、まとめてアップロードしたい
みたいな、一括処理のための「下準備」作業です。
やっていること自体はシンプルで、
- 商品CSV全体から、カテゴリやブランドなどで「対象商品だけ」を抜き出す
- その絞り込んだデータをもとに、商品説明などをチマチマ手作業で修正
- 修正後のCSVを、一括アップロード用として使う
これ、Excel のフィルター機能でも一応できるんですが、
- CSV のレコード数が多くなると、そもそも開くのに時間がかかる
- フィルター条件を変えるたびに「チェックを付け直し → 適用 → また外す」を繰り返す必要がある
- 「いらないグループを一気に消す」「必要なグループだけ残す」といった操作を、もう少し視覚的にやりたい
というストレスがじわじわ溜まってきます。
そこで、
「先に pandas で、必要な行だけ抜き出して『軽いCSV』にしておいたほうが早いよね?」 ってもともと思っていたけど後回しに来て 我慢の限界に到達(笑) サクッとできるのになぜ後回しに…..(´;ω;`)
という発想で作ったのが、今回の CSV/Excel 専用「行フィルター GUI ツール」 です。
今の v1 では「列の値ベースでの絞り込み」がメインですが、今後は
- キーワードでの絞り込み(商品名や型番や説明文で検索して絞る)
なども追加して、v2 として育てていく予定です。
とはいえ、そこは時間があるときにゆっくりでいいかな、という感じで、
まずは「Excel フィルターの前に軽く前処理するツール」として動くところまで仕上げています。
できること(ユーザー視点の機能まとめ)
このツールでできることを、ユーザー視点でざっくり並べるとこんな感じです。
- CSV または Excel ファイルを選択して読み込み
- 文字コードは自動判定(UTF-8 / CP932 / EUC-JP など、日本でよくあるものをカバー)
- 区切り文字もカンマ、タブ、セミコロンなどを順番にトライ
- pandas で DataFrame に変換
- 任意の「列(ヘッダー)」を選択
- その列に含まれる 値ごとに行をグループ化
- 同じ値を持つ行はひとまとまりに
- 「◯◯(123件)」のように、件数付きで一覧表示
- 値の一覧は、縦一列ではなく3列グリッド表示で見やすく配置
- グループ単位で複数選択
- クリックで ON/OFF(もう一度クリックで解除)
- Shift+クリックで範囲選択も可能
- 選んだグループに属する行を
- 「削除する」(選んだ値の行だけ除外)
- 「残す」(選んだ値の行だけを残して他を捨てる)
- 最後に、元ファイルと同じ形式(CSV or Excel)で保存
実際の使い方としては、例えば:
- 「ブランド名」の列を選ぶ
- 値一覧から「このブランドは一旦全部抜きたい」というものをポチポチ選ぶ
- 「削除する」を選んで保存する
これだけで、特定ブランドだけを一気に除外したCSV ができるので、
あとは残ったデータに対して、商品説明の修正や価格調整などを集中して行えます。
ツールのコンセプトと設計のポイント
このツールは、最初から「どこか1つのモールだけに特化したもの」ではなく、 どのECの全商品CSVでも使える汎用ツールとして設計しています。
設計上、特に意識したポイントはこのあたりです。
- モール非依存
- 列名やレイアウトに強く依存しない
- 「どの列を使って絞り込むか」はユーザーが選ぶ
- GUIとロジックの分離
- CustomTkinter を使った画面部分は GUI 用モジュールに閉じ込める
- 行のグループ化やフィルター処理は、純粋な Python ロジックとして別モジュールへ分離
- 将来 FastAPI 版を作るときに、そのままロジックだけ再利用できる構造にしておく
- 文字コードの自動判定
- 毎回「UTF-8で開く?SJISで開く?」と悩みたくない
- 先頭のバイト列だけを読んで、
chardetがあればそれを活用 - 判定が微妙でも、よく使う日本語エンコード(UTF-8 / CP932 / EUC-JP)を順番に試す
- グループ単位で考えるUI
- 1行ずつチェックボックスを付けるのではなく、「同じ値を持つ行まとめて扱う」
- 「ブランド名 × 件数」をざっと眺めてから、どれを残すか決められる
- Python をインストールしていない環境でも利用できます
- ZIP を展開すると、フォルダが1つ作成されます
- その中にある EXE ファイルをダブルクリックするだけで起動します(インストール不要)
- 特別な設定やインストール作業は必要ありません
- ブログからダウンロードして、すぐに試せる形にしています
なぜここまでモジュール分割しているのか
今回のツールは、正直「自分用に動けばOK」の世界なんですが、あえて最初からモジュールに分けています。
理由はいくつかあって、ざっくりまとめるとこんな感じです。
- UIを差し替えやすくしておきたい
- 今は CustomTkinter でGUIですが、将来 FastAPI でWeb版を作りたくなるかもしれない
- そのときに「ロジックごと全部書き直し」になるのはもったいないので、最初から
encoding_utils.py/data_io.py/row_filter_logic.pyに 処理を寄せておく - GUI側(
gui_row_filter_app.py)は「見た目とイベント処理」だけにしておくイメージ
- CLI やバッチ処理にも流用しやすくするため
- 将来「GUIなしで、コマンドラインからサクッと一括処理したい」というケースが出てくるかもしれない
- そのときは、
row_filter_logic.pyとdata_io.pyをそのまま使って 「行フィルターCLI版」を作ればよいだけになる - GUIにべったりな設計だと、毎回ロジックを引きはがすところからスタートになるので、最初に分けておくほうがトク
- テストとデバッグを楽にしたい
- 「ファイル読み込み」「エンコード判定」「行フィルター処理」などを別モジュールにしておくと、 GUIを起動しなくても、Python の対話モードやテストコードから単体で動作確認できる
- バグが出たときも「GUIのせいなのか、ロジックのせいなのか」が切り分けやすい
- 未来の自分が迷子にならないようにするため
- 1年後くらいにコードを開いたとき、「この巨大な1ファイル何してたっけ?」となる未来が見えている
- モジュールごとに役割をはっきり分けておくと、「エンコード周りはここ」「行フィルターはここ」と 頭の切り替えがしやすい
- ブログの“設計メモ”としても読みやすくするため
- 「このツール便利でした」だけで終わらせるのではなく、 「こう分割しておくと後からバージョンアップしやすいよ」という設計の考え方も残しておきたい
- 同じように EC まわりのツールを作りたい人がいたときの、ひとつの参考例になればいいな、というおまけの狙いもあります
自分用ツールだからこそ、「今の自分」と「未来の自分」と「別UI版」に優しくしておく設計、という感じです。
その意味で、このツール自体が「モジュール設計のお試し台」になっています。
内部構成(モジュール設計)
コード全文はここでは省略して、どう分割しているかだけメモしておきます。
ディレクトリ構成はざっくりこんな感じです。
project_root/
├─ run_row_filter_app.py ← 起動用スクリプト(EXE化のエントリポイント)
└─ row_filter_tool/
├─ __init__.py
├─ gui_row_filter_app.py ← CustomTkinter の UI & イベント
├─ encoding_utils.py ← 文字コード判定(chardet + フォールバック)
├─ data_io.py ← DataFrame の読み込み・保存
└─ row_filter_logic.py ← 行グループ化とフィルター処理
encoding_utils.py(文字コード判定)
役割:
- ファイル先頭の一部だけをバイナリで読み込む
chardetがあればそれで推定し、ある程度の信頼度があれば採用- そうでなければ、UTF-8 / UTF-8-SIG / CP932 / EUC-JP の順に decode を試して通ったものを採用
- どれもダメなら例外を投げる
これにより、「毎回エンコーディングを意識して開く」手間をなくすのが狙いです。
data_io.py(ファイル読み込み・保存)
役割:
- 拡張子(.csv / .tsv / .txt / .xls / .xlsx / .xlsm)から「CSV系」か「Excel系」かを判定
- CSV系の場合は
encoding_utilsで文字コードを推定してからpandas.read_csvを実行 - Excel系の場合は
pandas.read_excelを使って読み込み - 保存時は、元ファイルと同じ形式で
to_csv/to_excelを呼ぶ
「ファイルパス ↔ DataFrame ↔ 保存パス」の責務をこのモジュールに寄せて、
GUI 側は極力「DataFrame という箱」とだけやり取りするようにしています。
row_filter_logic.py(行グループ化とフィルター適用)
役割:
- 指定した列を見て、値ごとに行インデックスをまとめる
- 「値」と「対応する行インデックスのリスト」をセットにしたオブジェクト(例:
ValueGroup)の一覧を返す - 選択されたグループのインデックスを集約して、「削除」「残す」のどちらかのモードで DataFrame をフィルタリングする
ここは GUI に一切依存させず、純粋な関数群として作ってあります。
将来 FastAPI 版(Webフォームから列名と値を送り込むような形)を作るときも、
このモジュールをそのまま使い回せるようにするための分割です。
gui_row_filter_app.py(画面とイベント)
役割:
- CustomTkinter を使ったウィンドウ・フレーム・ボタン・コンボボックスの定義
- 列選択コンボボックスの変更イベントで、値リストを再生成
- 3列の Listbox に値を割り振り(1列目:1,4,7… 2列目:2,5,8… という感じ)
- クリック時に ON/OFF トグルできるようにするイベントハンドラ
- 「実行して保存」ボタンから
row_filter_logicとdata_ioを呼び出す
UI 部分はここに集約しているので、
「見た目を少し変えたい」「列数を3列から4列にしたい」といった調整も、このファイルだけ見れば済みます。
run_row_filter_app.py(ランチャースクリプト)
役割:
- Python を触らない人向けに、起動用の入口を1つにまとめる
- このファイルを PyInstaller で EXE 化することで、単体EXEを作る
sys.dont_write_bytecode = Trueを設定して、__pycache__を作らないようにしている
EXE化と配布イメージ
今回は、インストール不要で動く「EXEひとつだけ」の形にしたかったので、
PyInstaller を使ってワンファイル化しています。
コマンドはこんなイメージです(参考程度のメモ):
pyinstaller --noconsole --onefile --name RowFilterTool run_row_filter_app.py
--noconsole: コンソール(黒い画面)を出さない--onefile: 必要なモジュールを1つのEXEに固める--name: 出力されるEXEファイル名
これで dist/RowFilterTool.exe ができるので、あとは
- ブログからその EXE をダウンロードしてもらう
- Windows でダブルクリックして起動
という使い方ができます。
Python をインストールしていない人(奥さん含む)でも、そのまま「行フィルターツール」として使える想定です。
なぜコードではなく「設計」を残すか
正直、AI 時代になると「コードそのもの」は、
かなりの部分を AI に任せることができるようになってきました。
実際、自分でも
- 具体的な処理は AI に手伝ってもらう
- 自分は「どう分割するか」「どこまで汎用にするか」「どこをモール依存にするか」を考える
という使い方をすることが増えています。
なので、ブログではあえてソースコード全文は載せず、
- どういう課題を解決したかったのか
- どういうコンセプトで設計したのか
- どこをモジュールとして分けたのか
といった設計レベルのメモを残しておくことにしました。
自分自身にとっても、
- 後で FastAPI 版を作りたくなったとき
- v2 でキーワード絞り込みを追加したくなったとき
- 別のECモールのCSV用ツールを増やしたくなったとき
「何がどこまでできていて、どこから先を足すべきか」を思い出すためのログとしても役立つはずです。
これからの拡張アイデア
今回の v1 で一旦満足してはいるものの、「そのうちやりたいな」というネタもいくつかあります。
- モール別プリセット
- カラーミー / Yahoo / 楽天 など、モールごとに「よく使う列」を事前にセット
- ブランド列やカテゴリ列をワンクリックで選べるようにする
- キーワード絞り込み
- 商品名や説明文に含まれる文字列で絞り込む
- 「◯◯を含む/含まない」でフィルターできるようにする
- FastAPI版Webアプリ
- ブラウザからCSVをアップロードして、同じロジックでフィルターする
- 結果をそのままダウンロード、みたいな簡易Webツール化
これは、チョー適当につくったツールです。
(※のちのちバージョンアップ予定)
**個人で作成した Windows 用の実行ファイル(RowFilterTool_v1.0.exe)**
として配布しています。
そのため、環境によっては 初回起動時のみ、
・Norton
・Windows Defender
・その他ウイルス対策ソフト
による 自動チェック が行われる場合があります。
私の環境(Norton)では、次のような挙動でした。
・EXE をダブルクリック
・ウイルスチェックが自動的に開始
・チェック中に、一度だけエラーダイアログが表示される
・チェック完了後、再度起動すると正常に起動
初回起動時にエラーが表示された場合でも、
少し待ってからもう一度起動してみてください。
「エクセルでいちいちフィルターかけるの飽きたな…」という方は、
自分用のこういう小さなツールを一つ持っておくと、
地味に作業ストレスが減るのでおすすめです。
※ 本ツールは個人制作の無償ツールです。 利用は自己責任でお願いします。 必ず元データのバックアップを取ってからご利用ください。
そしてサックは今日も元気にロングリードを引きちぎりそうなので、
次のパラコード版は、もう少し金具を強いものにしようと思います…。