OSDN Git Service

InputStreamを引数とするmakeReportでのExcel2007以降のテンプレートファイルOpenError対応
[jaxcel/jaxcel.git] / Jaxcel / src / org / hanei / jaxcel / report / ReportMaker.java
1 /**\r
2  * Copyright 2014 Hanei Management Co.,Ltd. \r
3  * \r
4  * This file is part of Jaxcel\r
5  * \r
6  *  Jaxcel is free software: you can redistribute it and/or modify\r
7  *  it under the terms of the GNU Lesser General Public License as published by\r
8  *  the Free Software Foundation, either version 3 of the License, or\r
9  *  (at your option) any later version.\r
10  *\r
11  *  Jaxcel is distributed in the hope that it will be useful,\r
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  *  GNU Lesser General Public License for more details.\r
15  *\r
16  *  You should have received a copy of the GNU Lesser General Public License\r
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
18  */\r
19 package org.hanei.jaxcel.report;\r
20 \r
21 import java.io.BufferedInputStream;\r
22 import java.io.File;\r
23 import java.io.FileOutputStream;\r
24 import java.io.IOException;\r
25 import java.io.InputStream;\r
26 import java.io.OutputStream;\r
27 import java.util.Map;\r
28 \r
29 \r
30 import org.apache.poi.hssf.usermodel.HSSFSheet;\r
31 import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
32 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
33 import org.apache.poi.openxml4j.opc.OPCPackage;\r
34 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;\r
35 import org.apache.poi.poifs.filesystem.OfficeXmlFileException;\r
36 import org.apache.poi.ss.usermodel.Cell;\r
37 import org.apache.poi.ss.usermodel.Row;\r
38 import org.apache.poi.ss.usermodel.Sheet;\r
39 import org.apache.poi.ss.usermodel.Workbook;\r
40 import org.apache.poi.ss.usermodel.WorkbookFactory;\r
41 import org.apache.poi.ss.util.CellReference;\r
42 import org.apache.poi.xssf.usermodel.XSSFChartSheet;\r
43 import org.apache.poi.xssf.usermodel.XSSFDialogsheet;\r
44 import org.apache.poi.xssf.usermodel.XSSFWorkbook;\r
45 import org.hanei.jaxcel.exception.JaxcelInputException;\r
46 import org.hanei.jaxcel.exception.JaxcelOutputException;\r
47 import org.slf4j.LoggerFactory;\r
48 import org.slf4j.Logger;\r
49 \r
50 /**\r
51  * Excel帳票生成クラス<br>\r
52  * テンプレートのExcelファイルにデータを挿入することでExcel帳票を生成する。\r
53  * \r
54  * <h4>テンプレートの書式について</h4>\r
55  * <h5>${expression}</h5>\r
56  * <p>値出力。expressionを解析し値を出力する。</p>\r
57  * \r
58  * <h5>#foreach(${object in aryObject}[ rows:"number"][ cols:"number"][ direction:"row|col"][ style:"copy|^copy"][ shift:"true|false"][ block:"true|false"][ start:"number"][ end:"number"])</h5>\r
59  * <p>foreach句。配列やListオブジェクト、Mapオブジェクトの繰返し出力を行う。<br>\r
60  * プロパティにより、繰返し出力方向の指定や、繰返し回数、出力範囲以降のセルのシフト方法等を指定可能。</p>\r
61  * <table border="1" cellspacing="1">\r
62  * <tr><th>属性</th><th>説明</th></tr>\r
63  * <tr>\r
64  *              <td>${object in aryObject}</td>\r
65  *              <td>"${" 要素オブジェクト in 配列オブジェクト "}" のフォーマットで指定する。配列オブジェクトには配列、List、Mapが使用可能。<br>\r
66  *              rows・colsオプションで指定した範囲内で、要素オブジェクトで指定した名称で各インデックスの要素が出力可能。</td>\r
67  * </tr>\r
68  * <tr>\r
69  *              <td>rows</td>\r
70  *              <td>繰返し元の行数を正の整数で指定する。"1"指定で#foreach指示子が記述された行のみとなる。省略すると規定値である "1"となる。</td>\r
71  * </tr>\r
72  * <tr>\r
73  *              <td>cols</td>\r
74  *              <td>繰返し元の列数を正の整数で指定する。"1"指定で#foreach指示子が記述された列のみとなる。省略すると規定値である "1"となる。</td>\r
75  * </tr>\r
76  * <tr>\r
77  *              <td>direction</td>\r
78  *              <td>繰返し処理の方向を指定する。省略すると規定値である"row"となる。<br>\r
79  *              <table>\r
80  *              <tr><td>row</td><td>行方向に繰返す。</td></tr>\r
81  *              <tr><td>col</td><td>列方向に繰返す。</td></tr>\r
82  *              </table></td>\r
83  * </tr>\r
84  * <tr>\r
85  *              <td>style</td>\r
86  *              <td>繰返し元範囲(rows・colsオプションで指定する範囲)のセルスタイルのコピーについて指定する。省略すると規定値である"copy"となる。<br>\r
87  *              <table>\r
88  *              <tr><td>copy</td><td>セルスタイルをコピーする。</td></tr>\r
89  *              <tr><td>copy以外</td><td>セルスタイルをコピーしない。</td></tr>\r
90  *              </table></td>\r
91  * </tr>\r
92  * <tr>\r
93  *              <td>shift</td>\r
94  *              <td>繰返し範囲より後方の範囲のシフト方法について指定する。省略すると規定値である"true"となる。<br>\r
95  *              <table>\r
96  *              <tr><td>true</td><td>繰返し範囲より後方の範囲をdirectionオプションで指定した方向にシフトする。</td></tr>\r
97  *              <tr><td>false</td><td>シフトしない。</td></tr>\r
98  *              </table></td>\r
99  * </tr>\r
100  * <tr>\r
101  *              <td>block</td>\r
102  *              <td>矩形範囲での繰返し処理を行うかについて指定する。省略すると規定値である"true"となる。<br>\r
103  *              <table>\r
104  *              <tr><td>true</td><td>繰返し範囲を矩形範囲(rows・colsオプションで指定する範囲)とする。</td></tr>\r
105  *              <tr><td>false</td><td>繰返し範囲を繰返し元範囲に含まれる行・列全体とする。<br>\r
106  *              directionオプションが"row"の場合、繰返し元範囲に含まれる行全体が繰返し範囲となる。<br>\r
107  *              directionオプションが"col"の場合、繰返し元範囲に含まれる列全体が繰返し範囲となる。</td></tr>\r
108  *              </table></td>\r
109  * </tr>\r
110  * <tr>\r
111  *              <td>start</td>\r
112  *              <td>配列オブジェクトの出力開始インデックス(1起点)を正の整数、もしくは、正の整数を返却する関数で指定する。省略すると規定値である"1"となる。</td>\r
113  * </tr>\r
114  * <tr>\r
115  *              <td>end</td>\r
116  *              <td>配列オブジェクトの出力終了インデックス(1起点)を正の整数、もしくは、正の整数を返却する関数で指定する。省略すると配列オブジェクトの要素数となる。</td>\r
117  * </tr>\r
118  * <tr>\r
119  *              <td colspan="2">startオプションよりendオプションの指定値が小さい場合、配列オブジェクトを降順で出力する。<br>\r
120  *              配列オブジェクトの要素数は"size(配列オブジェクト)"関数で取得可能。</td>\r
121  * </tr>\r
122  * </table>\r
123  * \r
124  * <h5>#if(${expression}[ rows:"number"][ cols:"number"][ delete:"left|up|clear"][ block:"true|false"])</h5>\r
125  * <p>if句。expression判定式がtrue判定の場合は指定範囲の出力、false判定の場合は指定の方法で範囲を削除する。</p>\r
126  * <table border="1" cellspacing="1">\r
127  * <tr><th>属性</th><th>説明</th></tr>\r
128  * <tr>\r
129  *              <td>${expression}</td>\r
130  *              <td>判定式。"${" 式 "}" のフォーマットで指定する。Bool値を返す式を指定する。Bool値を返さない式の場合は、値がnullでなければtrueと判断する。</td>\r
131  * </tr>\r
132  * <tr>\r
133  *              <td>rows</td>\r
134  *              <td>制御範囲の行数を正の整数で指定する。"1"指定で#if指示子が記述された行のみとなる。省略すると規定値である "1"となる。</td>\r
135  * </tr>\r
136  * <tr>\r
137  *              <td>cols</td>\r
138  *              <td>制御範囲の列数を正の整数で指定する。"1"指定で#if指示子が記述された列のみとなる。省略すると規定値である "1"となる。</td>\r
139  * </tr>\r
140  * <tr>\r
141  *              <td>delete</td>\r
142  *              <td>判定式がflse判定の場合の制御範囲に対する操作を指定する。省略すると規定値である"left"となる。<br>\r
143  *              <table>\r
144  *              <tr><td>left</td><td>制御範囲セルを削除し、左に詰める。</td></tr>\r
145  *              <tr><td>up</td><td>制御範囲セルを削除し、上に詰める。</td></tr>\r
146  *              <tr><td>clear</td><td>制御範囲セルの値・計算式をクリアするのみで詰めない。</td></tr>\r
147  *              </table>\r
148  * </tr>\r
149  * <tr>\r
150  *              <td>block</td>\r
151  *              <td>矩形範囲での制御を行うかについて指定する。省略すると規定値である"true"となる。<br>\r
152  *              <table>\r
153  *              <tr><td>true</td><td>制御範囲を矩形範囲(rows・colsオプションで指定する範囲)とする。</td></tr>\r
154  *              <tr><td>false</td><td>制御範囲を矩形範囲に含まれる行・列全体とする。<br>\r
155  *              deleteオプションが"left"の場合、矩形範囲に含まれる列全体が制御範囲となる。<br>\r
156  *              deleteオプションが"up"の場合、矩形範囲に含まれる行全体が制御範囲となる。<br>\r
157  *              deleteオプションが"clear"の場合は無効。</td></tr>\r
158  *              </table></td>\r
159  * </tr>\r
160  * </table>\r
161  * \r
162  * @version 1.00.00\r
163  * @author Noboru Saito\r
164  */\r
165 public class ReportMaker {\r
166 \r
167         private static final Logger log = LoggerFactory.getLogger(ReportMaker.class);\r
168 \r
169         /**\r
170          * POIファイルシステム<br>\r
171          * Excel 2003 形式(.xls)\r
172          */\r
173         private NPOIFSFileSystem npoifs = null;\r
174         \r
175         /**\r
176          * POIファイルシステム<br>\r
177          * Excel 2007 形式(.xlsx, .xlsm)\r
178          */\r
179         private OPCPackage pkg = null;\r
180         \r
181         /**\r
182          *  EL式マネージャ\r
183          */\r
184         private ELManager elMgr = null;\r
185         \r
186         /**\r
187          *  コンテキスト\r
188          */\r
189         private JaxcelContext context  = null;\r
190 \r
191         /**\r
192          *  テンプレート一時ファイル\r
193          */\r
194         private File templateFile = null;\r
195         \r
196         /**\r
197          * コンストラクタ\r
198          */\r
199         public ReportMaker() {}\r
200 \r
201         /**\r
202          * 入力ストリームのExcelテンプレートファイルにデータを挿入することでExcel帳票を生成、Workbookオブジェクトを返却する。<br>\r
203          * 返却されたWorkbookオブジェクトはPOIを使用し、加工・出力が可能。<br>\r
204          * 入力ストリームは別途クローズが必要。<br>\r
205          * Workbookオブジェクトの使用終了後はclose()メソッドでExcelテンプレートファイルのクローズが必要。\r
206          * \r
207          * @param template Excelテンプレートファイル入力ストリーム\r
208          * @param parameter テンプレートに挿入するデータ\r
209          * \r
210          * @return Workbookオブジェクト\r
211          * \r
212          * @throws JaxcelInputException 入力例外発生時\r
213          */\r
214         public Workbook makeReport(InputStream template, Map<String, Object> parameter) {\r
215                 log.trace("makeReport start");\r
216 \r
217                 // 引数チェック\r
218                 if(template == null) {\r
219                         log.error("template is null");\r
220                         throw new JaxcelInputException("template is null");\r
221                 }\r
222                 \r
223                 // 一時ファイル作成\r
224                 if (templateFile != null && templateFile.exists()) {\r
225                         templateFile.delete();\r
226                         log.debug("template file delete: {}", templateFile.getPath());\r
227                         templateFile = null;\r
228                 }\r
229                 templateFile = createTempFile(template);\r
230                 \r
231                 // Excel帳票生成\r
232                 Workbook book = makeReport(templateFile, parameter);\r
233                 \r
234                 log.trace("makeReport end");\r
235                 return book;\r
236         }\r
237 \r
238         /**\r
239          * 入力ストリームのExcelテンプレートファイルにデータを挿入することでExcel帳票を生成、出力ストリームにExcel帳票を出力する。<br>\r
240          * 入出力ストリームは別途クローズが必要。\r
241          * \r
242          * @param template Excelテンプレートファイル入力ストリーム\r
243          * @param parameter テンプレートに挿入するデータ\r
244          * @param output Excel帳票出力ストリーム\r
245          *\r
246          * @throws JaxcelInputException 入力例外発生時\r
247          * @throws JaxcelOutputException 出力例外発生時\r
248          */\r
249         public void makeReport(InputStream template, Map<String, Object> parameter, OutputStream output) {\r
250                 log.trace("makeReport start");\r
251                 \r
252                 // Excel帳票生成\r
253                 Workbook book = makeReport(template, parameter);\r
254                 \r
255                 // 出力\r
256                 outputReport(book, output);\r
257 \r
258                 // テンプレートファイルクローズ\r
259                 close();\r
260 \r
261                 log.trace("makeReport end");\r
262         }\r
263 \r
264          /**\r
265          * 入力ストリームのExcelテンプレートファイルにデータを挿入することでExcel帳票を生成、Excel帳票ファイルを出力する。<br>\r
266          * 入力ストリームは別途クローズが必要。\r
267          * \r
268          * @param template Excelテンプレートファイル入力ストリーム\r
269          * @param parameter テンプレートに挿入するデータ\r
270          * @param output Excel帳票出力ファイル\r
271          *\r
272          * @throws JaxcelInputException 入力例外発生時\r
273          * @throws JaxcelOutputException 出力例外発生時\r
274          */\r
275         public void makeReport(InputStream template, Map<String, Object> parameter, File output) {\r
276                 log.trace("makeReport start");\r
277                 \r
278                 // Excel帳票生成\r
279                 Workbook book = makeReport(template, parameter);\r
280                 \r
281                 // 出力ストリーム\r
282                 FileOutputStream _output;\r
283                 try {\r
284                         _output = new FileOutputStream(output);\r
285                 }\r
286                 catch(Exception e) {\r
287                         log.error("output file open error: {}", e.getMessage(), e);\r
288                         throw new JaxcelOutputException("output file open error");\r
289                 }\r
290 \r
291                 // 出力\r
292                 outputReport(book, _output);\r
293                 try {\r
294                         _output.close();\r
295                 } catch (IOException e) {\r
296                         log.error("output file close error: {}", e.getMessage(), e);\r
297                         throw new JaxcelOutputException("output file close error");\r
298                 }\r
299 \r
300                 // テンプレートファイルクローズ\r
301                 close();\r
302 \r
303                 log.trace("makeReport end");\r
304         }\r
305         \r
306         /**\r
307          * Excelテンプレートファイルにデータを挿入することでExcel帳票を生成、Workbookオブジェクトを返却する。<br>\r
308          * 返却されたWorkbookオブジェクトはPOIを使用し、加工・出力が可能。<br>\r
309          * Workbookオブジェクトの使用終了後はclose()メソッドでExcelテンプレートファイルのクローズが必要。\r
310          * \r
311          * @param template Excelテンプレートファイル\r
312          * @param parameter テンプレートに挿入するデータ\r
313          * \r
314          * @return Workbookオブジェクト\r
315          * \r
316          * @throws JaxcelInputException 入力例外発生時\r
317          */\r
318         public Workbook makeReport(File template, Map<String, Object> parameter) {\r
319                 log.trace("makeReport start");\r
320 \r
321                 // 引数チェック\r
322                 if(template == null) {\r
323                         log.error("template file is null");\r
324                         throw new JaxcelInputException("template file is null");\r
325                 }\r
326                 else if(!template.exists()) {\r
327                         log.error("template file does not exist: {}", template.getAbsolutePath());\r
328                         throw new JaxcelInputException("template file does not exist");\r
329                 }\r
330                 else if(!template.canRead()) {\r
331                         log.error("template file can not read: {}", template.getAbsolutePath());\r
332                         throw new JaxcelInputException("template file can not read");\r
333                 }\r
334                 if(parameter == null) {\r
335                         log.debug("parameter is null");\r
336                 }\r
337 \r
338                 // Excelテンプレートファイルオープン\r
339                 Workbook book = openWorkbook(template);\r
340                 \r
341                 // Excel帳票生成\r
342                 makeReport(book, parameter);\r
343                 \r
344                 log.trace("makeReport end");\r
345                 return book;\r
346         }\r
347 \r
348         /**\r
349          * Excelテンプレートファイルにデータを挿入することでExcel帳票を生成、出力ストリームにExcel帳票を出力する。<br>\r
350          * 出力ストリームは別途クローズが必要。\r
351          * \r
352          * @param template Excelテンプレートファイル\r
353          * @param parameter テンプレートに挿入するデータ\r
354          * @param output Excel帳票出力ストリーム\r
355          * \r
356          * @throws JaxcelInputException 入力例外発生時\r
357          * @throws JaxcelOutputException 出力例外発生時\r
358          */\r
359         public void makeReport(File template, Map<String, Object> parameter, OutputStream output) {\r
360                 log.trace("makeReport start");\r
361 \r
362                 // Workbook生成\r
363                 Workbook book = makeReport(template, parameter);\r
364 \r
365                 // 出力\r
366                 outputReport(book, output);\r
367         \r
368                 // テンプレートファイルクローズ\r
369                 close();\r
370 \r
371                 log.trace("makeReport end");\r
372         }\r
373 \r
374         /**\r
375          * Excelテンプレートファイルにデータを挿入することでExcel帳票を生成、Excel帳票ファイルを出力する。<br>\r
376          * \r
377          * @param template Excelテンプレートファイル\r
378          * @param parameter テンプレートに挿入するデータ\r
379          * @param output Excel帳票出力ファイル\r
380          * \r
381          * @throws JaxcelInputException 入力例外発生時\r
382          * @throws JaxcelOutputException 出力例外発生時\r
383          */\r
384         public void makeReport(File template, Map<String, Object> parameter, File output) {\r
385                 log.trace("makeReport start");\r
386 \r
387                 // Workbook生成\r
388                 Workbook book = makeReport(template, parameter);\r
389 \r
390                 // 出力ストリーム\r
391                 FileOutputStream _output;\r
392                 try {\r
393                         _output = new FileOutputStream(output);\r
394                 }\r
395                 catch(Exception e) {\r
396                         log.error("output file open error: {}", e.getMessage(), e);\r
397                         throw new JaxcelOutputException("output file open error");\r
398                 }\r
399 \r
400                 // 出力\r
401                 outputReport(book, _output);\r
402                 try {\r
403                         _output.close();\r
404                 } catch (IOException e) {\r
405                         log.error("output file close error: {}", e.getMessage(), e);\r
406                         throw new JaxcelOutputException("output file close error");\r
407                 }\r
408                 \r
409                 // テンプレートファイルクローズ\r
410                 close();\r
411 \r
412                 log.trace("makeReport end");\r
413         }\r
414         \r
415         /**\r
416          * ExcelテンプレートのWorkbookオブジェクトにデータを挿入することでExcel帳票を生成する。<br>\r
417          * Workbookオブジェクトの使用終了後はclose()メソッドでExcelテンプレートファイルのクローズが必要。\r
418          * \r
419          * @param book Workbookオブジェクト\r
420          * @param parameter テンプレートに挿入するデータ\r
421          * \r
422          * @throws JaxcelInputException 入力例外発生時\r
423          */\r
424         public void makeReport(Workbook book, Map<String, Object> parameter) {\r
425                 log.trace("makeReport start");\r
426 \r
427                 // 引数チェック\r
428                 if(book == null) {\r
429                         log.error("workbook is null");\r
430                         throw new JaxcelInputException("Workbook is null");\r
431                 }\r
432                 else if(!(book instanceof HSSFWorkbook) && !(book instanceof XSSFWorkbook)) {\r
433                         log.error("Workbook is unsupport type: {}", book.getClass().getName());\r
434                         throw new JaxcelInputException("Workbook is unsupported type");\r
435                 }\r
436                 if(parameter == null) {\r
437                         log.debug("parameter is null");\r
438                 }\r
439 \r
440                 // Jaxlsコンテキスト生成\r
441                 context = new JaxcelContext();\r
442 \r
443                 // EL式マネージャ生成。パラメータ設定\r
444                 elMgr = new ELManager();\r
445                 elMgr.setParameter(parameter);\r
446                 \r
447                 // JaxlsコンテキストにEL式マネージャ設定\r
448                 context.setElManager(elMgr);\r
449 \r
450                 // Book生成\r
451                 makeBook(book);\r
452                 \r
453                 log.trace("makeReport end");\r
454         }\r
455 \r
456         /**\r
457          * ワークブックのオープン\r
458          * \r
459          * @param template Excelテンプレートファイル\r
460          * \r
461          * @throws JaxcelInputException Excelテンプレートファイルオープン失敗時\r
462          */\r
463         private Workbook openWorkbook(File template) {\r
464                 log.trace("openWorkbook start");\r
465 \r
466                 // Workbookオブジェクト \r
467                 Workbook book = null;\r
468 \r
469                 // Excel2003以前\r
470                 try {\r
471                         npoifs = new NPOIFSFileSystem(template);\r
472                         book = WorkbookFactory.create(npoifs);\r
473                 } catch (OfficeXmlFileException | IOException e1) {\r
474                         // Excel2007以降\r
475                         try {\r
476                                 pkg = OPCPackage.open(template);\r
477                                 book = WorkbookFactory.create(pkg);\r
478                         } catch (InvalidFormatException | IOException e2) {\r
479                                 log.error("template file open error: [{}]. [{}]", e1.getMessage(), e2.getMessage());\r
480                         }\r
481                 }\r
482 \r
483                 // チェック\r
484                 if(book == null) {\r
485                         throw new JaxcelInputException("template file open error");\r
486                 }\r
487         \r
488                 log.trace("openWorkbook end");\r
489                 return book;\r
490         }\r
491 \r
492         \r
493         /**\r
494          * 出力ストリームにワークブックを出力する\r
495          * \r
496          * @version 1.00.00\r
497          * @param book  Workbookオブジェクト\r
498          * @param output        出力ストリーム\r
499          *\r
500          * @throws JaxcelOutputException 出力例外発生時\r
501          */\r
502         private void outputReport(Workbook book, OutputStream output) {\r
503                 log.trace("outputReport start");\r
504 \r
505                 try {\r
506                         book.write(output);\r
507                 } catch (Exception e) {\r
508                         log.error("workbook output error: {}", e.getMessage(), e);\r
509                         throw new JaxcelOutputException("workbook output error");\r
510                 }\r
511                 \r
512                 log.trace("outputReport end");\r
513         }\r
514 \r
515         /**\r
516          * Excelテンプレートファイルのクローズ<br>\r
517          * テンプレートファイルの変更は保存しません。\r
518          * \r
519          * @throws JaxcelOutputException 出力例外発生時\r
520          */\r
521         public void close() {\r
522                 log.trace("close start");\r
523 \r
524                 try {\r
525                         if (npoifs != null) {\r
526                                 npoifs.close();\r
527                                 log.debug("template file close.");\r
528                                 npoifs = null;\r
529                         }\r
530                         if (pkg != null) {\r
531                                 pkg.revert();\r
532                                 log.debug("template file close.");\r
533                                 pkg = null;\r
534                         }\r
535                         if (templateFile != null && templateFile.exists()) {\r
536                                 templateFile.delete();\r
537                                 log.debug("template file delete: {}", templateFile.getPath());\r
538                                 templateFile = null;\r
539                         }\r
540                 } catch (IOException e) {\r
541                         log.error("template file close error: {}", e.getMessage(), e);\r
542                         throw new JaxcelOutputException("template file close error");\r
543                 }\r
544 \r
545                 log.trace("close end");\r
546         }\r
547 \r
548         /**\r
549          * InputStreamから一時ファイルを作成\r
550          * @param template\r
551          * @return Fileオブジェクト\r
552          * \r
553          * @throws JaxcelInputException 一時ファイル作成エラー発生時\r
554          */\r
555         private File createTempFile(InputStream template) {\r
556                 log.trace("createTempFile start");\r
557                 \r
558                 final String PREFIX = "org.hanei.jaxcel_";\r
559                 final String SUFFIX = ".tmp";\r
560                 final int BUF_SIZE = 1024;\r
561                 \r
562                 BufferedInputStream inStream = null;\r
563                 File tmpFile = null;\r
564                 \r
565                 if(template instanceof BufferedInputStream) {\r
566                         inStream = (BufferedInputStream) template;\r
567                 }\r
568                 else {\r
569                         inStream = new BufferedInputStream((InputStream) template);\r
570                 }\r
571                 try {\r
572                         tmpFile = File.createTempFile(PREFIX, SUFFIX);\r
573                         FileOutputStream outStream = new FileOutputStream(tmpFile);\r
574                         \r
575                         byte buf[]=new byte[BUF_SIZE];\r
576                         int len;\r
577                         while((len = inStream.read(buf)) != -1){\r
578                                  outStream.write(buf, 0, len);\r
579                         }\r
580                         outStream.flush();\r
581                         outStream.close();\r
582                         log.debug("createTempFile: {}", tmpFile.getPath());\r
583                 } catch (SecurityException | IOException e) {\r
584                         log.error("template file create error: {}", e.getMessage());\r
585                         throw new JaxcelInputException("template file create error");\r
586                 }\r
587                 \r
588                 log.trace("createTempFile end");\r
589                 return tmpFile;\r
590         }\r
591 \r
592         /**\r
593          * Workbook生成\r
594          * @param book Workbookオブジェクト\r
595          */\r
596         private void makeBook(Workbook book) {\r
597                 log.trace("makeBook start");\r
598                 \r
599                 // シートでループ\r
600                 log.debug("sheet count: {}", book.getNumberOfSheets());\r
601                 for(int i = 0; i < book.getNumberOfSheets(); i++) {\r
602                         // カレントシート取得\r
603                         Sheet sheet = book.getSheetAt(i);\r
604                         if(sheet == null) {\r
605                                 log.warn("sheet[{}] is null. skip", i);\r
606                                 continue;\r
607                         }\r
608                         else if((sheet instanceof HSSFSheet && ((HSSFSheet)sheet).getDialog()) || (sheet instanceof XSSFDialogsheet)) {\r
609                                 log.debug("sheet[{}] is dialog sheet. skip", i);\r
610                                 continue;\r
611                         }\r
612                         else if(sheet instanceof XSSFChartSheet) {\r
613                                 log.debug("sheet[{}] is chart sheet. skip", i);\r
614                                 continue;\r
615                         }\r
616                         \r
617                         log.debug("sheet[{}] name: {}", i, sheet.getSheetName());\r
618 \r
619                         // シート生成\r
620                         makeSheet(sheet);\r
621                 }\r
622                 \r
623                 // 再計算\r
624                 book.setForceFormulaRecalculation(true);\r
625                 \r
626                 log.trace("makeBook end");\r
627         }\r
628         \r
629         /**\r
630          * ワークシート生成\r
631          * @param sheet ワークシートオブジェクト\r
632      */\r
633         private void makeSheet(Sheet sheet) {\r
634                 log.trace("makeSheet start");\r
635                 \r
636                 Row row;                                                // 行オブジェクト\r
637                 Cell cell;                                              // セルブジェクト\r
638                 TLParser tlParser;                              // パーサ\r
639 \r
640                 // カレントシート設定、パーサ生成\r
641                 context.setCurrentSheet(sheet);\r
642                 tlParser = new TLParser(context);\r
643 \r
644                 //最大行数\r
645                 int lastRowNum = sheet.getLastRowNum();\r
646                 log.debug("lastRowNum: {}", lastRowNum);\r
647                 \r
648                 //最大セル数\r
649                 int maxColNum = 0;\r
650                 \r
651                 // 行方向にループ\r
652                 for(int rowIdx = 0; rowIdx <= lastRowNum; rowIdx++) {\r
653                         // 行取得\r
654                         row = sheet.getRow(rowIdx);\r
655 \r
656                         // チェック\r
657                         if(row == null) {\r
658                                 log.debug("row[{}] is null", (rowIdx + 1));\r
659                                 continue;\r
660                         }\r
661 \r
662                         // 列最終取得・最大列数更新\r
663                         if(row.getLastCellNum() > maxColNum) {\r
664                                 maxColNum = row.getLastCellNum();\r
665                                 log.debug("maxColNum: {}", maxColNum);\r
666                         }\r
667 \r
668                         // 列方向にループ\r
669                         for(int cellIdx = 0; cellIdx <= maxColNum; cellIdx++) {\r
670                                 // セル取得\r
671                                 cell = row.getCell(cellIdx);\r
672 \r
673                                 // チェック\r
674                                 if(cell == null) {\r
675                                         log.debug("cell[{}] is null", (new CellReference(rowIdx, cellIdx)).formatAsString());\r
676                                         continue;\r
677                                 }\r
678                                 \r
679                                 // セルタイプにより分岐\r
680                                 switch (cell.getCellType()) {\r
681                                 // 文字列セル、計算式セル\r
682                                 case Cell.CELL_TYPE_STRING:\r
683                                 case Cell.CELL_TYPE_FORMULA:\r
684                                         // パース\r
685                                         tlParser.parse(cell);\r
686                                         // 再パースフラグONなら\r
687                                         if(tlParser.isReParseCell()) {\r
688                                                 // もう一度そのセルからループする\r
689                                                 cellIdx--;\r
690                                         }\r
691                                         break;\r
692                                 // 文字列セル、計算式セル以外\r
693                                 default:\r
694                                         log.debug("cell type is not string or formula");\r
695                                         continue;\r
696                                 }\r
697 \r
698                                 // 列最終取得・最大列数更新\r
699                                 if(row.getLastCellNum() > maxColNum) {\r
700                                         maxColNum = row.getLastCellNum();\r
701                                         log.debug("maxColNum update: {}", maxColNum);\r
702                                 }\r
703                         }\r
704                         //最大行数更新\r
705                         if(lastRowNum < sheet.getLastRowNum()) {\r
706                                 lastRowNum = sheet.getLastRowNum();\r
707                                 log.debug("lastRowNum update: {}", lastRowNum);\r
708                         }\r
709                 }\r
710                 log.trace("transformSheet end");\r
711         }\r
712 }\r