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