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