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 }