报表基本语法
报表表达式的语法规则:单元格、数据集字段和参数的引用写法,字面量,运算符与优先级,文本与数值运算规则,类型转换,空值和真假判断。
概述
报表表达式是一段写在单元格、条件或参数里的小程序,算出一个值。语法与 JavaScript 接近,加上了报表特有的引用写法:A1(单元格)、$name(参数)、$$record.字段(数据集字段)。本文说明这些写法本身;表达式可以放在哪些位置见 表达式概述,可调用的函数见 内置函数总览,多行脚本见 脚本使用指南。
在单元格或公式栏中直接输入时,以 = 开头才会成为公式单元格(= 不属于表达式,保存时被去掉);「数据」标签的「内容公式」输入框直接写表达式,不带 =。见 单元格基础。
一段只含一个表达式的脚本,其值自动作为结果返回;含多条语句时必须用 return 明确返回。
1 + 2 // 结果 3
var a = 10; return a * 2 // 多条语句,需要 return,结果 20
单元格引用
在公式里写单元格名称即可取得该单元格计算后的值。名称由 1 到 3 个大写字母加数字组成,如 A1、B12、AA3,后面不能紧跟标识符字符。
| 写法 | 含义 | 返回 |
|---|---|---|
A1 |
单元格 A1 的值 |
只有一个值时是该值本身;A1 向下或向右扩展出多个值时是包含全部值的列表 |
A1:B5 |
矩形区域内所有单元格 | 展平后的列表 |
A1[!0] |
A1 扩展出的全部值,覆盖整张报表,不受当前所在分组限制 |
始终是列表,即使只有一个值 |
&A1 |
A1 展开后的迭代序号,从 1 开始;找不到时为 0 |
整数 |
要点:
- 列表参与
sum、avg、count等聚合函数时被展开计算,sum(B2)就是B2扩展列的合计。 A1[!0]只有这一种精确写法,必须紧跟单元格名、中间不能有空格;[!1]、[! 0]等其他形式会报错「组引用只支持 [!0] 写法」。- 在自己所属的扩展关系内引用某格(同一行的另一个数据格)得到本行的单个值,跨关系引用得到全部值。扩展关系的规则见 父子格与数据绑定。
- 引用的单元格值为空时得到
null。
示例:合计行的占比列写 B2 / sum(B2[!0]),其中 B2 是本行的值,sum(B2[!0]) 是整列合计。给数据行编序号写 &B2。
数据集字段引用
数据绑定的单元格,其「数据字段」下的「计算表达式」里,用 $$record 表示当前记录:
| 写法 | 含义 |
|---|---|
$$record.数量 |
当前记录的「数量」字段 |
$$record['单价'] |
同上,字段名含空格、连字符或特殊字符时使用 |
示例:金额列的计算表达式写 $$record.数量 * $$record.单价。
要在其他位置读取数据集的整列数据,使用函数 dataset('数据集名', '字段名'),返回该字段所有行的列表,见 报表与数据集函数。
参数引用
报表参数用 $ 加参数名引用:
| 写法 | 含义 |
|---|---|
$startDate |
报表参数 startDate 的值 |
$$config.名称 |
「系统」>「自定义参数」中配置的全局参数 |
$$reportVars.名称 |
报表设置「报表变量」中定义的变量 |
规则:
- 参数名请使用英文字母、数字和下划线:在下文「文本中的参数」(不加引号的文字里直接嵌
$参数)里,$之后只识别这些字符,中文会被当作普通文字;参数值是对象时,.之后的成员名可以是中文。 - 引用未定义的参数,不报错,值为
null。 - 参数的声明、类型与默认值见 报表参数。
文本中的参数
在文本、标题、页眉等以「文本」形式输入的位置,可以直接把参数嵌进文字里,系统会先把它改写成拼接表达式:
| 写法 | 效果 |
|---|---|
就诊日期从$startDate至$endDate |
文字与参数拼接为一段文本 |
合计:${sum(B2)} |
${} 内可以写任意表达式 |
内置变量
以 $$ 开头的是系统提供的变量,只在特定位置有值,详见 脚本使用指南。
| 变量 | 含义 | 可用位置 |
|---|---|---|
$$value |
当前单元格的值。数字文本自动转为数值,以 0 开头的编码(如 001)保持文本 |
条件渲染 |
$$record |
当前数据记录 | 数据绑定单元格的计算表达式 |
$$data |
数据集的记录列表 | 数据集后处理脚本 |
$$config |
自定义参数 | 各处表达式 |
$$reportVars |
报表变量 | 各处表达式 |
$$line $$lines $$isFirstLine $$isLastLine |
按行拆分打印的当前行、总行数、是否首行、是否末行;默认 0、1、true、true |
按行拆分打印 |
字面量
| 类型 | 写法 | 示例 |
|---|---|---|
| 整数、小数 | 数字 | 42、3.14 |
| 带类型后缀的数字 | b 字节,s 短整型,L 长整型,f 单精度,d 双精度,m BigDecimal |
10L、2.5m |
| 十六进制 | 0x 开头 |
0xFF |
| 文本 | 单引号或双引号;双引号内不能换行 | '内科'、"内科" |
| 模板文本 | 反引号,${} 内嵌表达式,可换行 |
`共${n}行` |
| 多行文本 | 三个双引号 | """多行""" |
| 布尔 | true、false |
|
| 空值 | null |
|
| 列表 | 方括号 | [1, 2, 3] |
| 键值对 | 花括号 | {'k': 1} |
注释:// 单行 与 /* 多行 */。
保留关键字:import as var let const return break continue if for in new true false null else try catch finally async while exit and or throw,不能用作变量名。
运算符与优先级
从低到高:
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1(最低) | ? : |
三元条件,条件 ? 值1 : 值2 |
| 2 | =、复合赋值 += -= 等 |
赋值(= 略低于复合赋值) |
| 3 | || or |
逻辑或 |
| 4 | && and |
逻辑与 |
| 5 | | |
按位或 |
| 6 | ^ |
按位异或 |
| 7 | & |
按位与 |
| 8 | == != === !== |
相等比较 |
| 9 | < <= > >= instanceof |
大小比较 |
| 10 | + - |
加减、文本连接 |
| 11 | 移位 | 位移 |
| 12 | * / % |
乘除取余 |
| 13(最高) | 一元 - + ! ~ ++ -- |
单目运算 |
说明:
- 用
()明确顺序,不要依赖优先级记忆。 &&与||短路求值,返回决定结果的那个操作数本身,不一定是布尔值:'' \|\| '默认'得'默认'。- 没有
?:空值合并写法(Elvis)和??,用ifNull(a, b)或a ? a : b。有?.安全导航:a?.b在a为null时得null。 <>只能用于select ... from查询语法内;在普通表达式里写<>会报错「<> 只能在Linq中使用」,不等于请写!=。=是赋值,==才是相等比较。条件里写$$value = 1会把1赋给变量,不是比较。
算术与文本连接
加号
+ 有两种含义,按两侧的值决定:
| 情形 | 行为 | 示例 | 结果 |
|---|---|---|---|
| 任一侧明确是文本(文本字面量、模板文本、返回文本的函数) | 连接文本 | '1' + 2 |
"12" |
两侧的值都能解析为数字(如单元格里存的文本 "1" 和 "2") |
数值相加 | A1 + B1,A1、B1 为 "1"、"2" |
3 |
| 其他 | 连接文本 | '总计' + A1 |
总计 加 A1 的文本 |
需要强制按文本连接时写成 A1::string + B1::string,强制按数值相加写成 A1::double + B1::double。
减、乘、除、取余
- * / % 总是数值运算:
- 文本先转成数值:
"1,234"得1234,"12%"和"¥1,234.5"这类带千分位、百分号、货币符号的文本也能解析;空白文本按null处理。 - 文本不是数字(如
'abc')时该运算无法计算,最终结果为null(默认的严格模式,配置项app.report.formula.strict-numeric-text,默认true)。 null作被减数、被除数按0;作乘数按1;作除数时(严格模式)结果为null。- 除以 0:
/得null;%抛出错误。 - 参与运算的一方是列表时,先对列表求和再运算,所以
B2 / 100在B2展开为多个值时,得到列合计除以 100。
比较与逻辑
比较
- 与
null比较大小得false。 - 文本与数值比较:两边都能解析为数字时按数值比较,
'10' > 9为true;否则报错。 ==只要有一侧是数值,就尝试按数值判等,'1.0' == 1为true。- 文本之间的
==按文本判等。
真假判断
条件表达式(if、三元、&&、||、!)用下面的规则把任意值当作布尔值:
| 值 | 真假 |
|---|---|
null、false |
假 |
| 文本 | 非空为真,空文本 '' 为假;注意 'false'、'0' 是非空文本,为真 |
| 数值 | 非 0 为真,0 为假 |
| 列表、数组、Map | 非空为真,空为假 |
| 其他 | 真 |
注意:条件渲染的公式条件不使用上面的规则,只有结果恰好是布尔 true 或文本 "true" 才算成立。
类型转换
在值后面用 ::类型 转换:
| 写法 | 结果类型 |
|---|---|
x::int |
整数 |
x::long x::short x::byte |
长整型、短整型、字节 |
x::double x::float |
双精度、单精度浮点 |
x::string |
文本 |
x::date('格式') |
日期,必须给出格式串,如 'yyyy-MM-dd' |
转换失败时返回 null;数值类转换可以给默认值:x::int(0) 失败时返回 0。
示例:
'12'::int // 12
'abc'::int // null
'abc'::int(0) // 0
'2026-01-05'::date('yyyy-MM-dd') // 日期
amount::int // 数据集数值列往往是 BigDecimal,作 substring 等函数的整数参数前先转换
类型不匹配导致函数「找不到」的情形见 内置函数总览 的「调用规则」。
空值处理
| 需求 | 写法 |
|---|---|
| 为空时用默认值 | ifNull(x, 0)、ifEmpty(x, '-'),见 逻辑与空值函数 |
| 取第一个非空 | coalesce(a, b, c) |
| 判断为空 | isNull(x)、isEmpty(x)(null、空文本、空集合均为空) |
| 安全访问成员 | a?.b |
| 未定义的参数 | 自动为 null,不报错 |
各种运算遇到 null 的行为汇总:
- 聚合函数:
sum、avg、max、min忽略null元素;count的行为见 聚合与集合函数。 - 日期函数:
year(null)等把null当作当前时间,见 日期函数。 - 比较:与
null比较大小得false。 - 算术:见上文「减、乘、除、取余」。
语句
多行脚本支持 var/let/const 声明变量,if/else、for、while、try/catch/finally、import、return、break/continue。循环形式:
for (item in list) { ... }
for (index, value in list) { ... }
for (var i = 0; i < 3; i++) { ... }