<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    海鷗航際

    JAVA站
    posts - 11, comments - 53, trackbacks - 1, articles - 102

    JasperReport經驗談

    Posted on 2005-01-07 18:26 海天一鷗 閱讀(2984) 評論(4)  編輯  收藏 所屬分類: 報表專題
    JasperReport和iReport是不錯的Java報表工具. 在實際項目中, 本人用它們開發了20個Report, 涉及SubReport, Image, Graph, 積累了一些經驗. 尤其是關于Export到Excel方面, 文檔上也很少提及, 純粹是摸索出來的, 有的問題還是通過讀源代碼才解決的. 此貼并非入門教程, 差不多算是筆記吧, 以問答形式記錄. 

    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,出現java.lang.NoSuchMethodError錯誤,一般是JDK版本太低。如果確認已安裝了1.4或以上,檢查path系統變量,看看有1.3的JRE是不是排在前面(比如安裝了Oracle的客戶端,往往有1.3的JRE),如果出現Class Not Found,檢查classpath。對于通過ant的方式運行,一般都沒什么問題,所以推薦下載src版本
    JasperReport 常見問題 
    .jrxml vs .jasper 
    如果在運行時載入.jrxml, 那么每次調用還得編譯, 不如預先編譯成.jasper.不過預先編譯的jasper,必須用同樣版本的JasperReport載入,而且靈活性差些. 不過對于大部分報表,還是預先編譯成jasper方便
    如果批量編譯jrxml 
    用Ant很容易解決

     

    ..... 

      


    如何使用圖片? 
    很容易,用Image控件就可以了. 在Image Express里面可以用String來表示圖片的路徑, 或者用InputStream, File對象.不過不管用File還是String對象, 都不得不用絕對路徑, 這顯然很不靈活. 解決辦法是,穿入一個$P的參數,表示圖片所在的目錄,然后用$P和文件名拼接出完整的絕對路徑. 更好的方法是用InputStream, 例如this.getClass().getResourceAsStream("logo.jpg") ,這時只要把圖片放在當前.jasper所在的目錄就可以了,不必考慮什么參數,什么路徑了
    顯示非數據庫字段變量 
    顯示如運行日期等,可以直接在Text Field里面輸入new java.util.Date(), 然后把Pattern設成如mm/dd/yyyy. 
    動態控制某些Field是否顯示 
    每個Static Text, Text Field甚至整個Band的屬性里面都有Print When Expression, 比如設成new Boolean(!$P{isDisplay}.equalsIgnoreCase("yes")), 那么只有當參數display的值為yes的時候才顯示
    使用Sub Report, 如何使用相對路徑 
    見1.3, 和使用圖片類似, 用InputStream或者傳入參數
    Query里面如何使用參數 
    $P!{xxx} 或者 $P{xxx} 后者只能用于類似PreparedStatement參數綁定, 而前者可替換Sql的任意部分. 在需要動態排序的時候, 前者特別有用. 比如 select a,b,c from t order by $P!{orderClause}   不管用$P還是$P!, SQL最終是以PreparedStatement方式執行的, 不必太擔心性能問題   注意:參數是不能嵌套的, 比如$P{a} =''$P{b}''   , $P{b}=''value'', 不要指望$P{a}能被替換成''value''
    如何使用圖表(Graph) 
    JasperReport本身沒有圖表功能, 只有顯示Image的功能(見4.3). iReport里有個Graph向導, 其實質是通過jFreeChart生成Image. 更另外, 更直接的做法是放一個Image控件, Image Express Class設置成java.awt.Image, 在Image Expression里通過自定義的類返回java.awt.Image對象. 例如''GraphProvider.getImage($P{REPORT_DATASOURCE},title, subtitle.....)''.  GraphProvider是自己的類, public static Image getImage(JRDataSource, ....)
    如果顯示多個圖表 
    在一張報表上顯示一個圖表和顯示多個圖表是不同的. 假設Query是select name,price,qty from xxx, 第一張圖顯示name-price, 第二張圖顯示name-qty, 如果還是按3.8的方法, 第二張圖根本顯示不出來! 為什么? 因為傳入的是JRDataSource, 而JRDataSource僅僅是對ResultSet的簡單封裝, 在第一張圖處理完后, 游標已經到了eof位置了, 在開始處理第二張圖的時候,就必然拋出游標耗盡的異常! 怎么辦?? 自己寫個JRDataSourceAdapter, 把JRDataSource對象里面的值預先保存到一個Collection (相當于一個Offline的數據集), 然后把這個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刪除(把其高度設為0). 如果僅僅是export到Excel的時候不需要報表頭, 而輸出到PDF等仍然需要保留, 那么使用print when expression, 見4.4
    如果讓Excel看起來整齊 
    不要有空白地方! 首先把所有的Field設成一樣高, 對齊! 把所在Band的高度也設成和Field一樣高, 讓Field正好放入Band. 然后調整Field的寬度, 讓每個Field都相鄰,沒有空隙. 最后,記得設置參數: exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
                        Boolean.TRUE);

    如何保留GridLine 
    首先, 設置參數exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE); 然后,把每個Field或者Static Text框的''Transparent''屬性都勾上
    如何使字段名只顯示一次 
    如果把字段名放在ColumnHead區域, 那么輸出到Excel, 會每個Page都顯示一遍. 在設計Report時候, 一般會設定Page大小. 然而對于Excel, 這個Page設定仍然存在,而且往往很討厭, 因為在Excel里, 通常希望得到連續的數據, 然而Jasper仍然會''自作多情''進行分頁. 比如說, 設計JasperReport的時候, 設定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設成只有輸出Excel的時候才顯示
    為什么Excel里面的數據是從第二行,第B列開始顯示的? 
    因為第一行和第A列分別是用來表示page top margin 和 page left margin的. 對于Excel來說, 純粹多余. 解決方法是把page margin 設成0. 不過如果這個report還需要以PDF等顯示, 那么設成0就不好看了. 最好能動態的改變page margin. 當然,這個改變只能在外部(調用Report的地方) 進行, 在設計Report的時候是無能為力的. 不幸的是, JasperReport類居然沒有setMargin的方法,只有getter. 折中的方法只能是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的關系, Excel中每隔幾十行,就有一個高度為0的row, 即使把page botom margin設為0, 把page footer去掉都沒有辦法. 唯一的解決辦法是把page height設為很大. 同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一個德行. 不過網上有流傳, 寫的還可以, 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));

           }
    }

    Feedback

    # re: JasperReport經驗談  回復  更多評論   

    2006-03-20 17:51 by xiangyu
    請問您是怎么生成csv格式的文件的,我這邊每次生成csv格式的報表,里面的中文就會顯示???,奇怪了,謝謝您能給幫忙看看

    # re: JasperReport經驗談  回復  更多評論   

    2006-08-23 16:12 by 深圳深呼吸
    回:“請問您是怎么生成csv格式的文件的,。。。”

    缺少中文包的緣故。
    1,下載iTextAsian.jar包,放在lib下。

    2,在代碼中加入以下語句:
    exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK");

    3,設計時,在IReport中,設置字段控件的字體為宋體.


    # re: JasperReport經驗談  回復  更多評論   

    2006-08-23 16:15 by 深圳深呼吸
    不同格式報表文件的輸出問題也困擾我好久,終于解決。爽啊!!!!

    # re: JasperReport經驗談  回復  更多評論   

    2006-08-24 11:33 by 王鴻雁
    請教一個問題,我做的是日文的報表 在生成CSV格式的報表時,我沒有拿到程序里看,而是直接運行后看的 怎么日文字都顯示為?????以前PDF時我設PDF
    FONTNAME 和PDF Enconding 就能正確顯示日文字體 為什么 在CSV時就不能顯示了呢?

    比較急 勞駕您了!
    主站蜘蛛池模板: 亚洲高清有码中文字| 亚洲中文字幕无码久久2017| 无人影院手机版在线观看免费| 欧美好看的免费电影在线观看| 日本不卡免费新一二三区| 免费一级成人毛片| 亚洲av无码不卡| 亚洲最大福利视频| 亚洲精品国产日韩无码AV永久免费网| a在线视频免费观看| 久久久久久久91精品免费观看| 免费在线一级毛片| 美女羞羞视频免费网站| 久久国产免费观看精品| 暖暖免费高清日本中文| 亚洲.国产.欧美一区二区三区| 久久久久成人片免费观看蜜芽| 国产男女猛烈无遮挡免费网站| 亚洲av无码国产精品色午夜字幕 | 亚洲色偷偷av男人的天堂| 亚洲乱人伦中文字幕无码| 久久成人免费电影| 久久久久久久亚洲精品| 亚洲成av人片在线天堂无| 97性无码区免费| 亚洲动漫精品无码av天堂| 国产亚洲综合精品一区二区三区| 69堂人成无码免费视频果冻传媒 | 久久一区二区三区免费播放 | 国产无遮挡无码视频免费软件| 亚洲欧洲日韩不卡| 国产男女爽爽爽免费视频| 青青青青青青久久久免费观看| 久久久久久久亚洲Av无码| 在线观看国产一区亚洲bd| h在线观看视频免费网站| 久久精品九九亚洲精品天堂 | 日本一道在线日本一道高清不卡免费| 成年大片免费视频播放一级| 四虎成人免费影院网址| 亚洲日本久久一区二区va|