Python导出excel,首先确认是否下载pandas openpyxl 库
pip install pandas openpyxl
pandas
: 用于数据操作和分析。openpyxl
: 用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件。
如果没有下载 fastapi uvicorn,需要一并下载,方法同上
创建和写入Excel文件
接下来,我们编写代码来创建一个包含特定字段的Excel文件,并对标题行进行样式设置(例如:背景颜色)。
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from io import BytesIO
from urllib.parse import quote
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/export")
def export():
# 示例数据
data = {
'day': ['2025-02-05', '2025-02-06'],
'user_ame': ['张三', '李四'],
'project_name': ['项目A', '项目B'],
'work_type_name': ['任务1', '任务2'],
'duration_hours': [8, 7],
'update_time': ['2025-02-05 14:00', '2025-02-06 10:00'],
'content': ['完成了模块X的开发', '修复了Y模块中的错误']
}
#数据类型转换 将这个字典转换为一个DataFrame对象,这里字段名就会被设置为 标题名
df = pd.DataFrame(data)
# 创建Excel文件
output = BytesIO()
wb = Workbook()
ws = wb.active
#设置sheet页的名称,不设置就是默认的名字
ws.title = "sheetName"
#写入数据
for r in dataframe_to_rows(df, index=False, header=True):
ws.append(r)
# 设置标题行样式 这里是设置背景色
header_fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
#给第一行设置标题
for cell in ws[1]: # 标题行是第一行
cell.fill = header_fill
wb.save(output)
output.seek(0)
#设置响应头
response = StreamingResponse(output,
media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response.headers = {"Content-Disposition": f"attachment; filename*=UTF-8''{quote('导出文件.xlsx')}"}
return response
为了确保浏览器能够正确地提示用户下载文件而不是尝试在浏览器中打开它,我们需要正确设置HTTP响应头部。这里使用了filename*
参数支持UTF-8编码的文件名。
在结尾设置响应头中,如果导出是个英文命名,可以这么写:
response = StreamingResponse(output, media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response.headers["Content-Disposition"] = "attachment; filename=exporter_name.xlsx"
导出中文名需要加quote是因为HTTP响应头中传递一个包含非ASCII字符(如中文、日文等)的文件名时,为了确保跨浏览器的兼容性和正确性,需要通过百分比编码(URL编码)的方式来指定文件名,并明确指出使用的字符集(在这个例子中为UTF-8)。
如果期望返回的excel标题是汉字,可以选择在设置data时就用中文字段返回,或者单独设置映射处理列表
#在方法内部使用
# 定义要导出的字段和对应的表头
fields = [
('day', '日报时间'),
('real_name', '填报人员'),
('project_name', '处理项目'),
('work_type_name', '处理事项'),
('duration_hours', '处理时间(小时)'),
('daily_report_update_time', '创建时间'),
('content', '事项描述')
]
# 从记录中提取指定字段的数据
data_to_export = [{header: getattr(item, field) for field, header in fields} for item in data]
#在方法外
# 定义字段映射,从原始字段到自定义标题
fields_mapping = {
'day': '日期',
'link_user_real_name': '填报人',
'link_project_name': '处理项目',
'link_dict_work_type_name': '处理事项',
'duration_hours': '处理时间(小时)',
'daily_report_update_time': '创建时间',
'content': '事项描述'
}
def export():
……
# 根据字段映射重命名DataFrame的列
df.rename(columns=fields_mapping, inplace=True)
……