Spaces:
Runtime error
Runtime error
Update invoice.py
Browse files- invoice.py +29 -22
invoice.py
CHANGED
|
@@ -239,33 +239,36 @@ def _clear_data(ws: Worksheet, start_row: int, col_first: int, col_last: int):
|
|
| 239 |
if c: c.value = None
|
| 240 |
|
| 241 |
def _apply_print_setup(ws: Worksheet):
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
ws.print_area = dim
|
| 254 |
|
| 255 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
ws.sheet_properties.pageSetUpPr.fitToPage = True
|
| 257 |
ps = ws.page_setup
|
| 258 |
ps.orientation = "portrait"
|
| 259 |
ps.paperSize = ws.PAPERSIZE_A4
|
| 260 |
ps.fitToWidth = 1
|
| 261 |
-
ps.fitToHeight =
|
| 262 |
-
ps.scale = None
|
| 263 |
|
| 264 |
-
#
|
| 265 |
ws.print_options.gridLines = False
|
| 266 |
-
ws.page_margins = PageMargins(
|
| 267 |
-
|
| 268 |
-
)
|
| 269 |
# ---------- date / numbering ----------
|
| 270 |
def today_str() -> str:
|
| 271 |
if sys.platform == "win32":
|
|
@@ -507,14 +510,17 @@ def _soffice_path() -> Optional[str]:
|
|
| 507 |
|
| 508 |
def _convert_with_libreoffice(xlsx_path: str, pdf_path: str) -> bool:
|
| 509 |
soffice = _soffice_path()
|
| 510 |
-
if not soffice:
|
|
|
|
| 511 |
try:
|
|
|
|
| 512 |
cmd = [
|
| 513 |
soffice, "--headless", "--nologo", "--nofirststartwizard",
|
| 514 |
"--convert-to", "pdf:calc_pdf_Export",
|
| 515 |
-
"--outdir", os.path.dirname(pdf_path),
|
|
|
|
| 516 |
]
|
| 517 |
-
r = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=
|
| 518 |
out_pdf = os.path.splitext(os.path.abspath(xlsx_path))[0] + ".pdf"
|
| 519 |
if r.returncode == 0 and os.path.exists(out_pdf):
|
| 520 |
os.replace(out_pdf, pdf_path)
|
|
@@ -523,6 +529,7 @@ def _convert_with_libreoffice(xlsx_path: str, pdf_path: str) -> bool:
|
|
| 523 |
pass
|
| 524 |
return False
|
| 525 |
|
|
|
|
| 526 |
def _convert_with_excel_win32(xlsx_path: str, pdf_path: str) -> bool:
|
| 527 |
if not win32_available: return False
|
| 528 |
try:
|
|
|
|
| 239 |
if c: c.value = None
|
| 240 |
|
| 241 |
def _apply_print_setup(ws: Worksheet):
|
| 242 |
+
# 0) If template defines a print area, keep it
|
| 243 |
+
try:
|
| 244 |
+
dn = ws.parent.defined_names.get('_xlnm.Print_Area') or ws.parent.defined_names.get('Print_Area')
|
| 245 |
+
if dn:
|
| 246 |
+
# Ensure the defined area is attached to this sheet
|
| 247 |
+
for title, ref in dn.destinations:
|
| 248 |
+
if title == ws.title:
|
| 249 |
+
ws.print_area = ref
|
| 250 |
+
break
|
| 251 |
+
except Exception:
|
| 252 |
+
pass
|
|
|
|
| 253 |
|
| 254 |
+
# If still not set, use a generous fixed area that covers header, table, notes, footer banner
|
| 255 |
+
if not ws.print_area:
|
| 256 |
+
# Adjust columns/rows to your template; L x row 110 usually covers the full design
|
| 257 |
+
ws.print_area = "A1:L110"
|
| 258 |
+
|
| 259 |
+
# Fit the entire print area onto one page (A4 portrait)
|
| 260 |
ws.sheet_properties.pageSetUpPr.fitToPage = True
|
| 261 |
ps = ws.page_setup
|
| 262 |
ps.orientation = "portrait"
|
| 263 |
ps.paperSize = ws.PAPERSIZE_A4
|
| 264 |
ps.fitToWidth = 1
|
| 265 |
+
ps.fitToHeight = 1 # ensure the footer/banner is included on the single page
|
| 266 |
+
ps.scale = None
|
| 267 |
|
| 268 |
+
# Clean print
|
| 269 |
ws.print_options.gridLines = False
|
| 270 |
+
ws.page_margins = PageMargins(left=0.3, right=0.3, top=0.5, bottom=0.5, header=0.25, footer=0.25)
|
| 271 |
+
|
|
|
|
| 272 |
# ---------- date / numbering ----------
|
| 273 |
def today_str() -> str:
|
| 274 |
if sys.platform == "win32":
|
|
|
|
| 510 |
|
| 511 |
def _convert_with_libreoffice(xlsx_path: str, pdf_path: str) -> bool:
|
| 512 |
soffice = _soffice_path()
|
| 513 |
+
if not soffice:
|
| 514 |
+
return False
|
| 515 |
try:
|
| 516 |
+
# calc_pdf_Export with defaults reliably keeps drawing layer
|
| 517 |
cmd = [
|
| 518 |
soffice, "--headless", "--nologo", "--nofirststartwizard",
|
| 519 |
"--convert-to", "pdf:calc_pdf_Export",
|
| 520 |
+
"--outdir", os.path.dirname(pdf_path),
|
| 521 |
+
os.path.abspath(xlsx_path),
|
| 522 |
]
|
| 523 |
+
r = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=90)
|
| 524 |
out_pdf = os.path.splitext(os.path.abspath(xlsx_path))[0] + ".pdf"
|
| 525 |
if r.returncode == 0 and os.path.exists(out_pdf):
|
| 526 |
os.replace(out_pdf, pdf_path)
|
|
|
|
| 529 |
pass
|
| 530 |
return False
|
| 531 |
|
| 532 |
+
|
| 533 |
def _convert_with_excel_win32(xlsx_path: str, pdf_path: str) -> bool:
|
| 534 |
if not win32_available: return False
|
| 535 |
try:
|