Aggiungi export XLSX diagnostica

This commit is contained in:
2026-07-06 18:14:13 +02:00
parent 8e9294f80b
commit 7f3ce9d3af
3 changed files with 119 additions and 2 deletions

View File

@@ -3,7 +3,8 @@
from __future__ import annotations
import tkinter as tk
from tkinter import messagebox, ttk
from datetime import datetime
from tkinter import filedialog, messagebox, ttk
from typing import Any
import customtkinter as ctk
@@ -72,6 +73,7 @@ class DiagnosticaWindow(ctk.CTkToplevel):
self._load_in_progress = False
self._current_check = ""
self.var_status = tk.StringVar(value="")
self._last_export_slug = "diagnostica"
self.title(
versioned_title(
@@ -124,6 +126,15 @@ class DiagnosticaWindow(ctk.CTkToplevel):
font=button_font,
).grid(row=0, column=0, sticky="w", padx=(0, 8))
self.btn_export = ctk.CTkButton(
top,
text=loc_text("diagnostics.button.export", catalog=self._locale_catalog, default="Esporta XLSX"),
command=self._export_xlsx,
font=button_font,
state="disabled",
)
self.btn_export.grid(row=0, column=2, sticky="e")
ctk.CTkLabel(
self,
textvariable=self.var_status,
@@ -205,6 +216,11 @@ class DiagnosticaWindow(ctk.CTkToplevel):
self._load_in_progress = True
self._current_check = key
self._last_export_slug = key
try:
self.btn_export.configure(state="disabled")
except Exception:
pass
try:
self._busy.show(busy_text)
self._async.run(job(), self._on_loaded, self._on_error)
@@ -237,6 +253,10 @@ class DiagnosticaWindow(ctk.CTkToplevel):
),
tags=(zebra_tag(index),),
)
try:
self.btn_export.configure(state="normal" if rows else "disabled")
except Exception:
pass
self._set_status(
loc_text(
"diagnostics.status.rows",
@@ -264,6 +284,91 @@ class DiagnosticaWindow(ctk.CTkToplevel):
parent=self,
)
def _export_xlsx(self) -> None:
"""Export the currently visible diagnostic grid to an Excel file."""
rows = [self.tree.item(iid, "values") for iid in self.tree.get_children("")]
if not rows:
messagebox.showinfo(
loc_text("diagnostics.export.title", catalog=self._locale_catalog, default="Esporta"),
loc_text(
"diagnostics.export.empty",
catalog=self._locale_catalog,
default="Non ci sono righe da esportare.",
),
parent=self,
)
return
try:
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font
from openpyxl.utils import get_column_letter
except Exception as exc:
messagebox.showerror(
loc_text("diagnostics.export.title", catalog=self._locale_catalog, default="Esporta"),
loc_text(
"diagnostics.export.dep",
catalog=self._locale_catalog,
default="Per l'esportazione serve 'openpyxl' (pip install openpyxl).",
).format(error=exc),
parent=self,
)
return
ts = datetime.now().strftime("%Y%m%d_%H%M")
default_name = f"{self._last_export_slug}_{ts}.xlsx"
path = filedialog.asksaveasfilename(
parent=self,
title=loc_text("diagnostics.export.title", catalog=self._locale_catalog, default="Esporta"),
defaultextension=".xlsx",
filetypes=[("Excel Workbook", "*.xlsx")],
initialfile=default_name,
)
if not path:
return
try:
wb = Workbook()
ws = wb.active
ws.title = "Diagnostica"
columns = list(self.tree["columns"])
headers = [str(self.tree.heading(col, "text") or col) for col in columns]
for col_index, header in enumerate(headers, start=1):
cell = ws.cell(row=1, column=col_index, value=header)
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal="center", vertical="center")
for row_index, row in enumerate(rows, start=2):
for col_index, value in enumerate(row, start=1):
ws.cell(row=row_index, column=col_index, value=value)
widths: dict[int, int] = {}
for row in ws.iter_rows(values_only=True):
for col_index, value in enumerate(row, start=1):
widths[col_index] = max(widths.get(col_index, 0), len("" if value is None else str(value)))
for col_index, width in widths.items():
ws.column_dimensions[get_column_letter(col_index)].width = min(max(width + 2, 12), 70)
wb.save(path)
messagebox.showinfo(
loc_text("diagnostics.export.title", catalog=self._locale_catalog, default="Esporta"),
loc_text("diagnostics.export.ok", catalog=self._locale_catalog, default="File creato:\n{path}").format(path=path),
parent=self,
)
except Exception as exc:
log_exception(__name__, exc, context="export diagnostica xlsx")
messagebox.showerror(
loc_text("diagnostics.export.title", catalog=self._locale_catalog, default="Esporta"),
loc_text(
"diagnostics.export.error",
catalog=self._locale_catalog,
default="Errore durante l'esportazione:\n{error}",
).format(error=exc),
parent=self,
)
def open_diagnostica_window(parent: tk.Misc, db_client, session=None) -> tk.Misc:
"""Open the diagnostics window."""

View File

@@ -78,11 +78,17 @@
"history.picking.msg.detail_error": "Errore dettaglio:\n{error}",
"diagnostics.title": "Diagnostica",
"diagnostics.button.shipped_not_disassociated": "UDC spedite non disassociate",
"diagnostics.button.export": "Esporta XLSX",
"diagnostics.busy.shipped_not_disassociated": "Cerco UDC spedite ma ancora in cella...",
"diagnostics.status.rows": "Righe trovate: {count}",
"diagnostics.col.udc": "UDC",
"diagnostics.col.shipped_not_disassociated": "Spedita ma non disassociata",
"diagnostics.col.symbolic_cell": "Nome simbolico cella",
"diagnostics.export.title": "Esporta",
"diagnostics.export.empty": "Non ci sono righe da esportare.",
"diagnostics.export.dep": "Per l'esportazione serve 'openpyxl' (pip install openpyxl).",
"diagnostics.export.ok": "File creato:\n{path}",
"diagnostics.export.error": "Errore durante l'esportazione:\n{error}",
"reset.title": "Gestione Corsie - svuotamento celle per corsia",
"reset.label.aisle": "Corsia:",
"reset.button.refresh": "Carica",
@@ -201,11 +207,17 @@
"history.picking.msg.detail_error": "Detail load failed:\n{error}",
"diagnostics.title": "Diagnostics",
"diagnostics.button.shipped_not_disassociated": "Shipped UDC not disassociated",
"diagnostics.button.export": "Export XLSX",
"diagnostics.busy.shipped_not_disassociated": "Searching shipped UDC still assigned to cells...",
"diagnostics.status.rows": "Rows found: {count}",
"diagnostics.col.udc": "UDC",
"diagnostics.col.shipped_not_disassociated": "Shipped but not disassociated",
"diagnostics.col.symbolic_cell": "Symbolic cell name",
"diagnostics.export.title": "Export",
"diagnostics.export.empty": "There are no rows to export.",
"diagnostics.export.dep": "Export requires 'openpyxl' (pip install openpyxl).",
"diagnostics.export.ok": "File created:\n{path}",
"diagnostics.export.error": "Export failed:\n{error}",
"reset.title": "Aisle Management - empty cells by aisle",
"reset.label.aisle": "Aisle:",
"reset.button.refresh": "Load",

View File

@@ -18,7 +18,7 @@ MODULE_VERSIONS: dict[str, str] = {
"barcode_service": "1.0.24",
"busy_overlay": "1.0.0",
"db_config": "1.0.0",
"diagnostica": "1.0.0",
"diagnostica": "1.0.1",
"gestione_aree": "1.0.1",
"gestione_layout": "1.0.2",
"gestione_pickinglist": "1.0.4",