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