#!/usr/bin/env python3 """ Script to extract data from Production Order (mrp.production).xlsx and populate the template A4004_v3.0-260617.ods, saving the result as a new ODS file named after cell A2 from the source file. Dependencies: - openpyxl - ezodf Install with: pip install openpyxl ezodf """ import sys from openpyxl import load_workbook from openpyxl.utils import column_index_from_string import ezodf def find_fa_suffix(ws): """Find the suffix after 'FA-' in column B and return it.""" for row in ws.iter_rows(min_col=2, max_col=2, values_only=False): cell = row[0] if isinstance(cell.value, str) and "FA-" in cell.value: parts = cell.value.split("FA-") if len(parts) > 1: return parts[1].strip() return None def find_value_to_right(ws, search_str): """Find a cell containing `search_str` and return the value of the cell to its right.""" for row in ws.iter_rows(values_only=False): for cell in row: if isinstance(cell.value, str) and search_str in cell.value: # Get cell to the right (next column) right_cell = ws.cell(row=cell.row, column=cell.column + 1) return right_cell.value return None def fill_range(sheet, start, end, value): """Fill a rectangular range (inclusive) with `value`.""" start_col = column_index_from_string(start[:1]) - 1 start_row = int(start[1:]) - 1 end_col = column_index_from_string(end[:1]) - 1 end_row = int(end[1:]) - 1 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(): source_file = "Production Order (mrp.production).xlsx" template_file = "A4004_v3.0-260617.ods" # Load source workbook try: src_wb = load_workbook(source_file, data_only=True) except Exception as e: sys.exit(f"Failed to load source file '{source_file}': {e}") src_ws = src_wb.active # Extract values fa_suffix = find_fa_suffix(src_ws) if fa_suffix is None: sys.exit("FA- suffix not found in column B of source file.") # Mapping of search strings to target ranges in the template mappings = { "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"), } # Load template ODS try: doc = ezodf.opendoc(template_file) except Exception as e: sys.exit(f"Failed to load template file '{template_file}': {e}") sheet = doc.sheets[0] # Fill FA- suffix into B1:C2 fill_range(sheet, "B1", "C2", fa_suffix) # Fill other values for search_str, (start_cell, end_cell) in mappings.items(): value = find_value_to_right(src_ws, search_str) if value is None: sys.exit(f"Value for '{search_str}' not found in source file.") fill_range(sheet, start_cell, end_cell, value) # Determine output filename from cell A2 output_name_raw = src_ws["A2"].value if output_name_raw is None: sys.exit("Cell A2 is empty; cannot determine output filename.") output_name = f"{output_name_raw}.ods" # Save new file try: doc.saveas(output_name) except Exception as e: sys.exit(f"Failed to save output file '{output_name}': {e}")