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 */ 016package org.opengion.hayabusa.report; 017 018import org.opengion.hayabusa.common.HybsSystemException; 019import org.opengion.fukurou.util.StringUtil; 020import org.opengion.fukurou.util.HybsDateUtil ; 021import org.opengion.fukurou.util.Closer ; 022 023import org.apache.poi.poifs.filesystem.POIFSFileSystem; 024import org.apache.poi.hssf.record.RecordFormatException; 025 026import org.apache.poi.hssf.usermodel.HSSFWorkbook; 027import org.apache.poi.hssf.usermodel.HSSFSheet; 028import org.apache.poi.hssf.usermodel.HSSFRow; 029import org.apache.poi.hssf.usermodel.HSSFCell; 030import org.apache.poi.hssf.usermodel.HSSFDateUtil; 031import org.apache.poi.hssf.usermodel.HSSFRichTextString; 032 033import java.io.File; 034import java.io.InputStream; 035import java.io.FileInputStream; 036import java.io.IOException; 037 038// import java.text.DateFormat; 039// import java.text.SimpleDateFormat; 040// import java.util.Locale ; 041import java.text.NumberFormat ; 042import java.text.DecimalFormat ; 043import java.util.Iterator ; 044 045/** 046 * 【EXCEL取込】雛形EXCELシートの解析処理を行う為の、HSSFListener 拡張クラスです。 047 * このオブジェクトは、HSSFRequest クラスの addListenerForAllRecords メソッドに渡す 048 * HSSFListener インターフェースを実装しています。また、雛形EXCEL を処理後、ExcelLayout 049 * 管理クラスを取得することが出来ます。 050 * 051 * ※ 最新のPOIでは、org.apache.poi.ss.usermodel を使う事で、2003形式、2007形式に対応させます。 052 * report パッケージは保守対象外なので、あえて修正しません。 053 * 054 * @og.rev 3.8.0.0 (2005/06/07) 新規追加 055 * @og.group 帳票システム 056 * 057 * @version 4.0 058 * @author Kazuhiko Hasegawa 059 * @since JDK5.0, 060 */ 061public class ExcelDataPickup { 062 063 private final ExcelLayout layout ; 064// private final File filename; 065 066 private final InputStream in; 067 private final HSSFWorkbook wb; 068// private DateFormat dateFormat = null; // 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正 069 private NumberFormat numFormat = null; 070 071 private final boolean debug; 072 073 /** 074 * 雛形EXCELを処理済みのExcelLayoutオブジェクトと、 075 * データEXCELファイル名よりオブジェクトを構築します。 076 * 077 * 内部で、HSSFWorkbook を構築します。 078 * 079 * @param layout 雛形EXCELを処理済みのExcelLayoutオブジェクト 080 * @param filename データEXCELファイル名 081 * @param debug デバッグフラグ 082 */ 083// public ExcelDataPickup( final ExcelLayout layout,final File fname, final boolean debug ) { 084 public ExcelDataPickup( final ExcelLayout layout,final File filename, final boolean debug ) { 085 this.layout = layout; 086// filename = fname; 087 this.debug = debug; 088 089 try { 090 in = new FileInputStream( filename ); 091 092 POIFSFileSystem fs = new POIFSFileSystem( in ); 093 wb = new HSSFWorkbook( fs ); 094 } 095 catch (IOException ex) { 096 String errMsg = "ファイル読込みエラー[" + filename.getName() + "]" ; 097 throw new HybsSystemException( errMsg,ex ); 098 } 099 catch (RecordFormatException ex) { 100 String errMsg = "無効の形式/データが使用されています。[" + filename.getName() + "]" 101 + "現バージョンのPOIでは読み取ることが出来ません。" 102 + "例えば、自動フィルタの設定されたシートが含まれる場合などです。" ; 103 throw new HybsSystemException( errMsg,ex ); 104 } 105 } 106 107 /** 108 * データEXCELファイル名のシート数を返します。 109 * 110 * 内部で、HSSFWorkbook を構築します。 111 * 112 * @return シート数 113 */ 114 public int getSheetSize() { 115 return wb.getNumberOfSheets(); 116 } 117 118 /** 119 * データEXCELファイル名のデータをピックアップします。 120 * 121 * この処理を行うと、ExcelLayout オブジェクトにデータEXCEL解析結果を 122 * 保存しますので、処理側でその結果を取り出して使用します。 123 * 124 * @og.rev 3.8.1.1 (2005/11/21) デバッグ用コメント修正 125 * 126 * @param modelSheetNo 雛形シート番号 127 * @param sheetNo データシート番号 128 * @param loopClm 繰返必須カラム(なければ通常の1対1処理) 129 */ 130 public void execute( final int modelSheetNo, final int sheetNo, final String loopClm ) { 131 132 HSSFSheet sheet = wb.getSheetAt( sheetNo ); 133 layout.dataClear(); 134 135 if( debug ) { System.out.println( sheetNo + ":" + wb.getSheetName( sheetNo ) ); } 136 137 Iterator<ExcelLayoutData> ite = layout.getLayoutDataIterator( modelSheetNo,loopClm ) ; 138 while( ite.hasNext() ) { 139// ExcelLayoutData data = (ExcelLayoutData)ite.next(); 140 ExcelLayoutData data = ite.next(); 141 String clm = data.getClm(); 142 int edbn = data.getEdbn(); 143 int row = data.getRowNo(); 144 short col = data.getColNo(); 145 146 // if( clm.indexOf( debugClm ) >= 0 ) { debug = true; } 147 // else { debug = false; } 148 149 String val = getValue( sheet,row,col ); 150 layout.addData( clm,edbn,val ); 151 if( debug ) { System.out.println( data.toString() + "=[" + val + "]" ); } 152 } 153 } 154 155 /** 156 * シートオブジェクト(HSSFSheet)から行列番号を指定して値を取り出します。 157 * 行オブジェクト(HSSFRow)や列オブジェクト(HSSFCell)が存在しない場合は、nullを返します。 158 * それ以外は、各セルタイプに応じて、処理を行います。 159 * 関数タイプ(HSSFCell.CELL_TYPE_FORMULA)の場合は、まず、文字列として取り出し、ゼロ文字列の 160 * 場合は、数字タイプとして取り出します。 161 * 162 * @og.rev 3.8.0.9 (2005/10/17) 結果を rtrim(右スペース削除)します。 163 * @og.rev 3.8.1.1 (2005/11/21) デバッグ用コメント修正 164 * @og.rev 3.9.0.5 (2008/11/27) POI3.2対応 引数の型変更(short⇒int) 165 * 166 * @param sheet EXCELのシートオブジェクト 167 * @param row 行番号 168 * @param col 列番号 169 * 170 * @return セルの値 171 */ 172// private String getValue( final HSSFSheet sheet,final int row, final short col ) { 173 private String getValue( final HSSFSheet sheet,final int row, final int col ) { 174 175 HSSFRow oRow = sheet.getRow(row); 176 if( oRow == null ) { return null; } 177 HSSFCell oCell = oRow.getCell(col); 178 if( oCell == null ) { return null; } 179 180 String strText = ""; 181 HSSFRichTextString richText ; 182 int nCellType = oCell.getCellType(); 183 switch( nCellType ) { 184 case HSSFCell.CELL_TYPE_NUMERIC: 185 strText = getNumericTypeString( oCell ); 186 break; 187 case HSSFCell.CELL_TYPE_STRING: 188 // POI3.0 strText = oCell.getStringCellValue(); 189 richText = oCell.getRichStringCellValue(); 190 strText = richText.getString(); 191 if( debug ) { System.out.print( "String :" ); } 192 break; 193 case HSSFCell.CELL_TYPE_FORMULA: 194 // strText = oCell.getCellFormula(); 195 // POI3.0 strText = oCell.getStringCellValue(); 196 richText = oCell.getRichStringCellValue(); 197 strText = richText.getString(); 198 if( strText == null || strText.length() == 0 ) { 199 strText = getNumericTypeString( oCell ); 200 } 201 else { 202 if( debug ) { System.out.print( "Formula:" ); } 203 } 204 break; 205 case HSSFCell.CELL_TYPE_BOOLEAN: 206 strText = String.valueOf(oCell.getBooleanCellValue()); 207 if( debug ) { System.out.print( "Boolean:" ); } 208 break; 209 case HSSFCell.CELL_TYPE_BLANK : 210 if( debug ) { System.out.print( "Blank :" ); } 211 break; 212 case HSSFCell.CELL_TYPE_ERROR : 213 if( debug ) { System.out.print( "Error :" ); } 214 break; 215 default : 216 if( debug ) { System.out.print( "Other " + nCellType + ":" ); } 217 break; 218 } 219 220 return StringUtil.rTrim( strText ); // 3.8.0.9 (2005/10/17) 221 } 222 223 /** 224 * セル値が数字の場合に、数字か日付かを判断して、対応する文字列を返します。 225 * 226 * @og.rev 3.8.1.1 (2005/11/21) デバッグ用コメント修正 227 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 228 * ※ 最新のPOIでは、org.apache.poi.ss.usermodel を使う事で、2003形式、2007形式に対応させます。 229 * report パッケージは保守対象外なので、あえて修正しません。 230 * 231 * @param oCell Cellオブジェクト 232 * 233 * @return 数字の場合は、文字列に変換した結果を、日付の場合は、"yyyyMMddHHmmss" 形式で返します。 234 */ 235 private String getNumericTypeString( final HSSFCell oCell ) { 236 final String strText ; 237 238 double dval = oCell.getNumericCellValue() ; 239 if( HSSFDateUtil.isCellDateFormatted( oCell ) ) { 240 strText = HybsDateUtil.getDate( HSSFDateUtil.getJavaDate( dval ).getTime() , "yyyyMMddHHmmss" ); 241 242// if( dateFormat == null ) { 243// dateFormat = new SimpleDateFormat( "yyyyMMddHHmmss",Locale.JAPAN ); 244// } 245// strText = dateFormat.format( HSSFDateUtil.getJavaDate( dval ) ); 246 if( debug ) { System.out.print( "Date :" ); } 247 } 248 else { 249 // 3.8.0.9 (2005/10/17) 数字について、NumberFormat を行います。 250 if( numFormat == null ) { 251 numFormat = NumberFormat.getInstance(); 252 if( numFormat instanceof DecimalFormat ) { 253 ((DecimalFormat)numFormat).applyPattern( "#.####" ); 254 } 255 } 256 strText = numFormat.format( dval ); 257 if( debug ) { System.out.print( "Numeric:" ); } 258 } 259 return strText ; 260 } 261 262 /** 263 * EXCEL をオープンした InputStream を閉じます。 264 */ 265 public void close() { 266 Closer.ioClose( in ); // 4.0.0 (2006/01/31) close 処理時の IOException を無視 267 } 268}