版本 16 中引入
get_xlsx_styles 模块方法允许你为报表导出定义自定义 Excel 样式。
注意: 此方法仅在将标准脚本报表或查询报表导出为 Excel 格式(非 CSV)时被调用。
基本用法
在报表的 Python 文件中定义一个 get_xlsx_styles 函数:
from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder
def get_xlsx_styles(metadata: XLSXMetadata) -> dict:
builder = XLSXStyleBuilder(metadata)
# Add your custom styles here...
return builder.result
注意: 当
XLSXStyleBuilder初始化时,默认样式(表头、筛选器、字段类型格式、货币)会自动应用。
要禁用此功能,请传入
default_styling=False:builder = XLSXStyleBuilder(metadata, default_styling=False)
XLSXMetadata
metadata 对象提供对报表数据和辅助方法的访问。
属性
| 属性 | 类型 | 描述 |
|---|---|---|
report_name |
str |
报表名称 |
filters |
dict |
原始筛选值 |
column_map |
dict[int, dict] |
列索引 → 列定义 |
row_map |
dict[int, dict \| list] |
行索引 → 行数据 |
applied_filters_map |
dict[int, list] |
筛选行索引 → [标签, 值] |
has_total_row |
bool |
最后一行是否为合计行 |
has_indentation |
bool |
是否应用缩进样式 |
注意: 所有索引必须从 0 开始,遵循 XlsxWriter 的索引规则。
XLSXStyleBuilder
该构建器提供注册和应用样式的方法。
注册样式
# Register a style and get its ID
style_id = builder.register_style({"bold": True, "bg_color": "#FFFF00"})
应用样式
# Style an entire column
builder.style_column(col_idx, style_id)
# Style an entire row
builder.style_row(row_idx, style_id)
# Style a specific cell
builder.style_cell(row_idx, col_idx, style_id)
样式属性
字体样式
builder.register_style({
"bold": True,
"italic": True,
"underline": True,
"font_size": 12,
"font_color": "#FF0000",
"font_name": "Arial",
})
背景颜色
builder.register_style({
"bg_color": "#FFFF00",
})
边框
# Border thickness: 1 = thin, 2 = medium, 3 = thick
builder.register_style({
"border": 1,
"border_color": "#000000",
})
# Individual borders
builder.register_style({
"left": 2,
"right": 2,
"top": 1,
"bottom": 3,
})
对齐方式
builder.register_style({
"align": "center", # left, center, right
"valign": "vcenter", # top, vcenter, bottom
"text_wrap": True,
"indent": 2,
})
数字格式
builder.register_style({
"num_format": "#,##0.00", # Custom number format
})
完整示例
from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder
def get_xlsx_styles(metadata: XLSXMetadata) -> dict:
builder = XLSXStyleBuilder(metadata)
# --- Register Styles (do this once, reuse style_id) --- #
success_style = builder.register_style({"font_color": "#006100", "bg_color": "#C6EFCE"})
warning_style = builder.register_style({"font_color": "#9C5700", "bg_color": "#FFEB9C"})
error_style = builder.register_style({"font_color": "#9C0006", "bg_color": "#FFC7CE"})
highlight_style = builder.register_style({"bold": True, "bg_color": "#DDEBF7"})
total_row_border = builder.register_style({"border": 3, "border_color": "#15137e"})
right_align = builder.register_style({"align": "right"})
# --- Style entire column --- #
amount_col_idx = builder.field_index_map.get("net_amount")
if amount_col_idx is not None:
builder.style_column(amount_col_idx, right_align)
# --- Style total row with border --- #
if metadata.has_total_row:
builder.style_row(metadata.get_last_row_index(), total_row_border)
# --- Conditional Cell Styling --- #
status_col_idx = builder.field_index_map.get("status")
for row_idx, row_data in metadata.row_map.items():
if not isinstance(row_data, dict):
continue
# Status-based styling
if status_col_idx is not None:
status = row_data.get("status")
if status == "Completed":
builder.style_cell(row_idx, status_col_idx, success_style)
elif status == "Pending":
builder.style_cell(row_idx, status_col_idx, warning_style)
elif status == "Cancelled":
builder.style_cell(row_idx, status_col_idx, error_style)
# High value highlighting
if amount_col_idx is not None:
amount = row_data.get("net_amount")
if amount and amount > 10000:
builder.style_cell(row_idx, amount_col_idx, highlight_style)
return builder.result
示例输出
带样式的导出示例
建议
- 注册一次样式并重复使用 — 在开始时注册样式,并在整个过程中使用返回的
style_id,以避免创建重复样式。
参考
- 有关所有可用的样式属性,请访问 xlsxwriter 格式文档。