from openpyxl.styles import PatternFill, Border, Side, Alignment, Font from openpyxl.utils import get_column_letter center = Alignment(horizontal="center", vertical="center") left = Alignment(horizontal="left", vertical="center") red_fill = PatternFill(start_color="FF9999", fill_type="solid") orange_fill = PatternFill(start_color="FFCC99", fill_type="solid") yellow_fill = PatternFill(start_color="FFFF99", fill_type="solid") thick_border = Border(*(Side(style="thick"),)*4) thin_border = Border(*(Side(style="thin"),)*4) def style_service_groups(ws, service_groups): col_group, col_member, col_proto, col_port = 1, 2, 3, 4 start_row = 2 max_width = {1: 0, 2: 0, 3: 0, 4: 0} for row in range(2, ws.max_row + 1): g = ws.cell(row=row, column=col_group).value m = ws.cell(row=row, column=col_member).value proto = ws.cell(row=row, column=col_proto).value port = ws.cell(row=row, column=col_port).value ws.cell(row=row, column=col_group).fill = red_fill ws.cell(row=row, column=col_group).font = Font(bold=True) ws.cell(row=row, column=col_member).fill = ( orange_fill if m in service_groups else yellow_fill ) ws.cell(row=row, column=col_proto).fill = yellow_fill ws.cell(row=row, column=col_port).fill = yellow_fill for col in range(1, 5): ws.cell(row=row, column=col).border = thin_border max_width[1] = max(max_width[1], len(str(g or ""))) max_width[2] = max(max_width[2], len(str(m or ""))) max_width[3] = max(max_width[3], len(str(proto or ""))) max_width[4] = max(max_width[4], len(str(port or ""))) next_val = ws.cell(row=row + 1, column=col_group).value if row < ws.max_row else None if g != next_val: if row > start_row: ws.merge_cells(f"A{start_row}:A{row}") for r in range(start_row, row + 1): for c in range(1, 5): ws.cell(r, c).border = thick_border ws.cell(r, c).alignment = center if c in [1, 3, 4] else left start_row = row + 1 for col, width in max_width.items(): ws.column_dimensions[get_column_letter(col)].width = width + 4 for row in range(2, ws.max_row + 1): ws.row_dimensions[row].height = 18