歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java報表學習札記之 JasperReports & iReport

Java報表學習札記之 JasperReports & iReport

日期:2017/3/1 9:11:38   编辑:Linux編程

前言

說到Java報表工具,我接觸過的只有FineReport(帆軟)和JasperReports,這兩個都用過,帆軟是收費的而JasperReports是免費的,首先第一感覺帆軟功能強大,支持導出的報表格式豐富,但是坑很多(一個格子的屬性設置不對整個報表都會亂掉,比如左父格什麼的,而且有時少量數據測試是沒問題但數據量一大報表就亂掉了,不管什麼原因引起,首先這就直接導致不容易發現問題,去年項目上線後就被這樣坑過一次),再來談談JasperReports,開源免費,使用方面和帆軟比是不如它強大,不能導Excel,通常情況下只用來導PDF,但在大多數情況下還是能滿足需求的,畢竟免費的不能要求太高哈,So,本篇blog就總結一下JasperReports以及iReport的使用方法和細節。

下載iReport

地址如下:
http://community.jaspersoft.com/download

我們可以看到目前官方首推的可視化報表設計工具是Jaspersoft Studio(基於Eclipse),早期的iReport從5.5之後就不再提供更新了,但之前一直用的是iReport開發報表所以本篇blog就基於iReport這個工具進行開發,個人感覺還是蠻好用的(聯想到了當年用Eclipse開發Android打死都不換Android Studio T_T),我們直接下載iReport Designer可視化編輯器即可,如下圖所示:

當然還必須要有JasperReports Library才能通過Java程序來調用報表,由於只是一個jar包所以我就直接上傳到CSDN供大家下載了,我使用的版本是jasperreports-5.6.1,下載地址:
http://download.csdn.net/detail/wlwlwlwl015/9509567

下載安裝之後就可以使用它來創建報表文件了。

創建報表

打開iReport,點擊文件–>new,可以看到一個New file面板:

可以看到左側的菜單提供了多種報表圖表類型,由於我們主要做基礎報表所以只關注Report(報表)就可以了,而右側提供了一些模板,比如縱向A4,橫向A4等,通常我們用的最多就是第一個縱向A4了,選擇它並點擊“Open this Template”,接下來會彈出命名和定位的面板,輸入報名文件名稱和文件存儲的目錄即可:

最後點擊完成即可進入報表的編輯界面了:

編輯報表

首先我們來看一下iReport的主界面:

上圖是一個設置好的標准的編輯界面,左側是inspector區域,中間是主編輯區域,右上是組件面板區域(如果沒有通過Ctrl+Shift+8組合鍵調出),右下是屬性窗口,底部是輸出區域,左側是Problem Window(報錯窗口),右側是Output Window(輸出窗口),在菜單欄下面標出的是DB連接設置區域。首先我們從主編輯區域看起:

如上圖,iReport把一個報表按如上圖的方式進行分割,顧名思義也就是不同的區域應當放置不同的內容,操作起來的話和C#做WinForm程序的感覺差不多,就是拖控件!設屬性!下面我們舉例做一個成績報表,首先是標題,一般靜態文本我們統一用組件面板中的Static Text(Lable),如下圖:

Title

注意一下這裡最常用的兩個組件就是Static Text和下面的Text Field了,Static Text通常用於放靜態文本,例如:標題、列名等等,而Text Field通常用來放動態的表達式,例如數據庫的查詢結果,函數等等。下面從組件面板中拖動Static Text到編輯區的Title中:

如圖上面的一排工具欄可以設置組件內容的對齊方式以及字體樣式等等,但更多情況下我們還是會在屬性面板來設置這些:

關於屬性這裡有非常重要的一點就是要設置報表字體和編碼,將屬性面板滑動到底部可以看到這兩個屬性:

如上圖,因為我們的標題是中文,所以我們必須設置為中文字體和編碼:

  • STSong-Light
  • UniGB-UCS2-H (Chinese Simplified)

只有這樣我們在報表中才能正確顯示中文,包括後面所有包含中文的控件都需要此設置。

標題很簡單,接下來是頁頭,我們可以在頁頭放一些通用屬性,諸如:學校、班級信息等等,如下圖所示:

我們在頁頭(Page Header)中放了學校、班級和時間,可以看到我們用了6個控件,3個Static Text和3個Text Filed,就像之前說的,Static Text用來放靜態文本,而Text Filed用來放動態表達式,學校和班級是我們在DB中查出來的(後面再細說),而時間這裡用了一個動態表達式來完成,如下圖:

關於Expressions(表達式)是一個值得深入研究的話題,iReport為我們提供了多種類型的表達式,例如:

這裡看到了我們非常熟悉的Java代碼,Java語言也正是iReport官方推薦的第一語言(盡管還支持Groovy、Javascript語言的表達式):

iReport為我們提供了豐富的表達式語法,上圖可以看到甚至包括三目表達式,可以讓我們方便的進行相關操作,比如下面的設置指定格式時間並輸出:

這樣我們就可以把當前時間按照指定的格式顯示在報表中了。

Column Header

看完了Page Header,接下來就是Column Header了,這個區域通常會放列頭,所以也應當是靜態文本,這個報表的表格我沒有用table控件去做,而是通過多個Static Text和Text Field拼成的表格,如下圖所示:

ireport自帶的拖動對齊線可以方便的讓我們將控件拖拽至合適的位置,包括調整它們的大小,當然也可以通過Ctrl+鼠標左鍵選中多個控件來為它們設置一致的屬性值,關於Static Text或Text Field的邊框(border)需要注意一下,因為在屬性面板中並不能找到它們,我們需要選中控件然後點擊鼠標右鍵在彈出的“Padding and Borders”中來設置邊框,如下圖所示:

我們依次點擊Borders中的4條邊,然後將Line width設置為1即可,現在我們就可以看到邊框了:

Create DataSource

到此為止我們的報表中所有靜態的內容基本算是完成了,接下來就是主要的動態生成的部分了,由於項目的持久層采用的是MyBatis框架,所以在這裡我們選用SQL作為Query language。首先需要確認數據源,最開始已經提到了DB數據源設置的位置,點擊這個圖標:

之後我們會看見如下窗口:

可以看到上圖就是用來創建數據源的面板,前兩個是ireport提前創建好的一個空數據源和一個Sample數據源,第3個是我已經創建好的,我在這裡重新再創建一個新的數據源,點擊New:

可以看到上圖中提供了非常豐富的數據源類型,諸如:JDBC、Hibernate、EJB等等,由於我的項目中的持久層用的是MyBatis框架,所以在這裡選擇第一個——Database JDBC connection即可,然後點擊next:

顯而易見,選擇JDBC Driver並依次輸入URL、Username和Password,最後點擊Test,如果提示成功,那麼我們的數據源就算成功創建好了,接下來就可以寫報表的查詢語句了。

Report Query

首先我們需要知道在哪裡輸入查詢SQL,點擊如下圖標識的按鈕:

之後就可以看到Query窗口了:

如上圖,我們勾選Automatically Retrieve Fields之後,當我們輸入完SQL語句後在下面會自動取回查詢結果的所有列,同時我們在底部可以看到數據預覽:

這樣報表的查詢SQL就算成功完成,最後我們根據列名依次把每一個放置在報表Detail 1區域的Text Field中即可。

Detail 1

沒錯,這個區域就是報表的主數據展示區,首先依次將Text Field拖放至Detail 1區並和列頭對齊,然後設置邊框,效果如下:

可以看到每個Text Field都有一個默認值$F{field},這個是什麼意思呢?我們在官方文檔中可以找到答案:

沒錯,$F是引用一個域(field)的意思,那什麼又是Fields?顯而易見,我們剛才寫查詢SQL語句返回的查詢結果的每一列就是一個Field,這一點我們也可以在左側的Inspector區中看到:

有了這些概念接下來的問題就簡單了,我們只需要根據field name來一一修改每一個Text Field裡的表達式即可,例如修改准考證號這一列:

下面是修改好的簡單浏覽一下:

有幾點需要著重注意一下:

  1. 第一點也是最重要的一點在上圖已經標出了,就是Detail 1區域的高度要和Text Field的行高保持一致,這樣循環行生成報表的時候才會沒有行間距。
  2. 所有包含中文的Text Field或Static Text都需要統一設置中文字體(STSong-Light)和中文編碼(UniGB-UCS2-H (Chinese Simplified))。
  3. 由於我們沒有用table組件而是用一個個的Text Field拼成的表格所以最好放大看一下邊框細節和對齊細節等等:
  4. 統一設置所有Text Field和Static Text的內容對齊方式,最好是水平居中()和垂直居中()。
  5. 還有一個需要注意的細節就是如果SQL語句查詢為空的字段如果不做處理那麼默認在報表中會顯示NULL,所以不太美觀,但解決方案也很簡單,就是將所有可能出現空值的格子(Text Field)均設置為Blank When Null,即:為null時用空格子代替:
  6. 最後應當在iReport中預覽一下報表效果,點擊Peview進入預覽視圖:

    然後就可以看到我們的報表預覽效果了:

整體還算完美吧!預覽的同時注意一下底部的iReport output窗口,可以看到這樣的提示信息:

沒錯,是對源文件report1.jrxml進行了編譯而生成了report1.jasper文件,在JasperReports中,jrxml是源文件,而能運行的則是源文件編譯後的jasper文件。我們預覽的同時會自動編譯,當然在編寫源文件的同時我們也可以手動編譯,編譯按鈕在這裡:

再回過頭來看預覽的報表,注意到序號這一列亂掉了,由於我們的SQL是按照准考證號asc升序排列,所以用Oracle的rownum做序號仿佛有些不合適,不過沒關系,iReport也自帶了類似的序號功能!我們通過添加變量(Variables)來實現。首先我們需要先創建一個新的變量,在左側的Inspector區域找到Variables並new一個Variable命名為rownumber:

關於變量(Variables)我們可以在官方文檔的Chapter 6中找到它的相關說明:

首先我們定義這個變量的類型為java.lang.Integer,Caculation設置為Count,Reset type設置為Report:

可以看到Reset type設置為Report時變量只會為初始化1次,並且是使用intital value expression的值作為初始值,那麼我們將intital value expression設置為1即可,如下圖:

最後設置變量表達式(Variable Expression)為$V{rownumber}.valueOf(1)即可。現在修改序號的Text Filed,將原來引用域改為引用變量rownumber,之後再次預覽看看效果:

可以看到序號可以正常顯示!至此我們的報表部分就算開發完成了,接下來看看如何在Java程序中調用報表。

java調用報表

和帆軟的FineReport有些區別,帆軟是將報表服務器的servlet封裝在了jar包中我們只需要在web.xml中引用即可,但JasperReports就需要我們自己來寫了,思路都是一樣的,直接看代碼:

package net.xnzz.servlet;


import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.HashMap;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperRunManager;
import net.xnzz.util.DBUtils;

public class JRPDFServlet extends HttpServlet 
{
    private static final long serialVersionUID = 1L;

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException 
    {
        Connection connection = DBUtils.getDBInstance().getInitDBConnection();
        try 
        {
            //據據jasper文件生成JasperPrint對象
            ServletContext context = this.getServletConfig().getServletContext();
            String fileName = request.getParameter("fileName");//ireport編譯文件:*.jasper(由模板文件*.jrxml文件編譯生成)
            File reportFile = new File(context.getRealPath("/WEB-INF/jaspers/"+fileName));
            HashMap<String, Object> parameters = new HashMap<String, Object>();//給報表模板文件傳參

            //得到枚舉類型的參數名稱,參數名稱若有重復的只能得到第一個--獲取頁面傳來的參數,和模板中文件的sql參數名稱一一對應
            Enumeration<?> temp = request.getParameterNames();
               while (temp.hasMoreElements()) 
               {
                String paramName = (String) temp.nextElement();
                String paramValue = request.getParameter(paramName);
                parameters.put(paramName, paramValue);
               }
            byte[] bytes = JasperRunManager.runReportToPdf(reportFile.getPath(), parameters,connection);
            response.setContentType("application/pdf");
            response.setContentLength(bytes.length);
            ServletOutputStream out = response.getOutputStream();
            out.write(bytes, 0, bytes.length);
            out.flush();
            out.close();
        } 
        catch (JRException e) 
        {
            e.printStackTrace();
        }       
    }
}

思路很簡單,就是通過IO流先讀取到項目中的編譯後的.jasper文件,然後再通過JasperRunManager向客戶端輸出一個格式為pdf的報表文件即可,由於參數和文件名等等都做了參數化的封裝所以這個servlet可以供所有JasperReports復用。服務器端代碼完成了,下面再看一下客戶端是如何調用報表的,看一下下面這段jsp代碼:

<body>
    <iframe id="reportFrame" width="100%" height="88%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no" allowtransparency="yes"></iframe>
</body>

<script type="text/javascript">
    function getSearch() {
        var path = "${pageContext.request.contextPath}/servlet/JRPDFTYServlet?fileName=report222.jasper"
        $("#reportFrame").attr("src", path);
}

很簡單吧!我這裡定義了一個iframe,僅僅只需要將報表servlet路徑設置給iframe的src屬性即可,當然如果報表有參數的話可以用js字符串拼接再串到servlet地址後面即可,到此為止所有工作就已經完成了,最後看一下程序中的報表效果。Google浏覽器的效果:

IE浏覽器的效果:

還不錯吧~ 這樣的報表用戶不論是打印還是導出PDF都非常方便,關於JasperReports的介紹到此就算全部結束了,當然這只是個大概的內容,感興趣的同學可以自己通過官方文檔再進一步詳細學習,下載官方文檔

到Linux公社1號FTP服務器下載

------------------------------------------分割線------------------------------------------

FTP地址:ftp://ftp1.linuxidc.com

用戶名:ftp1.linuxidc.com

密碼:www.linuxidc.com

在 2016年LinuxIDC.com\9月\Java報表學習札記之 JasperReports & iReport\

下載方法見 http://www.linuxidc.com/Linux/2013-10/91140.htm

------------------------------------------分割線------------------------------------------

總結

簡單記錄一下JasperReports以及它的可視化報表編輯器——iReport的使用方法,希望對這方面感興趣的同學有所幫助, The End。

Copyright © Linux教程網 All Rights Reserved