2011年6月15日 星期三

jasperreport+ireport

在TAC系統中, 實作jasperreport報表說明:(參考TAC程式Tac113Controller, Tac113ReportTest, Tac113ManagerImpl)
前提: 完成fdc report設定.
步驟:
  1. 拉報表樣板 jrxml, 編譯jrxml成 japser檔
  2. 測試報表 撰寫 TACxxxReportTest 測試類別
  3. controller 中 注入 TACReportUtil
  4. 透過manager取得報表表頭, 明細資料.參數
  5. 使用TACReportUtil 利用資料參數產生報表

1.拉報表樣板 jrxml
  使用IReport 拉jrxml, 注意事項:
  a. ireport 欄位(fields) 名稱 要與 預計轉換的VO 屬性名稱一致.
  b. ireport 可以做 group分頁 及 計算 sum, 頁數 , column數之類的處理.
  c. 儲存jrxml後, 記得執行編譯, 以產生 .jasper檔

2. 測試報表產出 撰寫 TACxxxTest 測試類別
  參考TAC113ReportTest 建立類別 TACxxxTest .
  a. 需要繼承 BaseReportTest.
  b. doPrint() method 將報表的步驟做好了, 所以原則上不用特別修改.只需要特別實作getTestParams、getTestReportData、reportAssert

/**
 * 
 */
package gov.fdc.tac.report;

import static org.junit.Assert.assertEquals;
...

import org.junit.Before;
import org.junit.Test;

/**
 * @author ropin13
 * 
 */
// @Ignore
public class TAC113ReportTest extends BaseReportTest {
   ...

    /**
     * @throws Exception
     *             Exception
     */
    @Test
    public void doPrint() throws Exception {
        // 取得parameter 標頭
        Map params = getTestParams();

        // 取得fields details
        List details = getTestReportData();

        // 產生報表
        this.genReport(jobNo, pageDef, params, details);
        // validate
        reportAssert(details);
        logger.info("Done!");
    }


    /**
     * 處理驗證
     * 
     * @param details
     *            details
     * @throws Exception
     *             Exception
     */
    private void reportAssert(List details) throws Exception {
        assertEquals(9, details.size());// 確認筆數正確 欄位數*資料筆數
    }

    /**
     * 取得測試parameter資料作為header...等等
     * 
     * @return Map
     */
    public static Map getTestParams() {
        Map parameters = new HashMap();
        // title
        parameters.put("TITLE_DST", "台北市");
        ...
        return parameters;
    }

    /**
     * 取得reportData, 作為details資料
     * 
     * @return ReportData
     * @throws Exception
     *             Exception
     */
    public static List getTestReportData() throws Exception {
        List tact001NewList = new ArrayList();
        tact001NewList.add(getTestTACT001List("A", "35", "1", "00001"));
        ..
        return tact001NewList;
    }

    /**
     * 產生測試資料
     * 
     * @param taxTp
     *            taxTp
     * @param taxCd
     *            taxCd
     * @param baTaxFineTp
     *            baTaxFineTp
     * @param serialNo
     *            serialNo
     * @return TACT001
     * @throws Exception
     *             Exception
     */
    public static TACT001 getTestTACT001List(String taxTp, String taxCd, String baTaxFineTp, String serialNo)
        throws Exception {
        String DateString = "1000101";
        TACT001 tact001 = new TACT001();

        // 復查編號:由行救主檔之復查編號(稅別、縣市代號、總分局處所代號、申請年、本稅罰鍰註記、流水號)移入。
        TACT001PK id = new TACT001PK();
        tact001.setId(id);
        id.setTaxTp(taxTp);
        id.setHsnCd("1");
        id.setDstCd("11");
        id.setAppYy("11");
        id.setBaTaxFineMk("1");
        id.setSerialNo(serialNo);
        ...
        return tact001;
    }
}
3. controller處理
  a. 由manager取得資料,
  // 取得報表header、report data
  tac113Manager.doPrint(keyinBDate, keyinEDate, keyinIdCd, hsnCd, acptUnit, taxCdList);
manager:
  a.1.tac113Manager透過getTAC113Params 取得 報表Parameters, 一般作為報表title, header
  a.2.tac113Manager透過getTAC113ReportData 取得reportData, 作為報表的details資料


    @Override
    public Map doPrint(String keyinBDate, String keyinEDate, String keyinIdCd, String hsnCd,
            String acptUnit, List taxCdList) throws FDCDefineException {
        User user = UserUtil.getUser();
        Map map = new HashMap();
        map.put(Report.RAWDATA_PARAMS, getTAC113Params(keyinBDate, keyinEDate, user, keyinIdCd, hsnCd, acptUnit));
        map.put(Report.RAWDATA_REPORTDATA,getTAC113ReportData(keyinBDate, keyinEDate, keyinIdCd, hsnCd, acptUnit, taxCdList));
        return map;
    }

  接下來我們來看看tac113Manager.getTAC113ReportData裡面的程式.
  主要步驟為:
  1.取得資料
  2.轉換成ReportData(此步驟已經抽取到TACReportUtil處理).
由於Fdcreport api的要求,必須使用reportData作為報表的資料來源. 這邊要注意 ReportDataBuilder.createReportData
     將tact001NewList轉換為ReportData的函式. 由於原始的fdcreport作法是用 reportData.add(xxx) 一個欄位一個欄位的加入,不僅不方便,而且因為有順序的關係,寫起來容易錯誤. 所以這邊透過createReportData,來轉換.
     原理是透過讀取jrxml取得fields的順序,在依照此順序讀取tact001NewList中的entity來進行reportData.add, 因此不會有report 欄位變更造成 程式也要變動的狀況.

    private List getTAC113ReportData(String keyinBDate, String keyinEDate, String  keyinIdCd, String hsnCd,String acptUnit, List taxCdList) throws FDCDefineException {

        // 設定where條件
        Map parameters = new HashMap();
        parameters.put("keyinBDate", keyinBDate);
        parameters.put("keyinEDate", keyinEDate);
        parameters.put("taxCdList", taxCdList);

        // 依據selectTp 切換jpql
        String jpql = "TAC113.querykeyinIdCd";
        ...

        // 查詢acptStus為9、符合挑檔條件、稅別、登入日期介於keyinBDate、keyinEDate間的行救主檔
        List tact001List = tact001Dao.query(new TACT001(), jpql, parameters);

        if (CollectionUtils.isEmpty(tact001List)) {
            throw new FDCDefineException(UserUtil.getUser().getProgramID(), TACMsgType.TAC,
                    TACMsgSeq.DATA_DOES_NOT_EXIST, MsgLevel.INFO);
        }
        List tact001NewList = new ArrayList();
        tact001NewList.addAll(tact001List);// 由於從JPA取出的List是final的,不可變更,所以複製一份,進行排序
        return tact001NewList;
    }


  b.使用TACReportUtil 產生 報表
  // 產生報表
  TACReportUtil.printOnlinePdf(res, TACReportConstant.TAC113_PAGE_DEF, rawData);

/**
* 程式資訊摘要:
* 類別名稱:TAC113Controller.java
* 程式內容說明:
* 版本資訊:1.0
* 程式設計人員姓名:池哲緯
* 程式修改記錄:2011-04-12初版
*       2011-06-03調整為新架構
* 
* 版權宣告: FDC all rights reserved.
*/
package gov.fdc.tac.web.front.controller;

import gov.fdc.tac.web.util.TACReportUtil;
...

@Controller
@RequestMapping("/front/TAC113W")
public class TAC113Controller extends BaseController {
@Autowired
protected TAC113Manager tac113Manager;
@Autowired
protected TACReportUtil TACReportUtil;

...

/**
* 處理功能鍵F7-Print
* 
* @param formBean
*            formBean
* @param res
*            res
* @param session
*            session
* @throws Exception
*             Exception
*/
@RequestMapping(value = "/showReport", method = RequestMethod.GET)
@Secured("FUNCID_TAC113W")
public @ResponseBody
void processF7Key(TAC113DataBean formBean, final HttpServletResponse res, HttpSession session) throws Exception {
//取得畫面傳入的值
String keyinBDate = formBean.getKeyinBDate();
...

// 取得報表header、report data
Map rawData = tac113Manager.doPrint(keyinBDate, keyinEDate, keyinIdCd, hsnCd, acptUnit, taxCdList);

// 產生報表
TACReportUtil.printOnlinePdf(res, TACReportConstant.TAC113_PAGE_DEF, rawData);
}
...

沒有留言:

張貼留言