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 }