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