<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 海天一鷗 閱讀(2975) 評論(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時就不能顯示了呢?

    比較急 勞駕您了!
    主站蜘蛛池模板: 亚洲AV永久无码天堂影院| 亚洲色婷婷综合开心网| 亚洲午夜免费视频| 久久青草免费91观看| 最近2019中文免费字幕| 亚洲高清免费在线观看| 亚洲三级在线免费观看| 亚洲欧洲精品一区二区三区| 天天影院成人免费观看| 一本色道久久88—综合亚洲精品| 在线免费视频一区二区| 亚洲精品GV天堂无码男同| 免费a级毛片18以上观看精品| 黄色毛片免费网站| 久久精品国产亚洲综合色| 好久久免费视频高清| 亚洲视频免费一区| 妞干网免费观看视频| 深夜a级毛片免费无码| 亚洲色中文字幕无码AV| 3344免费播放观看视频| 亚洲精品无码日韩国产不卡av| 国产午夜无码视频免费网站| 和老外3p爽粗大免费视频| 五月天网站亚洲小说| 最近中文字幕无吗免费高清 | 亚洲欧洲国产日韩精品| 91九色老熟女免费资源站 | 免费大片av手机看片高清| 亚洲精品午夜无码专区| 69堂人成无码免费视频果冻传媒 | 亚洲av永久无码精品漫画| 99蜜桃在线观看免费视频网站| 亚洲中文字幕乱码AV波多JI| 亚洲国产成人久久精品99| 无码专区AAAAAA免费视频| 亚洲丰满熟女一区二区哦| 好看的亚洲黄色经典| 女人毛片a级大学毛片免费| 国产黄色片免费看| 国产成人精品日本亚洲11|