Exporter first version, merged cells broken
This commit is contained in:
158
techdb/flightslot/actions/exportweek.py
Normal file
158
techdb/flightslot/actions/exportweek.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, PatternFill, Alignment
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
from typing import List
|
||||
import calendar
|
||||
|
||||
from ..models.weekpref import WeekPreference
|
||||
from ..models.missions import Training
|
||||
from ..models.hourbuildings import HourBuilding
|
||||
|
||||
def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse:
|
||||
|
||||
if not queryset.first():
|
||||
raise Exception("Empty queryset")
|
||||
|
||||
# Init Variables
|
||||
year = date.today().year
|
||||
week = queryset.first().week if queryset.first() else date.today().isocalendar().week
|
||||
|
||||
# Prepare export filename and http content
|
||||
filename = f"{year}-week{week}_export.xlsx"
|
||||
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||
response['Content-Disposition'] = f'attachment; filename="{filename}"'
|
||||
|
||||
# Create workbook and sheet
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
if not ws:
|
||||
raise Exception("Export: cannot select active workbook")
|
||||
ws.title = f"{year} Week {week} Preferences"
|
||||
|
||||
# Header titles
|
||||
days = [f"{datetime.strptime(f"{year} {week} {x}", "%G %V %u").strftime("%A")} {datetime.strptime(f"{year} {week} {x}", "%G %V %u").day}" for x in range(1,8)]
|
||||
headers = ["Week", "Student", "Course", *days, "Cell.", "Mail", "Notes"]
|
||||
|
||||
# Header fields positions
|
||||
student_index: int = headers.index("Student") + 1
|
||||
course_index: int = headers.index("Course") + 1
|
||||
cell_index: int = headers.index("Cell.") + 1
|
||||
mail_index: int = headers.index("Mail") + 1
|
||||
|
||||
# Stile header
|
||||
header_fill = PatternFill("solid", fgColor="0e005c")
|
||||
bold_white = Font(color="FFFFFF", bold=True)
|
||||
bold_black = Font(color="000000", bold=True)
|
||||
center = Alignment(horizontal="center", vertical="center")
|
||||
|
||||
# Scrittura header
|
||||
for col, h in enumerate(headers, start=1):
|
||||
cell = ws.cell(row=1, column=col, value=h)
|
||||
cell.fill = header_fill
|
||||
cell.font = bold_white
|
||||
cell.alignment = center
|
||||
|
||||
# Scrittura dati
|
||||
row: int = 2
|
||||
row_offset: int = 0
|
||||
|
||||
# Fill worksheet with EVERY training and hb for every student
|
||||
for i, q in enumerate(queryset.order_by("student__surname", "student__name", "student__course"), start=1):
|
||||
student_data: List[str]
|
||||
student_phone: str = q.student.phone if q.student.phone else ""
|
||||
student_email: str = q.student.email
|
||||
if q.student.course:
|
||||
student_data = [f"{q.student.surname} {q.student.name}", f"{q.student.course.ctype}-{q.student.course.cnumber}"]
|
||||
else:
|
||||
student_data = [f"{q.student.surname} {q.student.name}", f"No Course Assigned"]
|
||||
|
||||
# Fill Training mission rows
|
||||
mission_name: str
|
||||
mission_days: List[str]
|
||||
mission_notes: str
|
||||
mission_data: List[List[str]] = []
|
||||
for t in Training.objects.filter(weekpref = q.id):
|
||||
if not t.mission:
|
||||
raise Exception("No Training Mission Assigned")
|
||||
mission_name = f"{t.mission.mtype}-{t.mission.mnum}"
|
||||
mission_days = [
|
||||
mission_name if t.monday else "",
|
||||
mission_name if t.tuesday else "",
|
||||
mission_name if t.wednesday else "",
|
||||
mission_name if t.thursday else "",
|
||||
mission_name if t.friday else "",
|
||||
mission_name if t.saturday else "",
|
||||
mission_name if t.sunday else ""
|
||||
]
|
||||
mission_notes = t.notes if t.notes else "--"
|
||||
mission_data.append([str(week), *student_data, *mission_days, student_phone, student_email, mission_notes])
|
||||
|
||||
# Fill HourBuilding rows
|
||||
hb_name: str
|
||||
hb_days: List[str]
|
||||
hb_notes: str
|
||||
hb_data: List[List[str]] = []
|
||||
for h in HourBuilding.objects.filter(weekpref = q.id):
|
||||
hb_name = f"HB-{h.aircraft}"
|
||||
hb_days = [
|
||||
hb_name if h.monday else "",
|
||||
hb_name if h.tuesday else "",
|
||||
hb_name if h.wednesday else "",
|
||||
hb_name if h.thursday else "",
|
||||
hb_name if h.friday else "",
|
||||
hb_name if h.saturday else "",
|
||||
hb_name if h.sunday else ""
|
||||
]
|
||||
hb_notes = h.notes if h.notes else "--"
|
||||
hb_data.append([str(week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes])
|
||||
|
||||
# Build rows for table
|
||||
student_start: int = row + row_offset
|
||||
for r in mission_data + hb_data:
|
||||
prev_cell_val: str | None = None
|
||||
merge_start: bool = False
|
||||
merge_col_start: int = 1
|
||||
for j, c in enumerate(r, start=1):
|
||||
if prev_cell_val is None:
|
||||
prev_cell_val = c
|
||||
cell = ws.cell(row = row + row_offset, column = j, value = c)
|
||||
cell.alignment = center
|
||||
# Format Student Name
|
||||
if j == student_index:
|
||||
cell.font = bold_black
|
||||
# Format Course Column
|
||||
if j == course_index and q.student.course:
|
||||
cell.fill = PatternFill("solid", fgColor=str(q.student.course.color).lstrip('#').lower())
|
||||
# Merge cells in the row
|
||||
if c == prev_cell_val and not merge_start:
|
||||
merge_start = True
|
||||
merge_col_start = max(j-1, 1)
|
||||
elif c != prev_cell_val and merge_start:
|
||||
merge_start = False
|
||||
ws.merge_cells(start_row=row+row_offset,
|
||||
end_row=row+row_offset,
|
||||
start_column=merge_col_start,
|
||||
end_column=max(j-1,1))
|
||||
|
||||
# Incement row counter
|
||||
row_offset += 1
|
||||
|
||||
# End f preferences for this student
|
||||
student_end: int = row + row_offset -1
|
||||
# Merge Name
|
||||
ws.merge_cells(start_row=student_start, end_row=student_end, start_column=student_index, end_column=student_index)
|
||||
# Merge Course
|
||||
ws.merge_cells(start_row=student_start, end_row=student_end, start_column=course_index, end_column=course_index)
|
||||
# Merge Cell
|
||||
ws.merge_cells(start_row=student_start, end_row=student_end, start_column=cell_index, end_column=cell_index)
|
||||
# Merge Mail
|
||||
ws.merge_cells(start_row=student_start, end_row=student_end, start_column=mail_index, end_column=mail_index)
|
||||
|
||||
# Save document in HttpResponse
|
||||
wb.save(response)
|
||||
|
||||
return response
|
||||
Reference in New Issue
Block a user