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.plugin.io;
017    
018    import java.io.BufferedReader;
019    import java.io.FileInputStream;
020    import java.io.IOException;
021    import java.io.InputStream;
022    // import java.text.DateFormat;
023    import java.text.DecimalFormat;
024    import java.text.NumberFormat;
025    // import java.text.SimpleDateFormat;
026    // import java.util.Locale;
027    import java.util.List;
028    import java.util.ArrayList;
029    
030    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
031    import org.apache.poi.ss.usermodel.Cell;
032    import org.apache.poi.ss.usermodel.DateUtil;
033    import org.apache.poi.ss.usermodel.RichTextString;
034    import org.apache.poi.ss.usermodel.Row;
035    import org.apache.poi.ss.usermodel.Sheet;
036    import org.apache.poi.ss.usermodel.Workbook;
037    import org.apache.poi.ss.usermodel.WorkbookFactory;
038    import org.apache.poi.ss.usermodel.CreationHelper;
039    import org.apache.poi.ss.usermodel.FormulaEvaluator;
040    import org.opengion.fukurou.util.Closer;
041    import org.opengion.fukurou.util.StringUtil;
042    import org.opengion.fukurou.util.HybsDateUtil;
043    import org.opengion.hayabusa.common.HybsSystem;
044    import org.opengion.hayabusa.common.HybsSystemException;
045    import org.opengion.hayabusa.db.DBTableModelUtil;
046    
047    /**
048     * POI による、EXCELバイナリファイルを読み取る実è£?‚¯ラスですã?
049     *
050     * ファイル名ã?シート名を指定して、データを読み取ることが可能ですã?
051     * 第ä¸?‚«ラãƒ?�Œ # で始まる行ã?、コメント行なので、読み飛ã?しますã?
052     * カラãƒ?��のæŒ?®š行で、カラãƒ?��ã�?null の場合ã?、その列ã?読み飛ã?しますã?
053     *
054     * 入力形式ã?、openXML形式にも対応してã�?�¾すã?
055     * ファイルのå†?®¹に応じてã€?xlsと.xlsxのどちらで読み取るかã?、å?部çš?�«
056     * 自動判定されますã?
057     *
058     * @og.rev 3.5.4.8 (2004/02/23) 新規作æ?
059     * @og.rev 4.3.6.7 (2009/05/22) ooxml形式対å¿?
060     * @og.group ファイル入åŠ?
061     *
062     * @version  4.0
063     * @author   Kazuhiko Hasegawa
064     * @since    JDK5.0,
065     */
066    public class TableReader_Excel extends TableReader_Default {
067            //* こã?プログラãƒ??VERSIONæ–?­—å?を設定しますã?       {@value} */
068            private static final String VERSION = "5.5.8.2 (2012/11/09)" ;
069    
070            private String  filename                = null;         // 3.5.4.3 (2004/01/05)
071            private String  sheetName               = null;         // 3.5.4.2 (2003/12/15)
072            private String  sheetNos                = null;         // 5.5.7.2 (2012/10/09)
073    
074            private String  constKeys               = null;         // 5.5.8.2 (2012/11/09) 固定å?となるカラãƒ?��(CSV形å¼?
075            private String  constAdrs               = null;         // 5.5.8.2 (2012/11/09) 固定å?となるアドレス(è¡?åˆ?è¡?åˆ?・・・)
076            private String  nullBreakClm    = null;         // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
077    
078            /**
079             * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
080             * コメンãƒ?空行を除きã?æœ??の行ã?、å¿?�šé ?›®名がå¿?¦�ですã?
081             * それ以降ã?、コメンãƒ?空行を除きã?ãƒ??タとして読み込んでã�?��ますã?
082             * こã?メソãƒ?ƒ‰は、EXCEL 読み込み時に使用しますã?
083             *
084             * @og.rev 4.0.0.0 (2006/09/31) 新規追åŠ?
085             * @og.rev 5.1.6.0 (2010/05/01) columns 処ç�?追åŠ?
086             * @og.rev 5.1.6.0 (2010/05/01) skipRowCountの追åŠ?
087             * @og.rev 5.1.8.0 (2010/07/01) Exception をきちっと記述(InvalidFormatException)
088             * @og.rev 5.2.1.0 (2010/10/01) setTableColumnValues メソãƒ?ƒ‰を経由して、テーブルにãƒ??タをセãƒ?ƒˆするã€?
089             * @og.rev 5.5.1.2 (2012/04/06) HeaderData ã‚?try の上にã�?�—、エラーメãƒ?‚»ージを取得できるようにするã€?
090             * @og.rev 5.5.7.2 (2012/10/09) sheetNos 追åŠ?�«よるè¤?•°シートã?マã?ジ読み取りサポã?ãƒ?
091             * @og.rev 5.5.8.2 (2012/11/09) HeaderData に ãƒ?ƒ�ãƒ?‚°フラグを渡しますã?
092             *
093             * @see #isExcel()
094             */
095            @Override
096            public void readDBTable() {
097                    InputStream  in = null;
098                    HeaderData data = null;         // 5.5.1.2 (2012/04/06)
099                    try {
100                            boolean isDebug = isDebug();                    // 5.5.7.2 (2012/10/09) ãƒ?ƒ�ãƒ?‚°æƒ??
101    
102                            if( isDebug ) { System.out.println( " Filename=" + filename ) ; }
103    
104                            in = new FileInputStream(filename);
105    
106    //                      POIFSFileSystem fs = new POIFSFileSystem(in);
107    //                      HSSFWorkbook wb = new HSSFWorkbook(fs);
108    //                      HSSFSheet sheet ;
109                            Workbook wb = WorkbookFactory.create(in);
110    //                      Sheet sheet ;
111                            Sheet[] sheets ;                                                                        // 5.5.7.2 (2012/10/09) 配å?に変更
112    
113                            if( isDebug ) { wb = ExcelUtil.activeWorkbook( wb ); }          // ãƒ?ƒ�ãƒ?‚°モード時には、エクセルのアクãƒ?‚£ブセル領域のみにシュリンクを行う
114    
115                            // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?sheetNos のæŒ?®šが優先されるã€?
116                            if( sheetNos != null && sheetNos.length() > 0 ) {
117                                    String[] sheetList = StringUtil.csv2ArrayExt( sheetNos , wb.getNumberOfSheets()-1 );    // æœ?¤§シート番号は、シート数-1
118                                    sheets = new Sheet[sheetList.length];
119                                    for( int i=0; i<sheetList.length; i++ ) {
120                                            sheets[i] = wb.getSheetAt( Integer.parseInt( sheetList[i] ) );
121                                    }
122                            }
123                            else if( sheetName != null && sheetName.length() > 0 ) {
124                                    Sheet sheet = wb.getSheet( sheetName );
125                                    if( sheet == null ) {
126                                            String errMsg = "対応するシートが存在しませんã€?Sheet=[" + sheetName + "]" ;
127                                            throw new HybsSystemException( errMsg );
128                                    }
129                                    sheets = new Sheet[] { sheet };
130                            }
131                            else {
132                                    Sheet sheet = wb.getSheetAt(0);
133                                    sheets = new Sheet[] { sheet };
134                            }
135    
136    //                      if( sheetName == null || sheetName.length() == 0 ) {
137    //                              sheet = wb.getSheetAt(0);
138    //                      }
139    //                      else {
140    //                              sheet = wb.getSheet( sheetName );
141    //                              if( sheet == null ) {
142    //                                      String errMsg = "対応するシートが存在しませんã€?Sheet=[" + sheetName + "]" ;
143    //                                      throw new HybsSystemException( errMsg );
144    //                              }
145    //                      }
146    
147                            boolean  nameNoSet = true;
148                            table = DBTableModelUtil.newDBTable();
149    
150                            int numberOfRows = 0;
151    //                      HeaderData data = new HeaderData();
152                            data = new HeaderData();                                // 5.5.1.2 (2012/04/06)
153    
154                            data.setDebug( isDebug );                               // 5.5.8.2 (2012/11/09)
155    
156                            // 5.1.6.0 (2010/05/01) columns 処ç�?
157                            data.setUseNumber( isUseNumber() );
158    
159                            // 5.5.8.2 (2012/11/09) 固定å?となるカラãƒ?��(CSV形å¼?とアドレス(è¡?åˆ?è¡?åˆ?・・・)を設å®?
160                            data.setSheetConstData( constKeys,constAdrs );
161    
162                            int nullBreakClmAdrs = -1;                                              // 5.5.8.2 (2012/11/09) nullBreakClm の DBTableModel上ã?アドレスã€?1 は、未使用
163                            if( data.setColumns( columns ) ) {
164                                    nameNoSet = false;
165                                    table.init( data.getColumnSize() );
166                                    setTableDBColumn( data.getNames() ) ;
167                                    nullBreakClmAdrs = table.getColumnNo( nullBreakClm, false );    // 5.5.8.2 (2012/11/09) カラãƒ?•ª号取得ã?存在しなければ -1 を返すã€?
168                            }
169    
170                            int skip = getSkipRowCount();                                   // 5.1.6.0 (2010/05/01)
171                            // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?
172                            for( int i=0; i<sheets.length; i++ ) {                       // 5.5.7.2 (2012/10/09) シートé?列を処ç�?�—ますã?
173                                    Sheet sheet = sheets[i] ;                                       // 5.5.7.2 (2012/10/09)
174    
175                                    data.setSheetConstValues( sheet );                              // 5.5.8.2 (2012/11/09) シート単位に固定カラãƒ??値をキャãƒ?‚·ュするã€?
176    
177                                    int nFirstRow = sheet.getFirstRowNum();
178                                    if( nFirstRow < skip ) { nFirstRow = skip; } // 5.1.6.0 (2010/05/01)
179                                    int nLastRow  = sheet.getLastRowNum();
180                                    if( isDebug ) {         // 5.5.7.2 (2012/10/09) ãƒ?ƒ�ãƒ?‚°æƒ??
181                                            System.out.println( " Debug: 行é?番=" + numberOfRows + " : Sheet= " + sheet.getSheetName() + " , 開å§?" + nFirstRow + " , 終äº?" + nLastRow );
182                                    }
183                                    for( int nIndexRow = nFirstRow; nIndexRow <= nLastRow; nIndexRow++) {
184            //                              HSSFRow oRow = sheet.getRow(nIndexRow);
185                                            Row oRow = sheet.getRow(nIndexRow);
186                                            if( data.isSkip( oRow ) ) { continue; }
187                                            if( nameNoSet ) {
188                                                    nameNoSet = false;
189                                                    table.init( data.getColumnSize() );
190                                                    setTableDBColumn( data.getNames() ) ;
191                                                    nullBreakClmAdrs = table.getColumnNo( nullBreakClm, false );    // 5.5.8.2 (2012/11/09) カラãƒ?•ª号取得ã?存在しなければ -1 を返すã€?
192                                            }
193    
194                                            if( numberOfRows < getMaxRowCount() ) {
195                                                    String[] tblData = data.row2Array( oRow );                      // 5.5.8.2 (2012/11/09) nullBreakClm の判定ã?ため、ä¸?—¦配å?に受けるã?
196                                                    if( nullBreakClmAdrs >= 0 && ( tblData[nullBreakClmAdrs] == null || tblData[nullBreakClmAdrs].isEmpty() ) ) {
197                                                            break;          // nullBreakClm ã�?null の場合ã?、そのSheet処ç�?‚’中止するã€?
198                                                    }
199                                                    setTableColumnValues( tblData );                                        // 5.5.8.2 (2012/11/09)
200    //                                              setTableColumnValues( data.row2Array( oRow ) );         // 5.2.1.0 (2010/10/01)
201    //                                              table.addColumnValues( data.row2Array( oRow ) );
202                                                    numberOfRows ++ ;
203                                            }
204                                            else {
205                                                    table.setOverflow( true );
206                                            }
207                                    }
208    
209                                    // æœ?¾Œまでã€?NAME が見つから無かったå?å�?
210                                    if( nameNoSet ) {
211                                            String errMsg = "æœ?¾Œまでã€?NAME が見つかりませんでしたã€?
212                                                                            + HybsSystem.CR
213                                                                            + "ファイルが空かã?もしくã?損傷してã�?‚‹可能性がありますã?"
214                                                                            + HybsSystem.CR ;
215                                            throw new HybsSystemException( errMsg );
216                                    }
217                            }
218                    }
219    //              catch (Exception e) {
220                    catch ( IOException ex ) {
221                            String errMsg = "ファイル読込みエラー[" + filename + "]"  ;
222                            if( data != null ) { errMsg = errMsg + data.getLastCellMsg(); }         // 5.5.1.2 (2012/04/06)
223                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並びé ?¤‰更
224                    }
225                    // 5.1.8.0 (2010/07/01) Exception をきちっと記述
226                    catch (InvalidFormatException ex) {
227                            String errMsg = "ファイル形式エラー[" + filename + "]"  ;
228                            if( data != null ) { errMsg = errMsg + data.getLastCellMsg(); }         // 5.5.1.2 (2012/04/06)
229                            throw new HybsSystemException( errMsg,ex );
230                    }
231                    finally {
232                            Closer.ioClose( in );           // 4.0.0 (2006/01/31) close 処ç�?™‚の IOException を無è¦?
233                    }
234            }
235    
236            /**
237             * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
238             * コメンãƒ?空行を除きã?æœ??の行ã?、å¿?�šé ?›®名がå¿?¦�ですã?
239             * それ以降ã?、コメンãƒ?空行を除きã?ãƒ??タとして読み込んでã�?��ますã?
240             *
241             * @og.rev 3.5.4.3 (2004/01/05) 引数に、BufferedReader を受け取る要に変更しますã?
242             * @og.rev 4.0.0.0 (2006/09/31) UnsupportedOperationException を発行しますã?
243             *
244             * @param   reader å�?½¢式ã?ãƒ??タ(使用してã�?�¾せん)
245             */
246            @Override
247            public void readDBTable( final BufferedReader reader ) {
248                    String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
249                    throw new UnsupportedOperationException( errMsg );
250            }
251    
252            /**
253             * DBTableModelのãƒ??タとしてEXCELファイルを読み込ã‚?�¨きã?シート名を設定しますã?
254             * これにより、è¤?•°の形式ã?異なるデータをé?次読み込ã‚?�“とã‚??シートをæŒ?®šして
255             * 読み取ることが可能になりますã?
256             * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
257             * のでご注意くã�?�•ã�??
258             *
259             * @og.rev 3.5.4.2 (2003/12/15) 新規追åŠ?
260             *
261             * @param   sheetName シート名
262             */
263            @Override
264            public void setSheetName( final String sheetName ) {
265                    this.sheetName = sheetName;
266            }
267    
268            /**
269             * EXCELファイルを読み込ã‚?�¨きã?シート番号を指定しまã�?初期値:0)ã€?
270             *
271             * EXCEL読み込み時にè¤?•°シートをマã?ジして取り込みますã?
272             * シート番号はã€? から始まる数字で表しますã?
273             * ヘッãƒ??は、最初ã?シートã?カラãƒ?½�置に合わせますã??ˆã?ãƒ?ƒ€ータイトルの自動認識ã?ありません。ï¼?
274             * よって、指定するシートã?、すべて同ä¸?ƒ¬イアウトでなã�?�¨取り込み時にカラãƒ??ずれが発生しますã?
275             * 
276             * シート番号のæŒ?®šã?、カンマ区åˆ?‚Šで、è¤?•°æŒ?®šできますã?またã?N-M の様にハイフンで繋げることでã€?
277             * N 番から、M 番のシートç¯?›²をä¸?‹¬æŒ?®š可能ですã?またã?"*" による、å?シート指定が可能ですã?
278             * これらã?çµ?�¿合わせも可能ですã???0,1,3,5-8,10-* ??
279             * ただしã?"*" に関しては例外的に、ä¸?–‡字だけで、すべてのシートを表すか、N-* を最後にæŒ?®šするかの
280             * どちらかですã?途中にはã€?*" は、現れませんã€?
281             * シート番号はã€?‡�è¤?1,1,2,2)ã€??転(3,2,1) でのæŒ?®šが可能ですã?これは、そのæŒ?®šé?で、読み込まれますã?
282             * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
283             * こã?メソãƒ?ƒ‰は、isExcel() == true の場合ã?み利用されますã?
284             * 
285             * 初期値はã€??ˆ第ä¸?‚·ートï¼?ですã?
286             *
287             * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
288             *
289             * @og.rev 5.5.7.2 (2012/10/09) 新規追åŠ?
290             *
291             * @param   sheetNos EXCELファイルのシート番号??から始まるï¼?
292             * @see         #setSheetName( String ) 
293             */
294            @Override
295            public void setSheetNos( final String sheetNos ) {
296                    this.sheetNos = sheetNos;
297            }
298    
299            /**
300             * EXCELファイルを読み込ã‚?�¨きã?シート単位ã?固定å?を設定するためã?カラãƒ?��とアドレスを指定しますã?
301             * カラãƒ?��は、カンマ区åˆ?‚ŠでæŒ?®šしますã?
302             * 対応するアドレスをã?EXCEL上ã?è¡?列を?�から始まる整数でカンマ区åˆ?‚ŠでæŒ?®šしますã?
303             * これにより、シートã?ä¸?�‹æ‰?�«書かれてã�?‚‹æƒ??をã?DBTableModel のカラãƒ?�«固定å?として
304             * 設定することができますã?
305             * 例として、DB定義書で、テーブル名をシートã?全レコードに設定したい場合などに使ã�?�¾すã?
306             * こã?メソãƒ?ƒ‰は、isExcel() == true の場合ã?み利用されますã?
307             *
308             * @og.rev 5.5.8.2 (2012/11/09) 新規追åŠ?
309             *
310             * @param   constKeys 固定å?となるカラãƒ?��(CSV形å¼?
311             * @param   constAdrs 固定å?となるアドレス(è¡?åˆ?è¡?åˆ?・・・)
312             */
313            @Override
314            public void setSheetConstData( final String constKeys,final String constAdrs ) {
315                    this.constKeys = constKeys;
316                    this.constAdrs = constAdrs;
317            }
318    
319            /**
320             * ここにæŒ?®šされたカラãƒ??に NULL が現れた時点で読み取りを中止しますã?
321             *
322             * これは、指定ã?カラãƒ??å¿??とã�?�†事を条件に、そのレコードだけを読み取る処ç�?‚’行いますã?
323             * è¤?•°Sheetの場合ã?、次のSheetを読みますã?
324             * 現時点では、Excel の場合ã?み有効ですã?
325             *
326             * @og.rev 5.5.8.2 (2012/11/09) 新規追åŠ?
327             *
328             * @param   clm カラãƒ??
329             */
330            @Override
331            public void setNullBreakClm( final String clm ) {
332                    nullBreakClm = clm;
333            }
334    
335            /**
336             * こã?クラスがã?EXCEL対応機è?を持ってã�?‚‹かどã�?�‹を返しますã?
337             *
338             * EXCEL対応機è?とは、シート名のセãƒ?ƒˆ、読み込みå…?ƒ•ァイルの
339             * Fileオブジェクト取得などの、特殊機è?ですã?
340             * 本来は、インターフェースをå?けるべきとè€?�ˆますが、taglib クラス等ã?
341             * 関係があり、問ã�?�ˆわせによる条件åˆ?²�で対応しますã?
342             *
343             * @og.rev 3.5.4.3 (2004/01/05) 新規追åŠ?
344             *
345             * @return      EXCEL対応機è?を持ってã�?‚‹かどã�?�‹(常にtrue)
346             */
347            @Override
348            public boolean isExcel() {
349                    return true;
350            }
351    
352            /**
353             * 読み取りå…?ƒ•ァイル名をセãƒ?ƒˆしますã?(DIR + Filename)
354             * これは、EXCEL追åŠ?©Ÿè?として実è£?�•れてã�?�¾すã?
355             *
356             * @og.rev 3.5.4.3 (2004/01/05) 新規作æ?
357             *
358             * @param   filename 読み取りå…?ƒ•ァイルå�?
359             */
360            @Override
361            public void setFilename( final String filename ) {
362                    this.filename = filename;
363                    if( filename == null ) {
364                            String errMsg = "ファイル名がæŒ?®šされてã�?�¾せんã€? ;
365                            throw new HybsSystemException( errMsg );
366                    }
367            }
368    }
369    
370    /**
371     * EXCEL ネイãƒ?‚£ブã?ãƒ??タをå?ç�?�™ã‚?ローカルクラスですã?
372     * こã?クラスでは、コメント行ã?スキãƒ??判定ã?ヘッãƒ??部のカラãƒ?��取得ã?
373     * 行情報(Row)から、カラãƒ??配å?の取得などを行いますã?
374     *
375     * @og.rev 3.5.4.8 (2004/02/23) 新規追åŠ?
376     * @og.group ファイル入åŠ?
377     *
378     * @version  4.0
379     * @author   儲
380     * @since    JDK5.0,
381     */
382    class HeaderData {
383            private String[] names ;
384    //      private short[]  index;
385            private int[]    index; // 4.3.4.0 (2008/12/01) POI3.2対å¿?
386            private int              columnSize = 0;
387            private boolean  nameNoSet = true;
388            private boolean  useNumber = true;
389            private boolean  isDebug   = false;             // 5.5.8.2 (2012/11/09)
390    
391            private String[] orgNames ;                     // 5.5.1.2 (2012/04/06) オリジナルのカラãƒ?��
392            private Cell     lastCell = null;       // 5.5.1.2 (2012/04/06) æœ?¾Œに実行してã�?‚‹セルを保持(エラー時に使用するã€?
393    
394            // 5.5.8.2 (2012/11/09) 固定å?のカラãƒ?��、DBTableModelのアドレス、Sheetのè¡?列番号
395            private int              cnstLen = 0;           // 初期値=0 の場合ã?、固定å?を使わなã�?�¨ã�?�†事ã?
396            private String[] cnstKeys ;
397            private int[]    cnstIndx ;
398            private int[]    cnstRowNo;
399            private int[]    cnstClmNo;
400            private String[] cnstVals ;                     // Sheet単位ã?固定å?のキャãƒ?‚·ュ(シートã?æœ??に値を取得して保持しておく)
401    
402            /**
403             * ãƒ?ƒ�ãƒ?‚°æƒ??をã?出力するかどã�?�‹[true/false]を指定しまã�?初期値:false)ã€?
404             *
405             * 初期値は、false(出力しなã�? ですã?
406             *
407             * @og.rev 5.5.8.2 (2012/11/09) 新規作æ?
408             *
409             * @param       isDebug ãƒ?ƒ�ãƒ?‚°æƒ?? [true:出力すã‚?false:出力しない]
410             */
411            void setDebug( final boolean isDebug ) {
412                    this.isDebug = isDebug ;
413            }
414    
415            /**
416             * 行番号æƒ??をã?使用してã�?‚‹かどã�?�‹[true/false]を指定しまã�?初期値:true)ã€?
417             *
418             * 初期値は、true(使用する) ですã?
419             *
420             * @og.rev 5.1.6.0 (2010/05/01) 新規作æ?
421             *
422             * @param       useNumber       行番号æƒ?? [true:使用してã�?‚‹/false:してã�?�ªい]
423             */
424            void setUseNumber( final boolean useNumber ) {
425                    this.useNumber = useNumber ;
426            }
427    
428            /**
429             * 固定å?となるカラãƒ?��(CSV形å¼?と、constAdrs 固定å?となるアドレス(è¡?åˆ?è¡?åˆ?・・・)を設定しますã?
430             *
431             * @param       constKeys       固定å?となるカラãƒ?��(CSV形å¼?
432             * @param       constAdrs       固定å?となるアドレス(è¡?åˆ?è¡?åˆ?・・・)
433             *
434             * @og.rev 5.5.8.2 (2012/11/09) 新規追åŠ?
435             */
436            public void setSheetConstData( final String constKeys,final String constAdrs ) {
437                    if( constKeys == null || constKeys.isEmpty() ) {
438                            return ;
439                    }
440    
441                    cnstKeys  = constKeys.split( "," );
442                    cnstLen   = cnstKeys.length;
443                    cnstIndx  = new int[cnstLen];
444                    cnstRowNo = new int[cnstLen];
445                    cnstClmNo = new int[cnstLen];
446    
447                    String[] row_col = constAdrs.split( "," ) ;
448                    cnstRowNo = new int[cnstLen];
449                    cnstClmNo = new int[cnstLen];
450                    for( int j=0; j<cnstLen; j++ ) {
451                            cnstKeys[j] = cnstKeys[j].trim();               // 前後ã?不要なスペã?スを削除
452                            String rowcol = row_col[j].trim();              // 前後ã?不要なスペã?スを削除
453    
454                            int sep = rowcol.indexOf( '-' );
455                            cnstRowNo[j] = Integer.parseInt( rowcol.substring( 0,sep ) );
456                            cnstClmNo[j] = Integer.parseInt( rowcol.substring( sep+1 ) );
457    
458                            if( isDebug ) {
459                                    System.out.println( " Debug: constKey=" + cnstKeys[j] + " : RowNo= " + cnstRowNo[j] + " , ClmNo=" + cnstClmNo[j] );
460                            }
461                    }
462            }
463    
464            /**
465             * カラãƒ?��を外部からæŒ?®šしますã?
466             * カラãƒ?��がã?NULL でなければã€?¼ƒNAME より、こちらが優先されますã?
467             * カラãƒ?��はã€??番に、指定するå¿?¦�がありますã?
468             *
469             * @og.rev 5.1.6.0 (2010/05/01) 新規作æ?
470             * @og.rev 5.5.8.2 (2012/11/09) 固定å?取得用の cnstIndx の設定を行うã€?
471             *
472             * @param       columns EXCELのカラãƒ??(CSV形å¼?
473             *
474             * @return true:処ç�?®Ÿ施/false:無処ç�?
475             */
476            boolean setColumns( final String columns ) {
477                    if( columns != null && columns.length() > 0 ) {
478                            names = StringUtil.csv2Array( columns );
479                            columnSize = names.length ;
480                            index = new int[columnSize];
481                            int adrs = (useNumber) ? 1:0 ;  // useNumber =true の場合ã?ã€?¼‘件目(No)は読み飛ã?すã?
482                            // 5.5.8.2 (2012/11/09) 固定å?取得用の cnstIndx の設定を行うã€?
483    //                      for( int i=0; i<columnSize; i++ ) { index[i] = adrs++; }
484                            for( int i=0; i<columnSize; i++ ) {
485                                    index[i] = adrs++;
486                                    for( int j=0; j<cnstLen; j++ ) {
487                                            if( names[i].equalsIgnoreCase( cnstKeys[j] ) ) {
488                                                    cnstIndx[j] = index[i];
489                                            }
490                                    }
491                            }
492                            nameNoSet = false;
493    
494                            return true;
495                    }
496                    return false;
497            }
498    
499            /**
500             * EXCEL ネイãƒ?‚£ブã?ãƒ??タをå?ç�?�™ã‚?ローカルクラスですã?
501             * こã?クラスでは、コメント行ã?スキãƒ??判定ã?ヘッãƒ??部のカラãƒ?��取得ã?
502             * 行情報(Row)から、カラãƒ??配å?の取得などを行いますã?
503             *
504             * @og.rev 4.3.4.0 (2008/12/01) POI3.2対å¿?
505             *
506             * @param oRow Row EXCELの行オブジェクãƒ?
507             *
508             * @return true:コメントè¡?false:通常è¡?
509             */
510    //      boolean isSkip( HSSFRow oRow ) {
511            boolean isSkip( Row oRow ) {
512                    if( oRow == null ) { return true; }
513    
514    //              short nFirstCell = oRow.getFirstCellNum();
515                    int nFirstCell = oRow.getFirstCellNum();
516    //              HSSFCell oCell = oRow.getCell(nFirstCell);
517                    Cell oCell = oRow.getCell(nFirstCell);
518                    String strText =  getValue( oCell );
519                    if( strText != null && strText.length() > 0 ) {
520                            if( nameNoSet ) {
521                                    if( strText.equalsIgnoreCase( "#Name" ) ) {
522                                            makeNames( oRow );
523                                            nameNoSet = false;
524                                            return true;
525                                    }
526                                    else if( strText.charAt( 0 ) == '#' ) {
527                                            return true;
528                                    }
529                                    else {
530                                            String errMsg = "#NAME が見つかる前にãƒ??タが見つかりましたã€?
531                                                                            + HybsSystem.CR
532                                                                            + "可能性として、ファイルがã?ネイãƒ?‚£ブExcelでなã�?º‹がè€?�ˆられますã?"
533                                                                            + HybsSystem.CR ;
534                                            throw new HybsSystemException( errMsg );
535                                    }
536                            }
537                            else {
538                                    if( strText.charAt( 0 ) == '#' ) {
539                                            return true;
540                                    }
541                            }
542                    }
543    
544                    return nameNoSet ;
545            }
546    
547            /**
548             * EXCEL ネイãƒ?‚£ブã?行情報(Row)からカラãƒ?��æƒ??を取得しますã?
549             *
550             * @og.rev 4.3.4.0 (2008/12/01) POI3.2対å¿?
551             * @og.rev 5.1.6.0 (2010/05/01) useNumber(行番号æƒ??をã?使用してã�?‚‹(true)/してã�?�ªã�?false)を指å®?
552             * @og.rev 5.1.6.0 (2010/05/01) useNumber(行番号æƒ??をã?使用してã�?‚‹(true)/してã�?�ªã�?false)を指å®?
553             * @og.rev 5.5.1.2 (2012/04/06) オリジナルのカラãƒ?��を取å¾?
554             * @og.rev 5.5.8.2 (2012/11/09) 固定å?取得用の cnstIndx の設定を行うã€?
555             *
556             * @param oRow Row EXCELの行オブジェクãƒ?
557             */
558    //      private void makeNames( final HSSFRow oRow ) {
559            private void makeNames( final Row oRow ) {
560                    // 先é?カラãƒ??ã€?NAME 属æ?行であるかどã�?�‹をã?useNumber で判定しておくã€?
561                    short nFirstCell = (short)( (useNumber) ? 1:0 );
562    //              short nFirstCell = oRow.getFirstCellNum();
563                    short nLastCell  = oRow.getLastCellNum();
564    
565                    orgNames = new String[nLastCell+1];             // 5.5.1.2 (2012/04/06) オリジナルのカラãƒ?��を取å¾?
566    
567                    int maxCnt = nLastCell - nFirstCell;
568                    String[] names2 = new String[maxCnt];
569    //              short[]  index2 = new short[maxCnt];
570                    int[]  index2 = new int[maxCnt];
571    
572                    // 先é?カラãƒ??ã€?NAME 属æ?行であるã€?+ で、ä¸?�¤進めてã�?‚‹ã€?
573    //              for( short nIndexCell = ++nFirstCell; nIndexCell <= nLastCell; nIndexCell++) {
574    //              for( int nIndexCell = ++nFirstCell; nIndexCell <= nLastCell; nIndexCell++) {
575                    // 先é?カラãƒ??ã€?NAME 属æ?行であるかどã�?�‹をã?useNumber で判定しておくã€?
576                    for( int nIndexCell = nFirstCell; nIndexCell <= nLastCell; nIndexCell++) {
577    //                      HSSFCell oCell = oRow.getCell(nIndexCell);
578                            Cell oCell = oRow.getCell(nIndexCell);
579                            String strText = getValue( oCell );
580    
581                            orgNames[nIndexCell] = strText;         // 5.5.1.2 (2012/04/06) オリジナルのカラãƒ?��を取å¾?
582    
583                            // #NAME 行が、ゼロæ–?­—å?の場合ã?、読み飛ã?すã?
584                            if( strText != null && strText.length() > 0 ) {
585                                    names2[columnSize] = strText;
586                                    index2[columnSize] = nIndexCell;
587                                    columnSize++;
588                            }
589                    }
590    
591                    // #NAME を使用しなã�??合:noæ¬?�Œ存在しなã�?‚±ース
592                    if( maxCnt == columnSize ) {
593                            names = names2;
594                            index = index2;
595                    }
596                    else {
597                            names = new String[columnSize];
598    //                      index = new short[columnSize];
599                            index = new int[columnSize];
600                            System.arraycopy(names2, 0, names, 0, columnSize);
601                            System.arraycopy(index2, 0, index, 0, columnSize);
602                    }
603    
604                    // 5.5.8.2 (2012/11/09) 固定å?取得用の cnstIndx の設定を行うã€?
605                    if( cnstLen > 0 ) {
606                            for( int i=0; i<columnSize; i++ ) {
607                                    for( int j=0; j<cnstLen; j++ ) {
608                                            if( names[i].equalsIgnoreCase( cnstKeys[j] ) ) {
609                                                    cnstIndx[j] = index[i];
610                                            }
611                                    }
612                            }
613                    }
614            }
615    
616            /**
617             * カラãƒ?��æƒ??を返しますã?
618             * ここでは、å?部配å?をそのまま返しますã?
619             *
620             * @return String[] カラãƒ??配å?æƒ??
621             */
622            String[] getNames() {
623                    return names;
624            }
625    
626            /**
627             * カラãƒ?‚µイズを返しますã?
628             *
629             * @return      カラãƒ?‚µイズ
630             */
631            int getColumnSize() {
632                    return columnSize;
633            }
634    
635            /**
636             * Sheet単位ã?固定å?のキャãƒ?‚·ュ(シートã?æœ??に値を取得して保持しておく)を設定しますã?
637             * これは、シートチェンジのæœ??にä¸?º¦呼び出しておくことで、それ以降ã?列取得時に
638             * 固定å?を利用することで処ç�??度向上を目æŒ?�—ますã?
639             *
640             * @og.rev 5.5.8.2 (2012/11/09) 新規作æ?
641             *
642             * @param sheet Sheet EXCELのSheetオブジェクãƒ?
643             */
644            public void setSheetConstValues( final Sheet sheet ) {
645                    cnstVals = new String[cnstLen];
646                    for( int j=0; j<cnstLen; j++ ) {
647                            Row  oRow  = sheet.getRow( cnstRowNo[j] );
648                            Cell oCell = oRow.getCell( cnstClmNo[j] );
649                            cnstVals[j] = getValue( oCell );
650    
651                            if( isDebug ) {
652                                    System.out.println( " Debug: Sheet=" + sheet.getSheetName() + " : RowNo= " + cnstRowNo[j] + " , ClmNo=" + cnstClmNo[j] + " , " + cnstKeys[j] + "=" + cnstVals[j] );
653                            }
654                    }
655            }
656    
657            /**
658             * カラãƒ?��æƒ??を返しますã?
659             *
660             * @og.rev 5.5.8.2 (2012/11/09) 固定å?の設定を行うã€?
661             *
662             * @param oRow Row EXCELの行オブジェクãƒ?
663             *
664             * @return String[] カラãƒ??配å?æƒ??
665             */
666    //      String[] row2Array( final HSSFRow oRow ) {
667            String[] row2Array( final Row oRow ) {
668                    if( nameNoSet ) {
669                            String errMsg = "#NAME が見つかる前にãƒ??タが見つかりましたã€?;
670                            throw new HybsSystemException( errMsg );
671                    }
672    
673                    String[] data = new String[columnSize];
674                    for( int i=0;i<columnSize; i++ ) {
675    //                      HSSFCell oCell = oRow.getCell( index[i] );
676                            Cell oCell = oRow.getCell( index[i] );
677                            data[i] = getValue( oCell );
678                    }
679    
680                    // 5.5.8.2 (2012/11/09) 固定å?の設定を行うã€?
681                    for( int j=0; j<cnstLen; j++ ) {
682                            data[cnstIndx[j]] = cnstVals[j];
683                    }
684                    return data;
685            }
686    
687            /**
688             * セルオブジェクãƒ?Cell)から値を取りå?しますã?
689             *
690             * @og.rev 3.8.5.3 (2006/08/07) 取り出し方法を少し修正
691             * @og.rev 5.5.1.2 (2012/04/06) フォーマットセルを実行して、その結果をå?帰çš?�«処ç�?�™るã?
692             *
693             * @param oCell Cell EXCELのセルオブジェクãƒ?
694             *
695             * @return      セルの値
696             */
697    //      private String getValue( final Cell oCell ) {
698            private String getValue( final Cell oCell ) {
699                    lastCell = oCell;       // 5.5.1.2 (2012/04/06) 今から実行するセルを取得しておきますã?
700    
701                    if( oCell == null ) { return null; }
702    
703                    String strText = "";
704    //              HSSFRichTextString richText;
705                    RichTextString richText;
706                    int nCellType = oCell.getCellType();
707                    switch(nCellType) {
708    //                      case HSSFCell.CELL_TYPE_NUMERIC:
709                            case Cell.CELL_TYPE_NUMERIC:
710                                            strText = getNumericTypeString( oCell );
711                                            break;
712    //                      case HSSFCell.CELL_TYPE_STRING:
713                            case Cell.CELL_TYPE_STRING:
714            // POI3.0               strText = oCell.getStringCellValue();
715                                            richText = oCell.getRichStringCellValue();
716                                            if( richText != null ) {
717                                                    strText = richText.getString();
718                                            }
719                                            break;
720    //                      case HSSFCell.CELL_TYPE_FORMULA:
721                            case Cell.CELL_TYPE_FORMULA:
722            // POI3.0               strText = oCell.getStringCellValue();
723                                            // 5.5.1.2 (2012/04/06) フォーマットセルを実行して、その結果をå?帰çš?�«処ç�?�™るã?
724                                            Workbook wb = oCell.getSheet().getWorkbook();
725                                            CreationHelper crateHelper = wb.getCreationHelper();
726                                            FormulaEvaluator evaluator = crateHelper.createFormulaEvaluator();
727    
728                                            try {
729                                                    strText = getValue(evaluator.evaluateInCell(oCell));
730                                            }
731                                            catch ( Throwable th ) {
732    //                                              String errMsg = "セルフォーマットが解析できませんã€?" + String.valueOf(oCell.getCellFormula()) + "]"
733                                                    String errMsg = "セルフォーマットが解析できませんã€?" + oCell.getCellFormula() + "]"
734                                                                            + getLastCellMsg();
735                                                    throw new HybsSystemException( errMsg,th );
736                                            }
737                                            break;
738    
739    //                                      richText = oCell.getRichStringCellValue();
740    //                                      if( richText != null ) {
741    //                                              strText = richText.getString();
742    //                                      }
743    //                                      else {
744    //                                              strText = getNumericTypeString( oCell );
745    //                                      }
746    //                                      break;
747    //                      case HSSFCell.CELL_TYPE_BOOLEAN:
748                            case Cell.CELL_TYPE_BOOLEAN:
749                                            strText = String.valueOf(oCell.getBooleanCellValue());
750                                            break;
751    //                      case HSSFCell.CELL_TYPE_BLANK :
752    //                      case HSSFCell.CELL_TYPE_ERROR:
753                            case Cell.CELL_TYPE_BLANK :
754                            case Cell.CELL_TYPE_ERROR:
755                                            break;
756                            default :
757                                    break;
758                    }
759                    return strText.trim();
760            }
761    
762            /**
763             * セル値が数字ã?場合に、数字か日付かを判断して、対応する文字å?を返しますã?
764             *
765             * @og.rev 3.8.5.3 (2006/08/07) 新規追åŠ?
766             * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正しますã?
767             *
768             * @param oCell Cell
769             *
770             * @return      数字ã?場合ã?、文字å?に変換した結果をã?日付ã?場合ã?ã€?yyyyMMddHHmmss" 形式で返しますã?
771             */
772    //      private String getNumericTypeString( final HSSFCell oCell ) {
773            private String getNumericTypeString( final Cell oCell ) {
774                    final String strText ;
775    
776                    double dd = oCell.getNumericCellValue() ;
777    //              if( HSSFDateUtil.isCellDateFormatted( oCell ) ) {
778                    if( DateUtil.isCellDateFormatted( oCell ) ) {
779                            strText = HybsDateUtil.getDate( DateUtil.getJavaDate( dd ).getTime() , "yyyyMMddHHmmss" );      // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
780    
781    //                      DateFormat dateFormat = new SimpleDateFormat( "yyyyMMddHHmmss",Locale.JAPAN );
782    // //                   strText = dateFormat.format( HSSFDateUtil.getJavaDate( dd ) );
783    //                      strText = dateFormat.format( DateUtil.getJavaDate( dd ) );
784                    }
785                    else {
786                            NumberFormat numFormat = NumberFormat.getInstance();
787                            if( numFormat instanceof DecimalFormat ) {
788                                    ((DecimalFormat)numFormat).applyPattern( "#.####" );
789                            }
790                            strText = numFormat.format( dd );
791                    }
792                    return strText ;
793            }
794    
795            /**
796             * æœ?¾Œに実行してã�?‚‹セルæƒ??を返しますã?
797             *
798             * エラー発生時に、どのセルでエラーが発生したかのæƒ??を取得できるようにしますã?
799             *
800             * @og.rev 5.5.1.2 (2012/04/06) 新規追åŠ?
801             * @og.rev 5.5.8.2 (2012/11/09) エラーæƒ??に、シート名も追åŠ?
802             *
803             * @return      æœ?¾Œに実行してã�?‚‹セルæƒ??のæ–?­—å?
804             */
805            String getLastCellMsg() {
806                    String lastMsg = null;
807    
808                    if( lastCell != null ) {
809                            int rowNo = lastCell.getRowIndex();
810                            int celNo = lastCell.getColumnIndex();
811                            int no = lastCell.getColumnIndex();
812                            String shtNm = lastCell.getSheet().getSheetName();
813    
814    
815                            lastMsg = "Sheet=" + shtNm + ", Row=" + rowNo + ", Cel=" + celNo ;
816                            if( orgNames != null && orgNames.length < no ) {
817                                    lastMsg = lastMsg + ", NAME=" + orgNames[no] ;
818                            }
819                    }
820                    return lastMsg;
821            }
822    }