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 }