# 报表设置模块
---
### 1.报表模板定义
#### 1.1概述
融租易的报表模板定义采用了ureport2报表引擎。UReport2是一款基于架构在Spring之上纯Java的高性能报表引擎，通过迭代单元格可以实现任意复杂的中国式报表。
#### 1.2报表计算模型介绍
在UReport2中单元格之间存在依赖关系，对于任意一个单元格都可以设置它的左父格与上父格。单元格父格是可选的，默认情况下，单元格的左父格就是其最近左边与其位于同一行的单元格；上父格则是其最近上方与其位于同一列的的单元格。如果一个单元格位于第一行，那默认它就没有上父格，同样，如果位于第一列，默认它就没有左父格。打开UReport2报表设计器，选中任意单元格，都可以在其属性面板看到它的默认上父格或左父格，如下图所示：
![](/assets/parent-cell.jpg)
 如上图所示，对于某一特定单元格，我们可以手动更改它的左父格或上父格。
任意单元格在绑定数据集中某个字段后，如果这个字段有一条以上的数据，那么单元格就可以展开以显示这些数据。对于父格而言，父格展开时会带动子格一起展开，如父格向下展开，则带其下所有子格及子格的子格一起向下展开；同时，如果子格中绑定的数据集与父格中数据集同属一个，则子格中的数据将受父格限制。子格绑定的数据集字段数据在展开时，同样也会带动其下子格一起展开，而当前子格的父格如与子格处于同一行或列，则会将父格拉大。
#### 1.3表达式
在报表使用过程当中，不可避免的要使用函数及表达式实现一些数据的计算，在UReport2当中，很多地方都支持编写表达式，比如最典型的我们可以将单元格类型改为“表达式”，这样就可以在下面的表达式编辑器里输入相应的表达式与函数，除此之外，UReport2还允许我们在条件、图片来源、二维码数据来源等地方使用表达式，所以学习并掌握UReport2中提供的表达式，是制作复杂报表的前提。
##### 1.3.1基本语法
与一般的编程语言类似，UReport2中的表达式也有一些基本的数据类型，如数字、字符串、布尔值。
上述的有三种基本的数据类型，可以单独使用，也可以用“+”、"-"、"*"、"/"、"%"连接，进行组合运算。
UReport2中还提供了几种类型的条件判断运算符，我们首先来看一下三元表达式。
##### 1.3.2三元表达式
 基本所有的语言都支持三元表达式判断，它的特点是简洁明晰，可以用最少的代码进行条件判断和普通的三元表达式一样，它的第一部分是条件部分，条件部分可以有多个条件（用and或or连接），“？”后面是条件满足后执行并返回的表达式部分，“：”后面则是条件不满足时执行返回的表达式部分。
 |三元表达式示例|说明|
 |-|-|
 |A1>1000 ? "正常值" : "低值"|表达式计算时，先取到A1单元格的值，判断值是否大于1000，如果是返回“正常值”字符串，否则返回“低值”字符串|
 |A1>1000 and A1<20000 ? "正常值" : "修正值："+(A1+100)	|条件部分，判断A1值是否大于1000且小于20000，如果是返回"正常值"，否则返回字符串”修正值“与A1值加100后结果连接的值，如果A1是2000，那么就返回”修正值：2100”|
##### 1.3.3if判断
if判断表达式则一个if条件判断部分加若干个可选的elseif条件判断部分，最后再加一个可选的else部分构成，语法结构类似java或javascript。
|if判断表达式示例|说明|
|-|-|
|if(A1>1000){return "正常值"}|判断A1单元格的值是不是大于1000，如果是返回”正常值“字符串，否则什么都不做|
|if(A1>1000){return "正常值"}else{"低值";}|判断A1单元格的值是不是大于1000，如果是返回”正常值“字符串，否则返回”低值“字符串。这里需要注意的是，在if表达式中，return关键字是可选的，同是行尾添加';'也是可选的，这主要是为了照顾一些java及javascript程序的习惯|
|if(A1>1000 and A1<20000){return "正常值:"+A1}else if(A>20000 and A1<40000){return "超高值"}else{"低值"}|在这个例子当中，条件部分添加了多个组合条件，同时elseif多重判断|
##### 1.3.4case判断
case判断是UReport2中提供的另一种条件判断形式，与if判断有些类似，但case判断看起来更为简洁,case判断要由case{...}包裹，然后是若干条件加返回值。
|case表达式示例|说明|
|-|-|
|case{A1==100 return "正常值",A1>100 and A1<1000 return '偏高'}|有两个条件，分别返回不同的值
|
|case{A1==100 return "正常值",A1>100 and A1<1000 '偏高'}|在case表达式中，return关键字同样是可选的|
##### 1.3.5单元格引用
在报表当中，大多数的计算都是针对单元格或与单元格有关，因为报表中单元格多数都与数据绑定，而数据往往又是多条，所以计算后的报表一个单元格会产生多个，这样对于单元格的引用就变的比较复杂。在UReport2中，引用的目标单元格是相对当前单元格来进行计算的，引用方法就是直接在表达式里书写单元格名称，比如引用A1单元格，就直接写A1即可，如下面的例子：
![](/assets/s1.png)
>**多个值的输出**
在取到值超过一个，输出时多个值间以“，”分隔。
***
>**目标格获取原则**
UReport2中单元格表达式在取目标格值时，优先考虑的是目标格是否与其位于同一行或列，如果是则取与其位于同一行或列的目标单元格，如果不是，则取与当前单元格有共同父格的所有目标单元格，如果他们有共同的上父格或共同的左父格，那么就取共同上父格与共同左格交集部分的目标单元格；如果他们没有共同的父格，那么就取迭代后所有的目标单元格。

可以多次利用更改当前单元格的上父格或左父格使得当前单元格与目标格处于某个特定的父格下。
##### 1.3.6单元格坐标
单元格坐标，也是相对于当前单元格来进行计算的，同样遵循上面的介绍的优先取同行、同列或共同父格的原则，一个标准的单元格坐标格式如下：
>单元格坐标格式
单元格名称[Li:li,Li-1:li-1,…;Ti:ti,Ti-1:ti-1…]{条件...}

|单元格坐标示例|说明|
|-|-|
|C1[A1:2,B1:1]|在找C1时先找单元格A1展开后的第2格；再找第二个A1下的B1单元格展开后的第一个单元格，然后再找这个B1单元格对应的C1单元格|
|C2[A1:2,B1:2;C1:3]	|在找C2时，先找A1单元格展开后的第二格，再找第二个A1单元格下B2单元格展开后的第二格，再根据第二个展开的B2单元格找其下名为C2单元格的左子格；然后再找到C1单元格展开后的第三格，再看其下的C2单元格，取C2单元格的交集|
|C2[A1:2,B2:2]{C2>1000}|表示取A2单元格展开后的第二格，再取其下B2单元格展开后第二格，再取B2下所有的C2单元格，最后再对取到的C2单元格进行条件过滤，只取出C2单元格值大于1000的所有C2单元格。|
|C2[A1:2,B2:2]{C2>1000 and C2<10000}|表示取A2单元格展开后的第二格，再取其下B2单元格展开后第二格，再取B2下所有的C2单元格，最后再对取到的C2单元格进行条件过滤，只取出C2单元格值大于1000且小于10000的所有C2单元格的值。|
##### 1.3.6数据集表达式
select(罗列数据)
datasetName.select(propertyName[,filter,order])

group(分组罗列数据)
datasetName.group(propertyName[,filter,order])

sum(累加数据)
datasetName.sum(propertyName,filter)

count(统计数量)
datasetName.count(filter)

max(取最大值)
datasetName.sum(propertyName,filter)

min(取最小值)
datasetName.sum(propertyName,filter)

avg(取平均值)
datasetName.sum(propertyName,filter)

详见http://wiki.bsdn.org/pages/viewpage.action?pageId=76448569
##### 1.4函数
count函数(统计数量)
sum函数(累加)
avg函数(求平均值)
max函数(求最大值)
min函数(求最小值)
row函数（取行号）
column函数（取列号）
order函数（排序）
list函数（罗列数据）
param函数（取参数）
formatdate函数（格式化日期）
formatnumber函数（格式化数字）
get函数（获取指定位置数据）
##### 1.5条件属性
点击属性面板上配置条件按钮，可弹出调教属性配置窗口，如下图所示：
![](/assets/prop-condition-dialog.jpg)
##### 1.6参数
UReport2中SQL参数传递采用的是命名参数的方式，这点与Spring中NamedParameterJdbcTemplate中采用命名参数的写法完全一致，所以如果您用过Spring中的NamedParameterJdbcTemplate，那对命名参数一定很熟悉。
|示例|说明|
|-|-|
|select * from emp where dept_id=:deptId|查询条件为dept_id=:deptId，运行时引擎将采用名为deptId的参数值来填充SQL|
|select * from emp where age > :age and dept_id in (:deptIds)|这个SQL中条件有两个，同样运行时引擎将尝试从外部参数中获取对应的值来填充SQL|
添加一个SQL数据集，即可在弹出的窗口中定义SQL及相关参数。
![](/assets/sql-dataset.jpg1)
SQL数据集中的SQL支持表达式，参数格式为：\${表达式}，也就是说，在\${}中输入的内容引擎认为是表达式，否则认为是标准SQL。一旦在${}中输入表达式，引擎会尝试进行语法检查。在SQL表达式中，我们可以对传入参数进行判断，这样就可以实现诸如当有参数传入SQL时，就取该参数过滤后的结果集，如果没有该参数传入时则取所有数据集需求，示例如下图所示：
![]
>表达式中返回sql的注意事项
我们在使用表达式返回SQL时，如果SQL中包含单引号包裹的字符串，那么需要加上“\”来为单引号转义，否则会出现语法错误，如下面的表达式：
\${
if(param("deptId")==null || param("deptId")==''){
return "select * from employee where dept_id=\'D11\'";
}
}
在上面的表达式中，return后面的SQL中dept_id=\'D11\'就用来“\”为单引号转义。

#### 其他更多功能详见http://wiki.bsdn.org/pages/viewpage.action?pageId=76448364
### 2.报表定义
#### 2.1进入报表定义功能
先在表格中定义好报表编码，报表名称信息进行保存。
|字段名|说明|
|-|-|
|报表编码|报表的编码|
|报表名称|生产的报表文件名，可以通过lov选择|
![](/assets/report-define1.png)
#### 2.2添加报表参数
在表格中定义好参数的名称，参数描述，参数设置信息，然后保存。
|字段名|说明|
|-|-|
|参数名称|在模板定义中，设置的数据集参数|
|参数描述| |
|参数设置|参数对应的lov|
![](/assets/report-define2.png)
#### 2.3报表编辑
点击报表编辑，可以弹出已经打开了该报表模板的模板定义页面。
#### 2.4预览
点击预览，可以查看已经添加的报表文件。如果添加了参数，可以选择右侧lov的内容，并点击应用按钮，即可通过改变传入的参数改变报表显示的内容。
![](/assets/report-define3.png)
### 3.报表查看
在报表查看功能中可以查看报表的编码，文件名以及查看。
查看功能同报表定义中的预览相同。
![](/assets/report-define4.png)
### 4.报表接口
前端预览接口：
http://hlscus.hand-china.com/hap_dev/ureport/preview?_u=file:报表名称

下载excel接口：
http://hlscus.hand-china.com/hap_dev/ureport/excel?_u=file:报表名称
>**关于报表参数**
如果要往报表中传入参数，可以直接将参数放到url后面使用。如：hlscus.hand-china.com/hap_dev/ureport/excel?_u=file:test.ureport.xml&deptId=D11&age=50





