You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.8 KiB

import io
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
def save_to_excel(data, filename):
"""
将数据集保存为格式化的Excel文件
参数:
data - 数据集 (列表字典格式,例如:[{"列1": "值1", "列2": "值2"}, ...])
filename - 输出文件名 (需包含.xlsx扩展名)
"""
# 转换数据为DataFrame
df = pd.DataFrame(data)
# 创建Excel写入对象
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
df.to_excel(writer, index=False, sheet_name='Sheet1')
# 获取工作表对象
workbook = writer.book
worksheet = writer.sheets['Sheet1']
# 定义边框样式
thin_border = Border(left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin'))
# 设置全局行高
for row in worksheet.iter_rows():
worksheet.row_dimensions[row[0].row].height = 20
# 为所有单元格添加边框
for cell in row:
cell.border = thin_border
# 设置标题样式
header_font = Font(bold=True, size=14)
header_fill = PatternFill(start_color='ADD8E6', end_color='ADD8E6', fill_type='solid')
for cell in worksheet[1]:
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center', vertical='center')
# 设置数据行样式
data_font = Font(size=14)
for row in worksheet.iter_rows(min_row=2):
for cell in row:
cell.font = data_font
cell.alignment = Alignment(vertical='center', wrap_text=True)
# 动态设置列宽
for idx, column in enumerate(df.columns):
# 获取列的最大长度
max_length = max(
df[column].astype(str).map(len).max(), # 数据列的最大长度
len(str(column)) # 列名的长度
)
# 计算列宽,确保在 10 到 120 之间
column_width = min(max(max_length + 2, 10)*2, 120) # 加 2 是为了留出一些空白
# 设置列宽
column_letter = get_column_letter(idx + 1)
worksheet.column_dimensions[column_letter].width = column_width
def save_to_excel_stream(data):
"""
将数据集保存为格式化的Excel文件流
参数:
data - 数据集 (列表字典格式,例如:[{"列1": "值1", "列2": "值2"}, ...])
返回:
BytesIO - 包含Excel文件内容的流
"""
# 转换数据为DataFrame
df = pd.DataFrame(data)
# 创建一个 BytesIO 对象作为缓冲区
output = io.BytesIO()
# 创建Excel工作簿
wb = Workbook()
ws = wb.active
ws.title = '统计报表'
# 写入数据
for row in pd.DataFrame(data).itertuples(index=False):
ws.append(row)
# 定义边框样式
thin_border = Border(left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin'))
# 设置全局行高
for row in ws.iter_rows():
ws.row_dimensions[row[0].row].height = 20
# 为所有单元格添加边框
for cell in row:
cell.border = thin_border
# 设置标题样式
header_font = Font(bold=True, size=14)
header_fill = PatternFill(start_color='ADD8E6', end_color='ADD8E6', fill_type='solid')
for cell in ws[1]:
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center', vertical='center')
# 设置数据行样式
data_font = Font(size=14)
for row in ws.iter_rows(min_row=2):
for cell in row:
cell.font = data_font
cell.alignment = Alignment(vertical='center', wrap_text=True)
# 动态设置列宽
for idx, column in enumerate(df.columns):
# 获取列的最大长度
max_length = max(
df[column].astype(str).map(len).max(), # 数据列的最大长度
len(str(column)) # 列名的长度
)
# 计算列宽,确保在 10 到 120 之间
column_width = min(max(max_length + 2, 10) * 2, 120) # 加 2 是为了留出一些空白
# 设置列宽
column_letter = get_column_letter(idx + 1)
ws.column_dimensions[column_letter].width = column_width
# 将工作簿保存到 BytesIO 对象
wb.save(output)
output.seek(0) # 将指针移动到流的开头
return output