利用JasperReport+iReport進行Web報表開發

出處:http://blog.csdn.net/kabini/article/details/1600073


用JasperReport+iReport進行Web報表開發

序言

在很多實際的項目裏,報表都是其中十分重要的組成部分,例如把查詢結果以報表的形式呈現出來。這裏所提到的報表可不是簡單的二維表,而是擁有複雜表頭的、多維的、可以在運行期從數據庫中自動讀取數據、可自動分頁、擁有豐富的頁面元素(圖片,超連接等)、支持分組和交叉表、支持打印、最好還能導出到Excel或Word…...(汗L)。但是顯而易見,報表功能越強大,提供的服務越豐富,其複雜度也就越提高,所以僅靠石器時代的手工方式生成報表是不能滿足需要的。所幸,目前我們所熟知的幾款報表工具功能上足夠強大,而且都附有很方便的報表生成工具。它們分別是:JasperReport(+iReport),BIRT(+eclipse),水晶報表(+eclipse,JBuiler等等)。

之所以提到這三種報表工具首先是因爲他們都是開放源碼的(CrystalReportForEclipse1.0已經開源了)。既然不用考慮費用,那在我們的項目中到底選用哪一個呢?對於水晶報表而言,雖然其在.Net平臺上表現十分搶眼,但是在Java平臺上,多數的實現都是要收費的(例如For JBuilder版),而且其Eclipse插件的資源消耗十分驚人(我的機器配置爲P4 3.0+512RAM,使用“Eclipse3.2+水晶報表插件”根本就跑不動)。所以我選擇了純Java的報表工具JasperReport與iReport的組合。但是關於JasperReport的文檔相對匱乏,其官方文檔還是要收費的,所我希望利用這篇文章展示如何利用這一強力組合來進行基於Web的報表開發,希望能爲那些苦於報表的同仁們解決一些實際問題。

本文將火力集中在如何在Web環境下配置和使用JasperReport報表和報表的導出功能等方面,由於在以前的Blog中我已經寫過如何設計普通的報表,所裏這裏將不再贅述。對於那些基本的操作則留給讀者自行體會,相信在iReport的幫助下,上手會很快的。

(注:本文已被《程序員》收錄,未經允許不得轉載


1     JasperReport簡介

2     Web報表開發

2.1      環境設置

2.2      報表預覽框架

2.3      使用JNLP技術實現客戶端預覽

3     結束語


1   JasperReport簡介

JasperReport是一個強大、靈活的報表生成工具,能夠展示豐富的頁面內容,並將之轉換成PDF,HTML,XML,Excel(通過POI或JExcelAPI實現)和Rtf(通過POI實現)格式。該庫完全由Java寫成,可以用於在各種Java應用程序,包括J2EE,Web應用程序中生成動態內容。它的主要目的是輔助生成面向頁面的(page oriented),準備付諸打印的文檔。JasperReport藉由定義於XML文檔中的report design進行數據組織。這些數據可能來自不同的數據源,包括關係型數據庫,collections,java對象數組。通過實現簡單的接口,用戶就可以將report library插入到訂製好的數據源中。用JasperReport進行報表開發的過程如下所示(Version=1.0):

目前JasperReport最新的版本是1.2.7,可以到Sourceforg網站下載其整個工程及代碼。其工程文件目錄下的demo子目錄中包含很多定義良好的例子,可以實現各種所需功能。鑑於它的文檔收費,想學習使用JasperReport的話我們也只能以這些demo作爲學習資料了。

但是繁瑣的XML標記和功能API在提供強大的動態及可擴展開發的同時也帶來了超高的複雜性,在沒有免費文檔的情況下,手工編寫報表設計所需的XML文件是極其不明智的。不過正如我們用JBuilder(或其他可視化開發工具)編寫SwingGUI時一樣,我們可以採用iReport進行可視化的報表設計來避免和可怕的XML文件及實現細節打交道。雖然可能會損失一些動態生成報表的靈活性,但是大多數情況下,我們只需要靜態的設計框架和動態的裝填數據而很少需要動態的報表框架,所以和我們所獲得的方便相比,這些小小的損失簡直可以忽略不計了。當然如果確實需要,且看到下面的東西你不暈的話,自己動手確實可以獲得所需的靈活性。

其中的VerticalFilling和HorizontalFilling表示裝填數據的順序。從上圖我們可以清楚地看到,一個報表的設計主要由PageHeader和報表內容組成,報表內容又是由列組成,內容既可以是一列也可以是多列,還可以是Group。具體的實例如下:

這些元素到底在JaserReport的XML設計文件中的定義爲何我並不想關心,因爲這都由iReport負責操心了,我們只需輕鬆的像搭積木一樣利用iReport添加各種可視化元素就可以了。相信用過之後你會對iReport愛不釋手,就像我一樣。出於實際需要,我會提供一個簡單的動態表單的生成框架供各位參考。 

2   Web報表開發

現今的環境是Web大行其道,一個工具如果不能融入Web功能就無法立足。JasperReport的開發者顯然很早就意識到了這一點,所以在JasperReport1.0以前就加入了支持Servlet/JSP的能力。也就是說,我們可以利用Servlet/JSP將生成好的報表導出成HTML(或PDF/RTF/EXCEL)格式供預覽或導出之用。然而唯一的缺憾在於JasperReport並未提供在客戶端直接打印的功能,而除了使用Applet之外我們又不能直接在客戶端顯示JRViewer這樣的預覽窗口,如何解決這些問題呢?

2.1環境設置

在Servlet/JSP中使用JasperReport無需更多的設置,只需要將JasperReport所用到的jar包放入工程中的WEB-INF/lib目錄下即可。在程序運行期,Servlet/JSP只需能夠正確加載報表文件,裝填數據並生成JasperPring對象,利用我下面給出的導出框架稍加修改即可生成一個帶有HTML/PDF/RTF/EXCEL導出功能以及可將HTML預覽進行分頁的功能模塊。

2.2報表預覽框架

<%@page contentType="text/html; charset=UTF-8"%>

<%@page import="javax.servlet.*"%>

<%@ page import="net.sf.jasperreports.engine.*" %>

<%@ page import="net.sf.jasperreports.engine.util.*" %>

<%@ page import="net.sf.jasperreports.engine.export.*" %>

<%@ page import="net.sf.jasperreports.j2ee.servlets.*" %>

<%@ page import="java.util.*" %>

<%@ page import="java.io.*" %>

<%

 JasperPrint jasperPrint = (JasperPrint)session.getAttribute("JasperPrint");

 session.setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,jasperPrint);

 String pageTitle = (String)session.getAttribute("pageTitle");

 

 JRHtmlExporter exporter = new JRHtmlExporter();

 int pageIndex = 0;

 int lastPageIndex = 0;

 if (jasperPrint.getPages() != null){

    lastPageIndex = jasperPrint.getPages().size() - 1;

 }

 

 String pageStr = request.getParameter("pageIndex");

 try{

    if( pageStr != null)

        pageIndex = Integer.parseInt(pageStr);

 }catch(Exception e){

    //e.printStackTrace();

 }

 

 if (pageIndex < 0){

    pageIndex = 0;

 }

 

 if (pageIndex > lastPageIndex){

    pageIndex = lastPageIndex;

 }

 

 StringBuffer sbuffer = new StringBuffer();

 

 exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

 exporter.setParameter(JRExporterParameter.OUTPUT_STRING_BUFFER, sbuffer);

 exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "ImageServlet?image=");

 exporter.setParameter(JRExporterParameter.PAGE_INDEX, new Integer(pageIndex));

 exporter.setParameter(JRHtmlExporterParameter.HTML_HEADER, "");

 exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML, "");

 exporter.setParameter(JRHtmlExporterParameter.HTML_FOOTER, "");

 try{

    exporter.exportReport();

    }catch(Exception e){

      e.printStackTrace();

    }

%>

這部分代碼用於將Servlet生成的JasperReport對象導出成HTML格式,導出所用的Servlet爲JasperReport自帶的ImageServlet。要特別注意的是我加了顏色部分的代碼,即一定要向Session變量中放入一個JasperPrint對象,其關鍵字爲“ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE”,這樣ImageServlet就可以獲取並自動導出報表了。

<html>

<head>

<title><%=pageTitle %></title>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<link rel="stylesheet" type="text/css" href="CSS/style.css">

</head>

<body>

<table class="titleBarT">

    <tr>

      <td>        &gt;&gt;

       <%=pageTitle %>

      </td>

    </tr>

</table>

 

<table width="98%" cellpadding="0" cellspacing="0" border="0" height="22">

<tr>

      <td>       

        <div class="menu"><a href="PdfServlet"><img src="Images/pdf.gif" border="0"></a></div>

        <div class="menu"><a href="RtfServlet"><img src="Images/word.gif" border="0"></a></div>

        <div class="menu"><a href="XlsServlet"><img src="Images/excel.gif" border="0"></a></div>

       

        <div class="menu"><a href="">&nbsp;&nbsp;</a></div>

        <div>

        <%

          if (pageIndex > 0)

          {

            %>

            <a href="本頁?pageIndex=0"><img src="Images/FirstPage.gif" border="0"></a>

            <a href="本頁?pageIndex=<%=pageIndex - 1%>"><img src="Images/PreviousPage.gif" ></a>

            <%

          }

          else

          {

            %>

            <img src="Images/FirstPage_disabled.gif" border="0"/>

            <img src="Images/PreviousPage_disabled.gif" border="0"/>

            <%

          }

 

          if (pageIndex < lastPageIndex)

          {

            %>

            <a href="本頁?pageIndex=<%=pageIndex + 1%>"><img src="Images/NextPage.gif" ></a>

            <a href="本頁?pageIndex=<%=lastPageIndex%>"><img src="Images/LastPage.gif" ></a>

            <%

          }

          else

          {

            %>

            <img src="Images/NextPage_disabled.gif" border="0">

            <img src="Images/LastPage_disabled.gif" border="0">

            <%

            }

            %>

            </div>

            </td>

        </tr>

</table>

這段代碼是將導出成HTML的報表進行分頁顯示。

<table width="98%" cellpadding="0" cellspacing="0" border="0">

<tr>

 <td width="50%">&nbsp;</td>

 <td align="left">

 <%=sbuffer.toString()%>

 </td>

 <td width="50%">&nbsp;</td>

</tr>

</table>

</body>

</html>

這裏導出報表內容的代碼。用Tomcat作爲WebContainer,顯示的結果如下:

利用這個框架我們可以輕易的實現自動分頁的功能並將報表導出成我們想要的格式:如PDF,Word,Excel的等。

限於篇幅,這裏我不能夠展現報表開發的每一個細節和過程,但是我已經儘量將Web報表開發的大概過程提取出來,並着重介紹數據源的設制,交叉表的設計,以及Web預覽框架這些相信每個做Web報表的人都會遇到的問題及其解決方案,在JasperReport的高端使用文檔相對匱乏的情況下,希望我的努力能給你帶來一點幫助。

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章