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 org.opengion.hayabusa.common.HybsSystem;
019 import org.opengion.hayabusa.common.HybsSystemException;
020 import org.opengion.hayabusa.db.DBTableModelUtil;
021 import org.opengion.hayabusa.io.AbstractTableReader;
022 import org.opengion.fukurou.util.StringUtil;
023
024 import jxl.Workbook;
025 import jxl.WorkbookSettings;
026 import jxl.Sheet;
027 import jxl.Cell;
028 import jxl.read.biff.BiffException;
029
030 import java.io.File;
031 import java.io.BufferedReader;
032 import java.io.IOException;
033
034 /**
035 * JExcelによるEXCELバイナリファイルを読み取る実è£?‚¯ラスですã?
036 *
037 * ファイル名ã?シート名を指定して、データを読み取ることが可能ですã?
038 * 第ä¸?‚«ラãƒ?�Œ # で始まる行ã?、コメント行なので、読み飛ã?しますã?
039 * カラãƒ?��のæŒ?®š行で、カラãƒ?��ã�?null の場合ã?、その列ã?読み飛ã?しますã?
040 *
041 * @og.rev 3.5.4.8 (2004/02/23) 新規作æ?
042 * @og.group ファイル入åŠ?
043 *
044 * @version 4.0
045 * @author Kazuhiko Hasegawa
046 * @since JDK5.0,
047 */
048 public class TableReader_JExcel extends AbstractTableReader {
049 //* こã?プログラãƒ??VERSIONæ–?—å?を設定しますã? {@value} */
050 private static final String VERSION = "5.5.7.2 (2012/10/09)" ;
051
052 private String sheetName = null; // 3.5.4.2 (2003/12/15)
053 private String sheetNos = null; // 5.5.7.2 (2012/10/09)
054 private String filename = null; // 3.5.4.3 (2004/01/05)
055
056 /**
057 * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
058 * コメンãƒ?空行を除きã?æœ??の行ã?、å¿?�šé ?›®名がå¿?¦�ですã?
059 * それ以降ã?、コメンãƒ?空行を除きã?ãƒ??タとして読み込んでã�?��ますã?
060 * こã?メソãƒ?ƒ‰は、EXCEL 読み込み時に使用しますã?
061 *
062 * @og.rev 4.0.0.0 (2006/09/31) 新規追åŠ?
063 * @og.rev 5.1.6.0 (2010/05/01) columns 処ç�?追åŠ?
064 * @og.rev 5.1.6.0 (2010/05/01) skipRowCount , useNumber の追åŠ?
065 * @og.rev 5.2.1.0 (2010/10/01) setTableColumnValues メソãƒ?ƒ‰を経由して、テーブルにãƒ??タをセãƒ?ƒˆするã€?
066 * @og.rev 5.5.7.2 (2012/10/09) sheetNos 追åŠ?�«よるè¤?•°シートã?マã?ジ読み取りサポã?ãƒ?
067 *
068 * @see #isExcel()
069 */
070 @Override
071 public void readDBTable() {
072 Workbook wb = null;
073 try {
074 WorkbookSettings settings = new WorkbookSettings();
075 // System.gc()「ガベã?ジコレクション」ã?実行をOFFに設å®?
076 settings.setGCDisabled(true);
077 wb = Workbook.getWorkbook(new File(filename),settings);
078
079 // Sheet sheet ;
080 Sheet[] sheets ; // 5.5.7.2 (2012/10/09) 配å?に変更
081
082 // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?sheetNos のæŒ?®šが優先されるã€?
083 if( sheetNos != null && sheetNos.length() > 0 ) {
084 String[] sheetList = StringUtil.csv2ArrayExt( sheetNos , wb.getNumberOfSheets()-1 ); // æœ?¤§シート番号は、シート数-1
085 sheets = new Sheet[sheetList.length];
086 for( int i=0; i<sheetList.length; i++ ) {
087 sheets[i] = wb.getSheet( Integer.parseInt( sheetList[i] ) );
088 }
089 }
090 else if( sheetName != null && sheetName.length() > 0 ) {
091 Sheet sheet = wb.getSheet( sheetName );
092 if( sheet == null ) {
093 String errMsg = "対応するシートが存在しませんã€?Sheet=[" + sheetName + "]" ;
094 throw new HybsSystemException( errMsg );
095 }
096 sheets = new Sheet[] { sheet };
097 }
098 else {
099 Sheet sheet = wb.getSheet(0);
100 sheets = new Sheet[] { sheet };
101 }
102
103 // if( sheetName == null || sheetName.length() == 0 ) {
104 // sheet = wb.getSheet(0);
105 // }
106 // else {
107 // sheet = wb.getSheet( sheetName );
108 // if( sheet == null ) {
109 // String errMsg = "対応するシートが存在しませんã€?Sheet=[" + sheetName + "]" ;
110 // throw new HybsSystemException( errMsg );
111 // }
112 // }
113
114 boolean nameNoSet = true;
115 table = DBTableModelUtil.newDBTable();
116
117 int numberOfRows = 0;
118 JxlHeaderData data = new JxlHeaderData();
119
120 // 5.1.6.0 (2010/05/01) columns 処ç�?
121 data.setUseNumber( isUseNumber() );
122 if( data.setColumns( columns ) ) {
123 nameNoSet = false;
124 table.init( data.getColumnSize() );
125 setTableDBColumn( data.getNames() ) ;
126 }
127
128 // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?
129 for( int i=0; i<sheets.length; i++ ) { // 5.5.7.2 (2012/10/09) シートé?列を処ç�?�—ますã?
130 Sheet sheet = sheets[i] ; // 5.5.7.2 (2012/10/09)
131 int rowCnt = sheet.getRows();
132 int skip = getSkipRowCount(); // 5.1.6.0 (2010/05/01)
133 // for( int nIndexRow = 0; nIndexRow < rowCnt; nIndexRow++) {
134 for( int nIndexRow = skip; nIndexRow < rowCnt; nIndexRow++) {
135 Cell[] cells = sheet.getRow( nIndexRow );
136 if( data.isSkip( cells ) ) { continue; }
137 if( nameNoSet ) {
138 nameNoSet = false;
139 table.init( data.getColumnSize() );
140 setTableDBColumn( data.getNames() ) ;
141 }
142
143 if( numberOfRows < getMaxRowCount() ) {
144 setTableColumnValues( data.toArray( cells ) ); // 5.2.1.0 (2010/10/01)
145 // table.addColumnValues( data.toArray( cells ) );
146 numberOfRows ++ ;
147 }
148 else {
149 table.setOverflow( true );
150 }
151 }
152
153 // æœ?¾Œまでã€?NAME が見つから無かったå?å�?
154 if( nameNoSet ) {
155 String errMsg = "æœ?¾Œまでã€?NAME が見つかりませんでしたã€?
156 + HybsSystem.CR
157 + "ファイルが空かã?もしくã?損傷してã�?‚‹可能性がありますã?"
158 + HybsSystem.CR ;
159 throw new HybsSystemException( errMsg );
160 }
161 }
162 }
163 catch (IOException ex) {
164 String errMsg = "ファイル読込みエラー[" + filename + "]" ;
165 throw new HybsSystemException( errMsg,ex );
166 }
167 catch (BiffException ex) {
168 String errMsg = "ファイル読込みエラー。データ形式が不正です[" + filename + "]" ;
169 throw new HybsSystemException( errMsg,ex );
170 }
171 finally {
172 if( wb != null ) { wb.close(); }
173 }
174 }
175
176 /**
177 * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
178 * コメンãƒ?空行を除きã?æœ??の行ã?、å¿?�šé ?›®名がå¿?¦�ですã?
179 * それ以降ã?、コメンãƒ?空行を除きã?ãƒ??タとして読み込んでã�?��ますã?
180 *
181 * @og.rev 3.5.4.3 (2004/01/05) 引数に、BufferedReader を受け取る要に変更しますã?
182 * @og.rev 4.0.0.0 (2006/09/31) UnsupportedOperationException を発行しますã?
183 *
184 * @param reader å�?½¢式ã?ãƒ??タ(使用してã�?�¾せん)
185 */
186 @Override
187 public void readDBTable( final BufferedReader reader ) {
188 String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
189 throw new UnsupportedOperationException( errMsg );
190 }
191
192 /**
193 * DBTableModelのãƒ??タとしてEXCELファイルを読み込ã‚?�¨きã?シート名を設定しますã?
194 * これにより、è¤?•°の形式ã?異なるデータをé?次読み込ã‚?�“とã‚??シートをæŒ?®šして
195 * 読み取ることが可能になりますã?
196 * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
197 * のでご注意くã�?�•ã�??
198 *
199 * @og.rev 3.5.4.2 (2003/12/15) 新規追åŠ?
200 *
201 * @param sheetName シート名
202 */
203 @Override
204 public void setSheetName( final String sheetName ) {
205 this.sheetName = sheetName;
206 }
207
208 /**
209 * EXCELファイルを読み込ã‚?�¨きã?シート番号を指定しまã�?初期値:0)ã€?
210 *
211 * EXCEL読み込み時にè¤?•°シートをマã?ジして取り込みますã?
212 * シート番号はã€? から始まる数字で表しますã?
213 * ヘッãƒ??は、最初ã?シートã?カラãƒ?½�置に合わせますã??ˆã?ãƒ?ƒ€ータイトルの自動認識ã?ありません。ï¼?
214 * よって、指定するシートã?、すべて同ä¸?ƒ¬イアウトでなã�?�¨取り込み時にカラãƒ??ずれが発生しますã?
215 *
216 * シート番号のæŒ?®šã?、カンマ区åˆ?‚Šで、è¤?•°æŒ?®šできますã?またã?N-M の様にハイフンで繋げることでã€?
217 * N 番から、M 番のシートç¯?›²をä¸?‹¬æŒ?®š可能ですã?またã?"*" による、å?シート指定が可能ですã?
218 * これらã?çµ?�¿合わせも可能ですã???0,1,3,5-8,10-* ??
219 * ただしã?"*" に関しては例外的に、ä¸?–‡字だけで、すべてのシートを表すか、N-* を最後にæŒ?®šするかの
220 * どちらかですã?途中にはã€?*" は、現れませんã€?
221 * シート番号はã€?‡�è¤?1,1,2,2)ã€??転(3,2,1) でのæŒ?®šが可能ですã?これは、そのæŒ?®šé?で、読み込まれますã?
222 * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
223 * こã?メソãƒ?ƒ‰は、isExcel() == true の場合ã?み利用されますã?
224 *
225 * 初期値はã€??ˆ第ä¸?‚·ートï¼?ですã?
226 *
227 * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
228 *
229 * @og.rev 5.5.7.2 (2012/10/09) 新規追åŠ?
230 *
231 * @param sheetNos EXCELファイルのシート番号??から始まるï¼?
232 * @see #setSheetName( String )
233 */
234 @Override
235 public void setSheetNos( final String sheetNos ) {
236 this.sheetNos = sheetNos;
237 }
238
239 /**
240 * こã?クラスがã?EXCEL対応機è?を持ってã�?‚‹かどã�?�‹を返しますã?
241 *
242 * EXCEL対応機è?とは、シート名のセãƒ?ƒˆ、読み込みå…?ƒ•ァイルの
243 * Fileオブジェクト取得などの、特殊機è?ですã?
244 * 本来は、インターフェースをå?けるべきとè€?�ˆますが、taglib クラス等ã?
245 * 関係があり、問ã�?�ˆわせによる条件åˆ?²�で対応しますã?
246 *
247 * @og.rev 3.5.4.3 (2004/01/05) 新規追åŠ?
248 *
249 * @return EXCEL対応機è?を持ってã�?‚‹かどã�?�‹(常にtrue)
250 */
251 @Override
252 public boolean isExcel() {
253 return true;
254 }
255
256 /**
257 * 読み取りå…?ƒ•ァイル名をセãƒ?ƒˆしますã?(DIR + Filename)
258 * これは、EXCEL追åŠ?©Ÿè?として実è£?�•れてã�?�¾すã?
259 *
260 * @og.rev 3.5.4.3 (2004/01/05) 新規作æ?
261 *
262 * @param filename 読み取りå…?ƒ•ァイルå�?
263 */
264 @Override
265 public void setFilename( final String filename ) {
266 this.filename = filename;
267 if( filename == null ) {
268 String errMsg = "ファイル名がæŒ?®šされてã�?�¾せんã€? ;
269 throw new HybsSystemException( errMsg );
270 }
271 }
272 }
273
274 /**
275 * EXCEL ネイãƒ?‚£ブã?ãƒ??タをå?ç�?�™ã‚?ローカルクラスですã?
276 * こã?クラスでは、コメント行ã?スキãƒ??判定ã?ヘッãƒ??部のカラãƒ?��取得ã?
277 * 行情報(HSSFRow)から、カラãƒ??配å?の取得などを行いますã?
278 *
279 * @og.rev 3.5.4.8 (2004/02/23) 新規追åŠ?
280 * @og.group ファイル入åŠ?
281 *
282 * @version 4.0
283 * @author 儲
284 * @since JDK5.0,
285 */
286 class JxlHeaderData {
287 private String[] names ;
288 private int[] index;
289 private int columnSize = 0;
290 private boolean nameNoSet = true;
291 private boolean useNumber = true;
292
293 /**
294 * 行番号æƒ??を使用するかどã�?�‹[true/false]を指定しまã�?初期値:true)ã€?
295 *
296 * 初期値は、true(使用する) ですã?
297 *
298 * @og.rev 5.1.6.0 (2010/05/01) 新規作æ?
299 *
300 * @param useNumber 行番号æƒ?? [true:使用してã�?‚‹/false:してã�?�ªい]
301 */
302 void setUseNumber( final boolean useNumber ) {
303 this.useNumber = useNumber ;
304 }
305
306 /**
307 * カラãƒ?��を外部からæŒ?®šしますã?
308 * カラãƒ?��がã?NULL でなければã€?¼ƒNAME より、こちらが優先されますã?
309 * カラãƒ?��はã€??番に、指定するå¿?¦�がありますã?
310 *
311 * @og.rev 5.1.6.0 (2010/05/01) 新規作æ?
312 *
313 * @param columns EXCELのカラãƒ??(CSV形å¼?
314 *
315 * @return true:処ç�?®Ÿ施/false:無処ç�?
316 */
317 boolean setColumns( final String columns ) {
318 if( columns != null && columns.length() > 0 ) {
319 names = StringUtil.csv2Array( columns );
320 columnSize = names.length ;
321 index = new int[columnSize];
322 int adrs = (useNumber) ? 1:0 ; // useNumber =true の場合ã?ã€?¼‘件目(No)は読み飛ã?すã?
323 for( int i=0; i<columnSize; i++ ) { index[i] = adrs++; }
324 nameNoSet = false;
325
326 return true;
327 }
328 return false;
329 }
330
331 /**
332 * EXCEL ネイãƒ?‚£ブã?ãƒ??タをå?ç�?�™ã‚?ローカルクラスですã?
333 * こã?クラスでは、コメント行ã?スキãƒ??判定ã?ヘッãƒ??部のカラãƒ?��取得ã?
334 * 行情報(HSSFRow)から、カラãƒ??配å?の取得などを行いますã?
335 *
336 * @param cells Cell[] EXCELのセル配å?(è¡?
337 *
338 * @return true:コメントè¡?false:通常è¡?
339 */
340 boolean isSkip( final Cell[] cells ) {
341 int size = cells.length ;
342 if( size == 0 ) { return true; }
343
344 String strText = cells[0].getContents();
345 if( strText != null && strText.length() > 0 ) {
346 if( nameNoSet ) {
347 if( strText.equalsIgnoreCase( "#Name" ) ) {
348 makeNames( cells );
349 nameNoSet = false;
350 return true;
351 }
352 else if( strText.charAt( 0 ) == '#' ) {
353 return true;
354 }
355 else {
356 String errMsg = "#NAME が見つかる前にãƒ??タが見つかりましたã€?
357 + HybsSystem.CR
358 + "可能性として、ファイルがã?ネイãƒ?‚£ブExcelでなã�?º‹がè€?�ˆられますã?"
359 + HybsSystem.CR ;
360 throw new HybsSystemException( errMsg );
361 }
362 }
363 else {
364 if( strText.charAt( 0 ) == '#' ) {
365 return true;
366 }
367 }
368 }
369
370 return nameNoSet ;
371 }
372
373 /**
374 * EXCEL ネイãƒ?‚£ブã?行ã?セル配å?からカラãƒ?��æƒ??を取得しますã?
375 *
376 * @og.rev 5.1.6.0 (2010/05/01) useNumber(行番号æƒ??をã?使用してã�?‚‹(true)/してã�?�ªã�?false)を指å®?
377 *
378 * @param cells Cell[] EXCELの行ã?セル配å?
379 */
380 private void makeNames( final Cell[] cells ) {
381 int maxCnt = cells.length;
382 String[] names2 = new String[maxCnt];
383 int[] index2 = new int[maxCnt];
384
385 // 先é?カラãƒ??ã€?NAME 属æ?行であるã€?
386 // for( int nIndexCell = 1; nIndexCell < maxCnt; nIndexCell++) {
387 // 先é?カラãƒ??ã€?NAME 属æ?行であるかどã�?�‹をã?useNumber で判定しておくã€?
388 int nFirstCell = (useNumber) ? 1:0 ;
389 for( int nIndexCell = nFirstCell; nIndexCell < maxCnt; nIndexCell++) {
390 String strText = cells[nIndexCell].getContents();
391
392 if( strText != null && strText.length() > 0 ) {
393 names2[columnSize] = strText;
394 index2[columnSize] = nIndexCell;
395 columnSize++;
396 }
397 }
398
399 // #NAME を使用しなã�??合:noæ¬?�Œ存在しなã�?‚±ース
400 if( maxCnt == columnSize ) {
401 names = names2;
402 index = index2;
403 }
404 else {
405 names = new String[columnSize];
406 index = new int[columnSize];
407 System.arraycopy(names2, 0, names, 0, columnSize);
408 System.arraycopy(index2, 0, index, 0, columnSize);
409 }
410 }
411
412 /**
413 * カラãƒ?��æƒ??を返しますã?
414 * ここでは、å?部配å?をそのまま返しますã?
415 *
416 * @return String[] カラãƒ??配å?æƒ??
417 */
418 String[] getNames() {
419 return names;
420 }
421
422 /**
423 * カラãƒ?‚µイズを返しますã?
424 *
425 * @return カラãƒ?‚µイズ
426 */
427 int getColumnSize() {
428 return columnSize;
429 }
430
431 /**
432 * カラãƒ?��æƒ??を返しますã?
433 *
434 * @param cells Cell[] EXCELの行ã?セル配å?
435 *
436 * @return String[] カラãƒ??配å?æƒ??
437 */
438 String[] toArray( final Cell[] cells ) {
439 if( nameNoSet ) {
440 String errMsg = "#NAME が見つかる前にãƒ??タが見つかりましたã€?;
441 throw new HybsSystemException( errMsg );
442 }
443
444 int cellSize = cells.length;
445 String[] data = new String[columnSize];
446 for( int i=0;i<columnSize; i++ ) {
447 int indx = index[i];
448 if( indx < cellSize ) {
449 data[i] = cells[indx].getContents();
450 }
451 else {
452 data[i] = null;
453 }
454 }
455
456 return data;
457 }
458 }