# -*- coding: utf-8 -*- import io import pandas as pd from typing import Any from openpyxl import Workbook from openpyxl.utils import get_column_letter from openpyxl.styles import Alignment, PatternFill from openpyxl.worksheet.datavalidation import DataValidation class ExcelUtil: """Excel文件处理工具类""" @classmethod def __mapping_list(cls, list_data: list[dict[str, Any]], mapping_dict: dict) -> list: """ 工具方法:将列表数据中的字段名映射为对应的中文字段名。 参数: - list_data (list[dict[str, Any]]): 数据列表。 - mapping_dict (dict): 字段名映射字典。 返回: - list: 映射后的数据列表。 """ mapping_data = [{mapping_dict.get(key): item.get(key) for key in mapping_dict} for item in list_data] return mapping_data @classmethod def get_excel_template(cls, header_list: list[str], selector_header_list: list[str], option_list: list[dict[str, list[str]]]) -> bytes: """ 生成 Excel 模板文件。 参数: - header_list (list[str]): 表头列表。 - selector_header_list (list[str]): 需要设置下拉选择的表头列表。 - option_list (list[dict[str, list[str]]]): 下拉选项配置列表。 返回: - bytes: Excel 文件的二进制数据。 """ wb = Workbook() ws = wb.active if not ws: raise ValueError("不存在活动工作表") # 设置表头样式 header_fill = PatternFill(start_color='ababab', end_color='ababab', fill_type='solid') # 写入表头 for col_num, header in enumerate(header_list, 1): cell = ws.cell(row=1, column=col_num) cell.value = header cell.fill = header_fill # 设置水平居中对齐 cell.alignment = Alignment(horizontal='center') # 设置列宽度为16 ws.column_dimensions[get_column_letter(col_num)].width = 12 # 设置下拉选择 for selector_header in selector_header_list: col_idx = header_list.index(selector_header) + 1 # 获取当前表头的选项列表 header_options = next((opt.get(selector_header) for opt in option_list if selector_header in opt), []) if header_options: dv = DataValidation(type='list', formula1=f'"{",".join(header_options)}"') dv.add(f'{get_column_letter(col_idx)}2:{get_column_letter(col_idx)}1048576') ws.add_data_validation(dv) # 导出为二进制数据 buffer = io.BytesIO() wb.save(buffer) buffer.seek(0) # 读取字节数据 excel_data = buffer.getvalue() return excel_data @classmethod def export_list2excel(cls, list_data: list[dict[str, Any]], mapping_dict: dict) -> bytes: """ 将列表数据导出为 Excel 文件。 参数: - list_data (list[dict[str, Any]]): 要导出的数据列表。 - mapping_dict (dict): 字段名映射字典。 返回: - bytes: Excel 文件的二进制数据。 """ mapping_data = cls.__mapping_list(list_data, mapping_dict) df = pd.DataFrame(mapping_data) buffer = io.BytesIO() df.to_excel(buffer, index=False, engine='openpyxl') binary_data = buffer.getvalue() return binary_data