dotfiles/VSCodium/User/History/-2f7fe65f/p5QE.py

109 lines
3.5 KiB
Python
Raw Normal View History

2026-06-19 12:29:55 +00:00
#!/usr/bin/env python3
import re
import sys
from pathlib import Path
import openpyxl
import ezodf
from openpyxl.utils import column_index_from_string
def find_suffix_in_column(ws, column_letter, prefix):
"""Search column for a cell starting with prefix and return the suffix."""
col_idx = column_index_from_string(column_letter)
for row in ws.iter_rows(min_col=col_idx, max_col=col_idx, values_only=False):
cell = row[0]
if isinstance(cell.value, str):
m = re.search(rf'{re.escape(prefix)}(.+)', cell.value)
if m:
return m.group(1)
return None
def find_cell_containing(ws, substring):
"""Return the first cell whose value contains the given substring."""
for row in ws.iter_rows(values_only=False):
for cell in row:
if isinstance(cell.value, str) and substring in cell.value:
return cell
return None
def address_to_indices(addr):
"""Convert an A1-style address to zerobased (row, col) indices."""
match = re.match(r'([A-Z]+)(\\d+)', addr)
col_letter, row_str = match.groups()
col = column_index_from_string(col_letter) - 1
row = int(row_str) - 1
return row, col
def fill_range(sheet, start_addr, end_addr, value):
"""Fill a rectangular range in the ODS sheet with the same value."""
start_row, start_col = address_to_indices(start_addr)
end_row, end_col = address_to_indices(end_addr)
for r in range(start_row, end_row + 1):
for c in range(start_col, end_col + 1):
sheet[r, c].set_value(value)
def main():
# Paths are relative to this script's location
source_path = Path(__file__).parent / "Production Order (mrp.production).xlsx"
template_path = Path(__file__).parent / "A4004_v3.0-260617.ods"
# Load source workbook
wb = openpyxl.load_workbook(source_path, data_only=True)
ws = wb.active
# 1. Serial number suffix after 'FA-'
suffix = find_suffix_in_column(ws, "B", "FA-")
if not suffix:
print("FA- suffix not found", file=sys.stderr)
sys.exit(1)
# 2. Component values
components = {
"All / Components / Barebone": "C10:D10",
"All / Components / GPU": "C20:D23",
"All / Components / RAM": "C12:D19",
"All / Components / CPU": "C11:D11",
"All / Components / SSD": "C24:D25",
"All / Components / RAID": "C27:D27",
}
comp_values = {}
for label, target_range in components.items():
cell = find_cell_containing(ws, label)
if cell:
right_cell = ws.cell(row=cell.row, column=cell.column + 1)
comp_values[label] = right_cell.value
else:
comp_values[label] = None
print(f"Warning: '{label}' not found", file=sys.stderr)
# Load ODS template
doc = ezodf.opendoc(str(template_path))
sheet = doc.sheets[0]
# Fill serial suffix into B1:C2
fill_range(sheet, "B1", "C2", suffix)
# Fill component ranges
for label, target_range in components.items():
value = comp_values[label]
if value is not None:
start_addr, end_addr = target_range.split(":")
fill_range(sheet, start_addr, end_addr, value)
# Output file name from A2
a2_value = ws["A2"].value
if not a2_value:
print("Cell A2 is empty; cannot determine output filename.", file=sys.stderr)
sys.exit(1)
output_name = f"{a2_value}.ods"
output_path = Path(__file__).parent / output_name
doc.saveas(str(output_path))