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

135 lines
5.5 KiB
Python
Raw Normal View History

2026-06-19 12:29:55 +00:00
#!/usr/bin/env python3
"""
populate_template.py
Script to copy data from a production order Excel file into an ODS template
and save the result as a new ODS file named after the value in cell A2.
Requirements:
pip install openpyxl odfpy
"""
import sys
from pathlib import Path
from openpyxl import load_workbook
from odf.opendocument import load, OpenDocumentSpreadsheet
from odf.table import Table, TableRow, TableCell
from odf.text import P
# ----------------------------------------------------------------------
# Configuration adjust if your filenames differ
# ----------------------------------------------------------------------
SOURCE_XLSX = Path("Production Order (mrp.production).xlsx")
TEMPLATE_ODS = Path("A4004_v3.0-260617.ods")
OUTPUT_DIR = Path(".") # current directory; change if you prefer another location
# ----------------------------------------------------------------------
# Helper functions for ODS manipulation
# ----------------------------------------------------------------------
def get_cell(table: Table, col_idx: int, row_idx: int) -> TableCell:
"""Return the TableCell at (col_idx, row_idx) 0based indices."""
rows = table.getElementsByType(TableRow)
if row_idx >= len(rows):
raise IndexError(f"Row {row_idx} out of range")
cells = rows[row_idx].getElementsByType(TableCell)
if col_idx >= len(cells):
raise IndexError(f"Column {col_idx} out of range")
return cells[col_idx]
def set_cell_value(table: Table, col_idx: int, row_idx: int, value: str):
"""Write a string value into the specified cell."""
cell = get_cell(table, col_idx, row_idx)
# Clear existing content
for child in list(cell.childNodes):
cell.removeChild(child)
# Insert new text
cell.addElement(P(text=str(value)))
def col_letter_to_index(letter: str) -> int:
"""Convert Excelstyle column letter (A=0, B=1, …) to zerobased index."""
return ord(letter.upper()) - ord('A')
# ----------------------------------------------------------------------
# Main processing
# ----------------------------------------------------------------------
def main() -> None:
# 1. Load source workbook
wb = load_workbook(SOURCE_XLSX, data_only=True)
ws = wb.active
# Helper to find a cell containing a given substring (casesensitive)
def find_cell_containing(text: str):
for row in ws.iter_rows(values_only=False):
for cell in row:
if isinstance(cell.value, str) and text in cell.value:
return cell
return None
# ------------------------------------------------------------------
# Extract required values from the source file
# ------------------------------------------------------------------
# a) FA suffix (column B)
fa_suffix = None
for cell in ws["B"]:
if isinstance(cell.value, str) and cell.value.startswith("FA-"):
fa_suffix = cell.value.split("FA-")[1].strip()
break
if fa_suffix is None:
sys.exit("Error: Could not find a cell in column B starting with 'FA-'")
# b) Adjacent values for the component strings
def get_right_adjacent(search_str: str) -> str:
match = find_cell_containing(search_str)
if not match:
sys.exit(f"Error: Could not find cell containing '{search_str}'")
right_cell = ws.cell(row=match.row, column=match.column + 1)
return right_cell.value if right_cell.value is not None else ""
barebone_val = get_right_adjacent("All / Components / Barebone")
gpu_val = get_right_adjacent("All / Components / GPU")
ram_val = get_right_adjacent("All / Components / RAM")
cpu_val = get_right_adjacent("All / Components / CPU")
ssd_val = get_right_adjacent("All / Components / SSD")
raid_val = get_right_adjacent("All / Components / RAID")
# c) File name from A2
file_name_cell = ws["A2"]
if file_name_cell.value is None:
sys.exit("Error: Cell A2 in source file is empty")
output_name = f"{file_name_cell.value}.ods"
# ------------------------------------------------------------------
# Load ODS template and write values
# ------------------------------------------------------------------
ods_doc: OpenDocumentSpreadsheet = load(str(TEMPLATE_ODS))
# Assuming the template has a single table; adjust index if needed
table: Table = ods_doc.spreadsheet.getElementsByType(Table)[0]
# Mapping of target ranges (topleft cell only) → value
# (col_letter, row_number) are 1based as in Excel/ODS UI
targets = {
("B", 1): fa_suffix, # B1:C2 → write to B1
("C", 10): barebone_val, # C10:D10 → write to C10
("C", 20): gpu_val, # C20:D23 → write to C20
("C", 12): ram_val, # C12:D19 -> write to C12
("C", 11): cpu_val, # C11:D11 -> write to C11
("C", 24): ssd_val, # C24:D25 -> write to C24
("C", 27): raid_val, # C27:D27 -> write to C27
}
for (col_letter, row_number), value in targets.items():
col_idx = col_letter_to_index(col_letter)
row_idx = row_number - 1 # zerobased for helper
set_cell_value(table, col_idx, row_idx, value)
# ------------------------------------------------------------------
# Save the modified document
# ------------------------------------------------------------------
output_path = OUTPUT_DIR / output_name
ods_doc.save(str(output_path))
print(f"Successfully created: {output_path}")
if __name__ == "__main__":
main()