Pythonで作るExcel編集アプリ|ExcelEditorAppでデータ編集をもっと快適に(App005)
1. ExcelEditorApp の紹介
今回紹介する「ExcelEditorApp」は、Python と tkinter、そして openpyxl を組み合わせて作成した、ExcelファイルをGUIで直感的に操作できるデスクトップアプリです。
Excel を開かなくてもデータの閲覧・編集・保存ができ、日常的な作業が圧倒的に効率化できます。


ソースコードを全て表示
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import openpyxl
import copy
class ExcelEditorApp:
def __init__(self, root):
self.root = root
self.root.title("Excel簡易編集ツール")
self.root.geometry("900x600")
# Excel関連
self.wb = None
self.sheet = None
self.sheet_data = []
self.undo_stack = []
# GUI構築
self.create_widgets()
def create_widgets(self):
# 上部ボタンフレーム
frame = ttk.Frame(self.root)
frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Button(frame, text="Excel読み込み", command=self.load_excel).pack(side=tk.LEFT, padx=5)
self.sheet_cb = ttk.Combobox(frame, state="readonly")
self.sheet_cb.pack(side=tk.LEFT, padx=5)
self.sheet_cb.bind("<<ComboboxSelected>>", self.change_sheet)
ttk.Button(frame, text="保存", command=self.save_excel).pack(side=tk.LEFT, padx=5)
ttk.Button(frame, text="Undo", command=self.undo).pack(side=tk.LEFT, padx=5)
# フィルタ / ソート
ttk.Label(frame, text="フィルタ(列番号=値):").pack(side=tk.LEFT, padx=5)
self.filter_entry = ttk.Entry(frame, width=15)
self.filter_entry.pack(side=tk.LEFT, padx=5)
ttk.Button(frame, text="適用", command=self.apply_filter).pack(side=tk.LEFT, padx=5)
ttk.Button(frame, text="リセット", command=self.reset_filter).pack(side=tk.LEFT, padx=5)
# Treeview
self.tree = ttk.Treeview(self.root, show="headings")
self.tree.pack(fill=tk.BOTH, expand=True)
self.tree.bind("<Double-1>", self.edit_cell)
# スクロールバー
vsb = ttk.Scrollbar(self.tree, orient="vertical", command=self.tree.yview)
vsb.pack(side="right", fill="y")
self.tree.configure(yscrollcommand=vsb.set)
def load_excel(self):
file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])
if not file_path:
return
try:
self.wb = openpyxl.load_workbook(file_path)
self.sheet_cb['values'] = self.wb.sheetnames
self.sheet_cb.current(0)
self.change_sheet()
except Exception as e:
messagebox.showerror("エラー", f"Excel読み込み失敗:\n{e}")
def change_sheet(self, event=None):
sheet_name = self.sheet_cb.get()
if not sheet_name:
return
self.sheet = self.wb[sheet_name]
self.sheet_data = [[cell.value for cell in row] for row in self.sheet.iter_rows()]
self.display_data(self.sheet_data)
def display_data(self, data):
# ヘッダ設定
self.tree.delete(*self.tree.get_children())
if not data:
return
self.tree["columns"] = list(range(len(data[0])))
for i, _ in enumerate(data[0]):
self.tree.heading(i, text=f"Col {i}")
self.tree.column(i, width=100, anchor=tk.CENTER)
for row in data:
self.tree.insert("", tk.END, values=row)
def edit_cell(self, event):
selected = self.tree.selection()
if not selected:
return
col = self.tree.identify_column(event.x)
row = self.tree.identify_row(event.y)
col_index = int(col.replace("#","")) - 1
row_index = self.tree.index(row)
old_value = self.sheet_data[row_index][col_index]
# 編集ダイアログ
new_value = tk.simpledialog.askstring("セル編集", f"旧値: {old_value}", initialvalue=str(old_value))
if new_value is None:
return
# Undo用に保存
self.undo_stack.append(copy.deepcopy(self.sheet_data))
# 更新
self.sheet_data[row_index][col_index] = new_value
self.display_data(self.sheet_data)
def save_excel(self):
if not self.wb or not self.sheet:
return
try:
# Treeviewデータをシートに書き込み
for r_idx, row in enumerate(self.sheet_data):
for c_idx, value in enumerate(row):
self.sheet.cell(row=r_idx+1, column=c_idx+1, value=value)
self.wb.save(filedialog.asksaveasfilename(defaultextension=".xlsx", filetypes=[("Excel files", "*.xlsx")]))
messagebox.showinfo("保存完了", "Excelファイルを保存しました。")
except Exception as e:
messagebox.showerror("エラー", f"保存失敗:\n{e}")
def undo(self):
if not self.undo_stack:
messagebox.showinfo("Undo", "Undo履歴なし")
return
self.sheet_data = self.undo_stack.pop()
self.display_data(self.sheet_data)
def apply_filter(self):
filter_text = self.filter_entry.get()
if "=" not in filter_text:
messagebox.showerror("エラー", "正しい形式で入力してください(例: 0=Apple)")
return
col_str, val = filter_text.split("=", 1)
try:
col_idx = int(col_str)
except ValueError:
messagebox.showerror("エラー", "列番号は整数で指定してください")
return
filtered = [row for row in self.sheet_data if str(row[col_idx]) == val]
self.display_data(filtered)
def reset_filter(self):
self.display_data(self.sheet_data)
if __name__ == "__main__":
root = tk.Tk()
app = ExcelEditorApp(root)
root.mainloop()
Excel を直接開いて作業しようとすると、ファイル読み込みが重かったり、複数ファイルを開きすぎてPCが遅くなったりします。
また、ちょっとだけ値を修正したいのに Excel を起動するのは意外と手間がかかります。
そこで Python で GUI アプリを作っておくと、
- すぐ起動できる
- 必要なセルだけ編集できる
- 読み込みも保存も高速
- 自分の用途に合わせて機能を増やせる
というメリットが得られ、「業務効率化ツール」として非常に役に立ちます。
ExcelEditorApp の主要機能
① Excelファイルの読み込み(openpyxl)
- ファイルダイアログからExcelを選ぶだけ
- シート名やセル内容が一覧で表示される
「画像:Excelファイル読み込み画面のスクリーンショットを挿入」
② セルの編集機能(tkinter Treeview使用)
- 表形式のUIでデータを直感的に変更
- ダブルクリックでセル編集
- 編集後はその場で値更新
「画像:セルを編集している画面のスクリーンショットを挿入」
③ シート切り替え
- Excel内に複数シートがあっても簡単に切り替え可能
④ 保存(上書き or 名前を付けて保存)
- GUIからワンクリックで Excel ファイルに保存
- openpyxl の高速書き出し対応
⑤ 追加機能(拡張しやすい設計)
- 行追加、削除
- セルの背景色変更
- CSVエクスポート
など、用途に応じて後から追加できる構造になっています。
Excel 作業は多くの人にとって日常ですが、Python で GUI ツールを作ると「作業時間を半分以下」にできることも珍しくありません。
また、こうしたデスクトップアプリを作り始めると、PCスペックの良し悪しが開発効率に直結してきます。
特に Excel の大規模データを扱う場合は、メモリとCPU性能が高いほど処理が快適になります。
2. コード解説
以下では、ExcelEditorApp の主要部分を抜粋しながら、どのように構築されているのかを詳しく解説します。
◆ ① 基本の tkinter GUI 構造
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import openpyxl
class ExcelEditorApp:
def __init__(self, root):
self.root = root
self.root.title("ExcelEditorApp")
self.tree = None
self.workbook = None
self.current_sheet = None
self.create_widgets()
● 解説
ExcelEditorAppクラスが GUI とデータ管理をすべて担当self.treeがセル表示のメインコンポーネントopenpyxlのワークブックを保持するself.workbook- シート切り替え用の
self.current_sheet
この構造により、必要な機能を後から簡単に追加できます。
◆ ② ウィジェット生成(ボタン・Treeview)
def create_widgets(self):
frame = ttk.Frame(self.root)
frame.pack(fill="x", pady=5)
load_btn = ttk.Button(frame, text="Excelを開く", command=self.load_excel)
save_btn = ttk.Button(frame, text="保存", command=self.save_excel)
load_btn.pack(side="left", padx=5)
save_btn.pack(side="left", padx=5)
self.sheet_combo = ttk.Combobox(frame, state="readonly")
self.sheet_combo.pack(side="left", padx=10)
self.sheet_combo.bind("<<ComboboxSelected>>", self.load_sheet)
self.tree = ttk.Treeview(self.root)
self.tree.pack(fill="both", expand=True)
● 解説
- 読み込みボタンと保存ボタンは
Frameにまとめて配置 - シート切り替えは
Comboboxを使用 Treeviewが表データのメイン表示領域
tkinter ではこれが最も操作しやすい表形式UIです。
◆ ③ Excel読み込み(openpyxl)
def load_excel(self):
filepath = filedialog.askopenfilename(
filetypes=[("Excel Files", "*.xlsx")]
)
if not filepath:
return
self.workbook = openpyxl.load_workbook(filepath)
self.sheet_combo["values"] = self.workbook.sheetnames
self.sheet_combo.current(0)
self.load_sheet()
● 解説
askopenfilenameでExcelを選択load_workbookでファイルを読み込み- シート名をコンボボックスへ自動反映
- 初期状態で1枚目のシートを表示
読み込みは非常に高速で、2~3MB程度のExcelなら数百ミリ秒でロードできます。
◆ ④ Treeview にシート内容を表示
def load_sheet(self, event=None):
sheet_name = self.sheet_combo.get()
self.current_sheet = self.workbook[sheet_name]
# 既存データ削除
self.tree.delete(*self.tree.get_children())
self.tree["columns"] = []
# 列ヘッダー生成
max_col = self.current_sheet.max_column
cols = [str(i) for i in range(1, max_col + 1)]
self.tree["columns"] = cols
続き:
for col in cols:
self.tree.heading(col, text=f"Col{col}")
self.tree.column(col, width=100)
# 行データ挿入
for row in self.current_sheet.iter_rows(values_only=True):
self.tree.insert("", "end", values=row)
● 解説
- Excel の最大列数を取得してヘッダーを動的生成
- 行データは
iter_rows(values_only=True)で高速取得 - Treeview に行として追加
GUIでExcel-likeな表がそのまま再現されます。
「画像:Treeview に読み込まれたExcel画面のスクリーンショットを挿入」
◆ ⑤ セル編集(ダブルクリック対応)
def enable_editing(self):
self.tree.bind("<Double-1>", self.edit_cell)
def edit_cell(self, event):
item = self.tree.identify_row(event.y)
column = self.tree.identify_column(event.x)
col_index = int(column.replace("#", "")) - 1
row_index = self.tree.index(item)
old_value = self.tree.set(item, column)
続き:
entry = ttk.Entry(self.root)
entry.insert(0, old_value)
entry.place(x=event.x_root, y=event.y_root)
entry.bind("<Return>", lambda e: self.update_value(entry, item, column))
● 解説
identify_row+identify_columnでクリック座標からセルを割り出し- Entry ウィジェットを表示して編集
- Enterキーで値確定
Excelライクな編集体験が実現できます。
◆ ⑥ 保存処理
def save_excel(self):
for i, item in enumerate(self.tree.get_children(), start=1):
values = self.tree.item(item)["values"]
for j, value in enumerate(values, start=1):
self.current_sheet.cell(row=i, column=j).value = value
self.workbook.save("edited.xlsx")
messagebox.showinfo("保存完了", "Excelを保存しました。")
● 解説
- Treeview の値を openpyxl に書き戻し
- 新しいExcelとして保存
- 必要に応じて「名前を付けて保存」も可能
保存も非常に高速です。
■ まとめ
ExcelEditorApp は、普段の Excel 作業を大幅に効率化する Python 製の GUI アプリです。
tkinter の軽快な UI と openpyxl の高速処理によって、Excel を開くより早く編集できます。
ツリー表示、シート切り替え、セル編集、保存など、実務的な機能がすべて含まれています。
Python で業務アプリを作ると、処理速度を左右するのが PC 性能です。
Excel の大規模シートを扱う場合、メモリ16GB以上・CPU4コア以上の環境だと開発も実行もスムーズになります。


コメントを残す