| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- from openpyxl import load_workbook, Workbook
- from datetime import datetime
- from openpyxl.drawing.image import Image
- import re
- from openpyxl.drawing.spreadsheet_drawing import AbsoluteAnchor
- from openpyxl.drawing.xdr import XDRPoint2D, XDRPositiveSize2D
- from openpyxl.utils.units import pixels_to_EMU
- from openpyxl.utils import get_column_letter
- def center_image_in_cell(ws, cell_address, img_path):
- """
- Center an image in a specific cell.
- Args:
- ws: The worksheet object.
- cell_address (str): The cell address (e.g., "B2") where the image will be centered.
- img_path (str): Path to the image file.
- Returns:
- None
- """
- # Load the image
- img = Image(img_path)
- img.width = img.height = 20
- # Get the cell
- cell = ws[cell_address]
- # Approximate pixel dimensions of the cell
- col_letter = get_column_letter(cell.column)
- col_width = ws.column_dimensions[col_letter].width or 10 # Default width
- row_height = ws.row_dimensions[cell.row].height or 15 # Default height
- # Convert dimensions to pixels
- col_width_pixels = col_width * 7 # Approximation: 1 Excel unit = ~7 pixels
- row_height_pixels = row_height * 0.75 # Approximation: 1 Excel unit = ~0.75 pixels
- # Calculate the center position
- cell_left = pixels_to_EMU(cell.column - 1) # Column start position in EMU
- cell_top = pixels_to_EMU((cell.row - 1) * row_height_pixels) # Row start position in EMU
- x_center = cell_left + pixels_to_EMU((col_width_pixels - img.width) / 2)
- y_center = cell_top + pixels_to_EMU((row_height_pixels - img.height) / 2)
- # Set the image position and size
- position = XDRPoint2D(x_center, y_center)
- size = XDRPositiveSize2D(pixels_to_EMU(img.width), pixels_to_EMU(img.height))
- img.anchor = AbsoluteAnchor(pos=position, ext=size)
- # Add the image to the worksheet
- ws.add_image(img)
- def gen_xlsx4(template_file, selected_sheets, prefix_filename, data):
- """
- Generate an Excel file from a template, fill placeholders, and include only selected sheets.
- Args:
- template_file (str): Path to the Excel template file.
- selected_sheets (list): List of sheet names to include in the output file.
- prefix_filename (str): Prefix for the output filename.
- data (dict): Data dictionary with sheet-specific keys and fallback keys.
- Returns:
- str: Path of the generated Excel file.
- """
- checked_image_path = "./checkbox_checked.jpg" # Path to the checked checkbox image
- unchecked_image_path = "./checkbox_unchecked.jpg" # Path to the unchecked checkbox image
- # Load the template workbook
- workbook = load_workbook(template_file)
- # Remove sheets not in selected_sheets
- for sheet_name in workbook.sheetnames:
- if sheet_name not in selected_sheets:
- del workbook[sheet_name]
- # Process the selected sheets
- for sheet_name in selected_sheets:
- if sheet_name not in workbook.sheetnames:
- raise ValueError(f"Sheet '{sheet_name}' not found in the template.")
- sheet = workbook[sheet_name]
- # Replace placeholders with actual values
- # Handle hiding rows based on patterns in data
-
- for row in sheet.iter_rows():
- for cell in row:
- if cell.value and isinstance(cell.value, str) and cell.value.startswith("<") and cell.value.endswith(">"):
- placeholder = cell.value.strip("<>")
-
- # Determine value priority: `sheet_name.key` > `key`
- value = None
- sheet_specific_key = f"{sheet_name}.{placeholder}"
- if sheet_specific_key in data:
- value = data[sheet_specific_key]
- elif placeholder in data:
- value = data[placeholder]
- if value is not None:
- if value is True:
- img = Image(checked_image_path)
- img.width = img.height = 20
- print(f"{cell.coordinate}")
- sheet.add_image(img, cell.coordinate)
- cell.value = None # Remove the placeholder text
- elif value is False:
- img = Image(unchecked_image_path)
- img.width = img.height = 20
- sheet.add_image(img, cell.coordinate)
- # center_image_in_cell(sheet, cell.coordinate, unchecked_image_path)
- cell.value = None # Remove the placeholder text
- else:
- # Insert the text value directly
- cell.value = value
- for key, value in data.items():
- if isinstance(value, str) and re.match(r"^\d+\[\d+:\d+\]$", value):
- # Parse the prefix and row range
- prefix, row_range = value.split("[")
- row_start, row_end = map(int, row_range[:-1].split(":"))
-
- # Hide rows if the prefix matches the condition
- if prefix == "0": # Adjust the condition as needed
- sheet.row_dimensions.group(row_start, row_end, hidden=True)
-
- # Generate the output filename with a timestamp
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
- output_path = f"{prefix_filename}_{timestamp}.xlsx"
- workbook.save(output_path)
- return output_path
- if __name__ == "__main__":
- # Example usage
- data = {
- "customer": "Tum Coder",
- "inspect_date": "2025-01-15",
- "lot_no": "12345",
- "size": "Large",
- "pcs": "10 pcs",
- "spec": "Spec-A",
- "hardness.d1_act": "10",
- "hardness.d2_act": "0[24:28]", # Hide rows 24 to 28 if the prefix is "0"
- "hardness.acc": True, # Hide rows 24 to 28 if the prefix is "0"
- "hardness.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
- "dimension_app.d1_act": "33",
- "dimension_app.d2_act": "0[26:32]", # Hide rows 24 to 28 if the prefix is "0"
- "dimension_app.acc": True, # Hide rows 24 to 28 if the prefix is "0"
- "dimension_app.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
- }
- output_file = gen_xlsx4(
- template_file="./hardness.xlsx",
- selected_sheets=["hardness", "dimension_app"], # Replace with your actual sheet names
- prefix_filename="./output/output",
- data=data
- )
- print(f"Generated file: {output_file}")
|