报表行类型
BaskReport 中行(Row)是报表纵向排列的基本单元,每一行由若干单元格(Cell)组成。系统通过行的 band(带区) 属性来区分「行类型」,用于控制分页时该行的重复行为。
说明:很多人会把「标题行 / 表头行 / 明细行 / 表尾行」称为行类型,但在 BaskReport 里它们不是独立的行类型枚举,而是用户在报表布局上的位置概念——通过单元格之间的父格关系(左父格 / 上父格)和数据展开方式来表达。真正的「行类型」只有下面三种(由
band枚举决定),其余行均为普通行。
一、行类型总览
| 行类型 | band 值 | 说明 | 分页行为 |
|---|---|---|---|
| 普通行 | none(band 为 null) |
默认行类型 | 随数据自然分页,不重复 |
| 重复表头 | headerrepeat |
作为「表头」固定区域 | 每页顶部重复显示 |
| 重复表尾 | footerrepeat |
作为「表尾」固定区域 | 每页底部重复显示 |
后台枚举位置:
com.basksoft.report.core.model.ReportBand.Band(none/headerrepeat/footerrepeat)。设计器中未设置行类型时,band为null,等价于none。
二、普通行(none)
最常见的行类型,也是所有新建行的默认值。
- 行为:随数据展开自然分页,不会在后续页重复。
- 适用:明细数据行、普通内容行。
- 当报表出现分页时,普通行只会按内容顺序出现在某一页,不会跨页重复。
三、重复表头(headerrepeat)
将某一行(或多行)标记为重复表头,在每一页的顶部都会重复渲染该区域。
典型用途:报表的列标题行(表头)。当明细数据跨越多页时,希望每一页都能看到列名,就把列标题行设为「重复表头」。
实现要点:
- 后台在分页构建(
PagingBuilder)时会收集所有band == headerrepeat的行,形成headerRows,在每一页开头插入。 - 重复表头行本身的高度不计入该页数据区高度的累加(分页时其原始行号被记录但占位高度单独处理),保证每页数据区可用高度一致。
设计器操作:
- 选中目标行(通常是列标题行)。
- 右键 → 重复表头(或勾选行属性中的「重复表头」)。
- 如需取消,再次右键选择 取消行类型 / 普通行。
注意:要区分「重复表头(headerrepeat,分页每页重复)」与「标题行(报表最顶部的报表标题)」。标题行通常只出现在第一页,不属于重复表头;若希望报表标题也每页显示,可将其设为
headerrepeat,但一般场景下标题只需首页出现。
四、重复表尾(footerrepeat)
将某一行(或多行)标记为重复表尾,在每一页的底部都会重复渲染该区域。
典型用途:报表的页脚、合计提示、版权说明等希望每页底部都出现的内容。
实现要点:
- 后台收集所有
band == footerrepeat的行,形成footerRows,在每一页末尾插入。 - 与重复表头同样,其高度为独立占位,不计入数据区累加高度。
设计器操作:
- 选中目标行。
- 右键 → 重复表尾。
- 取消:右键 → 取消行类型 / 普通行。
重复表尾与「报表页脚(page footer)」不同:本系统的
headerrepeat/footerrepeat是行级的重复区域,跟随数据分页每页出现;而全局页眉页脚由页面设置控制。请按实际需求选择。
五、重复行(表头 / 表尾)的使用限制
重复表头 / 表尾在分页时,每一页都是把原行「按当前值拷贝一份」后再固定显示在页头 / 页尾,因此它是固定区域,不支持依赖数据集的多条数据展开绑定,也不支持动态行高。
5.1 不支持多条数据的展开绑定
在重复表头 / 表尾区域内的单元格,即使配置了 down(纵向)/ right(横向)展开,也不会在每页重复区域里展开成多条数据。
原因是:每页的重复区并不是重新执行展开,而是直接复制原行当时的单元格值。因此重复区内只会显示原行「单次求值」的结果,不会产生由数据集驱动的多行 / 多列展开。
正确做法:
- 重复表头 / 表尾只放静态文本、固定值、或固定聚合表达式(如
=sum(...)这类不依赖展开的结果)。 - 明细数据的向下 / 向右展开,请放在普通行(none)区域,通过单元格的父子格(
上父格/左父格)驱动。
5.2 不支持动态行高
重复表头 / 表尾区域内的单元格不支持动态行高(即依赖内容自动撑开行高)。
原因是:重复区的高度在分页时按原行固定的高度占位,若运行时按内容动态撑高,会破坏每页已固定的高度占位与分页计算,导致分页错乱。引擎会对重复行动态行高给出告警。
正确做法:
- 重复表头 / 表尾请使用固定行高(在设计器中显式设置行高),确保每页重复区域高度一致。
- 若确实需要随内容自适应的高度,请将该内容放到普通行区域。
5.3 限制速查
| 能力 | 重复表头 / 表尾 | 普通行(none) |
|---|---|---|
| 静态文本 / 固定值 | ✅ 支持 | ✅ 支持 |
| 固定聚合表达式(如 sum) | ✅ 支持 | ✅ 支持 |
| 多条数据展开(down / right) | ❌ 不支持 | ✅ 支持(需父子格驱动) |
| 动态行高(内容自适应) | ❌ 不支持 | ✅ 支持 |
| 每页重复显示 | ✅ 支持 | ❌ 不重复 |
六、与设计器右键菜单的对应关系
在报表设计器中选中行后右键,行类型相关菜单项通常为:
- 普通行:清除行类型,恢复为
none。 - 重复表头:设置
band = headerrepeat。 - 重复表尾:设置
band = footerrepeat。
底层均通过 row.setBand(...) 维护,最终序列化到报表定义(*.json / *.xml)的 band 字段中。
七、容易混淆:行「类型」与行「行为属性」
除了 band 行类型外,每行还有若干独立的行为标志,它们不是行类型,但常与行类型一起使用,需要区分:
| 行属性 | 含义 | 是否与 band 冲突 |
|---|---|---|
band |
行类型(普通 / 重复表头 / 重复表尾) | — |
lock(锁定) |
锁定该行,禁止在设计器中被误编辑 / 移动 | 可与任意 band 共存 |
hide(隐藏) |
运行时该行不参与渲染,行高计为 0 | 可与任意 band 共存;隐藏的重复表头/表尾同样不显示 |
fillRemainingPageHeight |
自动拉伸填满当前页剩余高度(常用于末页补白) | 可与任意 band 共存 |
后台分页逻辑(
PagingBuilder.getRowHeight):当row.isHide()为真时行高返回0;当row.isFillRemainingPageHeight()为真时行高取「页面剩余高度」。这些与band互不干扰。
示例组合:
- 一个
headerrepeat行同时设置hide→ 该重复表头在所有页都不显示。 - 一个普通行设置
fillRemainingPageHeight→ 用于末页补白,但其本身仍是普通行,不会跨页重复。
八、快速对照表
| 我想要的效果 | 应使用的行类型 / 属性 |
|---|---|
| 列名每页都显示 | 重复表头(headerrepeat) |
| 页脚 / 合计提示每页都显示 | 重复表尾(footerrepeat) |
| 只在第一页出现的报表大标题 | 普通行(none)即可 |
| 某行不随数据分页重复,也不跨页 | 普通行(none) |
| 保护某行不被误改 | 普通行 + 锁定(lock) |
| 运行时根据条件隐藏某行 | 普通行 + 隐藏(hide) |
| 末页补满空白 | 普通行 + 自动填充剩余高度 |
| 数据展开的主区域 | 普通行(none),靠单元格父格与展开方式驱动 |
九、小结
- BaskReport 的「行类型」本质是
band枚举:普通行 / 重复表头 / 重复表尾 三种。 - 「标题行 / 表头行 / 明细行 / 表尾行」是布局概念,由父子格与展开方式决定,不是行类型枚举。
- 重复表头 / 表尾用于分页时每页重复显示固定区域(如列标题、页脚)。
- 限制:重复表头 / 表尾不支持多条数据的展开绑定(down / right),也不支持动态行高;其每页呈现的是原行的值快照,应使用固定行高与固定内容(静态文本 / 固定聚合表达式)。
- 明细数据展开、动态行高请放在普通行(none)区域,通过父子格驱动。
- 锁定、隐藏、自动填充剩余高度是独立于
band的行行为属性,可叠加使用。