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