Total Pageviews

Showing posts with label JasperReport. Show all posts
Showing posts with label JasperReport. Show all posts

2012/02/14

Apply IS_IGNORE_PAGINATION when export to CSV in JasperReports

Problem

I'm writing a report which needs to be exported to pdf and CSVformat.
when output format is CSV, it should be ignore pagination. 
The screenshot as bellowing is wrong, it has pagination in CSVfile:


Solution
JasperReports provides IS_IGNORE_PAGINATION.
It is a fill-time parameter, therefore you'll have to set it when filling the report:

params.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);
JasperFillManager.fillReport(jasperReport, params, dataSource);


See...CSV file does not have pagination after set IS_IGNORE_PAGINATION to TRUE.


2011/12/28

善用Oracle提供的function來提升系統效能



有關報表的日期欄位,資料庫是儲存成yyyMMDD or yyyMM。根據現有需求,需formatting成YYY/MM或者是YYY/MM/DD格式,因為效能考量,此類的formatting應在SQL裡頭做,不要放到AP level做。

舉個例子來說

  • 屆滿年月
    • NVL2(NIGT001.APL_LIMIT_YM, SUBSTR(NIGT001.APL_LIMIT_YM,0,3)||'/'||SUBSTR(NIGT001.APL_LIMIT_YM,4,2), ' ')
  • 作業日期
    • NVL2(NIGT001.PRST_PRCD_DATE, SUBSTR(NIGT001.PRST_PRCD_DATE,0,3)||'/'||SUBSTR(NIGT001.PRST_PRCD_DATE,4,2)||'/'||SUBSTR(NIGT001.PRST_PRCD_DATE,6,2), ' ')
 
Oracle相關語法簡介:
 

2011/12/22

No output specified for the exporter

Problem
As I would like to export pdf via JasperReports JRExporter, it throw "No output specified for the exporter" exception.

Root Cause
I forgot to set OutputStream to JRExporter parameter, i.e.
1:  JRExporter pdfExporter = new JRPdfExporter();  
2:  pdfExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);  
3:  //........  

2011/10/24

Grouping Data in Reports

Report groups are a flexible way to show grouped data based on one or more certain fields, or even on generic expression, that is, a group can be defined based on the specific column.

Here we will build a report to show the list of 違章案件派查明細表, 審理人員 will be grouped together, that is, the manger (suppose the report is for a manager) will know which violation case is reponsible by which 審理人員.

Follow the listed steps:
1. Go to File | New… | Report, select Simple Blue, and press Launch Report Wizard.
2. Set JavaBean as report's datasource: http://albert-myptc.blogspot.com/2011/06/how-toi-make-java-bean-datasource.html
3. Click Report Name | Right Click | Add Report Group, and New Group Wizard. Fill in Group Name | Choose field name | click Next, and Click Finish


4. You can see group header and group footer in your Report Inspector
5. Click group header | check "Start on a new page" and "Reset page number"

6. Report header and column header should all put into group header
7. JavaBean attriubtes will be dragged and dropped into detail band

8. Drag and drop group count variable to summary field

 9. Done.

How to start group data on a new page

Problem
I had some problems as I built a group by report
1. Each group data should start on a new page.
2. page number should be reset



Solution
1. Move report header from title band to group header band

2. Click group header


3. Check two checkboxs, including "Start on a new page" and "Reset page number"


Here has some group options:
Option Description
Name This is the name of the group. You can modify the name by just clicking on the button next to the name.
Start on a new page If this checkbox is checked, then the group starts on a new page.
Start on a new column If this checkbox is checked, then the group starts on a new column.
Reset page number When the group changes, the page number is reset if this option is checked.
Reprint header If you want to reprint the group header on each page, check this option.
Min Height to Start New Page If the value is greater than 0 (zero), it is considered as the minimum height required to keep the group on the current page.
Footer Position This option allows us to specify where to place the group footer. The available place options are Normal, Stack at bottom, Force at bottom, and Collate at bottom.
Keep Together This is a flag that prevents the group from splitting on two separate pages/columns.

Demo
It split to two pages as bellowing:


2011/10/11

How to add record sequence number in JasperReports

Requirement
I would like to add record sequence number in the first column.


How to do it?
1. Open iReport
2. Utilize the build-in variable, COLUMN_COUNT, drag and drop to specific location.




2011/10/07

如何在iReport中設定欄位高度依據其內容而延展

Problem
當textfield中,資料長度過長時,過長的部份會被截掉,希望若遇到過長的部份能夠折行處理。



Solution
利用iReport打開jrxml file,點選特定的textfield

將Stretch With Overflow此選項打勾即可。
 

Result



2011/10/05

How to count the total number of records in JasperReports

Objective
We would like to show the total number of records at the end of report: 

How to do it
It's very easy and straightforward, just utilize the build-in variable (REPORT_COUNT), drag and drop the build-in variable into report. That's all.




2011/08/24

JasperWave - designer for JasperReports




Another report designer tool choice for JasperReports: http://jasperwave.com/docs/introduction.html

2011/07/19

Avoid Producing Unnecessary Empty Columns as Export CSV File

Problem
it's our report resign in iReport

export to csv file

it has many unnecessary empty columns in csv file


Root Caluse / Solution
Because the width of text field should be aligned from top to down

So some text field will be split to more than one.

Or some text fields will be merged.

Check the result

Fail to Concat String with $V{PAGE_NUMBER}

Problem
I would like to concat String with $V{PAGE_NUMBER}

As I want to do preview in iReport, it show this error message in iReport console

Root Cause
Because of the Expression Class of $V{PAGE_NUMBER} is java.lang.Integer, so it will throw this error message.

Solution
Change the Expression Class of $V{PAGE_NUMBER} from java.lang.Integer java.lang.String, then the problem will be resolved.


2011/06/28

Utilize Maven 2 JasperReports Plugin to Compile jrxml Automatically

Motivation
We would like to compile jrxml automatically as we build our web application.


Mechanics
We use Maven 2 JasperReports Plugin to compiles JasperReports xml design files to Java source and .jasper serialized files.

How to do it
1. edit nig-web/pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   <dependencies>
      <dependency>
         <groupId>net.sf.jasperreports</groupId>
         <artifactId>jasperreports</artifactId>
         <version>4.0.1</version>
      </dependency>
   </dependencies>
   
   
   <build>
      ...
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jasperreports-maven-plugin</artifactId>
            <version>1.0-beta-2</version>
            <executions>
               <execution>
                  <goals>
                     <goal>compile-reports</goal>
                  </goals>
                  <configuration>
                     <!-- define where is your jrxml file -->
                     <sourceDirectory>src\\main\\java\\gov\\fdc\\nig\\report\\templates</sourceDirectory>
                     <sourceFileExt>.jrxml</sourceFileExt>
                     <compiler>net.sf.jasperreports.compilers.JRGroovyCompiler</compiler>
                     <!-- define where is the jasper file will be generated -->
                     <outputDirectory>src\\main\\resources\\report\\jasper</outputDirectory>
                  </configuration>
               </execution>
            </executions>
            <dependencies>
               <!--note this must be repeated here to pick up correct xml validation -->
               <dependency>
                  <groupId>net.sf.jasperreports</groupId>
                  <artifactId>jasperreports</artifactId>
                  <version>4.0.1</version>
               </dependency>
               <dependency>
                  <groupId>org.codehaus.groovy</groupId>
                  <artifactId>groovy-all</artifactId>
                  <version>1.7.5</version>
               </dependency>
            </dependencies>
         </plugin>
      </plugins>
   </build>

2. mvn install
3. check result

Benefits
1. Automate jrxml compilation process
2. We won't forget to compile jrxml file and lead to our program read old jasper file

2011/06/15

net.sf.jasperreports.engine.JRException: Provider com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl not found

Problem
As I use iReport 4.0.2 to open jrxml file, but it show this error message:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found
    at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:134)
    at org.netbeans.lib.uihandler.LogRecords.scan(LogRecords.java:127)
    at org.netbeans.modules.uihandler.Installer.getLogs(Installer.java:681)
    at org.netbeans.modules.uihandler.Installer$Submit.(Installer.java:1317)
    at org.netbeans.modules.uihandler.Installer$SubmitInteractive.(Installer.java:1771)
    at org.netbeans.modules.uihandler.Installer.doDisplaySummary(Installer.java:983)
    at org.netbeans.modules.uihandler.Installer.displaySummary(Installer.java:912)
    at org.netbeans.modules.uihandler.Installer.displaySummary(Installer.java:920)
    at org.netbeans.modules.uihandler.UIHandler.run(UIHandler.java:140)
    at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:573)
    at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1005)


Solution
Change your JAVA_HOME to standard JDK instead of IBM JDK.
WHAT THE HELL!

2011/06/14

ReportWrapper Class for JasperReport Implementation

在JasperReport開發,主要會分成五個部分:
  1. Get data source: 傳入List of value object,並建立JRBeanCollectionDataSource
  2. Read Jasper File: 讀取.jasper file
  3. Generate JasperPrint: 讀取report input stream並建立JasperPrint物件
  4. Set response content type and header: 根據user要輸出的格式,指定content type and header
  5. Export Report: 根據user要輸出的格式,用相對應的API進行報表輸出


其實每份報表都不外乎這五大步驟,這邊我建立一個ReportWrapper class,如下


 package gov.fdc.nig.report;  
 import gov.fdc.nig.enumeration.ExportFormatEnum;  
 import java.io.IOException;  
 import java.io.InputStream;  
 import java.io.OutputStream;  
 import java.util.List;  
 import java.util.Map;  
 import javax.servlet.http.HttpServletResponse;  
 import net.sf.jasperreports.engine.JRDataSource;  
 import net.sf.jasperreports.engine.JRException;  
 import net.sf.jasperreports.engine.JRExporter;  
 import net.sf.jasperreports.engine.JRExporterParameter;  
 import net.sf.jasperreports.engine.JasperFillManager;  
 import net.sf.jasperreports.engine.JasperPrint;  
 import net.sf.jasperreports.engine.JasperReport;  
 import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;  
 import net.sf.jasperreports.engine.export.JRCsvExporter;  
 import net.sf.jasperreports.engine.export.JRPdfExporter;  
 import net.sf.jasperreports.engine.util.JRLoader;  
 /**  
 * Report Wrapper Class  
 *  
 * @author albert  
 *  
 */  
 public class ReportWrapper {  
      private transient JRDataSource dataSource;  
      private final static String JASPER_CLASSPATH = "..\\..\\..\\..\\report\\templates\\";  
      private transient InputStream reportStream;  
      private transient JasperPrint print;  
      /**  
      * Set report data source  
      *  
      * @param data  
      * List of value object  
      */  
      private void setDataSource(final List data) {  
           dataSource = new JRBeanCollectionDataSource(data);  
      }  
      /**  
      * Get report input stream  
      */  
      private void getReportInputStream(final String fileName) {  
           reportStream = getClass().getResourceAsStream(  
           JASPER_CLASSPATH.concat(fileName.concat(".jasper")));  
      }  
      /**  
      * generate JasperPrint  
      *  
      * @param params parameters  
      * @throws JRException  
      */  
      public void generateJasperPrint(final Map params)  
      throws JRException {  
           final JasperReport report = (JasperReport) JRLoader  
           .loadObject(reportStream);  
           print = JasperFillManager.fillReport(report, params, dataSource);  
      }  
      /**  
      * Set content type and header  
      *  
      * @param fileName is File name  
      * @param response is HttpServletResponse  
      * @param exportEnum is ExportFormatEnum  
      */  
      public void setResponse(final String fileName,  
           final HttpServletResponse response,  
           final ExportFormatEnum exportEnum) {  
           response.setCharacterEncoding("UTF-8");  
           if ("pdf".equals(exportEnum.getValue())) {  
                response.setContentType("application/pdf");  
                response.setHeader("Content-Disposition", "attachment;filename=\""  
                .concat(fileName).concat(".pdf\""));  
           } else if ("csv".equals(exportEnum.getValue())) {  
                response.setContentType("application/octet-stream;charset=UTF-8");  
                response.setHeader("Content-Disposition", "attachment;filename="  
                .concat(fileName).concat(".csv"));  
           }  
      }  
      /**  
      * Export report  
      *  
      * @param exportEnum is ExportFormatEnum  
      * @param outputStream is OutputStream  
      * @throws JRException  
      * @throws IOException  
      */  
      public void exportReport(final ExportFormatEnum exportEnum,  
      final OutputStream outputStream) throws JRException, IOException {  
           if ("pdf".equals(exportEnum.getValue())) {  
                final JRExporter pdfExporter = new JRPdfExporter();  
                pdfExporter.setParameter(JRExporterParameter.JASPER_PRINT, print);  
                pdfExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);  
                pdfExporter.exportReport();  
           } else if ("csv".equals(exportEnum.getValue())) {  
                // byte-order marker (BOM)  
                final byte bomByteArr[] = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };  
                // insert BOM byte array into outputStream  
                outputStream.write(bomByteArr);  
                final JRExporter csvExporter = new JRCsvExporter();  
                csvExporter.setParameter(JRExporterParameter.JASPER_PRINT, print);  
                csvExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);  
                csvExporter.exportReport();  
           }  
           outputStream.flush();  
      }  
      /**  
      * do export report based on the parameters  
      *  
      * @param data is List of VO  
      * @param fileName is file name  
      * @param params is parameters  
      * @param response is HttpServletResponse  
      * @param exportEnum is ExportFormatEnum  
      * @param outputStream is OutputStream  
      * @throws JRException  
      * @throws IOException  
      */  
      public void execute(final List data, final String fileName,  
      final Map params,  
      final HttpServletResponse response,  
      final ExportFormatEnum exportEnum, final OutputStream outputStream)  
      throws JRException, IOException {  
           setDataSource(data);  
           getReportInputStream(fileName);  
           generateJasperPrint(params);  
           setResponse(fileName, response, exportEnum);  
           exportReport(exportEnum, outputStream);  
           if (reportStream != null) {  
                reportStream.close();  
           }  
      }  
 }  

未來我們在Contoller的processF7Key,只要建立ReportWrapper class,並將相對應的參數給execute method即可,請參考底下的程式片段
 /**  
 * Will be executed as user click Print button  
 *  
 * @param formBean  
 * NIG135DataBean  
 * @param session  
 * NIG135DataBean  
 * @return JSONObject  
 * @throws IllegalAccessException  
 * @throws InvocationTargetException  
 * @throws IOException  
 */  
 private @ResponseBody  
 void processF7Key(final NIG135DataBean formBean,  
 final HttpServletResponse response, final HttpSession session)  
 throws IllegalAccessException, InvocationTargetException,  
 IOException {  
      String jasperXMLFileName = "NIG135P1";  
      OutputStream outputStream = response.getOutputStream();  
      try {  
           if ("135".equals(formBean.getReportOption())) {  
                Map params = new HashMap();  
                params.put("rejectPeriod", formBean.doPrintForNIG135P1(covertToNIG135P1ReportBean(formBean));  
                if ("1".equals(formBean.getReportType())) {  
                     // export csv file  
                     if (ExportFormatEnum.CSV.getValue().equals(  
                     formBean.getExportFormat())) {  
                          new ReportWrapper().execute(data,  
                          jasperXMLFileName, params, response,  
                          ExportFormatEnum.CSV, outputStream);  
                     }  
                          // export pdf file  
                          else if (ExportFormatEnum.PDF.getValue().equals(  
                          formBean.getExportFormat())) {  
                          new ReportWrapper().execute(data,  
                          jasperXMLFileName, params, response,  
                          ExportFormatEnum.PDF, outputStream);  
                     }  
                }  
           }  
      }catch(Exception e){  
      //............  
      }  
 }  

nig.nig135w.js
 function nig135wFormF7(){  
      $("#fn").val("7");  
      $("#nig135wForm").attr("target", "_self");  
      $("#nig135wForm").attr("action", "/nig/front/NIG135W");  
      $("#nig135wForm").submit();  
 }  

Benefits
所有的報表程式,都透過這一支ReportWrapper class來處理。
我們只要專注於前端的business logic以及templates,後端如何去產生pdf, csv等格式,就交給ReportWrapper 處理就好。

How to Access .jasper file from EAR File


Problem
根據標準組所提供的讀取.jasper的方式,是將.jasper的目錄寫死,此寫法未來會有很大的問題。如:
1. 若有多位開發人員同時進行開發,大家都存放於不同的地方,會導致某人的環境可以執行,其他人卻無法執行的狀況。
2. 若開發機、測試機、正式機所放置的目錄不一樣,這樣deploy到不同的機器,又忘記手動去更改目錄,會導致在測試機可以執行,正式機卻無法執行的窘境。

為了改善上述的潛在問題,以下是解決方式:

File Structure
My ReportWrapper class is under gov.fdc.nig.report

.japser files are under resources/report


After we build our application to ear file, the file structure looks like this:


Source Code

1
2
3
4
5
    private final static String JASPER_CLASSPATH = "..\\..\\..\\..\\report\\templates\\";
    InputStream reportStream
     = getClass().getResourceAsStream(JASPER_CLASSPATH.concat(fileName.concat(".jasper")));
    JasperReport report = (JasperReport) JRLoader.loadObject(reportStream);
    


Benefit
透過上述的寫法,採相對路徑的方式來讀取.jasper file,避免上述的問題

2011/06/10

How to Write CSV Files as UTF-8 for Excel

Problem
As JasperReport export CSV file with UTF-8 encoding, Microsoft Excel wasn't displaying a CSV (comma separated values) file correctly.
The screenshot is as bellows:

But it can display correctly for notepad:


Root Cause
In the absence of any charset identification, Excel must guess about a file's content encoding. Therefore, Excel uses that default to read and display CSV files.


Solution
Use the byte-order marker (BOM) to identify the CSV file as a Unicode file. So I write an byte array into OutputStream, then Excel should uses UTF-8 read and display CSV files.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  //byte-order marker (BOM)
  byte b[] = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
  //insert BOM byte array into outputStream
  outputStream.write(b);
  JRExporter csvExporter = new JRCsvExporter();
  csvExporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
  csvExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
  csvExporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, reportName.concat(".csv"));
  csvExporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
  csvExporter.exportReport();



See....it's correct now!