ireport?

ireport 5.1.0初級教程之柱形圖的開發實現方法,本文介紹ireport中柱形圖的具體開發實現方法。

工具/原料

ireport

方法/步驟

下面以柱狀圖(bar3DChart)為例,詳細說明圖表的開發過程。

1. 確定數據源類型和其中參數

我選擇的是JRDataSourceProvider類型的數據源。我也試過JDBC數據源,沒問題,只是我的應用需求是要根據用戶的選擇展示,所以用JRDataSourceProvider更靈活和方便些,不必每次選擇都去查數據庫。

用iReport開發圖表,在定義圖表屬性中的數據時,需要添加category series,一個category series中包括series expression、category expression、Value expression、label expression等。當我開始看到這些東西時,真的時搞不明白是什麼意思。試來試去,基本上弄清楚了,關鍵是前3個,Value expression很明白是指數據的值,category expression代表分組,series expression則代表分組中的不同指標。舉例說明:我公司的一款數據產品銷往全國各地的不同電信運營商,圖表要按地區展示各運營商的產品套數,那麼這裡的地區就是category expression,運營商就是series expression,Value expression就是產品的套數了。

於是圖表數據源的參數有3個就夠了,即category、series和value。其他一些圖表可能情況略有不同,如餅圖(piechart),xylinechart等,如要做的通用些,可再加入些其他參數。我這裡有3個足夠了。

2. 開發數據源類

首先定義一個用戶圖表的bean:ChartDataBean,包括3個成員變量及相應的getter和setter。3個成員變量的名稱如前所述,無論圖表要顯示什麼樣的數據,都按這3個變量進行對應並賦值即可。這樣的名稱也與iReport中圖表的數據相對應,不至於搞錯。如下:

public class ChartDataBean {

String serieas;

String category;

float value;

public String getCategory() {

return category;

}

public void setCategory(String category) {

this.category = category;

}

public String getSerieas() {

return serieas;

}

public void setSerieas(String serieas) {

this.serieas = serieas;

}

public float getValue() {

return value;

}

public void setValue(float value) {

this.value = value;

}

}

然後定義一個ChartDataSource類,該類應用了JRDataSource接口。該類用於在生成圖表時將數據傳入。如下:

public class ChartDataSource implements JRDataSource {

private int m_nldx;

private Vector v;

public ChartDataSource(){

this(new Vector ());

}

public ChartDataSource(Vector v){

this.m_nldx=-1;

this.v=v;

}

public Object getFieldValue(JRField arg0) throws JRException {

Object o = null;

String sName = arg0.getName();

ChartDataBean resultset = v.elementAt(m_nldx);

if(resultset == null)

return null;

if(sName.equals("serieas"))

o =resultset.getSerieas();

else if(sName.equals("category"))

o = resultset.getCategory();

else if(sName.equals("value"))

o = resultset.getValue();

return o;

}

public boolean next() throws JRException {

// TODO Auto-generated method stub

m_nldx ++;

return (m_nldx < v.size());

}

}

最後定義一個ChartDataSourceProvider類,該類繼承類JRAbstractBeanDataSourceProvider,如下:

public class ChartDataSourceProvider extends JRAbstractBeanDataSourceProvider {

public ChartDataSourceProvider(Class arg0) {

super(arg0);

// TODO Auto-generated constructor stub

}

public ChartDataSourceProvider() {

super(ChartDataBean.class);

// TODO Auto-generated constructor stub

}

public JRDataSource create(JasperReport arg0) throws JRException {

// TODO Auto-generated method stub

ChartDataSource ds=new ChartDataSource(getQueryResult());

return ds;

}

public void dispose(JRDataSource arg0) throws JRException {

// TODO Auto-generated method stub

}

public static Vector getQueryResult(){

Vector vector = new Vector ();

ChartDataBean result = new ChartDataBean();

result.setCategory("北京");

result.setSerieas("聯通");

result.setValue(1500);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("北京");

result.setSerieas("電信");

result.setValue(1600);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("北京");

result.setSerieas("移動");

result.setValue(2000);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("上海");

result.setSerieas("聯通");

result.setValue(1900);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("上海");

result.setSerieas("電信");

result.setValue(600);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("上海");

result.setSerieas("移動");

result.setValue(1200);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("天津");

result.setSerieas("聯通");

result.setValue(900);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("天津");

result.setSerieas("電信");

result.setValue(800);

vector.addElement(result);

result = new ChartDataBean();

result.setCategory("天津");

result.setSerieas("移動");

result.setValue(1400);

vector.addElement(result);

return vector;

}

}

以上getQueryResult()方法中加入了一些數據用於在iReport開發中測試預覽用。實際上我認為,ChartDataSourceProvider類只是為iReport設計時從數據源中提取field信息而用的,在報表生成過程中並不會用到該類。

3. 圖表設計

在前面工作的基礎上,我們就可以利用iReport進行圖表開發了。

首先新建一個報表文件,文件名最好能反應報表的內容,如bar3DChart;

然後定義報表數據源,在定義數據源前要先設置class path,通過菜單option->classpath,在classpath對話框中點擊Add Folder,將你前面開發數據源類的java工程中放置編譯後的.class文件的目錄添加到classpath列表中,如我的是web工程,class的目錄是D:\Myprj\prj1\WebRoot\WEB-INF\classes;

添加一個新數據源,通過菜單data->connection/datasource,打開connection/datasource,點擊new按鈕,在connection properties對話框中選擇JRDataSourceProvider,點擊next按鈕,在新打開的對話框中有兩個輸入項:name和jasperreports datasource provider class。Name可任意輸入,如:ChartDataSourceProvider;jasperreports datasource provider class則要輸入你前面定義的ChartDataSourceProvider類,一定要輸入全路徑類名,和你在java工程中的包名類名一致:如com.project1.report.chart. ChartDataSourceProvider,輸入完成後可點擊test按鈕測試一下,如彈出Connection test successful!對話框則表明數據源類添加成功,否則要檢查一下classpath是否正確設置。

注:這裡有個情況說明一下,如果ChartDataSourceProvider類是在iReport打開後編譯的,那麼即使classpath設置正確,類名輸入也無問題,還是測試失敗。這時就必須將iReport關閉後再打開,測試才會成功,數據源才可用,我也不知道這是為什麼。這個問題在我剛開始用iReport時困擾了我一天,我新加了一個數據源,但怎麼都連不通,反覆檢查各種設置、路徑、名稱、大小寫等,就是不行,實在是莫名其妙呀!第二天上班,我開機後再試試,我什麼都沒改動,還是昨天那些東西,竟然連接成功了!我就琢磨了,是不是跟機器關開了一次有關係?機器一天都是開著的,下班才關,什麼都沒動,再開機問題就解決了?可也不能那麼邪乎吧,什麼東西做得非要重啟機器?於是經過幾次試驗我就發現:數據源類在重新編譯後,必須重新啟動一次iReport。

注意要將新加的數據源設為默認。

讀取Field,菜單file->report query打開report query對話框,在DataSource Provider屬性頁中點擊Get fields from data source按鈕,下面的列表裡會出現field的列表,有serieas、category、value和class,多了個class,不去管他;點擊ok;

下面設計圖表了。

在報表title或summary band中加入一個圖表工具(chart tool),在彈出的圖表選擇對話框中選擇bar 3D,並點擊ok確定。將band和圖表調整至合適的大小;

雙擊bar 3D圖表,打開bar3DChart對話框,在chart屬性頁中將Evaluation Time設為report(如選其他選項會出現我不想要的效果,我還沒去仔細琢磨),然後點擊Edit chart properties按鈕,打開chart properties對話框;

在chart properties對話框選擇Chart Data屬性頁,在Chart Data屬性頁中選擇Details屬性頁;

點擊Add按鈕添加一個category series,在彈出的對話框的data屬性頁中有4個需要定義的表達式(expression),我們定義前3個。如Series Expression,可以通過點擊右邊的按鈕打開表達式編輯器,在編輯器下邊的objects and expression屬性頁中左邊第一個框中選Field,然後在第二個框中雙擊seriesas,在上邊的文本編輯區中就會出現表達式:$F{serieas}。點擊應用按鈕(?我的iReport中顯示的是套用,我估計英文應該是apply,按咱們的習慣還是較應用吧)。其他兩個表達式如法炮製,結果應該是這樣的:series expression:$F{serieas}、category expression:$F{category}、Value expression:$F{value}、label expression:空白;點擊ok;然後關閉chart properties對話框。

這時可以通過菜單build->execute report(Using active conn.)來預覽圖表了。

至此,在iReport中的圖表設計工作完成。圖表在web工程中的部署、載入、展現等與報表的方法是一樣的。

4. 圖表部署

我用的web服務器是tomcat5,假定web工程部署在webapps/myproject/中,在webapps/myproject/下新建一個目錄reports用來放置報表文件。將前面iReport編譯生成的bar3DChart.jasper文件放在該目錄下。.jasper文件默認生成在iReport的安裝目錄下。

部署和生成報表所需的幾個jar包也要放到myproject/WEB-INF/lib下,這些jar包有:jasperreports-2.0.4、iReport、jfreechart-1.0.9、jcommon-1.0.12等。版本可能不太一樣。注意的是,iReport和jasperreport的圖表功能實際上是用了jfreechart工具來實現的,所以一定要將jfreechart的jar包導入到工程中。

5. 圖表的生成和展示

開發servlet。我這裡以servlet方式生成圖表。Servlet如下:

public class ReportServlet extends BaseHttpServlet {

/** * */

public void service(

HttpServletRequest request,

HttpServletResponse response

) throws IOException, ServletException

{

PrintWriter out = response.getWriter();

try

{

HttpSession session = request.getSession(false);

//獲得圖表數據。圖表數據是在其他地方查表得到並生成Vector 的數據列,然後保存在session中傳遞到servlet。

Vector dataList = (Vector) session.getAttribute ("storedDataList");

//載入圖表,一定要指對路徑和文件名

File reportFile = new File(context.getRealPath ("/reports/bar3DChart.jasper"));

if (!reportFile.exists())

throw new JRRuntimeException("File WebappReport.jasper not found. The report design must be compiled first.");

JasperReport jasperReport = (JasperReport)JRLoader.loadObject(reportFile.getPath());

//圖表的參數,及ireport中的定義變量,如報表標題、圖表日期等,也是於他處設置保存在session中

Map parameters =(Map)session.getAttribute

("jasper_parameters"); //這裡導入圖表數據,並生成報表

JasperPrint jasperPrint =

JasperFillManager.fillReport(

jasperReport,

parameters,

new ChartDataSource(dataList)

);

//JasperPrint jasperPrint =(JasperPrint)session.getAttribute

//(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE);

//注:以上的步驟實際上都可以在他處完成,最後將jasperPrint保存到session中,這樣在servlet中只需從session中取得jasperPrint即可(如上面註釋掉的這條語句),可以將servlet做成通用的類來展示輸出所有的報表。

//輸出html 用JRHtmlExporter

JRHtmlExporter exporter = new JRHtmlExporter();

Map imagesMap = new HashMap();

response.setContentType("text/html");

request.getSession().setAttribute("IMAGES_MAP", imagesMap); request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);

exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap); exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image="); exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML, "");

exporter.exportReport();

}

catch (JRException e)

{

out.println("");

out.println("");

out.println("JasperReports - Web Application Sample");

out.println(" ");

out.println("");

out.println("");

out.println("JasperReports encountered this error :");

out.println("

");

e.printStackTrace();

out.println("

");

out.println("");

out.println("");

}

}

6. 添加servlet映射

在web.xml中添加如下設置:

ReportServlet

com.project1.report.ReportServlet

ImageServlet net.sf.jasperreports.j2ee.servlets.ImageServlet

ImageServlet

/image

ReportServlet

/ReportServlet

ImageServlet幹嘛用的?注意到ReportServlet的代碼中有這麼一句:

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

ImageServlet就是為這句而來的,html方式輸出報表時要用到的小圖標就在這裡,如果沒有ImageServlet或設置不對,你可以看看輸出的報表是什麼樣的,盡是紅叉叉!

同為比較常用的java報表生成工具,FineReport對柱狀圖的解決方案和實現方法與ireport有所不同,具體實現思路和步驟如下,供ireport使用者借鑑:

在FineReport中,圖表有兩種插入方式:作為單元格元素插入或者作為懸浮元素插入,以下是用兩種思路實現柱形圖的過程:

單元格圖表

1. 描述

如下圖,每一組都跟隨有一個統計圖直觀的查看該組的數據情況,可以使用單元格圖表實現這樣的可擴展的效果效果。

ireport 5.1.0初級教程之柱形圖的開發實現方法

單元格圖表的優勢

圖表作為單元格元素插入到報表中,就可以通過單元格的父子關係,跟隨主格的擴展自動生成相應的圖表,而不需要對每組數據單獨製作對應的圖表。

2. 示例

以下我們詳細介紹上圖中跟隨擴展的圖表製作步驟。

2.1 數據準備

打開報表%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Primary\GroupReport\Group.cpt。在地區銷量分組報表的基礎上添加圖表,實現每個地區有一張銷量統計圖。

這邊擴展出來的每張圖表只顯示當前地區的數據,因此不能直接將數據集作為圖表數據來源(數據集是取出銷量表中的所有數據),只能使用報表中單元格數據。

注:單元格元素圖表與單元格數據源圖表不是一個概念,單元格元素圖表是指圖表插入方式為單元格,可跟隨單元格擴展,擁有單元格的一些屬性,而單元格數據源圖表是指圖表綁定數據的時候綁定的是單元格數據,而非數據集數據。

2.2 插入單元格圖表

合併第二行後面的一片區域,右擊單元格單元格元素>插入圖表>柱形圖,點擊確定。

ireport 5.1.0初級教程之柱形圖的開發實現方法

2.3 設置圖表數據

設置圖表數據如下圖,每個銷售員的銷量圖,點擊完成:

ireport 5.1.0初級教程之柱形圖的開發實現方法

2.4 設置圖表父格

由父子格概念可知,圖表所在單元格默認以銷售員數據列為父格,擴展出的每個銷售員都會對應有一張圖表;

而這裡我們只需要擴展出來的每個地區跟隨一張圖表,因此需要設置圖表所在單元格為地區單元格。

2.5 保存並預覽

保存模板並分頁預覽,便可以看到上圖效果了

懸浮元素圖表

圖表還可以作為懸浮元素插入到報表中。

懸浮圖表的優勢

作為懸浮元素插入到報表中的圖表,沒有單元格的限制,可以圖表位置固定,也可以隨意拖放到任何位置,大小設置後不會改變,沒有父格,不會因為其他單元格的擴展而受影響。

懸浮圖表的定義與單元格圖表是基本上完全相同的,只是在第一步插入圖表的時候,選擇摻入懸浮元素即可,這裡就不重複介紹了,可以看到,可以隨意拖動圖表及改變圖表大小,操作方便,如下圖:

ireport 5.1.0初級教程之柱形圖的開發實現方法

注:懸浮元素做出來的圖表不同於上一節單元格圖表,能根據父格進行數據過濾,進行擴展從而根據地區顯示對應的柱形圖,懸浮元素沒有父格概念一說,故,其不能通過設置父格來進行數據過濾,進行擴展,添加了幾個懸浮元素圖表,最後在web端查看的時候只會顯示幾個圖表。

相關問題答案