1. 程式人生 > >iReport預設引數和變數的含義解析【轉】

iReport預設引數和變數的含義解析【轉】

(1)
JasperReports是一個開源的java報表製作引擎
iReport是JasperReports的一個GUI工具,用來生成JasperReports的jrxml檔案。
JasperReports的報表是用XML檔案來定義的,約定用jrxml作字尾名。一個典型的jrxml檔案包含以下元素:
* <jasperReport> - 根元素
* <title> - 報表的標題,一篇報表裡只在開頭列印一次
* <pageHeader> - 頁首,報表每頁開頭列印一次
* <detail> - 報表正文
* <pageFooter> - 頁尾,報表每頁末尾列印一次
* <band> - 定義報表部件,以上所有元素都包含一個band元素作為他們唯一的子元素
·Summary:可能需要對幾頁(你的報表可能有幾個頁組成)的統計值。比如50個銷售記錄共佔用了3頁,那麼放置這些統計記錄的統計值最好的地方就是summary。
·groupHeader:每個表的內容可能需要根據某個屬性進行劃分顯示內容和計算內容,比如希望以月份為單位每組分開顯示銷售記錄,那麼就可以定義一個組(組的定義參考後文),groupHeader就是放置組說明或是組標誌最好的地方。
·Groupfooter:放置組的統計或是說明

(2)
各元素分析:
static text:靜態文字,只是用來在報表中顯示;
$P--->表示是引數;
如:"20"+$P{statement_current_date}

$F--->表示是textfield變數.
如:$F{account_code}
此變數是在<field name>中定義的.其值是在<queryString>中,通過select資料庫後,得到的.
select的列名 = field name

$V--->表示一個變數
如:$V{balance}
變數的預設值是在報表中設定的.一般設定為0.其真正的值是通過 $P或$F來獲得的.

(3)
A,報表中的QueryString語句,可以通過介面上的DataBase中的Report SQL Query來進行新增-->會自動生成相應的TextField.若不行,則可自動手動新增.
B,如果要直接修改程式碼,可以選擇介面上的'編輯'-->'直接編輯XML Source'-->先進行儲存-->就會出現程式碼介面.
C,如果要修改JASPER REPORT的屬性,可以選擇介面上的'預覽'-->'報表屬性'
E,新增group,可以通過點選介面上的相應'group'按鈕來新增.
F,隱藏不要的區域,要設bank=0,而不能刪除為空.刪除為空,則為預設值
G,IReport中的左欄中的各元素的後面的[X,Y]內的資料,是指此元素偏離'左上角'的X,Y距離.
H,設定子報表時,要將子報表的屬性中的"上邊界,下邊界,左邊界,右邊界"全部設定為0,否則會出現子報表傳回來的資料,在主報表中沒法對齊的現象.

(4)
當沒有資料(是指QueryString語句SELECT出來的資料為NULL)時,設定怎樣顯示:
相關程式碼:
whenNoDataType="NoPages / BlankPage / AllSectionsNoDetail"
NoPages:當沒資料時,會彈出一個對話方塊提示你沒資料,然後顯示一個沒啟用的框.
BlankPage :不會提示,只是顯示一個白紙.
AllSectionsNoDetail:不會提示,但那些靜態的文字,以及從上一層或JAVA檔案中傳來顯示的引數,都可以顯示.

(5)
內建的報表變數:
$V{PAGE_NUMBER}:(常用)
這個變數儲存當前的頁號,在報表裝填結束的時候,這個變數就儲存著最終文件的總頁數。所以要在JasperReport的文字欄位中顯示頁號和總頁數你都可以用它。
A,
只需要新增一個系統的變數:$V{PAGE_NUMBER};
對於$V{PAGE_NUMBER}:當evaluationTime="Now"時,即是計算當頁所在哪一頁. (now:即時執行此表示式.)
當evaluationTime="Report"時,即是計算當頁所在哪一頁.(Report:整個報表執行完後才執行此表示式)
B,
並將其轉換為String的型別.
C,總體程式碼:
<textField evaluationTime="Now">
<textFieldExpression class="java.lang.String">
"Page " + String.valueOf($V{PAGE_NUMBER}) + " Of"
</textFieldExpression>
</textField>
<textField evaluationTime="Report">
<textFieldExpression class="java.lang.String">
String.valueOf($V{PAGE_NUMBER})
</textFieldExpression>
</textField>
$V{REPORT_COUNT}:
當evaluationTime=Report時,將記錄報表的總記錄數.
當evaluationTime=Column時,將記錄報表從開始到當前頁的總記錄數.
Variable COLUMN_NUMBER
這個變數將記錄當前的列號。
Variable PAGE_COUNT
這個變數紀錄當前頁中處理的record的數目。
Variable COLUMN_COUNT
這個變數紀錄生成當前列時所處理的record的數目。

(6)
field的動態顯示+動態顯示不同的格式:
有些報表可能需要對同種型別的資料根據重要性不同而顯示不同的風格。例如,要在訂單列表中加亮顯示金額超過100$的訂單.
而文字域的現實格式不能動態改變,我們如何實現這種功能呢?
解決辦法是:
在同樣的位置放兩個文字域來顯示相同的內容,但是設定不同的顯示格式,一個正常顯示,一個加粗並加亮顯示紅色,同時還要為他們設定<printWhenExpression>元素,讓他們可以根據條件表示式來切換。這裡的表示式就是$F{value} < 100(正常顯示的文字域)和$F{value} >= 100(加亮顯示的文字域)。

(7)
建立子報表
1)
在程式碼中,將子報表以引數形式載入:
JasperReport sixUnitPrice = (JasperReport)JRLoader.loadObject("jasper/TrendAve_ItemIntel_6MonthUnitPrice.jasper");
parameters.put("sixUnitPrice", sixUnitPrice);
2)
在主報表中,建立上面的相應引數sixUnitPrice. 其型別為:net.sf.jasperreports.engine.JasperReport
3)
在iReprot中新增,劃拉出一塊子報表.
在subReport項中,選中:' use connection expression '
在subReport other項中:
設定image expression class=net.sf.jasperreports.engine.JasperReport
設定subreport expression中填寫程式碼中的相應引數:$P{sixUnitPrice}
4)
設定要傳到子報表的引數,並在主報表中建立相應的引數.
5)
新建子報表,建立一引數(與主報表傳遞的引數一樣),來接收從主報表傳來的引數.-->即可應用了.
說明:
位於多層之下的子報表,也需要從主報表開始時,就可以載入,傳遞下去,否則載入不了.因為一開始,都是從JAVA檔案中從傳過來,然後一層層傳下去的.

(8)
hashmap引數在報表間傳遞值的用法
1)
如何帶引數:
在某層子報表中建立一個新的子報表,此新子報表,必須從:報表java類中定義-->主報表-->各上級父報表中對此新子報表進行定義(定義此引數+各父報表新增此新報表引數,以便其子報表可以獲得)-->目的子報表
2)hashmap引數在報表間傳遞值的用法
如上的專題記錄,$P{group_total_hash}此引數是一個hashmap,從其定義是在子報表中的,最終用:是在主報表中,作為統計資料.
怎樣用:
1.
先在主報表,以及子報表中都要定義hashmap,並在子報表的各上層報表進行賦值,使引數可以主報表與子報表中間進行傳遞:
<parameter name="group_total_hash" isForPrompting="false" class="java.util.HashMap">
<defaultValueExpression ><![CDATA[new java.util.HashMap()]></defaultValueExpression>
</parameter>
2.
在子報表中,在區間的顯示屬性中新增:
$P{group_total_hash}.put();如下:
$P{trayout_hash}.put("trayout",$F{totalqty}) == null?
Boolean.TRUE:Boolean.TRUE
3.
/*
在主報表中:
子報表的返回值有一個問題:它們是在當前區域的所有元素都被處理之後才返回的。
所以,為了能在主報表中的子報表所在的同一區域顯示返回值,我們必須延遲文字域表示式的處理時機。這是通過加入一個無效的分組讓表示式在分組結束時處理來實現的,而這個無效分組的效果就是資料來源中的每條記錄就是一組,而且它自己沒有組頭和組尾區域。
*/
在主報表中:
新增一Field,設定資料型別為Double,且Evaluation time=Column(否則資料出不來)
$P{group_total_hash}.get();如下:
new Double
(
((Double)$P{trayout_hash}.get("trayout")).doubleValue()
-
((Double)$P{trayin_hash}.get("trayin")).doubleValue()
)
4.
具體可以參考ACCOUNT中的PL報表,或SCM中的item intelligence報表中的設定及用法:
主報表:
ProfitLoss_basic.jrxml
用於計算各部分total的子報表:
ProfitLoss_basic_subReport_profit_loss_total_year_list.jrxml

TrendAve_ItemIntelReport.jrxml
TrendAve_ItemIntel_trayout.jrxml.

(9)
Group的用法:
用法一:(分類顯示及計算)
假設有兩表:
mysql> select * from A;
+------+------+
| id | name |
+------+------+
| 1 | hk |
| 2 | hk |
+------+------+
mysql> select * from B;
+------+------+------+-------+
| id | Aid | name | value |
+------+------+------+-------+
| 1 | 1 | sz | 1 |
| 1 | 1 | cz | 1 |
| 2 | 2 | zh | 1 |
| 2 | 2 | gz | 1 |
+------+------+------+-------+
報表要分兩層,第一層迴圈查詢A表,第二層(即子報表)迴圈查詢B表在屬於A表的記錄.
若不用group,則會出現(-->後面是各元件中iReport中的位置):
ID Name value -->放於報表中的pageHeader
1 hk 1 -->放於第一層報表中的detail -->迴圈每一條記錄且顯示
1 sz 1 -->放於第二層報表中的detail
2 cz 1
2 hk 1 //name與上相同
1 zh 1
2 gz 1

若採用group按照name進行分組,則jasper會把name相同的放入一組,只顯示一次.

採用name分組後的效果:
ID Name value -->放於報表中的pageHeader
1 hk 1 -->放於第一層報表中groupHeader,將所有相同的name集合在一起,只顯示一次
1 sz 1 -->放於第二層報表中的detail
2 cz 1
1 zh 1
2 gz 1
sum value: 5 -->放於第一層報表中groupFooter
補充說明:
對於上面的group,須先點選"group"按鈕進行定義(如:nameGroup).

同時,可以以group的基準進行計算(結合變數variable),放於groupFooter.
(1)
在iRport中,新建變數sumValue,定義如下:
variable type: Double
caculation type: sum
Reset type: Group
Reset Group: 上面自定義的group名(如:nameGroup)
variable expression:(即進行計算的表示式) $F{value}
(2)
在groupFooter新增一field:
須定義:
Evaluation time : group,而不是now
Evaluation Group: 上面自定義的group名(如:nameGroup)

jasper報表,子報表內容顯示重疊
在jasper中,若在detail區域中,把兩個一模一樣的子報表上下放置.則在迴圈輸出時,會出現上下子報表
輸出內容相遮掩的結果.
解決方案:用group分離顯示.
把兩個子報表,分別放於兩個不同的group中,分組條件為主報表的每一個ID,這樣,主報表迴圈顯示時,就
會將各分組一一顯示出來,不會影響其顯示.

用法二:
利用group來進行分組和實現子報表返回值:
第(8)點的返回值,只適合於非迴圈性的.
若在主報表的detail區域,需要讓每條record都將子報表返回值到對應的record中,則要採用這種方法.上面的方法實現不了.
因為子報表的返回值有一個問題:它們是在當前區域的所有元素都被處理之後才返回的。如果你想在子報表所在的主報表區域顯示它的返回值,你最終將看到它們返回的太晚了。
具體實現方法:
1)
先在主報表,子報表建立一個同名的hashmap容器,且將主報表的這個引數作為子報表的傳遞引數,傳到
子報表中.
2)
在報表中,對視窗進行加值:
方式一:
在子報表中,在summary區域的屬性中新增:
$P{trayout_hash}.put("trayout",$F{totalqty}) == null?Boolean.TRUE:Boolean.TRUE
方式二:
在子報表中,在summary區域中新增一個不可見的直線元素,且在其中設定:
<line>
<reportElement x="0" y="0" width="0" height="0">
<printWhenExpression>
$P{trayout_hash}.put("trayout",$F{totalqty}) == null?Boolean.FALSE:Boolean.FALSE
</printWhenExpression>
</reportElement>
</line>
3)
在主報表中,新增一個分組,以每條記錄作為一個分組.操作如下:
A,點選GROUP按鈕.
B,填寫組名;
C,分組表示式: $F{item_code}.(也可以id作為分組) -->分組的關鍵所在
D,選擇:是否start on a new page -->讓最後所得的分組,是否以分頁的形式顯示.
4)
對於detail區域中,要返回值的field,這樣設定:
<textField evaluationTime="Group" evaluationGroup="itemcodeGroup">
<reportElement x="335" y="50" width="175" height="15"/>
<textFieldExpression >
$P{trayout_hash}.get("trayout")
</textFieldExpression>
</textField>
採用Group實現返回值的說明:
子報表的返回值有一個問題:它們是在當前區域的所有元素都被處理之後才返回的。如果你想在子報
表所在的主報表區域顯示它的返回值,你最終將看到它們返回的太晚了。
所以,為了能在主報表中的子報表所在的同一區域顯示返回值,我們必須延遲文字域表示式的處理時
機。這是通過加入一個無效的分組讓表示式在分組結束時處理來實現的,而這個無效分組的效果就是
資料來源中的每條記錄就是一組,而且它自己沒有組頭和組尾區域。
<group >
<groupExpression>$F{item_code}</groupExpression>
</group>


(10)
若資料型別設定為Double,則須:
$P{trayout_hash}.get("trayout")-->Object型別;
((Double)$P{trayout_hash}.get("trayout"))-->轉換成Double型別;
((Double)$P{trayout_hash}.get("trayout")).doubleValue()-->轉換成double型別,進行計算;
new Doubel(A-B)--->將最終結果轉換成Double,因為上面設定型別型別時,用了Double.
如下:
new Double
(
((Double)$P{trayout_hash}.get("trayout")).doubleValue()
-
((Double)$P{trayin_hash}.get("trayin")).doubleValue()
)

(11)
變數還可以宣告來完成引擎內建計算的求值,如:count、sum、average、lowest、highest、 variance等等。一個完成Quantity欄位sum計算的變數定義如下:
<variable name="QuantitySum"
class="java.lang.Double" calculation="Sum">
<variableExpression>$F{Quantity}</variableExpression>
</variable>
我們還可以通過制定初始化級別來改變計算過程,預設的級別是Report就是變數僅在報表開始處初 始化一次,一直到報表結束完成計算。
我們可以選擇更低的級別讓變數在每個Page、Column或者Group級別重新初始化。假如我們想計算 計算每頁的總數,變數宣告如下:
<variable name="QuantitySum" class="java.lang.Double"
resetType="Page" calculation="Sum">
<variableExpression>$F{Quantity}</variableExpression>
<initialValueExpression>new Double(0) </initialValueExpression>
</variable>
變數將在每一頁的開始處被初始化為0。

(12)
變數的resetType解釋:
報表變數的值可以在每一次迭代(iteration)中被改變,但也可以在裝填過程中的某一特定的時間(specified moments)通過它的初始的value表示式恢復其初始值。這一行為是由resetType屬性控制的,這一屬性規定了報表裝填過程中當報表變數在何時需要重新進行初始化(或恢復到初始值)。該元素有五種選項值:
4.1
No Reset:變數將不會使用其initial value expression對自身進行初始化,而將僅報表從變量表達式中所求得的值(resetType=”None”)。
4.2
Report Level Reset:變數將在報表填充過程的起始階段使用其初始化表示式初始化一次(resetType=”Report”)。
預設的屬性為resetType=”Report”
4.3
Page Level Reset:變數將在每一頁的起始時被重新初始化(resetType=”Page”)。
4.4
Colunm Level Reset:變數將在每個新列的開始被初始化(resetType=”Column”)
4.5
Group Level Reset:變數將在每次resetGroup屬性提供的break的地方被重新初始化(resetType=”Group”)。
Reset Group
如果存在的話,resetGroup屬性包含了報表的組的名字並且僅與resetType=”Gropu”的resetType屬性相關聯。

(13)
報表的分層顯示方法:
外層,在主報表中查詢迴圈顯示;
下層,在子報表中查詢迴圈顯示.