1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   /*
57    * FormulaViewer.java - finds formulas in a BIFF8 file and attempts to parse them and
58    * display info about them.
59    *
60    * Created on November 18, 2001, 7:58 AM
61    */
62   package org.apache.poi.hssf.dev;
63   
64   import java.io.InputStream;
65   import java.io.IOException;
66   import java.io.ByteArrayInputStream;
67   import java.io.FileInputStream;
68   import java.io.FileOutputStream;
69   
70   //import java.io.*;
71   import java.util.List;
72   
73   import org.apache.poi.poifs.filesystem.POIFSFileSystem;
74   import org.apache.poi.util.LittleEndian;
75   import org.apache.poi.util.HexDump;
76   import org.apache.poi.hssf.record.*;
77   import org.apache.poi.hssf.record.formula.*;
78   import org.apache.poi.hssf.model.*;
79   import org.apache.poi.hssf.usermodel.*;
80   
81   /**
82    * FormulaViewer - finds formulas in a BIFF8 file and attempts to read them/display
83    * data from them. Only works if Formulas are enabled in "RecordFactory"
84    * @author  andy
85    */
86   
87   public class FormulaViewer
88   {
89       private String file;
90   
91       /** Creates new FormulaViewer */
92   
93       public FormulaViewer()
94       {
95       }
96   
97       /**
98        * Method run
99        *
100       *
101       * @exception Exception
102       *
103       */
104  
105      public void run()
106          throws Exception
107      {
108          POIFSFileSystem fs      =
109              new POIFSFileSystem(new FileInputStream(file));
110          List            records =
111              RecordFactory
112                  .createRecords(fs.createDocumentInputStream("Workbook"));
113  
114          for (int k = 0; k < records.size(); k++)
115          {
116              Record record = ( Record ) records.get(k);
117  
118              if (record.getSid() == FormulaRecord.sid)
119              {
120                  parseFormulaRecord(( FormulaRecord ) record);
121              }
122          }
123      }
124  
125      /**
126       * Method parseFormulaRecord
127       *
128       *
129       * @param record
130       *
131       */
132  
133      public void parseFormulaRecord(FormulaRecord record)
134      {
135          System.out.println("In ParseFormula Record");
136          System.out.println("row   = " + record.getRow());
137          System.out.println("col   = " + record.getColumn());
138          System.out.println("value = " + record.getValue());
139          System.out.println("xf    = " + record.getXFIndex());
140          System.out.println("number of ptgs = "
141                             + record.getNumberOfExpressionTokens());
142          System.out.println("options = " + record.getOptions());
143          System.out.println(composeForumla(record));
144      }
145  
146      public String composeForumla(FormulaRecord record)
147      {
148          StringBuffer formula = new StringBuffer("=");
149          int          numptgs = record.getNumberOfExpressionTokens();
150          List         ptgs    = record.getParsedExpression();
151  
152          for (int ptgnum = numptgs - 1; ptgnum > (-1); ptgnum--)
153          {
154              Ptg          ptg      = ( Ptg ) ptgs.get(ptgnum);
155              OperationPtg optg     = ( OperationPtg ) ptg;
156              int          numops   = optg.getNumberOfOperands();
157              Ptg[]        ops      = new Ptg[ numops ];
158              int          opoffset = 1;
159  
160              for (int opnum = ops.length - 1; opnum > -1; opnum--)
161              {
162                  ops[ opnum ] = ( Ptg ) ptgs.get(ptgnum - opoffset);
163                  opoffset++;
164              }
165              formula.append(optg.toFormulaString(ops));
166              ptgnum -= ops.length;
167          }
168          return formula.toString();
169      }
170  
171      /**
172       * Method setFile
173       *
174       *
175       * @param file
176       *
177       */
178  
179      public void setFile(String file)
180      {
181          this.file = file;
182      }
183  
184      /**
185       * Method main
186       *
187       * pass me a filename and I'll try and parse the formulas from it
188       *
189       * @param args pass one argument with the filename or --help
190       *
191       */
192  
193      public static void main(String args[])
194      {
195          if ((args == null) || (args.length != 1)
196                  || args[ 0 ].equals("--help"))
197          {
198              System.out.println(
199                  "FormulaViewer .8 proof that the devil lies in the details (or just in BIFF8 files in general)");
200              System.out.println("usage: Give me a big fat file name");
201          }
202          else
203          {
204              try
205              {
206                  FormulaViewer viewer = new FormulaViewer();
207  
208                  viewer.setFile(args[ 0 ]);
209                  viewer.run();
210              }
211              catch (Exception e)
212              {
213                  System.out.println("Whoops!");
214                  e.printStackTrace();
215              }
216          }
217      }
218  }
219  ??????????????????createRecords????????????????????????????????fs???????????????????????????????????createDocumentInputStream?????????????????????????k?????????????????????????????records?????????????????????????????????????????????k?????????????Record???????????????????????????????Record????????????????????????????????????????records????????????????????????????????????????????????????k?????????????????record????????????????????????getSid????????????????????????????????????FormulaRecord??????????????????????????????????????????????????sid?????????????????parseFormulaRecord??????????????????????????????????????FormulaRecord??????????????????????????????????????????????????????record????????????????????????????????????????????????????????????????????????????????????????????????????????????parseFormulaRecord????????????????????????????????????FormulaRecord?????????????????????????????????????????record?????????????????????????????????????????record?????????????????????????????????????????record?????????????????????????????????????????record??????????????????????????????record???????????????????????????????????????????record????????????????????????????composeForumla???????????????????????????????????????????record???????????????????composeForumla??????????????????????????????????FormulaRecord????????????????????????????????record????????????????????????????????record???????????????????????????numptgs????????????????????????????????????????ptgnum???????????????????????????????????????????????????????ptgnum?????????????Ptg???????????????????????????????????????Ptg?????????????????????????????????????????????ptgs??????????????????????????????????????????????????????ptgnum?????????????OperationPtg???????????????????????????????????????OperationPtg??????????????????????????????????????????????????????ptg?????????????????????????????????????optg??????????????????????????????????????????getNumberOfOperands?????????????Ptg?????????????????????????????????????????Ptg??????????????????????????????????????????????numops??????????????????????????????ops??????????????????????????????????????????????opnum??????????????????????????????????????????????????????????opnum?????????????????ops??????????????????????opnum??????????????????????????????????Ptg????????????????????????????????????????ptgs?????????????????????????????????????????????????ptgnum??????????????????????????????????????????????????????????opoffset?????????????????opoffset?????????????formula????????????????????????????optg?????????????????????????????????toFormulaString?????????????????????????????????????????????????ops?????????????ptgnum???????????????????????ops????????????????formula???????????????????????????????????????????????????????????????????????????????????????????????setFile?????????????????????file???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????main??????????????args????????????????????????????????args????????????????????args?????????????????FormulaViewer????????????????????????????????????????????FormulaViewer?????????????????viewer????????????????????????setFile????????????????????????????????args?????????????????viewer????????????????????????run?????????????????e