iReport學習筆記
iReport學習筆記(2)
這篇開始來講一些比較細部的東西
Style(樣式)
在iReport中可以定義各種樣式並套用在元素上面,以控制元素與外觀相關的一組屬性(顏色、字型...等)
在左邊Report Inspector的最上面可以看到有個「Styles」,對著它按右鍵→加入→Style,接著底下就會出現一個新的Style,右邊的屬性視窗可以對其做修改
假設我現在設定Forecolor為深藍色,並將Style套用到獎金的欄位中,在屬性中的Style可以透過下拉式選單來選擇,選好後可以看到畫面上的字已經變深藍色了
也可以設定動態的條件,比如說當獎金大於0時顯示深藍色,等於0時還是顯示黑色
先將style的字體顏色改回來,接著在左邊Report Inspector找到剛剛新增的Style,對其按左鍵→加入Conditional Style,加入後可以在右邊看到它的屬性
透過設定Condition Expression來控制要在什麼時候套用該樣式,以剛剛的需求來講,輸入$F{COMM}.intValue() > 0 ? true : false
可以看到畫面上的字還是黑色,但是點Preview看一下,發現已經成功做出我要的效果了
Fields/Parameters/Variables
iReport中能夠儲存資料的主要有這幾種,可以把它們想成Java中的變數,隨著邏輯改變而有所不同,在使用的時候會對應到某種Java的類別,像是String、Date、Integer......
在左邊Report Inspector中可以看到它們,在每個種類上面按右鍵可以新增
Fields
Fields是用來顯示從Dataresource中動態取回來的資料,屬性有Name、Field Class(對應的Java類別)、Description(可選)
可以透過多種方式新增,以下簡單的介紹幾個
- 在Report Inspector的Fields按右鍵→加入Field
- 如上篇文章所示,透過SQL查詢來把table中的欄位加進Fields中,Field Class是根據該欄位在SQL中的類型來決定的
- 用JavaBean產生Fields
首先定義一個JavaBean
package test;
import java.sql.Date;
public class EmpVO implements java.io.Serializable{
private Integer empno;
private String ename;
private String job;
private Date hiredate;
private Double sal;
private Double comm;
private Integer deptno;
public EmpVO() {
}
public EmpVO(Integer empno, String ename, String job, Date hiredate, Double sal, Double comm, Integer deptno) {
super();
this.empno = empno;
this.ename = ename;
this.job = job;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public Double getSal() {
return sal;
}
public void setSal(Double sal) {
this.sal = sal;
}
public Double getComm() {
return comm;
}
public void setComm(Double comm) {
this.comm = comm;
}
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
}
再定義一個Factory類別,裡面有靜態方法可以產生一些EmpVO物件(因為只是簡單看一下能不能出現一樣的效果,所以直接用塞值的)
package test;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Vector;
public class EmpCollFactory {
public static Collection generateCollection() {
Vector collection = new Vector();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
collection.add(new EmpVO(7001, "KING", "PRESIDENT", new Date(sdf
.parse("1981-11-17").getTime()), 5000.5, 0D, 10));
collection.add(new EmpVO(7002, "BLAKE", "MANAGER", new Date(sdf
.parse("1981-05-01").getTime()), 2850D, 0D, 30));
collection.add(new EmpVO(7003, "CLARK", "MANAGER", new Date(sdf
.parse("1981-01-09").getTime()), 2450D, 0D, 10));
collection.add(new EmpVO(7004, "JONES", "MANAGER", new Date(sdf
.parse("1981-04-02").getTime()), 2975D, 0D, 20));
collection.add(new EmpVO(7005, "MARTIN", "SALESMAN", new Date(sdf
.parse("1981-09-28").getTime()), 1250D, 1400D, 30));
} catch (ParseException e) {
e.printStackTrace();
}
return collection;
}
public static EmpVO[] generateBeanArray() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
EmpVO[] empArray = new EmpVO[5];
try {
empArray[0] = new EmpVO(7001, "KING", "PRESIDENT", new Date(sdf.parse(
"1981-11-17").getTime()), 5000.5, 0D, 10);
empArray[1] = new EmpVO(7002, "BLAKE", "MANAGER", new Date(sdf.parse(
"1981-05-01").getTime()), 2850D, 0D, 30);
empArray[2] = new EmpVO(7003, "CLARK", "MANAGER", new Date(sdf.parse(
"1981-01-09").getTime()), 2450D, 0D, 10);
empArray[3] = new EmpVO(7004, "JONES", "MANAGER", new Date(sdf.parse(
"1981-04-02").getTime()), 2975D, 0D, 20);
empArray[4] = new EmpVO(7005, "MARTIN", "SALESMAN", new Date(sdf.parse(
"1981-09-28").getTime()), 1250D, 1400D, 30);
} catch (ParseException e) {
e.printStackTrace();
}
return empArray;
}
}
另外要注意一個非常重要的一點,不能用JDK1.8去Compile,我在這邊卡了好一陣子,想說明明設定都ok,為什麼就是沒反應,改用JDK1.7之後就好了
接著如上一篇文章所提到的步驟,在Classpath加入.class檔所在的位置(比如說D:\jdk7work\JavaBean\bin),接著新增Datasource,不一樣的是這次要選擇「JavaBeans set datasource」
設定如下:
Name:識別名稱,可以隨便打
Factory class:Factory類別的完整名稱,預設是com.jaspersoft.ireport.examples.SampleJRDataSourceFactory,用這個也可以,但在預覽的時候看不到實際的資料
Collection of javaBeans/Array of javaBeans:取決於Factory類別的方法是回傳一個集合還是一個陣列
The static method...:方法名稱
設定完後按下Test,如果出現Connection test successful!就可以按Save存起來了
一樣點選Preview旁邊的按鈕,這次選擇JavaBean Datasource,輸入JavaBean類別的完整名稱後按Read Attributes,底下就會出現這個類別所擁有的屬性
將要加入Field中的屬性選取,點選Add selected field(s),可以看到中間出現剛剛選取的屬性,這時再按Refresh Preview Data,底下就會出現之前在Factory類別中所塞的EmpVO們
在薪水跟獎金的部分,因為從資料庫撈出來的型態是BigDecimal,而JavaBean中是定義為Double,所以就算小數點後面為0也會顯示出來
Parameters
Parameters通常是從外部傳入的一些參數,可以用在報表的標題字串、或是在SQL中的查詢字串......等等,每個Parameters對應的類型也是一個Java類別
在Report Inspector可以看到目前有定義的Parameters,在報表中可以用$P{Parameter name}來取得值
- 報表的標題字串
假設新增一個名為title的Parameter,預設值放入"員工資料",接著將原本報表中Static Text的員工資料替代為Text Field的$P{title}
按下Preview時會出現一個視窗要求輸入參數值
這時可以輸入一個值,也可以按下Use default使用預設值,但如果沒有定義預設值時,就會出現null
- SQL的查詢字串
新增一個名為EMPNO的Parameter,接著點開Report query的畫面,將SQL指令改成select * from emp2 where EMPNO = $P{EMPNO}
按下Preview,舉例來說輸入7001,就只會出現EMPNO為7001的員工資料
此外也可以把Parameter當做一整個where的查詢條件,例如新增一個名為myQuery的Parameter,接著點開Report query的畫面,將SQL指令改成select * from emp2 $P!{myQuery}
按下Preview,輸入where EMPNO = 7001,出來的結果是一樣的
iReport內建的Parameters
iReport本身有內建一些Parameters,但它們是唯讀的,以下取其中幾個做說明
| 參數名 | 說明 |
|---|---|
| REPORT_PARAMETERS_MAP | java.util.Map物件,包含在填充報表時要傳給報表引擎的各種Parameter |
| REPORT_CONNECTION | java.sql.Connection物件,報表可以根據傳入的JDBC Connection取得相應的資料 |
| REPORT_DATA_SOURCE | net.sf.jasperreports.engine.JRDataSource物件,可以從外部的程式傳入一個Datasource |
| REPORT_SCRIPTLET | net.sf.jasperreports.engine.JRAbstractScriptlet物件,在填充報表時可以使用或控制Scriptlet物件在填充過程中已經準備好的資料。如果沒有指定使用的Scriptlet,則預設為net.sf.jasperreports.engine.JRDefaultScriptlet |
| IS_IGNORE_PAGINATION | java.lang.Boolean物件,可以控制分頁功能的開關,預設為打開,但在輸出html或excel時不做分頁處理 |
| REPORT_LOCALE | java.util.Locale物件,用來設定地區,如果沒有提供則用系統預設的 |
| REPORT_TIME_ZONE | java.util.TimeZone物件,用來設定時區,如果沒有提供則用系統預設的 |
| REPORT_RESOURCE_BOUNDLE | java.util.ResourceBundle物件,指定報表要載入的資源文件,可用於i18n |
Variables
Variables是用來儲存對某個表達式計算後的結果,可以在報表中使用$V{variable name}來表示,每個Variable也都一樣對應到一種Java類別,以下是各種設定的定義
Variable Class Type:對應的Java類別
Calculation:要如何對表達式做計算,iReport會根據指定的Calculation對從Datasource撈出來的每一筆資料做計算,並更新Variable的值
| 類型 | 說明 |
|---|---|
| Nothing | 不做任何計算,直接根據表達式把值印出 |
| Count | 計算有幾筆資料 |
| Distinct Count | 計算有幾筆不重複的資料 |
| Sum | 把資料的值累加 |
| Average | 累加結果的平均值 |
| Lowest | 表達式的最小值 |
| Highest | 表達式的最大值 |
| StandardDeviation | 根據表達式的所有值傳回標準差 |
| Variance | 根據表達式的所有值傳回變異數 |
| System | 可以自己控制計算方式(比如用Java程式) |
Reset Type:Variable在什麼時候進行重置(初始化)
| 類型 | 說明 |
|---|---|
| None | Variable不會被重置 |
| Report | 只有在報表創建時會進行重置 |
| Page | 在每一頁都重置一次 |
| Column | 在每一列都重置一次 |
| Group | 在每一個群組重置一次,需設定底下的Reset group |
Reset group:搭配Reset Type選擇Group時使用
Increment Type:這個網路上寫的定義有點籠統,應該可以理解成Variable在什麼時候做計算
| 類型 | 說明 |
|---|---|
| None | Variable對於每筆資料都會做運算 |
| Report | 只有在報表的最後計算一次 |
| Page | 在每一頁都計算一次 |
| Column | 在每一列的最後計算一次 |
| Group | 在每一個群組計算一次,需設定底下的Increment group |
Increment group:搭配Increment Type選擇Group時使用
Incrementer Factory Class Name:用來進行計算的一個Java類別,需要實作net.sf.jasperreports.engine.fill.JRIncrementerFactory介面,報表引擎會用它在執行期間根據Variable的Calculation屬性設定來實體化Incrementer物件
Variable Expression:要用來迭代做計算的變數
Initial Value Expression:Variable初始化時的值
假設定義一個名為COMMTOTAL的Variable來計算總共發了多少獎金,設定如下:
iReport內建的Variable
跟Parameter一樣,iReport也有一些內建的Variable,是無法做修改的
| 名稱 | 說明 |
|---|---|
| PAGE_NUMBER | 可以顯示當前所在的頁數,也可以顯示報表的總頁數(根據TextField的evaluationTime屬性設定為Now還是Report決定要顯示什麼) |
| COLUMN_NUMBER | 當前的列數 |
| REPORT_COUNT | 報表到目前為止共包含幾筆資料 |
| PAGE_COUNT | 當前頁包含幾筆資料 |
| COLUMN_COUNT | 當前列包含幾筆資料 |
| [GroupName]_COUNT | 當前組包含幾筆資料 |
假設在報表上使用了如圖的這些Variable,PAGE_NUMBER分別將evaluationTime屬性設定為Now跟Report





































