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.fukurou.util.Closer ; 019import org.opengion.fukurou.util.LogWriter; 020 021import org.apache.poi.poifs.filesystem.POIFSFileSystem; 022import org.apache.poi.hssf.eventusermodel.HSSFRequest ; 023import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; 024import org.apache.poi.hssf.eventusermodel.HSSFListener ; 025import org.apache.poi.hssf.record.SSTRecord ; 026import org.apache.poi.hssf.record.Record ; 027import org.apache.poi.hssf.record.BOFRecord ; 028import org.apache.poi.hssf.record.BoundSheetRecord; 029import org.apache.poi.hssf.record.LabelSSTRecord; 030import org.apache.poi.hssf.record.common.UnicodeString; // X.X.X.X (2012/XX/XX) POI3.0の場合 031 032import java.io.File; 033import java.io.InputStream; 034import java.io.FileInputStream; 035import java.io.IOException; 036 037/** 038 * 【EXCEL取込】雛形EXCELシートの解析処理を行う為の、HSSFListener 拡張クラスです。 039 * このオブジェクトは、HSSFRequest クラスの addListenerForAllRecords メソッドに渡す 040 * HSSFListener インターフェースを実装しています。また、雛形EXCEL を処理後、ExcelLayout 041 * 管理クラスを取得することが出来ます。 042 * 043 * @og.rev 3.8.0.0 (2005/06/07) 新規追加 044 * @og.group 帳票システム 045 * 046 * @version 4.0 047 * @author Kazuhiko Hasegawa 048 * @since JDK5.0, 049 */ 050public class HybsHSSFListener implements HSSFListener { 051 private SSTRecord sstrec; 052 private int sheetNo = -1; 053 private int sheetSize = 0; 054 private boolean trace = false; 055 056 private ExcelLayout laynot = null; 057 058 /** 059 * 雛形EXCELの {@カラム} 解析情報を設定します。 060 * 061 * 雛形EXCELは、HSSFListener を使用して、イベント駆動で取得します。その場合、 062 * {@カラム}を含むセルを見つける都度、このメソッドを呼び出して、{@カラム}の 063 * 位置(行列番号)を設定します。 064 * データEXCELからデータを読み出す場合は、ここで登録したカラムの行列より、読み込みます。 065 * 具体的には、HSSFListener#processRecord( Record )で、SSTRecord.sid の 情報をキープしておき、 066 * LabelSSTRecord.sid 毎に、{@カラム}を含むかチェックし、含む場合に、このメソッドに 067 * 解析情報を設定します。 068 * 069 * @og.rev 4.3.4.0 (2008/12/01) POI3.2対応 引数の型変更(SSTRecord の toString() 化) 070 * 071 * @param record Recordオブジェクト 072 */ 073 public void processRecord( final Record record ) { 074 switch ( record.getSid() ) { 075 // Workbook での シート毎に呼ばれます。先行するため、この回数をシート数として数えます。 076 case BoundSheetRecord.sid: 077 // 4.0.0.0 (2007/11/29) 入れ子if の統合 078 if( trace && record instanceof BoundSheetRecord ) { 079 BoundSheetRecord bsr = (BoundSheetRecord) record; 080 System.out.println("Sheet named: " + bsr.getSheetname() ); 081 } 082 sheetSize ++ ; 083 break; 084 // TYPE_WORKSHEET の場合、シート開始毎に呼ばれます。 085 case BOFRecord.sid: 086 if( record instanceof BOFRecord ) { 087 BOFRecord bof = (BOFRecord) record; 088 if(bof.getType() == BOFRecord.TYPE_WORKBOOK) { 089 if( trace ) { System.out.println("Encountered workbook"); } 090 } 091 else if(bof.getType() == BOFRecord.TYPE_WORKSHEET) { 092 // シート開始毎に呼ばれるため、現在のシート番号を得るのに使用します。 093 sheetNo++ ; 094 if( trace ) { System.out.println("Encountered sheet [" + sheetNo + "]" ); } 095 } 096 } 097 break; 098 // すべてのレコードにアクセスするために、一度だけ呼ばれます。ここで初期化しておきます。 099 case SSTRecord.sid: 100 if( record instanceof SSTRecord ) { 101 sstrec = (SSTRecord) record; 102 laynot = new ExcelLayout( sheetSize ); 103 if( trace ) { System.out.println( "SSTRecord:[" + sstrec.getNumUniqueStrings() + "]" ); } 104 // for( int k=0; k<sstrec.getNumUniqueStrings(); k++ ) { 105 // String val = sstrec.getString(k); 106 // System.out.println("SSTRecord id=[" + k + "]=[" + val + "]" ); 107 // } 108 } 109 break; 110 // 文字型のレコードです。 111 case LabelSSTRecord.sid: 112 if( record instanceof LabelSSTRecord ) { 113 LabelSSTRecord lrec = (LabelSSTRecord) record; 114 115 int row = lrec.getRow(); 116 short col = lrec.getColumn(); 117 // String val = sstrec.getString( lrec.getSSTIndex() ) ; // POI3.0の場合 118 UnicodeString ustr = sstrec.getString( lrec.getSSTIndex() ) ; 119 String val = ustr.getString(); 120 121 // カラムに、{@を含む場合は、laynot に雛形情報を追加します。 122 // 整合性チェックは、ExcelLayoutData クラスで行います。 123 if( val != null && val.indexOf( "{@" ) >= 0 ) { 124 if( trace ) { System.out.println("String cell id,sheet,row,col=[" + lrec.getSSTIndex() + "," + sheetNo + "," + row + "," + col + "] => " + val ); } 125 laynot.addModel( sheetNo,val,row,col ); 126 } 127 } 128 break; 129 default : 130 LogWriter.log( "想定外のイベントを受け取りました。=[" + record.getSid() + "]" ); 131 break; 132 } 133 } 134 135 /** 136 * 雛形EXCELシートの {@カラム} 解析データ管理クラスを返します。 137 * 138 * 雛形EXCELを解析し終わった後で、解析データ管理クラスを取り出します。 139 * 雛形EXCELと、データEXCELが1対1ではないため、リアルタイム処理が出来ません。 140 * 一旦、すべての雛形EXCELを解析し終わった後で、データEXCEL処理を行う必要があります。 141 * 142 * @return 雛形EXCELシート 143 */ 144 public ExcelLayout getLayout() { return laynot; } 145 146 /** 147 * 雛形EXCEL のシート数を返します。 148 * 149 * @return 雛形シート数 150 */ 151 public int getSheetSize() { return sheetSize; } 152 153 /** 154 * 処理経過情報を表示するかどうか[true/false]を指定します(初期値:false) 155 * 156 * イベント毎の状況を、標準出力に出力するかどうかのフラグです。 157 * 初期値は、false です。 158 * 159 * @param flag 処理経過情報を表示するかどうか[true/false] 160 */ 161 public void setTrace( final boolean flag ) { trace = flag; } 162 163 /** 164 * EXCELレイアウト情報を取得します。 165 * 166 * POIのイベント処理(HSSFListener)で、各イベントごとに処理を行います。 167 * イベントは、BOFRecord、BoundSheetRecord、SSTRecord、LabelSSTRecord について 168 * 発生するように設定しています。 169 * 170 * @param file 処理するEXCELファイル 171 * @param trace 標準出力にトレース情報を出力するかどうかを指定します。 172 * 173 * @return EXCELレイアウト情報 174 * @throws IOException 入出力エラーが発生した場合 175 */ 176 public static ExcelLayout makeExcelLayout( final File file ,final boolean trace ) throws IOException { 177 178 FileInputStream fin = null; 179 InputStream din = null; 180 final HybsHSSFListener event ; 181 try { 182 fin = new FileInputStream( file ); 183 POIFSFileSystem poifs = new POIFSFileSystem( fin ); 184 din = poifs.createDocumentInputStream( "Workbook" ); 185 HSSFRequest req = new HSSFRequest(); 186 187 event = new HybsHSSFListener(); 188 event.setTrace( trace ); // 標準出力にトレース情報を出力します。 189 190 // req.addListenerForAllRecords( event ); // 全イベントを処理 191 req.addListener( event,BOFRecord.sid ); 192 req.addListener( event,BoundSheetRecord.sid ); 193 req.addListener( event,SSTRecord.sid ); 194 req.addListener( event,LabelSSTRecord.sid ); 195 196 HSSFEventFactory factory = new HSSFEventFactory(); 197 factory.processEvents( req,din ); 198 } 199 finally { 200 Closer.ioClose( fin ); // 4.0.0 (2006/01/31) close 処理時の IOException を無視 201 Closer.ioClose( din ); // 4.0.0 (2006/01/31) close 処理時の IOException を無視 202 // fin.close(); 203 // din.close(); 204 } 205 206 return event.getLayout(); 207 } 208}