最近試了一下
http://jxls.sourceforge.net/
他應該是算一個產生 xls 的 framework~
覺得是還不錯用。背後可以接 蠻常用的 poi 實作。
http://jxls.sourceforge.net/getting_started.html
Currently Jxls supplies two implementations of this interface in separate modules based on the well-known Apache POI and Java Excel API libraries.
只要引用不同的 maven lib 就可以換實作。
然後他把 xlsx, xls 的 method 合而為一了~~在 poi 上這是分屬兩套不同的系統,所以有解決自己刻時各自寫一套的麻煩。
還有很重要的一點是支援 el 的語法。常用的 取 bean 屬性, if ,each,都有 \(^_^)/...
看起來他還可以換 el 的語法系統。不過因為內建的已經夠用就先降子~
http://jxls.sourceforge.net/reference/expression_language.html
也有順便把 公式 統計算區間的部份給處理好了。(之前自己刻,在那邊算自己加了幾行,要怎麼下 xls 公式的區間的麻煩問題有幫解了。)
要入門的方式,應該是抓他的 sample code 來跑,是最方便的了。
http://jxls.sourceforge.net/source_code.html
https://bitbucket.org/leonate/jxls-demo
直接跑demo 修改跟看文件說明一起看就會清楚很多!因為這個要 xls template 和 java code 結合一起看才會準(那個文件貼圖是有貼到重點,但是...就還是手動操作一下上手比較快)
個人比較喜歡用 template 方式來做 xls,所以~最後選用全部mark-up 的方式。
http://jxls.sourceforge.net/reference/excel_markup.html
另外因為有多 sheet 的需求,demo 主要都是以單一sheet 的在放,所以我就小修了一下~
xls template 的設定~
最容易忘記的的大概就是一開始,jx:area 一定要設定...不然他不知道要幫你換多大的區塊...
還有就是當表有增刪欄位時,好好檢查一下區間的範圍~囧/
他裡面的 function, Context ,都是整個xls共用的,所以是只要給一次就好了~
另外是因為我做多sheet 測試,習慣就是 template sheet 對 產出 sheet 是一對一的方式,所以會刪掉做為 template 的原本的 sheet。
(當然是jxls的架構, template area 是可以一直重覆利用的。)
Java code:
try(InputStream is = new FileInputStream(fullpath)) {
try (OutputStream os = new FileOutputStream(output)) {
//init 給定最主要的處理 transformer
Transformer transformer = TransformerFactory.createTransformer(is, os);
//register function 因為有用到method,一定要註冊才能用
JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig().getExpressionEvaluator();
Map<String, Object> functionMap = new HashMap<>();
functionMap.put("fn", new ReportFunction());
evaluator.getJexlEngine().setFunctions(functionMap);
//set context 給物件資料
Context context = new Context();
context.putVar("data", data);
//note comment: NEED define jx:area in the sheet beginning
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(transformer);
XlsCommentAreaBuilder.addCommandMapping("groupRow", GroupRowCommand.class);
List<Area> xlsAreaList = areaBuilder.build();
//取有定義的區塊出來處理
for(int i = 0 ; i < xlsAreaList.size() ; i++) {
Area xlsArea = xlsAreaList.get(i);
String theSheetName = xlsArea.getAreaRef().getSheetName();
//apply
if(sheetNames.containsKey(theSheetName)) {
CellRef newSheetCell = new CellRef(sheetNames.get(theSheetName), 0, 0);
//產出後的區塊,要寫到xls 的那邊
xlsArea.applyAt(newSheetCell, context);
//要跑小計,要記得叫他處理公式區間
xlsArea.processFormulas();
}
//刪除 做為 template 的 sheet
transformer.deleteSheet(theSheetName);
}
//write
transformer.write();
}
}
結果大概就是長降子~
多張 sheet 有出來。
(他會自動把 符合語法的 註解清掉。但是不合的會留著XD...)
看一下 if 的作用,還不錯~