Aggiungi export XLSX diagnostica
This commit is contained in:
107
diagnostica.py
107
diagnostica.py
@@ -3,7 +3,8 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox, ttk
|
from datetime import datetime
|
||||||
|
from tkinter import filedialog, messagebox, ttk
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import customtkinter as ctk
|
import customtkinter as ctk
|
||||||
@@ -72,6 +73,7 @@ class DiagnosticaWindow(ctk.CTkToplevel):
|
|||||||
self._load_in_progress = False
|
self._load_in_progress = False
|
||||||
self._current_check = ""
|
self._current_check = ""
|
||||||
self.var_status = tk.StringVar(value="")
|
self.var_status = tk.StringVar(value="")
|
||||||
|
self._last_export_slug = "diagnostica"
|
||||||
|
|
||||||
self.title(
|
self.title(
|
||||||
versioned_title(
|
versioned_title(
|
||||||
@@ -124,6 +126,15 @@ class DiagnosticaWindow(ctk.CTkToplevel):
|
|||||||
font=button_font,
|
font=button_font,
|
||||||
).grid(row=0, column=0, sticky="w", padx=(0, 8))
|
).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(
|
ctk.CTkLabel(
|
||||||
self,
|
self,
|
||||||
textvariable=self.var_status,
|
textvariable=self.var_status,
|
||||||
@@ -205,6 +216,11 @@ class DiagnosticaWindow(ctk.CTkToplevel):
|
|||||||
|
|
||||||
self._load_in_progress = True
|
self._load_in_progress = True
|
||||||
self._current_check = key
|
self._current_check = key
|
||||||
|
self._last_export_slug = key
|
||||||
|
try:
|
||||||
|
self.btn_export.configure(state="disabled")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
self._busy.show(busy_text)
|
self._busy.show(busy_text)
|
||||||
self._async.run(job(), self._on_loaded, self._on_error)
|
self._async.run(job(), self._on_loaded, self._on_error)
|
||||||
@@ -237,6 +253,10 @@ class DiagnosticaWindow(ctk.CTkToplevel):
|
|||||||
),
|
),
|
||||||
tags=(zebra_tag(index),),
|
tags=(zebra_tag(index),),
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
|
self.btn_export.configure(state="normal" if rows else "disabled")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
self._set_status(
|
self._set_status(
|
||||||
loc_text(
|
loc_text(
|
||||||
"diagnostics.status.rows",
|
"diagnostics.status.rows",
|
||||||
@@ -264,6 +284,91 @@ class DiagnosticaWindow(ctk.CTkToplevel):
|
|||||||
parent=self,
|
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:
|
def open_diagnostica_window(parent: tk.Misc, db_client, session=None) -> tk.Misc:
|
||||||
"""Open the diagnostics window."""
|
"""Open the diagnostics window."""
|
||||||
|
|||||||
12
locale.json
12
locale.json
@@ -78,11 +78,17 @@
|
|||||||
"history.picking.msg.detail_error": "Errore dettaglio:\n{error}",
|
"history.picking.msg.detail_error": "Errore dettaglio:\n{error}",
|
||||||
"diagnostics.title": "Diagnostica",
|
"diagnostics.title": "Diagnostica",
|
||||||
"diagnostics.button.shipped_not_disassociated": "UDC spedite non disassociate",
|
"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.busy.shipped_not_disassociated": "Cerco UDC spedite ma ancora in cella...",
|
||||||
"diagnostics.status.rows": "Righe trovate: {count}",
|
"diagnostics.status.rows": "Righe trovate: {count}",
|
||||||
"diagnostics.col.udc": "UDC",
|
"diagnostics.col.udc": "UDC",
|
||||||
"diagnostics.col.shipped_not_disassociated": "Spedita ma non disassociata",
|
"diagnostics.col.shipped_not_disassociated": "Spedita ma non disassociata",
|
||||||
"diagnostics.col.symbolic_cell": "Nome simbolico cella",
|
"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.title": "Gestione Corsie - svuotamento celle per corsia",
|
||||||
"reset.label.aisle": "Corsia:",
|
"reset.label.aisle": "Corsia:",
|
||||||
"reset.button.refresh": "Carica",
|
"reset.button.refresh": "Carica",
|
||||||
@@ -201,11 +207,17 @@
|
|||||||
"history.picking.msg.detail_error": "Detail load failed:\n{error}",
|
"history.picking.msg.detail_error": "Detail load failed:\n{error}",
|
||||||
"diagnostics.title": "Diagnostics",
|
"diagnostics.title": "Diagnostics",
|
||||||
"diagnostics.button.shipped_not_disassociated": "Shipped UDC not disassociated",
|
"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.busy.shipped_not_disassociated": "Searching shipped UDC still assigned to cells...",
|
||||||
"diagnostics.status.rows": "Rows found: {count}",
|
"diagnostics.status.rows": "Rows found: {count}",
|
||||||
"diagnostics.col.udc": "UDC",
|
"diagnostics.col.udc": "UDC",
|
||||||
"diagnostics.col.shipped_not_disassociated": "Shipped but not disassociated",
|
"diagnostics.col.shipped_not_disassociated": "Shipped but not disassociated",
|
||||||
"diagnostics.col.symbolic_cell": "Symbolic cell name",
|
"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.title": "Aisle Management - empty cells by aisle",
|
||||||
"reset.label.aisle": "Aisle:",
|
"reset.label.aisle": "Aisle:",
|
||||||
"reset.button.refresh": "Load",
|
"reset.button.refresh": "Load",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ MODULE_VERSIONS: dict[str, str] = {
|
|||||||
"barcode_service": "1.0.24",
|
"barcode_service": "1.0.24",
|
||||||
"busy_overlay": "1.0.0",
|
"busy_overlay": "1.0.0",
|
||||||
"db_config": "1.0.0",
|
"db_config": "1.0.0",
|
||||||
"diagnostica": "1.0.0",
|
"diagnostica": "1.0.1",
|
||||||
"gestione_aree": "1.0.1",
|
"gestione_aree": "1.0.1",
|
||||||
"gestione_layout": "1.0.2",
|
"gestione_layout": "1.0.2",
|
||||||
"gestione_pickinglist": "1.0.4",
|
"gestione_pickinglist": "1.0.4",
|
||||||
|
|||||||
Reference in New Issue
Block a user