- iReport
- 安裝
- 下載,解壓iReport 0.4.0 (推薦src版本)
- 確認JDK是1.4以上
- 把JDK /lib下的tools.jar拷貝到{ireport_home}/lib目錄中
- 運行
- 對于下載的Binary版本,只能運行/bin/startup.bat
- 對于下載的Src版本,可以通過ant iReport運行(先安裝ant)
- 如果運行startup.bat,出現(xiàn)java.lang.NoSuchMethodError錯誤,一般是JDK版本太低。如果確認已安裝了1.4或以上,檢查path系統(tǒng)變量,看看有1.3的JRE是不是排在前面(比如安裝了Oracle的客戶端,往往有1.3的JRE),如果出現(xiàn)Class Not Found,檢查classpath。對于通過ant的方式運行,一般都沒什么問題,所以推薦下載src版本
- JasperReport 常見問題
- .jrxml vs .jasper
- 如果在運行時載入.jrxml, 那么每次調(diào)用還得編譯, 不如預先編譯成.jasper.不過預先編譯的jasper,必須用同樣版本的JasperReport載入,而且靈活性差些. 不過對于大部分報表,還是預先編譯成jasper方便
- 如果批量編譯jrxml
- 如何使用圖片?
- 很容易,用Image控件就可以了. 在Image Express里面可以用String來表示圖片的路徑, 或者用InputStream, File對象.不過不管用File還是String對象, 都不得不用絕對路徑, 這顯然很不靈活. 解決辦法是,穿入一個$P的參數(shù),表示圖片所在的目錄,然后用$P和文件名拼接出完整的絕對路徑. 更好的方法是用InputStream, 例如this.getClass().getResourceAsStream("logo.jpg") ,這時只要把圖片放在當前.jasper所在的目錄就可以了,不必考慮什么參數(shù),什么路徑了
- 顯示非數(shù)據(jù)庫字段變量
- 顯示如運行日期等,可以直接在Text Field里面輸入new java.util.Date(), 然后把Pattern設(shè)成如mm/dd/yyyy.
- 動態(tài)控制某些Field是否顯示
- 每個Static Text, Text Field甚至整個Band的屬性里面都有Print When Expression, 比如設(shè)成new Boolean(!$P{isDisplay}.equalsIgnoreCase("yes")), 那么只有當參數(shù)display的值為yes的時候才顯示
- 使用Sub Report, 如何使用相對路徑
- 見1.3, 和使用圖片類似, 用InputStream或者傳入?yún)?shù)
- Query里面如何使用參數(shù)
- $P!{xxx} 或者 $P{xxx} 后者只能用于類似PreparedStatement參數(shù)綁定, 而前者可替換Sql的任意部分. 在需要動態(tài)排序的時候, 前者特別有用. 比如 select a,b,c from t order by $P!{orderClause} 不管用$P還是$P!, SQL最終是以PreparedStatement方式執(zhí)行的, 不必太擔心性能問題 注意:參數(shù)是不能嵌套的, 比如$P{a} =‘‘$P‘‘ , $P=‘‘value‘‘, 不要指望$P{a}能被替換成‘‘value‘‘
- 如何使用圖表(Graph)
- JasperReport本身沒有圖表功能, 只有顯示Image的功能(見4.3). iReport里有個Graph向?qū)? 其實質(zhì)是通過jFreeChart生成Image. 更另外, 更直接的做法是放一個Image控件, Image Express Class設(shè)置成java.awt.Image, 在Image Expression里通過自定義的類返回java.awt.Image對象. 例如‘‘GraphProvider.getImage($P{REPORT_DATASOURCE},title, subtitle.....)‘‘. GraphProvider是自己的類, public static Image getImage(JRDataSource, ....)
- 如果顯示多個圖表
- 在一張報表上顯示一個圖表和顯示多個圖表是不同的. 假設(shè)Query是select name,price,qty from xxx, 第一張圖顯示name-price, 第二張圖顯示name-qty, 如果還是按3.8的方法, 第二張圖根本顯示不出來! 為什么 因為傳入的是JRDataSource, 而JRDataSource僅僅是對ResultSet的簡單封裝, 在第一張圖處理完后, 游標已經(jīng)到了eof位置了, 在開始處理第二張圖的時候,就必然拋出游標耗盡的異常! 怎么辦 自己寫個JRDataSourceAdapter, 把JRDataSource對象里面的值預先保存到一個Collection (相當于一個Offline的數(shù)據(jù)集), 然后把這個Collection傳個getImage方法. 具體是, 建一個Variable mydate, 類型是java.util.Map, Calculation Type- System, Initial Value Expression是JRDataSourceAdapter.JRDataSource2Map($P{REPORT_DATA_SOURCE},new String[]{"NAME","PRICE","QTY"},new Class[]{java.lang.String.class,java.lang.Double.class,java.lang.Double.class}), JRDataSource2Map是自己寫的一個Adapter. 然后在Image的Expression里面換成如‘‘GraphProvider.getImage(mydata,title, other params...), 當然得修改getImage方法
- Export到Excel的問題
- 如何去掉報表頭等
- 直接把不需要的Band刪除(把其高度設(shè)為0). 如果僅僅是export到Excel的時候不需要報表頭, 而輸出到PDF等仍然需要保留, 那么使用print when expression, 見4.4
- 如果讓Excel看起來整齊
- 不要有空白地方! 首先把所有的Field設(shè)成一樣高, 對齊! 把所在Band的高度也設(shè)成和Field一樣高, 讓Field正好放入Band. 然后調(diào)整Field的寬度, 讓每個Field都相鄰,沒有空隙. 最后,記得設(shè)置參數(shù): exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
Boolean.TRUE);
- 如何保留GridLine
- 首先, 設(shè)置參數(shù)exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE); 然后,把每個Field或者Static Text框的‘‘Transparent‘‘屬性都勾上
- 如何使字段名只顯示一次
- 如果把字段名放在ColumnHead區(qū)域, 那么輸出到Excel, 會每個Page都顯示一遍. 在設(shè)計Report時候, 一般會設(shè)定Page大小. 然而對于Excel, 這個Page設(shè)定仍然存在,而且往往很討厭, 因為在Excel里, 通常希望得到連續(xù)的數(shù)據(jù), 然而Jasper仍然會‘‘自作多情‘‘進行分頁. 比如說, 設(shè)計JasperReport的時候, 設(shè)定page size為Letter, Portrait, 那么輸出到Excel的時候每隔大約30行(具體取決于Field的高度), page header, column header, column foot, page foot 會被重復一次, 而且還附帶一個高度為0的Excel Row, 表示Page Break的地方. 把字段名放在title band里, 可以解決字段名重復的問題, 當然page header也不要顯示了. 如果需要, 可以把title band的print when expression設(shè)成只有輸出Excel的時候才顯示
- 為什么Excel里面的數(shù)據(jù)是從第二行,第B列開始顯示的
- 因為第一行和第A列分別是用來表示page top margin 和 page left margin的. 對于Excel來說, 純粹多余. 解決方法是把page margin 設(shè)成0. 不過如果這個report還需要以PDF等顯示, 那么設(shè)成0就不好看了. 最好能動態(tài)的改變page margin. 當然,這個改變只能在外部(調(diào)用Report的地方) 進行, 在設(shè)計Report的時候是無能為力的. 不幸的是, JasperReport類居然沒有setMargin的方法,只有g(shù)etter. 折中的方法只能是reflect了. 代碼示意如下: //use reflect to set the private field of JRBaseReport
java.lang.reflect.Field margin = JRBaseReport.class.getDeclaredField(
"leftMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0); margin = JRBaseReport.class.getDeclaredField("topMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0); margin = JRBaseReport.class.getDeclaredField("bottomMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0);
- 如何去掉Excel中隱藏的行
- 如前說述, 由于page break的關(guān)系, Excel中每隔幾十行,就有一個高度為0的row, 即使把page botom margin設(shè)為0, 把page footer去掉都沒有辦法. 唯一的解決辦法是把page height設(shè)為很大. 同5.5一樣, 不得不使用reflect:
- java.lang.reflect.Field pageHeight = JRBaseReport.class.getDeclaredField(
"pageHeight");
pageHeight.setAccessible(true);
pageHeight.setInt(myRpt, Integer.MAX_VALUE);
- 文檔
- 哪里有文檔
- JasperReport有份Ultimate Guide, 不過不是免費的, 和jFreeChart一個德行. 不過網(wǎng)上有流傳, 寫的還可以, 60多頁, 不過也沒詳細到哪里去. 如果下載源代碼版, 那么看看自帶的Demo也不錯. SF的論壇也是問問題的最好地方
- 源代碼 僅供參考(reportProvider--一個Servlet, GraphProider, JRDataAdapter都是普通類)
/**
*
Title: ReportProviderServlet
*
Description: Servlet to generate Jasper reports
*
Copyright: Copyright (c) 2004
*
Company: *****
* @author zephyr
* @version 1.0
*/
package xyz;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.base.*;
import net.sf.jasperreports.engine.export.*;
import net.sf.jasperreports.engine.util.*;
import org.apache.log4j.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ReportProviderServlet extends HttpServlet
{
private static Logger log = LogManager.getLogger(ReportProviderServlet.class);
//Initialize: Setup DataSourceManager
public void init() throws javax.servlet.ServletException
{
String prefix = getServletContext().getRealPath("/");
String file = getInitParameter("data-source-file");
DataSourceManager.configure(prefix + file);
log.info("initialized successfully!");
}
//Process the HTTP request
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String reportClass = request.getParameter("reportClass");
log.debug("Running Report:" + reportClass);
boolean isExcelFormat = false;
if (reportClass == null)
{
throw new IllegalArgumentException("Jasper Class Unspecified");
}
String reportFormat = request.getParameter("reportFormat");
if (reportFormat == null)
{
reportFormat = "jasperPrint";
}
try
{
JasperReport myRpt = JasperManager.loadReport(this.getClass()
.getResourceAsStream("/jasperReports/" +
reportClass + ".jasper"));
//set ReprintHeaderOnEachPage=false for Excel Format
isExcelFormat = reportFormat.equalsIgnoreCase("excel");
if (isExcelFormat)
{
//use reflect to set the private field of JRBaseReport
//No margin for excel format, max pageHeight
java.lang.reflect.Field margin = JRBaseReport.class.getDeclaredField(
"leftMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0);
margin = JRBaseReport.class.getDeclaredField("topMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0);
margin = JRBaseReport.class.getDeclaredField("bottomMargin");
margin.setAccessible(true);
margin.setInt(myRpt, 0);
java.lang.reflect.Field pageHeight = JRBaseReport.class.getDeclaredField(
"pageHeight");
pageHeight.setAccessible(true);
pageHeight.setInt(myRpt, Integer.MAX_VALUE);
//Don‘t print group header on each page
if (null != myRpt.getGroups())
{
for (int i = 0; i < myRpt.getGroups().length; i++)
{
myRpt.getGroups()[i].setReprintHeaderOnEachPage(false);
}
}
}
Map params = new HashMap(10);
Enumeration enu = request.getParameterNames();
while (enu.hasMoreElements())
{
String key = (String) enu.nextElement();
params.put(key,
request.getParameter(key).toUpperCase().replaceAll("‘", "‘‘"));
log.debug(key + "=" + request.getParameter(key));
}
log.debug("Before Filling");
OutputStream httpOut = response.getOutputStream();
Connection conn = DataSourceManager.getConnection(request.getSession());
JasperPrint rptPnt = JasperManager.fillReport(myRpt, params, conn);
conn.close();
if (reportFormat.equalsIgnoreCase("jasperPrint"))
{
response.setContentType("application/octet-stream");
JRSaver.saveObject(rptPnt, httpOut);
}
else if (reportFormat.equalsIgnoreCase("pdf"))
{
response.setContentType("application/pdf");
response.setHeader("Content-Disposition",
"attachment;filename=\"" + reportClass + ".PDF\"");
JasperManager.printReportToPdfStream(rptPnt, httpOut);
}
else if (reportFormat.equalsIgnoreCase("excel"))
{
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment;filename=\"" + reportClass + ".XLS\"");
JRXlsExporter exporter = new JRXlsExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, rptPnt);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, httpOut);
exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
Boolean.TRUE);
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,
Boolean.FALSE);
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
Boolean.FALSE);
exporter.exportReport();
}
else if (reportFormat.equalsIgnoreCase("html"))
{
JRHtmlExporter exporter = new JRHtmlExporter();
response.setContentType("text/html");
Map imagesMap = new HashMap();
request.getSession().setAttribute("IMAGES_MAP", imagesMap);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP,
imagesMap);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,
"image.jsp image=");
exporter.setParameter(JRExporterParameter.JASPER_PRINT, rptPnt);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, httpOut);
exporter.exportReport();
}
log.debug("Report Exported");
}
catch (Exception ex)
{
log.error("Error Occured", ex);
}
}
}
/**
*
Title: JRDataSourceAdapter
*
Description: Converting JRDataSource to Mapped ArrayList
*
Copyright: Copyright (c) 2004
*
Company: *****
* @author zephyr
* @version 1.0
*/
package xyz;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.design.*;
import java.util.*;
public class JRDataSourceAdapter
{
public static Map JRDataSource2Map(JRDataSource dataSource, String[] fieldNames,
Class[] fieldClasses) throws JRException
{
HashMap result;
if (fieldNames.length != fieldClasses.length)
{
throw new JRException("Number of Field Name & Class unmatch");
}
JRDesignField[] fields = new JRDesignField[fieldNames.length];
result = new HashMap(4);
for (int i = 0; i < fieldNames.length; i++)
{
fields[i] = new JRDesignField();
fields[i].setName(fieldNames[i]);
fields[i].setValueClass(fieldClasses[i]);
result.put(fieldNames[i], new ArrayList());
}
do
{
for (int i = 0; i < fields.length; i++)
{
Object value = dataSource.getFieldValue(fields[i]);
((ArrayList) result.get(fields[i].getName())).add(value);
}
}
while (dataSource.next());
return result;
}
}
/**
*
Title: GraphProvider
*
Description: Generate JFreeChart Image
*
Copyright: Copyright (c) 2004
*
Company: ****
* @author zephyr
* @version 1.0
*/
package xyz;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.design.*;
import net.sf.jasperreports.engine.export.*;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.data.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
public class GraphProvider
{
public static Image getImage(Map dataSource, String fieldNameX, String fieldNameY,
String chartName, String titleX, String titleY, boolean isBarChart, int imageWidth,
int imageHeight) throws JRException
{
JRDesignField fieldX = new JRDesignField();
fieldX.setName(fieldNameX);
fieldX.setValueClass(java.lang.String.class);
JRDesignField fieldY = new JRDesignField();
fieldY.setName(fieldNameY);
fieldY.setValueClass(java.lang.Double.class);
ArrayList periods = (ArrayList) dataSource.get(fieldNameX);
ArrayList values = (ArrayList) dataSource.get(fieldNameY);
DefaultCategoryDataset categoryDs = new DefaultCategoryDataset();
for (int i = 0; i < values.size(); i++)
{
Object obj = values.get(i);
double dataValue = 0;
if (obj != null)
{
dataValue = ((Double) obj).doubleValue();
}
categoryDs.addValue(dataValue, null, (String) periods.get(i));
}
JFreeChart c = null;
if (isBarChart)
{
c = ChartFactory.createBarChart(chartName, titleX, titleY, categoryDs,
PlotOrientation.VERTICAL, false, false, false);
}
else
{
c = ChartFactory.createLineChart(chartName, titleX, titleY, categoryDs,
PlotOrientation.VERTICAL, false, false, false);
}
c.getTitle().setFont(new Font("Arial", Font.BOLD, 16));
NumberAxis axis = (NumberAxis) c.getCategoryPlot().getRangeAxis();
axis.setAutoRange(true);
TickUnitSource tickUnits = NumberAxis.createIntegerTickUnits();
axis.setStandardTickUnits(tickUnits);
return (c.createBufferedImage(imageWidth, imageHeight));
}
}
posted on 2004-11-08 05:55 zephyr
- 作者: e-silver 2005年01月21日, 星期五 10:15