001    /*
002     * Copyright (c) 2009 The openGion Project.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013     * either express or implied. See the License for the specific language
014     * governing permissions and limitations under the License.
015     */
016    package org.opengion.hayabusa.report;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.common.HybsSystemException;
020    import org.opengion.fukurou.util.Closer ;
021    
022    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
023    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
024    import org.apache.poi.hssf.usermodel.HSSFSheet;
025    import org.apache.poi.hssf.usermodel.HSSFRow;
026    import org.apache.poi.hssf.usermodel.HSSFCell;
027    import org.apache.poi.hssf.usermodel.HSSFRichTextString;
028    
029    import java.io.FileInputStream;
030    import java.io.FileOutputStream;
031    import java.io.IOException;
032    
033    import java.util.regex.Pattern;
034    import java.util.regex.Matcher;
035    
036    /**
037     * DBTableReport インターフェース を実?たネイ?ブEXCEL形式で出力するクラスです?
038     * AbstractDBTableReport を継承して?す?で?writeReport() のみオーバ?ライドして??
039     * 固定長?ファイルの出力機?を実現して?す?
040     *
041     * @og.group 帳票シス?
042     *
043     * @version  4.0
044     * @author   Kazuhiko Hasegawa
045     * @since    JDK5.0,
046     */
047    public class DBTableReport_Excel extends AbstractDBTableReport {
048    
049            private static final String EXCEL_FILE_EXT        = ".xls";
050            private static final Pattern PATTERN_KEY =
051                              Pattern.compile("\\{@((\\w+?)(?:_(\\d+?))?)\\}", java.util.regex.Pattern.MULTILINE);
052    
053            // POIの解析した式?中に変な属?が付けられて、これを取り除?patternExcludeInFormula)
054            private static final Pattern PATTERN_EXIN =
055                              Pattern.compile("ATTR\\(semiVolatile\\)", java.util.regex.Pattern.MULTILINE);
056    
057            HSSFWorkbook wb = null;
058    
059            /**
060             * DBTableModel から ??タを作?して,PrintWriter に書き?します?
061             *
062             */
063            @Override
064            public void writeReport() {
065                    setHeaderFooter();
066                    initReader();
067                    initWriter();
068                    changeSheet();
069                    close();
070            }
071    
072            /**
073             * POIFSFileSystem を?初期化します?
074             * これは?型ファイルの終端まで読取り、??た?合?もう?
075             * 初めから読み込みなおす処?行います?
076             * 基本?、書き込みも?期化する?があります?
077             *
078             * メモリ上に読み込んで、繰り返し利用するかど?は、実?存です?
079             *
080             */
081            @Override
082            protected void initReader() {
083                    if( null != wb ) { wb = null; }
084    
085                    FileInputStream  istream = null;
086                    try {
087                            istream = new FileInputStream(templateFile);
088                            POIFSFileSystem fs = new POIFSFileSystem(istream);
089                            wb = new HSSFWorkbook(fs);
090                    }
091                    catch( IOException ex ) {
092                            String errMsg = "ファイル名がオープン出来ませんでした?
093                                                    + HybsSystem.CR
094                                                    + "  File:" + templateFile;
095                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び?更
096                    }
097                    finally {
098                            Closer.ioClose( istream );      // 4.0.0 (2006/01/31) close 処?の IOException を無?
099                    }
100            }
101    
102            /**
103             * FileOutputStream を?初期化します?
104             * これは?型ファイルを終端まで読取り、??た?合?出力ファイル名を
105             * 変えて、別ファイルとして出力する為のも?です?
106             * 基本?、読取も初期化する?があります?
107             *
108             * 現在の??POIはメモリ上にExcelファイルを作?する為、作?したファイルの書く込?
109             * ファイル閉じる時点に伸ばされます?
110             *
111             */
112            @Override
113            protected void initWriter() {
114                    // ここでは処?行いません?
115            }
116    
117            /**
118             * リー??、ライターの終???行います?
119             * こ?メソ?が呼ばれたタイミングで、実際にファイル出力を行います?
120             *
121             */
122            protected void close() {
123    
124                    String filename = htmlDir + HybsSystem.FS + htmlFileKey + EXCEL_FILE_EXT ;
125    
126                    FileOutputStream fileOut = null;
127                    try {
128                            // Write the output to a file
129                            fileOut = new FileOutputStream(filename);
130                            wb.write(fileOut);
131                    }
132                    catch( IOException ex ) {
133                            wb = null;
134                            String errMsg = "ファイル名がオープン出来ませんでした?
135                                                    + HybsSystem.CR
136                                                    + "  File:" + filename;
137                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び?更
138                    }
139                    finally {
140                            Closer.ioClose( fileOut );      // 4.0.0 (2006/01/31) close 処?の IOException を無?
141                    }
142            }
143    
144            /**
145             * Excelの雛型をコピ?して、そのシートに帳票??タを埋め込みます?
146             * ??な属?がある所に??対応して?予定?
147             * ?ブクラスで実?てください?
148             *
149             * @og.rev 4.3.4.0 (2008/12/01) POI3.2対?
150             *
151             */
152            protected void changeSheet() {
153                    HSSFSheet patternSheet = wb.getSheetAt(0);
154                    while(!rowOver) {
155                            HSSFSheet sheet2 = wb.cloneSheet(0);
156            //              HSSFRow oRow2;
157                            int nFirstRow = sheet2.getFirstRowNum();
158                            int nLastRow  = sheet2.getLastRowNum();
159            //              int nTotalRows = patternSheet.getPhysicalNumberOfRows();
160                            for( int nIndexRow = nFirstRow; nIndexRow <= nLastRow; nIndexRow++) {
161                                    HSSFRow oRow = patternSheet.getRow(nIndexRow);
162                                    if( null != oRow ) {
163            //                              int nTotalCells = oRow.getPhysicalNumberOfCells();
164                                            // 4.3.4.0 (2008/12/01) POI3.2対応?shortをintにする?
165                                            // short nFirstCell = oRow.getFirstCellNum();
166                                            // short nLastCell  = oRow.getLastCellNum();
167                                            int nFirstCell = oRow.getFirstCellNum();
168                                            int nLastCell  = oRow.getLastCellNum();
169    //                                      for( short nIndexCell = nFirstCell; nIndexCell <= nLastCell; nIndexCell++) {
170                                            for( int nIndexCell = nFirstCell; nIndexCell <= nLastCell; nIndexCell++) {
171                                                    HSSFCell oCell = oRow.getCell(nIndexCell);
172                                                    if( null != oCell ) { changeCell(oCell);}
173                                            }
174                                    }
175                            }
176                    }
177            }
178    
179            /**
180             * セル??を変更します?
181             *
182             * @og.rev 4.3.4.0 (2008/12/01) POI3.2対?
183             *
184             * @param oCell HSSFCellオブジェク?
185             */
186            protected void changeCell(final HSSFCell oCell) {
187                    String strText;
188                    HSSFRichTextString richText;
189                    int nCellType = oCell.getCellType();
190                    switch(nCellType) {
191                            case HSSFCell.CELL_TYPE_FORMULA:
192                                    strText = changeData(changeFormulaAttr(oCell.getCellFormula()));
193                                    if( null != strText ) {
194            //                              oCell.setCellType(HSSFCell.CELL_TYPE_FORMULA);
195            //                              oCell.setEncoding(HSSFCell.ENCODING_UTF_16);
196                                            oCell.setCellFormula(strText);
197                                    }
198                                    break;
199                            case HSSFCell.CELL_TYPE_STRING:
200            // POI3.0       strText =  changeData(oCell.getStringCellValue());
201                                    richText = oCell.getRichStringCellValue();
202                                    strText =  changeData(richText.getString());
203                                    if( null != strText ) {
204            //                              oCell.setCellType(HSSFCell.CELL_TYPE_STRING);
205            // POI3.0               oCell.setEncoding(HSSFCell.ENCODING_UTF_16);
206            // POI3.2               oCell.setCellValue( strText );  // POI3.0 Deprecation
207                                            oCell.setCellValue( new HSSFRichTextString(strText) );
208                                    }
209                                    break;
210            //              case HSSFCell.CELL_TYPE_NUMERIC:
211            //                      break;
212            //              case HSSFCell.CELL_TYPE_BOOLEAN:
213            //                      break;
214            //              case HSSFCell.CELL_TYPE_ERROR:
215            //                      break;
216                            default :
217                                    break;
218                    }
219            }
220    
221            /**
222             * POIで解釈したExcel式?中の変な属?を加工して、?力します?
223             * ??な属?がある所に??対応して?予定?
224             * ?ブクラスで実?てください?
225             *
226             * @param       inLine  入力文字?
227             *
228             * @return      出力文字?
229             */
230            protected String changeFormulaAttr( final String inLine ) {
231                    // rowOver で、かつ ペ?ジブレークか?ージエンドカ?の場合?処???
232                    Matcher  matcher = PATTERN_EXIN.matcher(inLine);
233                    return (matcher.find()) ? matcher.replaceAll("") : inLine;
234            }
235    
236            /**
237             * 入力文字? を加工して、?力します?
238             * ??タをテーブルモ?より読み取り、?をセ?します?
239             * ?ブクラスで実?てください?
240             *
241             * @param       inLine  入力文字?
242             *
243             * @return      出力文字?. ??の変換は要らな??合?nullを返しま?
244             */
245            @Override
246            protected String changeData( final String inLine ) {
247                    boolean bFind = false;
248    
249                    // rowOver で、かつ ペ?ジブレークか?ージエンドカ?の場合?処???
250                    Matcher  matcher = PATTERN_KEY.matcher(inLine);
251                    StringBuffer sb = new StringBuffer();   // Matcher.appendTail( StringBuffer ) の為
252    
253                    while (matcher.find()) {
254    //                      matcher.appendReplacement(sb, rowOver ? "" : getValue(matcher.group( 1 )));
255                            matcher.appendReplacement(sb, getValue(matcher.group( 1 )));
256                            bFind = true;
257                    }
258    
259                    if( bFind ) {
260                            matcher.appendTail(sb);
261                            return sb.toString();
262                    }
263                    else {
264                            return null;
265                    }
266            }
267    
268            /**
269             * 入力文字? を読み取って、?力します?
270             * tr タグを目印に??trタグ?ずつ取り出します?
271             * 読み取りを終?る?合?、null を返します?
272             * ?ブクラスで実?てください?
273             * ※ こ?クラスでは実?れて?せん?
274             *
275             * @return      出力文字?
276             */
277            @Override
278            protected String readLine() {
279                    throw new UnsupportedOperationException();
280            }
281    
282            /**
283             * 入力文字? を読み取って、?力します?
284             * ?ブクラスで実?てください?
285             * ※ こ?クラスでは実?れて?せん?
286             *
287             * @param line 入力文字?
288             */
289            @Override
290            protected void println( final String line ) {
291                    throw new UnsupportedOperationException();
292            }
293    }