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     */
016    package org.opengion.hayabusa.report;
017    
018    import org.opengion.fukurou.util.Closer ;
019    import org.opengion.fukurou.util.LogWriter;
020    
021    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
022    import org.apache.poi.hssf.eventusermodel.HSSFRequest ;
023    import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
024    import org.apache.poi.hssf.eventusermodel.HSSFListener ;
025    import org.apache.poi.hssf.record.SSTRecord ;
026    import org.apache.poi.hssf.record.Record ;
027    import org.apache.poi.hssf.record.BOFRecord  ;
028    import org.apache.poi.hssf.record.BoundSheetRecord;
029    import org.apache.poi.hssf.record.LabelSSTRecord;
030    import org.apache.poi.hssf.record.UnicodeString;
031    // import org.apache.poi.hssf.record.common.UnicodeString;              // X.X.X.X (2012/XX/XX) POI3.0の場å�?
032    
033    import java.io.File;
034    import java.io.InputStream;
035    import java.io.FileInputStream;
036    import 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     */
051    public 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シートã? {&#064;カラãƒ? 解析データ管ç�?‚¯ラスを返しますã?
138             *
139             * 雛形EXCELを解析し終わった後で、解析データ管ç�?‚¯ラスを取りå?しますã?
140             * 雛形EXCELと、データEXCELが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    }