diff --git a/app_state.py b/app_state.py index 7dc62fe..078f5ca 100644 --- a/app_state.py +++ b/app_state.py @@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it. import configparser 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") DEFAULT_GRID_SIZE = 10 DEFAULT_ADD_TIMESTAMP = True diff --git a/manage_kits.py b/manage_kits.py index 9fa8408..93b503c 100644 --- a/manage_kits.py +++ b/manage_kits.py @@ -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. """ +import os import tkinter as tk -from tkinter import messagebox, ttk +from tkinter import filedialog, messagebox, ttk import app_state import palette @@ -267,6 +268,9 @@ class KitsPanel: button_row, text="Update kits", command=self._update_marked, ).pack(side=tk.LEFT, padx=6) 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.row_by_item = {} @@ -286,6 +290,70 @@ class KitsPanel: self._close_editor() 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): if self._editor_widget is not None: self._editor_widget.destroy()