最近一直在用FastApi开发Web系统,经常需要遇到数据导出的需求。
分享一个我自己使用的导出函数。
优点:
1.以数据流生成并返回给前端下载,不占用服务器存储。
2.可以自定义表头和数据样式
代码里的注释都标记完整了,可以直接使用。
import xlwt
from io import BytesIO
from urllib.parse import quote
from fastapi.responses import StreamingResponsedef export_exl(header, data=None, data_col=None, file_name='download', need_order=False):"""以流的形式导出到excel:param header: ['列名1', '列名2']:param data: [{'a': 1, 'b': 2}] 数据集,与header、data_col对应:param data_col: ['与列名对应的字段1', '与列名对应的字段2']:param file_name: 文件名称:param need_order: 是否插入序号:return:"""def set_style():"""设置样式:return:"""# 居中设置alignment = xlwt.Alignment()alignment.horz = xlwt.Alignment.HORZ_CENTERalignment.vert = xlwt.Alignment.VERT_CENTERalignment.wrap=1 #设置自动换行# 设置表头字体样式head_style = xlwt.XFStyle()font = xlwt.Font()font.name = 'Times New Roman' # 字体font.height = 20 * 16 #字体大小font.bold = True # 字体加粗font.colour_index=9 #字体颜色# 设置背景颜色pattern = xlwt.Pattern()# 设置背景颜色的模式pattern.pattern = xlwt.Pattern.SOLID_PATTERN# 背景颜色pattern.pattern_fore_colour = 40head_style.pattern=patternhead_style.font = font # 设置字体head_style.alignment = alignment # Add Alignment to Style# 设置表中内容样式cont_style = xlwt.XFStyle()font = xlwt.Font()font.name = 'Times New Roman' # 字体font.bold = False # 字体加粗cont_style.font = font # 设置字体cont_style.alignment = alignment # Add Alignment to Style# 设置单元格边界borders = xlwt.Borders()borders.left = xlwt.Borders.THINborders.right = xlwt.Borders.THINborders.top = xlwt.Borders.THINborders.bottom = xlwt.Borders.THINhead_style.borders = borderscont_style.borders = bordersreturn head_style, cont_styledef get_sheet(_book, _index):"""创建sheet页:param _book::param _index::return:"""_name = "sheet_{}".format(str(_index))_sheet = _book.add_sheet(_name)return _sheetdef write_head(_head, _sheet, _head_style):"""写入表头:param _head::param _sheet::param _head_style::return:"""for head in range(len(header)):context = str(header[head])# need_width = (1 + len(context)) * 256need_width = 20 * 256table_sheet.col(head).width = need_widthtable_sheet.write(0, head, context, style=_head_style)# 是否插入序号if need_order:header.insert(0, '序号')sheet_index = 1book = xlwt.Workbook(encoding='utf-8') # 创建 Excel 文件table_sheet = get_sheet(book, sheet_index) # 添加sheet表h_style, c_style = set_style()write_head(header, table_sheet, h_style)if data and data_col:# 插入数据row = 1for item in data:if need_order:table_sheet.write(row, 0, row, style=c_style) # 写入序号for col in range(len(header[1:])):table_sheet.write(row, col+1, str(item.get(data_col[col], '-') if item.get(data_col[col]) else '-'), style=c_style)else:for col in range(len(header)):table_sheet.write(row, col, str(item.get(data_col[col], '-') if item.get(data_col[col]) else '-'), style=c_style)row += 1if row > 50000: # 单表数量超过 65535 条 添加新的表row = 1sheet_index += 1table_sheet = get_sheet(book, sheet_index) # 添加sheet表write_head(header, table_sheet, h_style)# print(help(table_sheet))# table_sheet.data_validation("A1", {'validate': 'list', 'source': [1, 2, 3, 4]})sio = BytesIO() # 返回文件流到浏览端下载,浏览端必须以form提交方式方能下载成功!book.save(sio) # 这点很重要,传给save函数的不是保存文件名,而是一个StringIO流sio.seek(0) # 保存流# 组装headerheaders = {"content-type": "application/vnd.ms-excel","content-disposition": f'attachment;filename={quote(file_name,"utf8")}.xlsx'}# 以流的形式返回浏览器return StreamingResponse(sio, media_type='xls/xlsx', headers=headers)
【注意】安装依赖:
pip install fastapi[all] xlwt