4729698049
git-subtree-dir: paste-framework git-subtree-split: 34e8684c4bc3cebbe177509f42ab4ef5b5425a7a
155 lines
4.2 KiB
Python
155 lines
4.2 KiB
Python
from typing import Union, List, Optional, Dict, Any
|
|
|
|
import pandas as pd
|
|
|
|
from paste.util import ufont
|
|
|
|
|
|
def cm_to_excel_units(cm):
|
|
"""
|
|
厘米转Excel列宽单位。
|
|
|
|
:param cm: 厘米单位
|
|
"""
|
|
return cm / 2.54 * 7 # 1英寸=2.54厘米, 1Excel单位=1/7英寸
|
|
|
|
|
|
def auto_width_cm(series: pd.Series, font_name='Microsoft YaHei', font_size=11, min_cm=1.5, max_cm=20):
|
|
"""
|
|
自动列宽计算方法(区分中英文)。
|
|
|
|
:param series: pandas Series (数据列)
|
|
:param font_name: 字体名称
|
|
:param font_size: 字号
|
|
:param min_cm: 最小列宽(厘米)
|
|
:param max_cm: 最大列宽(厘米)
|
|
:return: 建议的列宽(厘米)
|
|
"""
|
|
# 获取精确字体度量
|
|
en_width_cm, cn_width_cm = ufont.get_font_metrics(font_name, font_size)
|
|
|
|
def calculate_text_width(text):
|
|
"""计算文本总宽度"""
|
|
cn_count = 0
|
|
en_count = 0
|
|
for char in str(text):
|
|
if '\u4e00' <= char <= '\u9fff':
|
|
cn_count += 1
|
|
else:
|
|
en_count += 1
|
|
|
|
_total_width = (cn_count * cn_width_cm) + (en_count * en_width_cm)
|
|
return _total_width
|
|
|
|
# 计算列标题宽度
|
|
title_width = calculate_text_width(series.name)
|
|
|
|
# 计算数据内容最大宽度
|
|
content_width = series.astype(str).apply(calculate_text_width).max()
|
|
|
|
# 取最大值并增加边距,15%额外边距
|
|
total_width = max(title_width, content_width) * 1.2
|
|
|
|
return max(min(total_width, max_cm), min_cm)
|
|
|
|
|
|
def auto_column_width(df, worksheet):
|
|
"""
|
|
根据内容自动设置列的宽度。
|
|
|
|
:param df: pandas DataFrame
|
|
:param worksheet: 工作表
|
|
"""
|
|
_font_name_set = ufont.get_fonts()
|
|
for col_num, col_name in enumerate(df.columns):
|
|
# 计算列宽
|
|
width_cm = auto_width_cm(df[col_name], font_name=_font_name_set[0], font_size=11)
|
|
# 设置列宽
|
|
worksheet.set_column(col_num, col_num, cm_to_excel_units(width_cm))
|
|
|
|
|
|
def apply_header_style(df, worksheet, workbook, **kwargs):
|
|
"""
|
|
应用表头样式。
|
|
|
|
:param df: 原始 DataFrame
|
|
:param worksheet: xlsxwriter worksheet对象
|
|
:param workbook: xlsxwriter workbook对象
|
|
:param kwargs: 样式参数
|
|
:return: 无
|
|
"""
|
|
_style_sheet = {
|
|
'font_size': 12,
|
|
'bg_color': '#F2F2F2',
|
|
'border': 1,
|
|
'bold': True,
|
|
}
|
|
_header_style = workbook.add_format({**_style_sheet, **kwargs})
|
|
|
|
for col_num, value in enumerate(df.columns.values):
|
|
worksheet.write(0, col_num, value, _header_style)
|
|
|
|
|
|
def apply_data_style(df, worksheet, workbook, **kwargs):
|
|
"""
|
|
应用数据单元格样式。
|
|
|
|
:param df: 原始 DataFrame
|
|
:param worksheet: xlsxwriter worksheet对象
|
|
:param workbook: xlsxwriter workbook对象
|
|
:param kwargs: 样式参数
|
|
:return: 无
|
|
"""
|
|
_style_sheet = {
|
|
'font_size': 12,
|
|
'border': 1,
|
|
}
|
|
_cell_style = workbook.add_format({**_style_sheet, **kwargs})
|
|
|
|
for row in range(1, len(df) + 1):
|
|
for col in range(0, len(df.columns)):
|
|
worksheet.write(row, col, df.iloc[row - 1, col], _cell_style)
|
|
|
|
|
|
def insert_text_to_column(
|
|
worksheet,
|
|
workbook,
|
|
column: int,
|
|
start_row: int,
|
|
texts: Union[str, List[str]],
|
|
text_format: Optional[Dict[str, Any]] = None
|
|
) -> None:
|
|
"""
|
|
向Excel表格的指定列插入文本。
|
|
|
|
:param worksheet: xlsxwriter worksheet
|
|
:param workbook: xlsxwriter workbook
|
|
:param column: 列号
|
|
:param start_row: 开始插入的行号(1-based)
|
|
:param texts: 要插入的文本(字符串或字符串列表)
|
|
:param text_format: 格式字典,None则使用默认格式
|
|
:return: None
|
|
"""
|
|
# 设置默认格式
|
|
default_format = {
|
|
'font_size': 12,
|
|
}
|
|
|
|
# 合并用户自定义格式
|
|
fmt = workbook.add_format({**default_format, **(text_format or {})})
|
|
|
|
# 转换列号为数字索引(1-based)
|
|
if isinstance(column, str):
|
|
col_idx = ord(column.upper()) - ord('A') + 1
|
|
else:
|
|
col_idx = column
|
|
|
|
# 确保texts是列表形式
|
|
if isinstance(texts, str):
|
|
texts = [texts]
|
|
|
|
# 处理每行数据
|
|
for i, text in enumerate(texts):
|
|
row_num = start_row + i
|
|
worksheet.write(row_num, col_idx, text, fmt)
|