Aggiungi export XLSX diagnostica
This commit is contained in:
107
diagnostica.py
107
diagnostica.py
@@ -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."""
|
||||
|
||||
12
locale.json
12
locale.json
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user