Kit Manager: add Export as XLS button

Saves the kit table to an Excel file with section headers, check
marks, and all four data columns. Default filename is based on the
open SAX file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 13:06:30 +03:00
co-authored by Claude Opus 4.6
parent db8472371e
commit d3d141cca8
2 changed files with 70 additions and 2 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it.
import configparser import configparser
import os import os
VERSION = "0.0.0.069" VERSION = "0.0.0.070"
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties") PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
DEFAULT_GRID_SIZE = 10 DEFAULT_GRID_SIZE = 10
DEFAULT_ADD_TIMESTAMP = True DEFAULT_ADD_TIMESTAMP = True
+69 -1
View File
@@ -15,8 +15,9 @@ declared can be unticked, which turns its Action into REMOVE. An installed kit t
declared starts unticked, and ticking it adds it at its newest build. declared starts unticked, and ticking it adds it at its newest build.
""" """
import os
import tkinter as tk import tkinter as tk
from tkinter import messagebox, ttk from tkinter import filedialog, messagebox, ttk
import app_state import app_state
import palette import palette
@@ -267,6 +268,9 @@ class KitsPanel:
button_row, text="Update kits", command=self._update_marked, button_row, text="Update kits", command=self._update_marked,
).pack(side=tk.LEFT, padx=6) ).pack(side=tk.LEFT, padx=6)
ttk.Button(button_row, text="Close", command=self.close).pack(side=tk.RIGHT) ttk.Button(button_row, text="Close", command=self.close).pack(side=tk.RIGHT)
ttk.Button(
button_row, text="Export as XLS", command=self._export_xls,
).pack(side=tk.RIGHT, padx=6)
self.rows = [] self.rows = []
self.row_by_item = {} self.row_by_item = {}
@@ -286,6 +290,70 @@ class KitsPanel:
self._close_editor() self._close_editor()
self.frame.destroy() self.frame.destroy()
def _export_xls(self):
try:
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
except ImportError:
messagebox.showerror("Export", "openpyxl is not installed.")
return
default_name = ""
if app_state.current_file_path:
base = os.path.splitext(os.path.basename(app_state.current_file_path))[0]
default_name = f"{base}_kits.xlsx"
path = filedialog.asksaveasfilename(
title="Export Kit Table",
defaultextension=".xlsx",
initialfile=default_name,
filetypes=[("Excel Files", "*.xlsx")],
)
if not path:
return
wb = Workbook()
ws = wb.active
ws.title = "Kits"
headers = ["", "Kit name", "Installed", "Latest", "Action"]
header_font = Font(bold=True)
section_fill = PatternFill(start_color="DCDCDC", end_color="DCDCDC", fill_type="solid")
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col, value=header)
cell.font = header_font
row_num = 2
for row in self.rows:
if "section" in row:
cell = ws.cell(row=row_num, column=2, value=row["section"])
cell.font = Font(bold=True)
for col in range(1, 6):
ws.cell(row=row_num, column=col).fill = section_fill
row_num += 1
continue
check = "✓" if row["checked"] else ""
ws.cell(row=row_num, column=1, value=check).alignment = Alignment(horizontal="center")
ws.cell(row=row_num, column=2, value=row["kit"])
ws.cell(row=row_num, column=3, value=row["installed_text"])
ws.cell(row=row_num, column=4, value=row["latest_text"])
ws.cell(row=row_num, column=5, value=self._action_text(row))
row_num += 1
ws.column_dimensions["A"].width = 4
ws.column_dimensions["B"].width = 28
ws.column_dimensions["C"].width = 16
ws.column_dimensions["D"].width = 16
ws.column_dimensions["E"].width = 30
try:
wb.save(path)
app_state.set_status(f"Kit table exported to {os.path.basename(path)}")
except Exception as e:
messagebox.showerror("Export", f"Could not save file:\n{e}")
def _close_editor(self): def _close_editor(self):
if self._editor_widget is not None: if self._editor_widget is not None:
self._editor_widget.destroy() self._editor_widget.destroy()