深入淺出JasperReports

簡介

  • 為 Java 開發的開源程式庫

  • 開發易擴充的動態報表

  • 具有表格、圖表、地圖、子報表等功能

  • 支援匯出多種格式(docx、xls、odt、ods、pdf、html…​)

  • 可以通過多種方式提供數據(csv、JDBC、json…​)

生命週期

  • Design

  • Compile

  • Execution

  • Export

jasper life cycle

開發思考流程

  1. 了解使用者報表需求(是否需要影印,如果要,詢問紙張大小)

Page Type Dimensions in Pixels

A3

842x1190

A4

595x842

A5

421x595

B4

709x1002

B5

501x709

  1. 思考要使用的Band

  2. 設定預設的Styles(記得勾Default Style)

  3. 加上要用的Fields & Parameters

  4. 思考需不需要使用Variables

  5. 開始設計報表(拉元件到畫面)

  6. 設定屬性

Band

簡介

  • 十二個Band

  • Band寬度為100%,高度可以自定義

  • 大部分的Band高度會自動擴增(遇到subReport,或是TextField超出時),column Footer 、page Footer、last Page Footer除外。

  • 所有Band高度的總和必須小於等於整頁高度-上下的外距(margin)

  • Band三大屬性有Height、Split Type、Print When Expression

    • Split Type ,設定當該頁或該欄剩餘的空間不足以容納該 Band 時,要如何安排該 Band。

Table 1. Split Type
Split Type屬性 說明

Stretch

default,如果實際高度大於Band高度,超出的部分就可能被切斷。

Prevent

避免被切斷,整個 Band 移到下一頁或下一欄,但如果下一頁或下一欄還是不夠高的話,還是會被切斷。

Immediate

立即被切斷,該頁或該欄放不下的部份移到下一頁或下一欄,Band 會被切成兩塊以上。

Band介紹

Table 2. Band介紹
Band 名稱 描述

Title

標題,只會在報表的第一頁最上方出現。

Page Header

頁首,在報表的每一頁上面都會出現,除了第一頁是在Title底下以外,其他頁面的頁首都會在最上面。(如果有選Summary On A New Page,則最後一頁不會出現)

Column Header

表頭,一般用來放欄位名稱。

Group Header

組表頭,如果有設定Group會出現,介於Column Header 跟 Detail中間。

Detail

報表的內容,實際要呈現的內容放在這裡。Detail允許有多個Band(Detail1、Detail2、.. Detail n)。

Group Footer

組表尾,如果有設定Group會出現,介於Detail 跟 Column Footer之間。如果超過一個組被定義,組表尾出現在組定義的順序相反(Group3、Group2、Group1)。

Column Footer

表尾,出現在每頁Detail的下方。(如果有設定Float Column Footer就會動態的在最後一頁的Detail下方)

Page Footer

頁尾,出現在每個頁面的底部。

Last Page Footer

最後一頁的頁尾,如果有設定會取代最後一頁的Page Footer。

Summary

出現在報表最後一頁的Detail底下,可以放一些統計的東西。

No Data

無資料區塊,當資料為0筆且When No Data Type設定為No Data Section,才會顯示這塊的內容。

Background

用於創建浮水印用。背景部分會顯示在每一頁上,並且不能溢出到下一個頁面。放在這一部分的元素在頁面初始化的時候求值,並顯示在背景中。所有其他的頁面對象被顯示在背景上對象的頂部。用於創建浮水印用。

Fields & Parameters

Fields:用來顯示Datasource取回來的資料

  • Fields三大屬性

    • Name(欄位名稱)

    • Class(型別)

    • Description(說明)

Parameters:外部傳來的一些參數,可以用在標題字串、列印日期、判斷的boolean值等等。

  • Parameters屬性

    • Name(參數名稱,從後端傳來的變數名稱)

    • Class(型別)

    • Description(說明,可寫可不寫)

    • Is for Prompting(如果不打勾,用Preview預覽時就不會要求打參數)

    • Default Value Expression(預設的表達式)

    • Evaluation Time(決定連線前後,要執行預設表達式的時機)

      • Early:在連線前,執行預設的表達式

      • Late:在連線後,執行預設的表達式

Variables

Variables:用來儲存對某個表達式計算後的結果,可用來統計、傳遞子報表的參數。

  • Variables屬性

    • Name(參數名稱,畫面元件Expression用[$V{Name}])

    • Value Class Name(類別)

    • Calculation(要如何對表達式作計算)

      • Calculation只能做數字的計算

Table 3. Calculation
Calculation屬性 說明

Nothing

不做任何計算,直接根據表達式把值印出,可用這個做簡單的運算(ex:$P{a}+$P{b},但只能計算數字類型)

Count

計算有幾筆資料

Distinct Count

計算有幾筆不重複的資料

Sum

把資料的值累加

Average

累加結果的平均值

Lowest

表達式的最小值

Highest

表達式的最大值

StandardDeviation

根據表達式的所有值傳回標準差

Variance

根據表達式的所有值傳回變異數

System

可以自己控制計算方式(比如用Java程式)

  • Expression(用來做計算的變數)

  • Initial Value Expression(Variable初始化的值,如果沒給就指向Expression的值)

  • Increment Type(Variable在什麼時候做計算)

Table 4. Increment Type
Increment Type屬性 說明

Report

只有在報表的最後計算一次

Page

在每頁都計算一次(每經過一個Page Header計算一次)

Column

在每一列都計算一次(每經過一個Column Header計算一次)

Group

在每一個群組計算一次,需要設定Group

None

每筆資料都會做運算

  • Reset Type(Variable在什麼時候會重置,需要設定Initial Value Expression,沒給的話,重置會變成null)

Table 5. Reset Type
Reset Type屬性 說明

Report

只有在報表創建時會進行重置

Page

在每頁都重置一次(每個Page Header重置一次)

Column

在每一列都重置一次(每個Column Header重置一次)

Group

在每一個群組會重置一次,需要設定Group

None

Variable不會被重置,所以不用設定Initial Value Expression

  • Incrementer Factory Class Name(用來客製化計算的一個的Java類別,需要實作net.sf.jasperreports.engine.fill.JRIncrementerFactory介面)

    • 假如你的Variable的Value Class Name為java.lang.Integer,但你的Expression回傳字串型別的值,這個變數的值會為0

  • JasperReports內建Variables

    • 內建的Variables可以直接拿來使用,但無法做修改

Table 6. 內建Variables
Variables名稱 說明

REPORT_COUNT

報表到目前為止共包含幾筆資料(如果要流水編號可以用這個)

PAGE_NUMBER

可以顯示當前所在的頁數,也可以顯示報表的總頁數(根據TextField的evaluationTime屬性設定為Now還是Report決定要顯示什麼)

COLUMN_NUMBER

當前的COLUMN數(通常一頁只會有一個Column,所以為1,如果一頁有多個Column時,才會有用處)

PAGE_COUNT

當前頁包含幾筆資料(當前Page Header 跟 Page Footer之間的Detail裡面有幾筆)

COLUMN_COUNT

當前列包含幾筆資料(當前Column Header 跟 Column Footer之間的Detail裡面有幾筆)

Subreport

簡介

有時候遇到需要合併儲存格的表格,或是一對多的資料結構,這時候就可以使用子報表來呈現。

子報表的兩大好處

  1. 模組化報表

  2. 可以連不同的資料來源

Subreport 屬性

  • Run To Buttom(如果選true,該子報表會填滿該頁全部,適合子報表的內容為一筆資料一頁用)

  • Overflow Type(判斷子報表是否要超過母報表的高度)

  • Using Cache(是否快取)

  • Connection Expression or Datasource Expression(資料來源,可以是直接連DB或是用JRBeanCollectionDataSource傳資料)

  • Parameters Map Expression(可以傳一個Map當作參數進去)

  • Edit Return Values(子報表回傳的資料,通常用在傳總計或是數量)

  • Edit Parameters(傳進去子報表的資料,可以用在ID辨別)

  • Expression(子報表的檔案來源,用字串去記)

子報表Expression判斷順序

  1. 網址

  2. 同層資料夾的檔名

  3. 加上絕對路徑的檔案

    1. 不能使用相對路徑

參數傳遞

參數傳遞可分為從 主報表傳進子報表子報表傳回主報表

主報表傳進子報表

sub report parameter
  • Parameter Name :輸入參數名稱

  • Parameter Expression :輸入參數內容,expression可以為字串、數字、參數、變數等等。如下圖:

sub report parameter add

子報表傳回主報表

sub report parameter return

回傳參數需要設兩個變數,一個在主報表一個在子報表,如下圖:

sub report parameter return add

子報表的變數

  • Value Class Name改成跟主報表設定變數的類別一樣

  • Calculation 看你是否有要做計算,這邊是計算某欄位的總和

  • Expression 要做總和的Field,可以用三元運算子來做if判斷

  • Initial Value Expression 可以設定初始值,例如我這邊設0

sub export variable

主報表的變數 - Value Class Name改成跟子報表設定變數的類別一樣 - Increment type 跟 Reset type 設成 Report

main report variable
主報表要放傳回變數的TextField,要將Evaluation Time改成Band,如下圖:
return text field

問題分享

  1. 如果只要產製證書或申請表等只有參數的報表,將所有內容刻在Title的Band,並將該Jasper的Report設定中的When No Data Type選成 All Sections No Detail

  2. 有時候excel表格超過一定行數就自動跳頁,這時如果不想要自動跳頁,將report的主設定中的 Ignore Pagination 打勾,就不會幾行就自動跳頁了。如下圖:

jasper pagination
  1. 如果想要產生動態欄位報表 ,可以將Appearance 裡面的 Print When Expresion 設定布林條件,決定是否要顯示該欄位,如下圖:

print when expression
  1. 如果想要一個TextField裡有不同字體大小或顏色

    • 先將TextField裡的markUp改成html,如圖:

jasper markup
  • 在Expression裡面加上<font></font>,如圖:

font example
  • 也可以用<span style='font-size:16px;'>

  1. 如果TextField 靠右對齊時,發現離右邊框線太近時,可以用right Indent去微調靠近右邊的px,如下圖:

right indent
  1. 如何在japser加上正方形實心框框 ■ 或是 空心框框 □ ?

    • 將textField 的 markup 改成 html,如圖:

jasper markup
  • 在 expression 使用html Geometric Shapes

  1. 如何讓detail的每個欄位等長且與最高的欄位同高?

    • 一種方法是用成一個ElementGroup

    • 另一種方法是改變這些屬性

1. Set "Position" to "Float"
2. Set "Stretch Type" to "ContainerBottom"
3. Check "Print when detail overflows" checkbox.
4. Check the "Stretch with overflow" checkbox.
  1. 換行

    • staticText 欄位

      1. 點擊兩下該欄位,Shift + Enter 換行

    • textField

      1. 加上"\n"

      2. 將Markup 改成 html,用<br>

  1. 如何讓Field、Parameter、Variable的數字有三位一撇 ? (ex:1000→1,000)

    1. 將TextField的Expression加上DecimalFormat的方法format,如下圖:

number with common
  1. 背景顏色修改

    • 幾乎每個Elements有一個共有的屬性-Backcolor(背景顏色),但修改後如果發現畫面沒有做修改,可能是因為Transparent(透明)選取了,此時記得將下面的transparent的打勾取消,如下圖:

transparent
  1. 在產製儲存格合併的表格時,可能會遇到分頁中間有斷行的問題。

將Detail Band的 Split Type(分裂類型) 改成 Prevent(避免),這樣就能解決子報表跳頁底線跑版的問題。

sub report question solve
  1. 如果用同樣的JRBeanCollectionDataSource塞給兩個subReport,會產生第一個子報表有抓到值,而第二個沒有,這時候把子報表的資料參數改成用list接,如下:

Java裡寫

paramsMap.put("statsData", summaryList);

jrxml裡寫

<parameter name="statsData" class="java.util.List"/>
...
<subreportParameter name="statsData">
    <subreportParameterExpression>
        <![CDATA[new net.sf.jasperreports.engine.data.
JRBeanCollectionDataSource($P{statsData})]]>
    </subreportParameterExpression>
</subreportParameter>
...