From 95370ed0dc8a7f4b28e5d17792923624f07e5325 Mon Sep 17 00:00:00 2001 From: Emanuele Date: Mon, 24 Nov 2025 12:20:42 +0100 Subject: [PATCH] Improved excel formatting --- cntmanage/flightslot/actions/exportweek.py | 69 ++++++++++++++-------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/cntmanage/flightslot/actions/exportweek.py b/cntmanage/flightslot/actions/exportweek.py index 66fb991..9654ab8 100644 --- a/cntmanage/flightslot/actions/exportweek.py +++ b/cntmanage/flightslot/actions/exportweek.py @@ -59,9 +59,12 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> # Cell styles border_thick: Side = Side(style='thick', color='000000') + border_thin: Side = Side(style='thin', color='000000', border_style='dashed') border_bottom: Border = Border(bottom=border_thick) + border_bottom_thin: Border = Border(bottom=border_thin) border_left: Border = Border(left=border_thick) border_right: Border = Border(right=border_thick) + border_right_thin: Border = Border(right=border_thin) border_all: Border = Border(bottom=border_thick, top=border_thick, left=border_thick, right=None) # Scrittura header @@ -111,7 +114,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> hb_days: List[str] hb_data: List[List[str]] = [] for h in HourBuilding.objects.filter(weekpref = q.id): - hb_name = f"HB-{h.aircraft}\nVedi Note ->" + hb_name = f"HB - {h.aircraft}\nVedi Note ->" hb_days = [ hb_name if h.monday else "", hb_name if h.tuesday else "", @@ -124,59 +127,68 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> hb_notes: List[str] = [f"{h.notes}", "---"] if h.notes else [] hb_legs_all = HourBuildingLegBase.objects.filter(hb_id = h.id) for hh in hb_legs_all: + time_str: str = ':'.join(str(hh.time).split(':')[:2]) # keep only hours and minutes if isinstance(hh, HourBuildingLegFlight): - hb_notes.append(f"{hh.departure} -> {hh.destination} [{hh.time}]") + hb_notes.append(f"{hh.departure} -> {hh.destination} [{time_str}]{f' / PAX: {hh.pax.capitalize()}' if hh.pax else ''}") elif isinstance(hh, HourBuildingLegStop): - hb_notes.append(f"STOP [{hh.time}] {"Refuel" if hh.refuel else ""}" ) + hb_notes.append(f"STOP [{time_str}] {"Refuel" if hh.refuel else ""}" ) hb_data.append([str(q.week), *student_data, *hb_days, "\n".join(hb_notes), str(q.student.phone), q.student.email]) # Build rows for table all_data: List[List[str]] = mission_data + hb_data student_start: int = row + row_offset - for r in all_data: - for j, c in enumerate(r, start=1): - cell = ws.cell(row = row + row_offset, column = j, value = c) + for row_content in all_data: + for c, cell_content in enumerate(row_content, start=1): + cell = ws.cell(row = row + row_offset, column = c, value = cell_content) cell.alignment = center # Format Student Name - if j == student_index: + if c == student_index: cell.font = bold_black - # Format Course Column - if j == course_index and q.student.course: + # Format Course Column with color + elif c == course_index and q.student.course: cell.font = bold_black cell.fill = PatternFill("solid", fgColor=str(q.student.course.color).lstrip('#').lower()) - - prev_cell_val: str = r[0] + # Add internal borders between mix cells and notes + elif c > course_index and c <= note_index: + cell.border = border_bottom_thin + border_right_thin + # Fill mix cells if the cell is not empty + if c > course_index and c < note_index: + if len(cell_content): + cell.fill = PatternFill('solid', fgColor="f0f0f0") + + prev_cell_val: str = row_content[0] merge_start: bool = False merge_col_start: int = 1 - for c, v in enumerate(r, start=1): + for c, cell_content in enumerate(row_content, start=1): # Merge cells in the row - if v == prev_cell_val and not merge_start: + if cell_content == prev_cell_val and not merge_start: merge_start = True merge_col_start = c-1 # start merge from previous column - elif v != prev_cell_val and merge_start: + elif cell_content != prev_cell_val and merge_start: merge_start = False ws.merge_cells(start_row=row+row_offset, end_row=row+row_offset, start_column=max(merge_col_start,1), end_column=max(c-1,1)) # end merge to previous column - prev_cell_val = v + prev_cell_val = cell_content # Incement row counter row_offset += 1 # End week preferences for this student - student_end: int = row + row_offset -1 + student_end: int = row + row_offset - 1 # Add thick border to the last cell row of this student - for i in range(course_index, len(all_data[0])+1): - ws.cell(row=student_end, column=i).border = border_bottom - if i == len(all_data[0]): - for j in range(student_start, student_end + 1): - ws.cell(row=j, column=i).border += border_right + for c in range(course_index, mail_index + 1): + ws.cell(row=student_end, column=c).border = Border(bottom=border_thick, right=border_thin) + # And for last column also a vertical border all student high + if c == mail_index: + for row_content in range(student_start, student_end + 1): + ws.cell(row=row_content, column=c).border += border_right # Merge Week, thick border - #ws.cell(row=student_start, column=week_index).border = border_bottom - #ws.merge_cells(start_row=student_start, end_row=student_end, start_column=week_index, end_column=week_index) + ws.cell(row=student_start, column=week_index).border = border_all + ws.merge_cells(start_row=student_start, end_row=student_end, start_column=week_index, end_column=week_index) # Merge Name, thick border ws.cell(row=student_start, column=student_index).border = border_all ws.merge_cells(start_row=student_start, end_row=student_end, start_column=student_index, end_column=student_index) @@ -188,8 +200,14 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> ws.merge_cells(start_row=student_start, end_row=student_end, start_column=mail_index, end_column=mail_index) # Keep the largest column + max_len: List[int] = [] for column_cells in ws.columns: - length: int = max(len(str(cell.value)) for cell in column_cells) + for cell in column_cells: + cell_lines = str(cell.value).splitlines() + if len(cell_lines) == 0: + continue + max_len.append(max([len(ll) for ll in cell_lines])) + length: int = max(max_len) col_letter: str = "A" if column_cells[0].column: col_letter = get_column_letter(column_cells[0].column) @@ -197,8 +215,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> ### End of Student Loop ### - # Save document in HttpResponse wb.save(response) - return response \ No newline at end of file + return response