# excel_export.py from openpyxl import Workbook from openpyxl.styles import Font, Alignment, PatternFill, Border, Side from datetime import datetime from io import BytesIO def export_users_to_excel(users): """导出用户数据到Excel""" wb = Workbook() ws = wb.active ws.title = "用户数据" # 设置表头样式 header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(bold=True, color="FFFFFF", size=12) header_alignment = Alignment(horizontal="center", vertical="center") # 表头 headers = ["ID", "用户名", "邮箱", "手机号", "角色", "状态", "完成考试数", "注册时间"] for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = header_alignment # 数据行 for row, user in enumerate(users, 2): ws.cell(row=row, column=1, value=user.id) ws.cell(row=row, column=2, value=user.name) ws.cell(row=row, column=3, value=user.email or "") ws.cell(row=row, column=4, value=user.phone or "") ws.cell(row=row, column=5, value=user.role) ws.cell(row=row, column=6, value="已封禁" if user.is_banned else "正常") ws.cell(row=row, column=7, value=user.completed_exams) ws.cell(row=row, column=8, value=user.created_at.strftime("%Y-%m-%d %H:%M:%S") if user.created_at else "") # 调整列宽 ws.column_dimensions['A'].width = 8 ws.column_dimensions['B'].width = 20 ws.column_dimensions['C'].width = 30 ws.column_dimensions['D'].width = 15 ws.column_dimensions['E'].width = 12 ws.column_dimensions['F'].width = 10 ws.column_dimensions['G'].width = 12 ws.column_dimensions['H'].width = 20 # 保存到内存 output = BytesIO() wb.save(output) output.seek(0) return output def export_exams_to_excel(exams): """导出考试数据到Excel""" wb = Workbook() ws = wb.active ws.title = "考试数据" header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(bold=True, color="FFFFFF", size=12) header_alignment = Alignment(horizontal="center", vertical="center") headers = ["ID", "考试名称", "创建者ID", "总分", "时长(分钟)", "状态", "提交数", "创建时间"] for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = header_alignment for row, exam in enumerate(exams, 2): ws.cell(row=row, column=1, value=exam.id) ws.cell(row=row, column=2, value=exam.title) ws.cell(row=row, column=3, value=exam.creator_id) ws.cell(row=row, column=4, value=exam.total_score) ws.cell(row=row, column=5, value=exam.duration) ws.cell(row=row, column=6, value=exam.status) ws.cell(row=row, column=7, value=len(exam.submissions) if exam.submissions else 0) ws.cell(row=row, column=8, value=exam.created_at.strftime("%Y-%m-%d %H:%M:%S") if exam.created_at else "") ws.column_dimensions['A'].width = 8 ws.column_dimensions['B'].width = 30 ws.column_dimensions['C'].width = 12 ws.column_dimensions['D'].width = 10 ws.column_dimensions['E'].width = 15 ws.column_dimensions['F'].width = 12 ws.column_dimensions['G'].width = 10 ws.column_dimensions['H'].width = 20 output = BytesIO() wb.save(output) output.seek(0) return output def export_submissions_to_excel(submissions): """导出提交记录到Excel""" wb = Workbook() ws = wb.active ws.title = "提交记录" header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(bold=True, color="FFFFFF", size=12) header_alignment = Alignment(horizontal="center", vertical="center") headers = ["ID", "考试ID", "考试名称", "用户ID", "用户名", "得分", "总分", "状态", "提交时间"] for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = header_alignment for row, sub in enumerate(submissions, 2): ws.cell(row=row, column=1, value=sub.id) ws.cell(row=row, column=2, value=sub.exam_id) ws.cell(row=row, column=3, value=sub.exam.title if sub.exam else "") ws.cell(row=row, column=4, value=sub.user_id) ws.cell(row=row, column=5, value=sub.user.name if sub.user else "") ws.cell(row=row, column=6, value=sub.score if sub.score is not None else "") ws.cell(row=row, column=7, value=sub.total_score) ws.cell(row=row, column=8, value=sub.status) ws.cell(row=row, column=9, value=sub.submitted_at.strftime("%Y-%m-%d %H:%M:%S") if sub.submitted_at else "") ws.column_dimensions['A'].width = 8 ws.column_dimensions['B'].width = 10 ws.column_dimensions['C'].width = 30 ws.column_dimensions['D'].width = 10 ws.column_dimensions['E'].width = 20 ws.column_dimensions['F'].width = 10 ws.column_dimensions['G'].width = 10 ws.column_dimensions['H'].width = 12 ws.column_dimensions['I'].width = 20 output = BytesIO() wb.save(output) output.seek(0) return output def export_contests_to_excel(contests): """导出杯赛数据到Excel""" wb = Workbook() ws = wb.active ws.title = "杯赛数据" header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(bold=True, color="FFFFFF", size=12) header_alignment = Alignment(horizontal="center", vertical="center") headers = ["ID", "杯赛名称", "主办方", "开始日期", "结束日期", "状态", "参与人数", "创建时间"] for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = header_alignment for row, contest in enumerate(contests, 2): ws.cell(row=row, column=1, value=contest.id) ws.cell(row=row, column=2, value=contest.name) ws.cell(row=row, column=3, value=contest.organizer or "") ws.cell(row=row, column=4, value=contest.start_date or "") ws.cell(row=row, column=5, value=contest.end_date or "") ws.cell(row=row, column=6, value=contest.status) ws.cell(row=row, column=7, value=contest.participants) ws.cell(row=row, column=8, value=contest.created_at.strftime("%Y-%m-%d %H:%M:%S") if contest.created_at else "") ws.column_dimensions['A'].width = 8 ws.column_dimensions['B'].width = 30 ws.column_dimensions['C'].width = 20 ws.column_dimensions['D'].width = 15 ws.column_dimensions['E'].width = 15 ws.column_dimensions['F'].width = 12 ws.column_dimensions['G'].width = 12 ws.column_dimensions['H'].width = 20 output = BytesIO() wb.save(output) output.seek(0) return output def export_posts_to_excel(posts): """导出论坛帖子到Excel""" wb = Workbook() ws = wb.active ws.title = "论坛帖子" header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(bold=True, color="FFFFFF", size=12) header_alignment = Alignment(horizontal="center", vertical="center") headers = ["ID", "标题", "作者", "分类", "浏览数", "回复数", "点赞数", "创建时间"] for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = header_alignment for row, post in enumerate(posts, 2): ws.cell(row=row, column=1, value=post.id) ws.cell(row=row, column=2, value=post.title) ws.cell(row=row, column=3, value=post.author.name if post.author else "") ws.cell(row=row, column=4, value=post.category or "") ws.cell(row=row, column=5, value=post.views) ws.cell(row=row, column=6, value=post.reply_count) ws.cell(row=row, column=7, value=post.like_count) ws.cell(row=row, column=8, value=post.created_at.strftime("%Y-%m-%d %H:%M:%S") if post.created_at else "") ws.column_dimensions['A'].width = 8 ws.column_dimensions['B'].width = 40 ws.column_dimensions['C'].width = 20 ws.column_dimensions['D'].width = 15 ws.column_dimensions['E'].width = 10 ws.column_dimensions['F'].width = 10 ws.column_dimensions['G'].width = 10 ws.column_dimensions['H'].width = 20 output = BytesIO() wb.save(output) output.seek(0) return output