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 */
016package org.opengion.plugin.io;
017
018// import java.io.File;
019// import java.io.FileInputStream;
020// import java.io.FileOutputStream;
021// import java.io.IOException;
022import java.io.PrintWriter;
023// import java.util.Locale;
024
025// import org.apache.poi.ss.usermodel.Cell;
026// import org.apache.poi.ss.usermodel.CreationHelper;
027// import org.apache.poi.ss.usermodel.Font;
028// import org.apache.poi.ss.usermodel.RichTextString;
029// import org.apache.poi.ss.usermodel.Row;
030// import org.apache.poi.ss.usermodel.Sheet;
031// import org.apache.poi.ss.usermodel.Workbook;
032// import org.apache.poi.ss.usermodel.WorkbookFactory;
033
034import org.opengion.fukurou.model.NativeType;
035import org.opengion.fukurou.util.Closer;
036import org.opengion.fukurou.util.StringUtil;
037import org.opengion.hayabusa.common.HybsSystem;
038import org.opengion.hayabusa.common.HybsSystemException;
039import org.opengion.hayabusa.db.DBTableModel;
040
041import org.opengion.fukurou.model.ExcelModel;
042
043/**
044 * ネイティブEXCELファイルの書き出しクラスです。
045 *
046 * DefaultTableWriter を継承していますので,ラベル,名前,データの出力部のみ
047 * オーバーライドして,MIcrosoft Excelファイルの出力機能を実現しています。
048 *
049 * 出力形式は、openXML形式にも対応しています。
050 * 出力ファイルの拡張子が、.xlsならExcel2003のバイナリ形式、.xlsxならExcel2007の
051 * openXML形式で出力されます。
052 *
053 * @og.group ファイル出力
054 *
055 * @og.rev 4.3.4.3 (2008/12/22) 一部protected化
056 * @og.rev 4.3.6.7 (2009/05/22) ooxml形式対応
057 * @og.rev 6.0.1.2 (2014/08/08) ロジックの完全書き換え(保証もできない位・・・)
058 *
059 * @version  4.0
060 * @author       Kazuhiko Hasegawa
061 * @since    JDK5.0,
062 */
063public class TableWriter_Excel extends TableWriter_Default {
064        //* このプログラムのVERSION文字列を設定します。   {@value} */
065        private static final String VERSION = "6.0.1.2 (2014/08/08)" ;
066
067//      private Sheet   sheet                   = null;
068        private int             nRowIndex               = 0;                            // 6.0.1.2 (2014/08/08) private化
069        private String  filename                = null;                         // 3.5.4.3 (2004/01/05)
070        private String  sheetName               = "Sheet1";                     // 3.5.4.3 (2004/01/05)
071        private String  fontName                = null;                         // 3.8.5.3 (2006/08/07)
072        private short   fontPoint               = -1;                           // 3.8.5.3 (2006/08/07)
073        private String  refFilename             = null;                         // 3.5.4.3 (2004/01/05)
074        private String  refSheetName    = null;                         // 3.5.4.3 (2004/01/05)
075//      private CreationHelper createHelper     = null;                 // poi.xssf対応
076        // 5.1.4.0 (2010/03/01) 行番号情報を、出力する(true)/しない(false)を指定
077        private boolean         useNumber       = true;
078        private int             skipRowCount    = 0;                            // 6.0.1.2 (2014/08/08) データの書き込み開始位置設定
079
080        private ExcelModel excel                = null;                         // 6.0.2.0 (2014/08/29) 新規作成
081
082        /**
083         * DBTableModel から 各形式のデータを作成して,PrintWriter に書き出します。
084         * このメソッドは、EXCEL 書き出し時に使用します。
085         *
086         * 雛形シートを使う場合は、雛形シートの後ろに追加していきます。
087         * 最後には、雛形シートとして存在しな部分は、すべて削除します。
088         * 雛形シートを使わない場合は、新規シートに追加していくことになります。
089         * appendモードの場合は、オリジナルが雛形ファイルになります。
090         * 雛形ファイルの指定は、無効になります。
091         *
092         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
093         * @og.rev 5.1.4.0 (2010/03/01) columns 対応 、useNumber属性対応
094         * @og.rev 6.0.1.2 (2014/08/08) ロジックの完全書き換え(保証もできない位・・・)
095         *
096         * @see #isExcel()
097         */
098        @Override
099        public void writeDBTable() {
100//              if( ! createDBColumn() ) { return ; }           // 親クラスで実行
101
102                useNumber = isUseNumber();
103
104                // 3.5.6.0 (2004/06/18) 移動
105                if( filename == null ) {
106                        String errMsg = "ファイルが指定されていません。";
107                        throw new HybsSystemException(errMsg );
108                }
109
110                // appendモードの場合は、オリジナルが雛形ファイルになります。
111                // 雛形ファイルの指定は、無効になります。
112                if( isAppend() ) {
113                        // 互換性のため、雛形ファイルが出力ファイルと同じでない場合はエラーとします。
114                        if( refFilename != null && !filename.equalsIgnoreCase( refFilename ) ) {
115                                String errMsg = "追加(appendモード)の時、雛形ファイルの指定は無効です。" + HybsSystem.CR
116                                                                + " filename=[" + filename + "] , refFilename=[" + refFilename + "]"  + HybsSystem.CR ;
117                                throw new HybsSystemException( errMsg );
118                        }
119
120                        refFilename = filename ;
121                }
122
123                // 雛形があれば、雛形ファイルを読み込みます。なければ、オリジナルのファイルを読み込みます。
124                String  nameUse = filename;
125                boolean isRefFile = refFilename != null && refFilename.length() > 0;
126                if( isRefFile ) {
127                        nameUse = refFilename ;
128                }
129
130                // 既存の場合は、WorkbookFactoryで作成。新規の場合は、拡張子(.xlsx/.xls)に応じて、作成する。
131//              Workbook wb = createWorkbook( nameUse , isRefFile );
132                excel = new ExcelModel( nameUse , isRefFile );
133
134                // 雛形ファイルのシート数。最後にこの分は削除します。
135//              int refCnt = isRefFile ? wb.getNumberOfSheets() : 0 ;
136                int refCnt = isRefFile ? excel.getNumberOfSheets() : 0 ;
137
138                // appendモードの場合は、オリジナルが雛形ファイルになるため、雛形シートの削除は行いません。
139                if( isAppend() ) { refCnt = 0; }
140
141                // 雛形シートを使う場合
142                if( isRefFile ) {
143                        excel.setFont( fontName,fontPoint );
144                }
145                excel.createSheet( refSheetName,isRefFile );
146
147                // 雛形シートを使う場合
148//              if( isRefFile ) {
149//                      int refSheetIdx = 0;            // 雛形シート名の指定がない場合は、最初のシート
150//                      if( refSheetName != null ) { refSheetIdx = wb.getSheetIndex(refSheetName); }
151//
152//                      if( refSheetIdx < 0 ) {         // 雛形シート名が存在しなかった。
153//                              String errMsg = "指定の雛形シート名は、雛型ファイルに存在しませんでした。" + HybsSystem.CR
154//                                                              + " refFilename=[" + refFilename + "] , refSheetName=[" + refSheetName + "]"  + HybsSystem.CR ;
155//                              throw new HybsSystemException( errMsg );
156//                      }
157//
158//                      sheet = wb.cloneSheet( refSheetIdx );
159//              }
160//              else {
161//                      // 3.8.6.0 (2006/08/07) フォント名やフォントサイズの指定
162//                      // 雛形ファイルを使用しない場合のみ、設定可能です。
163//                      Font font = wb.getFontAt((short)0);
164//                      if( fontName != null ) {
165//                              font.setFontName( fontName );   // "MS Pゴシック" など
166//                      }
167//                      if( fontPoint > 0 ) {
168//                              font.setFontHeightInPoints( fontPoint );
169//                      }
170//
171//                      sheet = wb.createSheet();
172//              }
173
174                // シート名のセット。重複チェックと新しいシート名の作成処理を行う。
175//              wb.setSheetName(wb.getNumberOfSheets() -1, getNewSheetNameByName(wb, sheetName) );
176                excel.setLastSheetName( sheetName );
177
178                // poi.xssf対応(2009/04/08)
179//              createHelper = wb.getCreationHelper();
180
181                nRowIndex = skipRowCount;               // 6.0.1.2 (2014/08/08) 開始行の指定
182
183                super.writeDBTable( null );
184
185                // 指定以降の余計な行を削除
186//              removeSheetRow( sheet, nRowIndex );
187                excel.removeRow( nRowIndex );
188
189                // 雛型ファイルを使っていた場合、その雛形シートを削除する
190                if( isRefFile ) {
191                        excel.removeSheet( 0,refCnt-1);                 // 削除するシート番号は、From-To形式で自身を含みます。
192
193//                      for( int cnt=0; cnt<refCnt; cnt++ ) {
194//                              wb.removeSheetAt( 0 );
195//                      }
196                }
197
198                // メモリ中のデータをファイルに書き込む
199                excel.saveFile( filename );
200
201                // 3.5.6.0 (2004/06/18) close を finally で処理するように変更。
202//              FileOutputStream fileOut = null ;
203//              try {
204//                      fileOut = new FileOutputStream(filename);
205//                      wb.write(fileOut);
206//              }
207//              catch( IOException ex ) {
208//                      String errMsg = "ファイルへ書込み中にエラーが発生しました。" + HybsSystem.CR
209//                                              + ex.getMessage() + HybsSystem.CR
210//                                              + "  File=" + filename;                         // 5.1.8.0 (2010/07/01) errMsg 修正
211//                      throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
212//              }
213//              finally {
214//                      Closer.ioClose( fileOut );              // 4.0.0 (2006/01/31) close 処理時の IOException を無視
215//                      if( null != sheet ) { sheet = null; }
216//                      if( null != wb    ) { wb    = null; }
217//              }
218        }
219
220        /**
221         * DBTableModel から データを作成して,PrintWriter に書き出します。
222         *
223         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
224         * @og.rev 3.5.4.3 (2004/01/05) 引数に PrintWriter を受け取るように変更します。
225         * @og.rev 3.8.5.3 (2006/08/07) フォント名やフォントサイズの指定
226         * @og.rev 4.0.0.0 (2006/09/31) UnsupportedOperationException を発行します。
227         * @og.rev 6.0.1.2 (2014/08/08) 親クラスで同様の処理は定義済みのため、削除。
228         *
229         * @param       writer PrintWriterオブジェクト
230         */
231//      @Override
232//      public void writeDBTable( final PrintWriter writer )  {
233//              String errMsg = "このクラスでは実装されていません。";
234//              throw new UnsupportedOperationException( errMsg );
235//      }
236
237        /**
238         * PrintWriter に DBTableModelのラベル情報を書き込みます。
239         * 第一カラム目は、ラベル情報を示す "#Label" を書き込みます。
240         * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。
241         *
242         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
243         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
244         *
245         * @param       table  DBTableModelオブジェクト
246         * @param       writer PrintWriterオブジェクト
247         */
248        @Override
249        protected void writeLabel( final DBTableModel table,final PrintWriter writer ) {
250                short nColIndex = 0;
251//              Row   oRow = setFirstCellValue( nRowIndex++, nColIndex++, "#Label" );
252                excel.createRow( nRowIndex++ );
253                if( useNumber ) { headerCellValue( "Label",nColIndex++ ); }
254
255                for( int i=0; i<numberOfColumns; i++ ) {
256                        int clm = clmNo[i];
257                        if( clm < 0 ) {                 // 6.0.1.2 (2014/08/08) カラム飛ばし
258//                              setRowCellValue( oRow, nColIndex++, "", Cell.CELL_TYPE_STRING );
259                                headerCellValue( "",nColIndex++ );
260                                continue;
261                        }
262
263                        String val = dbColumn[clm].getLabel();
264                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、nColIndex を一つ戻して、値に # を付ける。
265//                      if( i==0 && !useNumber ) {
266//                              nColIndex-- ;
267//                              val = "#" + val;
268//                      }
269//                      setRowCellValue( oRow, nColIndex++, val,Cell.CELL_TYPE_STRING );
270                        headerCellValue( val,nColIndex++ );
271                }
272
273                // 余計なセルを削除
274//              removeRowCell( oRow, nColIndex );
275                excel.removeCell( nColIndex );
276        }
277
278        /**
279         * PrintWriter に DBTableModelの項目名情報を書き込みます。
280         * 第一カラム目は、項目名情報を示す "#Name" を書き込みます。
281         * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。
282         *
283         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
284         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
285         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
286         *
287         * @param       table  DBTableModelオブジェクト
288         * @param       writer PrintWriterオブジェクト
289         */
290        @Override
291        protected void writeName( final DBTableModel table,final PrintWriter writer ) {
292                short nColIndex = 0;
293//              Row   oRow = setFirstCellValue( nRowIndex++, nColIndex++, "#Name" );
294                excel.createRow( nRowIndex++ );
295                if( useNumber ) { headerCellValue( "Name",nColIndex++ ); }
296
297                for( int i=0; i<numberOfColumns; i++ ) {
298                        int clm = clmNo[i];
299                        if( clm < 0 ) {                 // 6.0.1.2 (2014/08/08) カラム飛ばし
300//                              setRowCellValue( oRow, nColIndex++, "",Cell.CELL_TYPE_STRING );
301                                headerCellValue( "",nColIndex++ );
302                                continue;
303                        }
304
305                        String val = table.getColumnName(clm);
306                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、nColIndex を一つ戻して、値に # を付ける。
307//                      if( i==0 && !useNumber ) {
308//                              nColIndex-- ;
309//                              val = "#" + val;
310//                      }
311//                      setRowCellValue( oRow, nColIndex++, val,Cell.CELL_TYPE_STRING );
312                        headerCellValue( val,nColIndex++ );
313                }
314
315                // 余計なセルを削除
316//              removeRowCell( oRow, nColIndex );
317                excel.removeCell( nColIndex );
318        }
319
320        /**
321         * PrintWriter に DBTableModelのサイズ情報を書き込みます。
322         * 第一カラム目は、サイズ情報を示す "#Size" を書き込みます。
323         * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。
324         *
325         * @og.rev 3.5.5.5 (2004/04/23) DBColumn の size と maxlength の 意味を変更
326         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
327         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
328         *
329         * @param       table  DBTableModelオブジェクト
330         * @param       writer PrintWriterオブジェクト
331         */
332        @Override
333        protected void writeSize( final DBTableModel table,final PrintWriter writer ) {
334                short nColIndex = 0;
335//              Row   oRow = setFirstCellValue( nRowIndex++, nColIndex++, "#Size" );
336                excel.createRow( nRowIndex++ );
337                if( useNumber ) { headerCellValue( "Size",nColIndex++ ); }
338
339                for( int i=0; i<numberOfColumns; i++ ) {
340                        int clm = clmNo[i];
341                        if( clm < 0 ) {                 // 6.0.1.2 (2014/08/08) カラム飛ばし
342//                              setRowCellValue( oRow, nColIndex++, "",Cell.CELL_TYPE_STRING );
343                                headerCellValue( "",nColIndex++ );
344                                continue;
345                        }
346
347                        // 4.0.0 (2005/01/31) メソッド名変更
348                        String val = String.valueOf(dbColumn[clm].getTotalSize());
349                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、nColIndex を一つ戻して、値に # を付ける。
350//                      if( i==0 && !useNumber ) {
351//                              nColIndex-- ;
352//                              val = "#" + val;
353//                      }
354//                      setRowCellValue( oRow, nColIndex++, val, Cell.CELL_TYPE_NUMERIC );
355                        headerCellValue( val,nColIndex++ );
356                }
357
358                // 余計なセルを削除
359//              removeRowCell( oRow, nColIndex );
360                excel.removeCell( nColIndex );
361        }
362
363        /**
364         * PrintWriter に DBTableModelのクラス名情報を書き込みます。
365         * 第一カラム目は、サイズ情報を示す "#Class" を書き込みます。
366         * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。
367         *
368         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
369         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
370         *
371         * @param       table  DBTableModelオブジェクト
372         * @param       writer PrintWriterオブジェクト
373         */
374        @Override
375        protected void writeClass( final DBTableModel table,final PrintWriter writer ) {
376                short nColIndex = 0;
377//              Row   oRow = setFirstCellValue( nRowIndex++, nColIndex++, "#Class" );
378                excel.createRow( nRowIndex++ );
379                if( useNumber ) { headerCellValue( "Class",nColIndex++ ); }
380
381                for( int i=0; i<numberOfColumns; i++ ) {
382                        int clm = clmNo[i];
383                        if( clm < 0 ) {                 // 6.0.1.2 (2014/08/08) カラム飛ばし
384//                              setRowCellValue( oRow, nColIndex++, "",Cell.CELL_TYPE_STRING );
385                                headerCellValue( "",nColIndex++ );
386                                continue;
387                        }
388
389                        String val = dbColumn[clm].getClassName();
390                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、nColIndex を一つ戻して、値に # を付ける。
391//                      if( i==0 && !useNumber ) {
392//                              nColIndex-- ;
393//                              val = "#" + val;
394//                      }
395//                      setRowCellValue( oRow, nColIndex++, val,Cell.CELL_TYPE_STRING );
396                        headerCellValue( val,nColIndex++ );
397                }
398
399                // 余計なセルを削除
400//              removeRowCell( oRow, nColIndex );
401                excel.removeCell( nColIndex );
402        }
403
404        /**
405         * PrintWriter に セパレーターを書き込みます。
406         * 第一カラム目は、サイズ情報を示す "#----" を書き込みます。
407         * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。
408         *
409         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
410         *
411         * @param       table  DBTableModelオブジェクト
412         * @param       writer PrintWriterオブジェクト
413         */
414        @Override
415        protected void writeSeparator( final DBTableModel table,final PrintWriter writer ) {
416                final String SEP = "----" ;
417
418                short nColIndex = 0;
419//              Row   oRow = setFirstCellValue( nRowIndex++, nColIndex++, "#----" );
420                excel.createRow( nRowIndex++ );
421                if( useNumber ) { headerCellValue( SEP,nColIndex++ ); }
422
423                for( int i=0; i<numberOfColumns; i++ ) {
424                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、単になにもしないだけ
425//                      if( i==0 && !useNumber ) {
426//                              continue;
427//                      }
428//                      setRowCellValue( oRow, nColIndex++, sep,Cell.CELL_TYPE_STRING );
429                        headerCellValue( SEP,nColIndex++ );
430                }
431
432                // 余計なセルを削除
433//              removeRowCell( oRow, nColIndex );
434                excel.removeCell( nColIndex );
435        }
436
437
438        /**
439         * ExcelModel#setCellValue(String.int) の第一カラムの場合に、コメントの # を追加する簡易メソッドです。
440         *
441         * colNo == 0 の場合だけ、引数の val に、"#" を追加します。
442         * これは、openGion特有のコメント行を意味するため、ヘッダーレコードにのみ適用します。
443         *
444         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
445         *
446         * @param       val   設定文字列
447         * @param       colNo 行番号
448         */
449        private void headerCellValue( final String val,final int colNo ) {
450                if( colNo == 0 ) {
451                        excel.setCellValue( "#" + val,colNo );
452                }
453                else {
454                        excel.setCellValue( val,colNo );
455                }
456        }
457
458        /**
459         * PrintWriter に DBTableModelのテーブル情報を書き込みます。
460         * このクラスでは,データを ダブルコーテーション(")で囲みます。
461         * PrintWriter に DBTableModelのテーブル情報を書き込みます。
462         *
463         * @og.rev 3.8.0.1 (2005/06/17) DBTypeが NVAR の場合は、元のUnicodeに戻します。
464         * @og.rev 3.8.5.3 (2006/08/07) DBType の nativeType に対応した、CELL_TYPE をセットします。
465         * @og.rev 4.1.1.2 (2008/02/28) NativeタイプをEnum型(fukurou.model.NativeType)に変更
466         * @og.rev 5.1.4.0 (2010/03/01) columns 対応
467         * @og.rev 5.1.4.0 (2010/03/01) useNumber属性対応
468         * @og.rev 5.2.1.0 (2010/10/01) useRenderer 対応
469         * @og.rev 5.7.6.3 (2014/05/23) stringOutput対応
470         * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加
471         *
472         * @param       table  DBTableModelオブジェクト
473         * @param       writer PrintWriterオブジェクト
474         */
475        @Override
476        protected void writeData( final DBTableModel table,final PrintWriter writer ) {
477                int numberOfRows =      table.getRowCount();
478
479                // 5.1.4.0 columns 対応。forループは、引数i で廻す。
480                boolean[] nvar  = new boolean[numberOfColumns];
481//              int[] cellType  = new int[numberOfColumns];
482                boolean[] isNums = new boolean[numberOfColumns];        // 6.0.2.0 (2014/08/29) NUMBER型かどうか
483                boolean useRenderer = isUseRenderer();                          // 5.2.1.0 (2010/10/01)
484
485                for( int i=0; i<numberOfColumns; i++ ) {
486                        int clm = clmNo[i];
487                        if( clm < 0 ) { continue; }                     // 6.0.1.2 (2014/08/08) カラム飛ばし
488
489                        // 5.7.6.3 (2014/05/23) ここでレンデラ時の文字タイプ判定を行う
490                        if( useRenderer && dbColumn[clm].isStringOutput() ){
491//                              cellType[i] = Cell.CELL_TYPE_STRING ;
492                                isNums[i]   = false;
493                        }
494                        else {
495                                NativeType nativeType = dbColumn[clm].getNativeType();
496                                switch( nativeType ) {
497                                        case INT    :
498                                        case LONG   :
499                                        case DOUBLE :
500//                                              cellType[i] = Cell.CELL_TYPE_NUMERIC ;
501                                                isNums[i]   = true;
502                                                        break;
503                                        case STRING :
504                                        case CALENDAR :
505                                        default :
506//                                                      cellType[i] = Cell.CELL_TYPE_STRING ;
507                                                        isNums[i]   = false;
508                                                        break;
509                                }
510                        }
511                        nvar[i] = "NVAR".equals( dbColumn[clm].getDbType()) ;
512                }
513//              boolean useRenderer = isUseRenderer();  // 5.2.1.0 (2010/10/01) , 5.7.6.3 (2014/05/23) 上へ移動
514
515                short nColIndex;
516//              Row   oRow;
517                for( int row=0; row<numberOfRows; row++ ) {
518                        nColIndex = 0;
519//                      oRow = setFirstCellValue( nRowIndex++, nColIndex++, String.valueOf( row+1 ) );
520                        excel.createRow( nRowIndex++ );
521                        if( useNumber ) { excel.setCellValue( String.valueOf( row+1 ),nColIndex++ ); }
522
523                        // 5.1.4.0 (2010/03/01) useNumber=false の場合は、nColIndex を一つ戻す。
524//                      if( !useNumber ) {
525//                              nColIndex-- ;
526//                      }
527
528                        for( int i=0; i<numberOfColumns; i++ ) {
529                                int clm = clmNo[i];
530                                if( clm < 0 ) {                 // 6.0.1.2 (2014/08/08) カラム飛ばし
531//                                      setRowCellValue( oRow, nColIndex++, "",Cell.CELL_TYPE_STRING );
532                                        excel.setCellValue( "",nColIndex++ );
533                                        continue;
534                                }
535
536                                String val = table.getValue(row,clm);
537                                if( nvar[i] ) {
538                                        val = StringUtil.getReplaceEscape( val );
539                                }
540                                // 5.2.1.0 (2010/10/01) useRenderer 対応
541                                else if( useRenderer ) {
542                                        val = StringUtil.spanCut( dbColumn[clm].getRendererValue( val ) );
543                                }
544
545//                              setRowCellValue( oRow, nColIndex++, val,cellType[i] );
546                                excel.setCellValue( val,nColIndex++,isNums[i] );
547                        }
548
549                        // 余計なセルを削除
550//                      removeRowCell( oRow, nColIndex );
551                        excel.removeCell( nColIndex );
552                }
553        }
554
555        /**
556         * Excelの指定行の一番目セルにデータを設定する。
557         *
558         * @og.rev 4.3.4.0 (2008/12/01) POI3.2対応
559         * @og.rev 4.3.4.3 (2008/12/22) protected化
560         * @og.rev 6.0.1.2 (2014/08/08) private化
561         *
562         * @param        indexOfRow 行の番号
563         * @param        indexOfCell セルの番号
564         * @param        dataVal    String文字列
565         *
566         * @return       Rowのobject型
567         */
568////    protected Row setFirstCellValue( final int indexOfRow, final int indexOfCell, final String dataVal ) {
569//      private Row setFirstCellValue( final int indexOfRow, final int indexOfCell, final String dataVal ) {
570//              Row oRow = sheet.getRow( indexOfRow );
571//              if( oRow == null ) { oRow = sheet.createRow( indexOfRow ); }
572//
573//              Cell oCell = oRow.getCell( indexOfCell );
574//              if( null == oCell ) { oCell = oRow.createCell( indexOfCell ); }
575//
576//              RichTextString richText = createHelper.createRichTextString( dataVal );
577//              oCell.setCellValue( richText );
578//
579//              return oRow;
580//      }
581
582        /**
583         * Excelの指定セルにデータを設定する。
584         *
585         * @og.rev 4.3.4.0 (2008/12/01) POI3.2対応
586         * @og.rev 4.3.4.3 (2008/12/22) protected化
587         * @og.rev 5.7.4.1 (2014/03/15) useRenderer対応
588         * @og.rev 5.7.6.3 (2014/05/23) stringOutput対応
589         * @og.rev 6.0.1.2 (2014/08/08) private化
590         *
591         * @param        oRow   Row型のオブジェクト
592         * @param        indexOfCell セルの番号
593         * @param        dataVal    String文字列
594         * @param        cellType   [Cell.CELL_TYPE_STRING/Cell.CELL_TYPE_NUMERIC]
595         */
596////    protected void setRowCellValue( final Row oRow, final int indexOfCell, final String dataVal,final int cellType ) {
597//      private void setRowCellValue( final Row oRow, final int indexOfCell, final String dataVal,final int cellType ) {
598//              Cell oCell = oRow.getCell( indexOfCell );
599//              if( null == oCell ) { oCell = oRow.createCell( indexOfCell ); }
600//
601//              // 5.7.4.1 (2014/03/15) useRendererがtrueの場合はdouble変換をかけない
602////            if( !isUseRenderer() && cellType == Cell.CELL_TYPE_NUMERIC ) {
603//              if( cellType == Cell.CELL_TYPE_NUMERIC ) {
604//                      oCell.setCellValue( StringUtil.parseDouble( dataVal ) );
605//              }
606//              else {
607//                      RichTextString richText = createHelper.createRichTextString( dataVal );
608//                      oCell.setCellValue( richText );
609//              }
610//      }
611
612        /**
613         * Excelの指定セルをシートから削除する。
614         *
615         * @og.rev 4.3.4.0 (2008/12/01) POI3.2対応
616         * @og.rev 4.3.4.3 (2008/12/22) protected化
617         * @og.rev 6.0.1.2 (2014/08/08) private化
618         *
619         * @param        oRow   Row型のオブジェクト
620         * @param        nBegin     セルの開始番号
621         */
622////    protected void removeRowCell( final Row oRow, final int nBegin ) {
623//      private void removeRowCell( final Row oRow, final int nBegin ) {
624//              int nEnd = oRow.getLastCellNum();
625////            for( int nIndex = nBegin; nIndex <= nEnd; nIndex++) {
626//              for( int nIndex = nEnd; nIndex >= nBegin; nIndex--) {
627//                      Cell oCell = oRow.getCell( nIndex );
628//                      if( null != oCell ) { oRow.removeCell(oCell); }
629//              }
630//      }
631
632        /**
633         * Excelの指定行をシートから削除する。
634         * nBegin は、すでに+1されているので、= になるまで削除します。
635         *
636         * @param        oThisSheet Sheet型のオブジェクト
637         * @param        nBegin     行の開始番号
638         */
639//      private void removeSheetRow( final Sheet oThisSheet, final int nBegin ) {
640//              int nEnd = oThisSheet.getLastRowNum();
641////            for( int nIndex = nBegin; nIndex <= nEnd; nIndex++) {
642//              for( int nIndex = nEnd; nIndex >= nBegin; nIndex--) {
643//                      Row oRow = oThisSheet.getRow( nIndex );
644//                      if( null != oRow ) { oThisSheet.removeRow(oRow); }
645//              }
646//      }
647
648        /**
649         * DBTableModelのデータとして書き込むときのシート名をセットします。
650         * 初期値は、"Sheet1" です。同じ名称のシートが存在する場合、そのシート
651         * 名の後に(2)、(3)のような文字列をくっ付けます。
652         *
653         * ※ 改造前は、シートの名前は30桁文字(31個文字)なので、そのチェックと
654         *    substring による桁数調整が入っていましたが、やめます。
655         *
656         * @og.rev 6.0.1.2 (2014/08/08) シート名の桁数チェックを廃止(簡略化と希望的観測)
657         *
658         * @param        workbook   Workbookオブジェクト
659         * @param        nameSet    String文字列,指定のシート名
660         * @return      シート名
661         */
662////    protected String getNewSheetNameByName( final Workbook workbook, final String nameSet) {
663//      private String getNewSheetNameByName( final Workbook workbook, final String nameSet) {
664//              String nameSheet = nameSet;
665//              int nCount  = 1;
666//
667//              while( workbook.getSheetIndex(nameSheet) >= 0 ) {       // シート名が存在している場合
668//                      nameSheet = nameSet + "(" + nCount + ")";
669//                      nCount++;
670//              }
671//
672//              return nameSheet;
673//      }
674
675        /**
676         * 出力先ファイル名をセットします。(DIR + Filename)
677         * これは、EXCEL追加機能として実装されています。
678         *
679         * @og.rev 3.5.4.3 (2004/01/05) 新規作成
680         *
681         * @param   fname EXCEL雛型参考ファイル名
682         */
683        @Override
684        public void setFilename( final String fname ) {
685                filename = fname;
686        }
687
688        /**
689         * DBTableModelのデータとして読み込むときのシート名を設定します。
690         * 初期値は、"Sheet1" です。
691         * これは、EXCEL追加機能として実装されています。
692         *
693         * @og.rev 3.5.4.2 (2003/12/15) 新規追加
694         *
695         * @param   shtName シート名
696         */
697        @Override
698        public void setSheetName( final String shtName ) {
699                if( shtName != null ) { this.sheetName = shtName; }
700        }
701
702        /**
703         * このクラスが、EXCEL対応機能を持っているかどうかを返します。
704         *
705         * EXCEL対応機能とは、シート名のセット、雛型参照ファイル名のセット、
706         * 書き込み元ファイルのFileオブジェクト取得などの、特殊機能です。
707         * 本来は、インターフェースを分けるべきと考えますが、taglib クラス等の
708         * 関係があり、問い合わせによる条件分岐で対応します。
709         *
710         * @og.rev 3.5.4.3 (2004/01/05) 新規追加
711         *
712         * @return      EXCEL対応機能を持っているかどうか(常に true)
713         */
714        @Override
715        public boolean isExcel() {
716                return true;
717        }
718
719        /**
720         * EXCEL雛型参考ファイル名をセットします。(DIR + Filename)
721         * これは、EXCEL追加機能として実装されています。
722         *
723         * @og.rev 3.5.4.3 (2004/01/05) 新規作成
724         *
725         * @param   rfname EXCEL雛型参考ファイル名
726         */
727        @Override
728        public void setRefFilename( final String rfname ) {
729                refFilename = rfname;
730        }
731
732        /**
733         * EXCEL雛型参考ファイルのシート名を設定します。
734         * これは、EXCEL追加機能として実装されています。
735         *
736         * EXCELファイルを書き出す時に、雛型として参照するシート名を指定します。
737         * これにより、複数の形式の異なるデータを順次書き出したり(appendモードを併用)する
738         * ことや、シートを指定して新規にEXCELを作成する場合にフォームを設定する事が可能になります。
739         * 初期値は、null(第一シート) です。
740         *
741         * @og.rev 3.5.4.3 (2004/01/05) 新規追加
742         *
743         * @param   rshtName シート名
744         */
745        @Override
746        public void setRefSheetName( final String rshtName )  {
747                if( rshtName != null ) { refSheetName = rshtName; }
748        }
749
750        /**
751         * データの書き込み開始位置を設定します(初期値:0)。
752         *
753         * TAB区切りテキストやEXCEL等のデータの書き込みの開始位置を指定します。
754         * 属性名は、行を飛ばす処理ということで、readTable タグと同じ名称です。
755         * ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす
756         * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。)
757         * 行の読み飛ばしと、カラムの読み飛ばし(columns)、refFileURL、refFilename、
758         * refSheetName とともに使用すれば、ある程度のレイアウト設定が可能です。
759         * なお、この機能は、TableWriter_Excel のみに実装します。
760         *
761         * @og.rev 6.0.1.2 (2014/08/08) 新規作成
762         *
763         * @param       skipCount 書き込み開始位置
764         */
765        @Override
766        public void setSkipRowCount( final int skipCount ) {
767                skipRowCount = skipCount ;
768        }
769
770        /**
771         * EXCEL出力時のデフォルトフォント名を設定します。
772         * これは、EXCEL追加機能として実装されています。
773         *
774         * EXCELファイルを書き出す時に、デフォルトフォント名を指定します。
775         * フォント名は、EXCELのフォント名をそのまま使用してください。
776         * 内部的に、POI の org.apache.poi.hssf.usermodel.HSSFFont#setFontName( String )
777         * に設定されます。
778         * 雛形ファイルを使用しない場合のみ、設定可能です。
779         *
780         * @og.rev 3.8.5.3 (2006/08/07) 新規追加
781         *
782         * @param   font デフォルトフォント名
783         */
784        @Override
785        public void setFontName( final String font ) {
786                fontName = font ;
787        }
788
789        /**
790         * EXCEL出力時のデフォルトフォントポイント数を設定します。
791         * これは、EXCEL追加機能として実装されています。
792         *
793         * EXCELファイルを書き出す時に、デフォルトポイント数を指定します。
794         * 内部的に、POI の org.apache.poi.hssf.usermodel.HSSFFont#setFontHeightInPoints( short )
795         * に設定されます。
796         * 雛形ファイルを使用しない場合のみ、設定可能です。
797         *
798         * @og.rev 3.8.5.3 (2006/08/07) 新規追加
799         *
800         * @param   point デフォルトフォントポイント数
801         */
802        @Override
803        public void setFontPoint( final short point ) {
804                fontPoint = point;
805        }
806
807        /**
808         * EXCELファイルのWookbookというStream(MicrosoftのOLE用語)を作ります
809         * 条件によって、新規かとファイルから読み込み書き込みかが分かれます。
810         *
811         * @og.rev 6.0.1.2 (2014/08/08) メソッド統合
812         *
813         * @param   fname  EXCEL参考ファイル名
814         * @param   isOpen true:ファイルオープン/false:新規作成
815         *
816         * @return  EXCELファイルのWorkbook
817         */
818////    protected Workbook createWorkbook( final String fname ) {
819//      private Workbook createWorkbook( final String fname , final boolean isOpen ) {
820//              final Workbook rtnWb ;
821//
822//              if( isOpen ) {
823//                      // File オブジェクトでcreate すると、ファイルがオープンされたままになってしまう。
824//                      FileInputStream fileIn  = null;
825//                      try {
826//                              fileIn = new FileInputStream(fname);
827//                              rtnWb = WorkbookFactory.create(fileIn);
828//                      }
829//                      catch ( Exception ex ) {
830//                              String errMsg = "ファイル読込みエラー[" + fname + "]"  ;
831//                              throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
832//                      }
833//                      finally {
834//                              Closer.ioClose( fileIn );               // 4.0.0 (2006/01/31) close 処理時の IOException を無視
835//                      }
836//              }
837//              else {
838//                      // 新規の場合、ファイル名に.xlsxで終了した場合⇒.xlsx形式ファイル作成、その他⇒.xls形式ファイル作成
839//                      if( fname.toLowerCase(Locale.JAPAN).endsWith( ".xlsx" ) ) {
840//                              rtnWb = new org.apache.poi.xssf.usermodel.XSSFWorkbook();
841//                      }
842//                      else {
843//                              rtnWb = new org.apache.poi.hssf.usermodel.HSSFWorkbook();
844//                      }
845//              }
846//              return rtnWb;
847//      }
848}