]> source.dussan.org Git - poi.git/commitdiff
Merge changes from trunk to the ooxml branch - revisions 634630 to
authorNick Burch <nick@apache.org>
Sat, 29 Mar 2008 16:41:25 +0000 (16:41 +0000)
committerNick Burch <nick@apache.org>
Sat, 29 Mar 2008 16:41:25 +0000 (16:41 +0000)
638000

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@642554 13f79535-47bb-0310-9956-ffa450edef68

35 files changed:
src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/FormulaParser.java
src/java/org/apache/poi/hssf/model/TextboxShape.java
src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java
src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java
src/java/org/apache/poi/poifs/common/POIFSConstants.java
src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java
src/java/org/apache/poi/poifs/storage/RawDataBlockList.java
src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PercentEval.java [new file with mode: 0755]
src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
src/scratchpad/src/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java [new file with mode: 0755]
src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java
src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java [new file with mode: 0755]
src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java
src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java [new file with mode: 0755]
src/scratchpad/testcases/org/apache/poi/hwpf/data/Bug28627.doc [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java
src/testcases/org/apache/poi/hssf/data/27349-vlookupAcrossSheets.xls [new file with mode: 0755]
src/testcases/org/apache/poi/hssf/data/Bug44593.xls [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFTextbox.java [new file with mode: 0755]
src/testcases/org/apache/poi/poifs/property/TestPropertyTable.java
src/testcases/org/apache/poi/poifs/storage/LocalRawDataBlockList.java
src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java
src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableReader.java

index fdead9b9b55fcb6c4151727c7914237813b379bf..4bfd32b0e679b6616dc55d2cf0c82749b1f53315 100644 (file)
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.1-beta1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">44609 - Handle leading spaces in formulas, such as '= 4'</action>
+           <action dev="POI-DEVELOPERS" type="add">44608 - Support for PercentPtg in the formula evaluator</action>
+           <action dev="POI-DEVELOPERS" type="fix">44606 - Support calculated string values for evaluated formulas</action>
+           <action dev="POI-DEVELOPERS" type="add">Add accessors to horizontal and vertical alignment in HSSFTextbox</action>
+           <action dev="POI-DEVELOPERS" type="add">44593 - Improved handling of short DVRecords</action>
+           <action dev="POI-DEVELOPERS" type="add">28627 / 44580 - Fix Range.delete() in HWPF</action>
            <action dev="POI-DEVELOPERS" type="add">44539 - Support for area references in formulas of rows >= 32768</action>
            <action dev="POI-DEVELOPERS" type="add">44536 - Improved support for detecting read-only recommended files</action>
            <action dev="POI-DEVELOPERS" type="fix">43901 - Correctly update the internal last cell number when adding and removing cells (previously sometimes off-by-one)</action>
index c59cae1a3da4b4ed1d9e1f03d2183e9b40a96bc1..a6467d51647da7f9534bafe47eb4d2366d3f01f7 100644 (file)
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1-beta1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">44609 - Handle leading spaces in formulas, such as '= 4'</action>
+           <action dev="POI-DEVELOPERS" type="add">44608 - Support for PercentPtg in the formula evaluator</action>
+           <action dev="POI-DEVELOPERS" type="fix">44606 - Support calculated string values for evaluated formulas</action>
+           <action dev="POI-DEVELOPERS" type="add">Add accessors to horizontal and vertical alignment in HSSFTextbox</action>
+           <action dev="POI-DEVELOPERS" type="add">44593 - Improved handling of short DVRecords</action>
+           <action dev="POI-DEVELOPERS" type="add">28627 / 44580 - Fix Range.delete() in HWPF</action>
            <action dev="POI-DEVELOPERS" type="add">44539 - Support for area references in formulas of rows >= 32768</action>
            <action dev="POI-DEVELOPERS" type="add">44536 - Improved support for detecting read-only recommended files</action>
            <action dev="POI-DEVELOPERS" type="fix">43901 - Correctly update the internal last cell number when adding and removing cells (previously sometimes off-by-one)</action>
index 7b89b90d81f27193380e8f1f7d594bb228152be3..07bb51483c0c304e0007cdc5bc357c609db53670 100644 (file)
@@ -943,23 +943,7 @@ end;
         }
         Stack stack = new Stack();
 
-           // Excel allows to have AttrPtg at position 0 (such as Blanks) which
-           // do not have any operands. Skip them.
-        int i;
-        if(ptgs[0] instanceof AttrPtg) {
-            AttrPtg attrPtg0 = (AttrPtg) ptgs[0];
-            if(attrPtg0.isSemiVolatile()) {
-                // no visible formula for semi-volatile
-            } else {
-                // TODO -this requirement is unclear and is not addressed by any junits
-                stack.push(ptgs[0].toFormulaString(book));
-            }
-            i=1;
-        } else {
-            i=0;
-        }
-
-        for ( ; i < ptgs.length; i++) {
+        for (int i=0 ; i < ptgs.length; i++) {
             Ptg ptg = ptgs[i];
             // TODO - what about MemNoMemPtg?
             if(ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {
@@ -973,21 +957,30 @@ end;
                 continue;
             }
 
-            if (ptg instanceof AttrPtg && ((AttrPtg) ptg).isOptimizedIf()) {
-                continue;
+            if (ptg instanceof AttrPtg) {
+                AttrPtg attrPtg = ((AttrPtg) ptg);
+                if (attrPtg.isOptimizedIf()) {
+                    continue;
+                }
+                if (attrPtg.isSpace()) {
+                    // POI currently doesn't render spaces in formulas
+                    continue;
+                    // but if it ever did, care must be taken:
+                    // tAttrSpace comes *before* the operand it applies to, which may be consistent
+                    // with how the formula text appears but is against the RPN ordering assumed here 
+                }
             }
 
             final OperationPtg o = (OperationPtg) ptg;
             int nOperands = o.getNumberOfOperands();
             final String[] operands = new String[nOperands];
 
-            for (int j = nOperands-1; j >= 0; j--) {
+            for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
                 if(stack.isEmpty()) {
-                    //TODO: write junit to prove this works
                    String msg = "Too few arguments suppled to operation token ("
                         + o.getClass().getName() + "). Expected (" + nOperands
-                        + " but got " + (nOperands - j + 1);
-                    throw new FormulaParseException(msg);
+                        + ") operands but got (" + (nOperands - j + 1) + ")";
+                    throw new IllegalStateException(msg);
                 }
                 operands[j] = (String) stack.pop();
             }
index 4b1027809150b3ddf92fcfd60b20a7eb84cdcd82..e55fcacbc378e4a15c12ff5b3e444dd4a06d6b21 100644 (file)
@@ -133,8 +133,8 @@ public class TextboxShape
         HSSFTextbox shape = hssfShape;
 
         TextObjectRecord obj = new TextObjectRecord();
-        obj.setHorizontalTextAlignment( TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED );
-        obj.setVerticalTextAlignment( TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_TOP );
+        obj.setHorizontalTextAlignment( hssfShape.getHorizontalAlignment() );
+        obj.setVerticalTextAlignment( hssfShape.getVerticalAlignment());
         obj.setTextLocked( true );
         obj.setTextOrientation( TextObjectRecord.TEXT_ORIENTATION_NONE );
         int frLength = ( shape.getString().numFormattingRuns() + 1 ) * 8;
index 2ba47238043efd6d447c9ded6d3949e021d9ed81..d355fbfa1f3d2bb9b5e8aa4a3ac2ea40e59a269c 100644 (file)
@@ -33,20 +33,42 @@ import org.apache.poi.util.BitFieldFactory;
  * @author Jason Height (jheight at chariot dot net dot au)
  */
 
-public class AttrPtg
-    extends OperationPtg
-{
+public final class AttrPtg extends OperationPtg {
     public final static byte sid  = 0x19;
     private final static int  SIZE = 4;
     private byte              field_1_options;
     private short             field_2_data;
-    private BitField          semiVolatile = BitFieldFactory.getInstance(0x01);
-    private BitField          optiIf       = BitFieldFactory.getInstance(0x02);
-    private BitField          optiChoose   = BitFieldFactory.getInstance(0x04);
-    private BitField          optGoto      = BitFieldFactory.getInstance(0x08);
-    private BitField          sum          = BitFieldFactory.getInstance(0x10);
-    private BitField          baxcel       = BitFieldFactory.getInstance(0x20);
-    private BitField          space        = BitFieldFactory.getInstance(0x40);
+    
+    // flags 'volatile' and 'space', can be combined.  
+    // OOO spec says other combinations are theoretically possible but not likely to occur.
+    private static final BitField semiVolatile = BitFieldFactory.getInstance(0x01);
+    private static final BitField optiIf       = BitFieldFactory.getInstance(0x02);
+    private static final BitField optiChoose   = BitFieldFactory.getInstance(0x04);
+    private static final BitField optGoto      = BitFieldFactory.getInstance(0x08); // skip
+    private static final BitField sum          = BitFieldFactory.getInstance(0x10);
+    private static final BitField baxcel       = BitFieldFactory.getInstance(0x20); // 'assignment-style formula in a macro sheet'
+    private static final BitField space        = BitFieldFactory.getInstance(0x40);
+    
+    public static final class SpaceType {
+        private SpaceType() {
+            // no instances of this class
+        }
+        
+        /** 00H = Spaces before the next token (not allowed before tParen token) */
+        public static final int SPACE_BEFORE = 0x00;
+        /** 01H = Carriage returns before the next token (not allowed before tParen token) */
+        public static final int CR_BEFORE = 0x01;
+        /** 02H = Spaces before opening parenthesis (only allowed before tParen token) */
+        public static final int SPACE_BEFORE_OPEN_PAREN = 0x02;
+        /** 03H = Carriage returns before opening parenthesis (only allowed before tParen token) */
+        public static final int CR_BEFORE_OPEN_PAREN = 0x03;
+        /** 04H = Spaces before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
+        public static final int SPACE_BEFORE_CLOSE_PAERN = 0x04;
+        /** 05H = Carriage returns before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
+        public static final int CR_BEFORE_CLOSE_PAREN = 0x05;
+        /** 06H = Spaces following the equality sign (only in macro sheets) */
+        public static final int SPACE_AFTER_EQUALITY = 0x06;
+    }
 
     public AttrPtg() {
     }
@@ -56,6 +78,19 @@ public class AttrPtg
         field_1_options = in.readByte();
         field_2_data    = in.readShort();
     }
+    private AttrPtg(int options, int data) {
+        field_1_options = (byte) options;
+        field_2_data = (short) data;
+    }
+    
+    /**
+     * @param type a constant from <tt>SpaceType</tt>
+     * @param count the number of space characters
+     */
+    public static AttrPtg createSpace(int type, int count) {
+        int data = type & 0x00FF | (count << 8) & 0x00FFFF;
+        return new AttrPtg(space.set(0), data);
+    }
 
     public void setOptions(byte options)
     {
@@ -131,21 +166,31 @@ public class AttrPtg
         return field_2_data;
     }
 
-    public String toString()
-    {
-        StringBuffer buffer = new StringBuffer();
+    public String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
 
-        buffer.append("AttrPtg\n");
-        buffer.append("options=").append(field_1_options).append("\n");
-        buffer.append("data   =").append(field_2_data).append("\n");
-        buffer.append("semi   =").append(isSemiVolatile()).append("\n");
-        buffer.append("optimif=").append(isOptimizedIf()).append("\n");
-        buffer.append("optchos=").append(isOptimizedChoose()).append("\n");
-        buffer.append("isGoto =").append(isGoto()).append("\n");
-        buffer.append("isSum  =").append(isSum()).append("\n");
-        buffer.append("isBaxce=").append(isBaxcel()).append("\n");
-        buffer.append("isSpace=").append(isSpace()).append("\n");
-        return buffer.toString();
+        if(isSemiVolatile()) {
+            sb.append("volatile ");
+        }
+        if(isSpace()) {
+            sb.append("space count=").append((field_2_data >> 8) & 0x00FF);
+            sb.append(" type=").append(field_2_data & 0x00FF).append(" ");
+        }
+        // the rest seem to be mutually exclusive
+        if(isOptimizedIf()) {
+            sb.append("if dist=").append(getData());
+        } else if(isOptimizedChoose()) {
+            sb.append("choose dist=").append(getData());
+        } else if(isGoto()) {
+            sb.append("skip dist=").append(getData()); 
+        } else if(isSum()) {
+            sb.append("sum ");
+        } else if(isBaxcel()) {
+            sb.append("assign ");
+        }
+        sb.append("]");
+        return sb.toString();
     }
 
     public void writeBytes(byte [] array, int offset)
index ae8a8253e6d8e11e38d3799774d305e1ba944498..ededf0d6480192920fa9189a91414749c4a0bc8b 100644 (file)
@@ -603,29 +603,30 @@ public class HSSFCell implements Cell
         if (hvalue == null)
         {
             setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex);
+            return;
         }
-        else
-        {
-            if ((cellType != CELL_TYPE_STRING ) && ( cellType != CELL_TYPE_FORMULA))
-            {
-                setCellType(CELL_TYPE_STRING, false, row, col, styleIndex);
-            }
-            int index = 0;
-
-            UnicodeString str = hvalue.getUnicodeString();            
-//          jmh            if (encoding == ENCODING_COMPRESSED_UNICODE)
-//          jmh            {
-//          jmh                str.setCompressedUnicode();
-//          jmh            } else if (encoding == ENCODING_UTF_16)
-//          jmh            {
-//          jmh                str.setUncompressedUnicode();
-//          jmh            }
-            index = book.addSSTString(str);            
-            (( LabelSSTRecord ) record).setSSTIndex(index);
-            stringValue = hvalue;
-            stringValue.setWorkbookReferences(book, (( LabelSSTRecord ) record));
-            stringValue.setUnicodeString(book.getSSTString(index));            
+        if (cellType == CELL_TYPE_FORMULA) {
+            // Set the 'pre-evaluated result' for the formula 
+            // note - formulas do not preserve text formatting.
+            FormulaRecordAggregate fr = (FormulaRecordAggregate) record;
+            // must make new sr because fr.getStringRecord() may be null
+            StringRecord sr = new StringRecord(); 
+            sr.setString(hvalue.getString()); // looses format
+            fr.setStringRecord(sr);
+            return;
+        }
+
+        if (cellType != CELL_TYPE_STRING) {
+            setCellType(CELL_TYPE_STRING, false, row, col, styleIndex);
         }
+        int index = 0;
+
+        UnicodeString str = hvalue.getUnicodeString();
+        index = book.addSSTString(str);
+        (( LabelSSTRecord ) record).setSSTIndex(index);
+        stringValue = hvalue;
+        stringValue.setWorkbookReferences(book, (( LabelSSTRecord ) record));
+        stringValue.setUnicodeString(book.getSSTString(index));
     }
 
     public void setCellFormula(String formula) {
index ac86b2d8dd2ae9de85eb979991abbf1ef82935f2..48816131a4a581d2294d9ce2ceef6bf94ec27c01 100644 (file)
@@ -19,6 +19,9 @@ package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.ss.usermodel.RichTextString;
 
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+
 /**
  * A textbox is a shape that may hold a rich text string.
  *
@@ -29,7 +32,27 @@ public class HSSFTextbox
 {
     public final static short       OBJECT_TYPE_TEXT               = 6;
 
+    /**
+     * How to align text horizontally
+     */
+    public final static short  HORIZONTAL_ALIGNMENT_LEFT = 1;
+    public final static short  HORIZONTAL_ALIGNMENT_CENTERED = 2;
+    public final static short  HORIZONTAL_ALIGNMENT_RIGHT = 3;
+    public final static short  HORIZONTAL_ALIGNMENT_JUSTIFIED = 4;
+    public final static short  HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7;
+
+    /**
+     * How to align text vertically
+     */
+    public final static short  VERTICAL_ALIGNMENT_TOP    = 1;
+    public final static short  VERTICAL_ALIGNMENT_CENTER = 2;
+    public final static short  VERTICAL_ALIGNMENT_BOTTOM = 3;
+    public final static short  VERTICAL_ALIGNMENT_JUSTIFY = 4;
+    public final static short  VERTICAL_ALIGNMENT_DISTRIBUTED= 7;
+
+
     int marginLeft, marginRight, marginTop, marginBottom;
+    short halign, valign;
 
     HSSFRichTextString string = new HSSFRichTextString("");
 
@@ -42,6 +65,9 @@ public class HSSFTextbox
     {
         super( parent, anchor );
         setShapeType(OBJECT_TYPE_TEXT);
+
+        halign = HORIZONTAL_ALIGNMENT_LEFT;
+        valign = VERTICAL_ALIGNMENT_TOP;
     }
 
     /**
@@ -123,4 +149,36 @@ public class HSSFTextbox
     {
         this.marginBottom = marginBottom;
     }
+
+    /**
+     * Gets the horizontal alignment.
+     */
+    public short getHorizontalAlignment()
+    {
+        return halign;
+    }
+
+    /**
+     * Sets the horizontal alignment.
+     */
+    public void setHorizontalAlignment( short align )
+    {
+        this.halign = align;
+    }
+
+    /**
+     * Gets the vertical alignment.
+     */
+    public short getVerticalAlignment()
+    {
+        return valign;
+    }
+
+    /**
+     * Sets the vertical alignment.
+     */
+    public void setVerticalAlignment( short align )
+    {
+        this.valign = align;
+    }
 }
index 438f5e59683f75976ecfef08a1bd8391b299551d..73804966fbedf026d4fb2aede7e2e1971c60f39a 100644 (file)
@@ -18,6 +18,9 @@ package org.apache.poi.hssf.util;
 
 import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
 import java.util.ArrayList;
 
 /**
@@ -38,6 +41,8 @@ import java.util.ArrayList;
 
 public class HSSFCellRangeAddress
 {
+       private static POILogger logger = POILogFactory.getLogger(HSSFCellRangeAddress.class);
+       
     /**
      * Number of following ADDR structures
      */
@@ -74,8 +79,19 @@ public class HSSFCellRangeAddress
                {
             short first_row = in.readShort(); 
             short first_col = in.readShort();
-            short last_row  = in.readShort();
-            short last_col  = in.readShort();
+            
+            short last_row  = first_row;
+            short last_col  = first_col;
+            if(in.remaining() >= 4) {
+                   last_row  = in.readShort();
+                   last_col  = in.readShort();
+            } else {
+               // Ran out of data
+               // For now, issue a warning, finish, and 
+               //  hope for the best....
+               logger.log(POILogger.WARN, "Ran out of data reading cell references for DVRecord");
+               k = this.field_addr_number;
+            }
 
                        AddrStructure region = new AddrStructure(first_row, first_col, last_row, last_col);
                        this.field_regions_list.add(region);
index 399f52be4ba3e8ab39631675c8ed2e6bce794451..ff2050274dcf20cd10460a993db7da08b333c6c0 100644 (file)
@@ -27,7 +27,11 @@ package org.apache.poi.poifs.common;
 
 public interface POIFSConstants
 {
+    /** Most files use 512 bytes as their big block size */
     public static final int BIG_BLOCK_SIZE = 0x0200;
+    /** Some use 4096 bytes */
+    public static final int LARGER_BIG_BLOCK_SIZE = 0x1000;
+    
     public static final int END_OF_CHAIN   = -2;
     public static final int PROPERTY_SIZE  = 0x0080;
     public static final int UNUSED_BLOCK   = -1;
index fe94b4aaf9ebc7ba74965552791fe82b0f0399c0..73911e6b0e05c9e27cb7f04dbf55cdd865cfabb0 100644 (file)
@@ -78,7 +78,7 @@ public class POIFSReader
         HeaderBlockReader header_block_reader = new HeaderBlockReader(stream);
 
         // read the rest of the stream into blocks
-        RawDataBlockList  data_blocks         = new RawDataBlockList(stream);
+        RawDataBlockList  data_blocks         = new RawDataBlockList(stream, header_block_reader.getBigBlockSize());
 
         // set up the block allocation table (necessary for the
         // data_blocks to be manageable
index ef9acfe60b7cd669b1bdeeb50d49a2f901a442a4..61774dc6768e8a599a20196fa561218104578843 100644 (file)
@@ -33,6 +33,7 @@ import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.dev.POIFSViewable;
 import org.apache.poi.poifs.property.DirectoryProperty;
 import org.apache.poi.poifs.property.Property;
@@ -63,7 +64,6 @@ public class POIFSFileSystem
 {
     private static final Log _logger = LogFactory.getLog(POIFSFileSystem.class);
     
-    
     private static final class CloseIgnoringInputStream extends InputStream {
 
         private final InputStream _is;
@@ -91,11 +91,16 @@ public class POIFSFileSystem
     private PropertyTable _property_table;
     private List          _documents;
     private DirectoryNode _root;
+    
+    /**
+     * What big block size the file uses. Most files
+     *  use 512 bytes, but a few use 4096
+     */
+    private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
 
     /**
      * Constructor, intended for writing
      */
-
     public POIFSFileSystem()
     {
         _property_table = new PropertyTable();
@@ -138,13 +143,15 @@ public class POIFSFileSystem
         this();
         boolean success = false;
 
-        // read the header block from the stream
         HeaderBlockReader header_block_reader;
-        // read the rest of the stream into blocks
         RawDataBlockList data_blocks;
         try {
+            // read the header block from the stream
             header_block_reader = new HeaderBlockReader(stream);
-            data_blocks = new RawDataBlockList(stream);
+            bigBlockSize = header_block_reader.getBigBlockSize();
+            
+            // read the rest of the stream into blocks
+            data_blocks = new RawDataBlockList(stream, bigBlockSize);
             success = true;
         } finally {
             closeInputStream(stream, success);
@@ -307,7 +314,7 @@ public class POIFSFileSystem
 
         // create a list of BATManaged objects: the documents plus the
         // property table and the small block table
-        List                       bm_objects = new ArrayList();
+        List bm_objects = new ArrayList();
 
         bm_objects.addAll(_documents);
         bm_objects.add(_property_table);
@@ -602,6 +609,13 @@ public class POIFSFileSystem
         return "POIFS FileSystem";
     }
 
+    /**
+     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+     */
+    public int getBigBlockSize() {
+       return bigBlockSize;
+    }
+    
     /* **********  END  begin implementation of POIFSViewable ********** */
 }   // end public class POIFSFileSystem
 
index 0d5bb817b4540c6e1e2b35ce23dd1df4ec08a402..b001b8105857f8fb61b2c170ddd8597b89d5ad4a 100644 (file)
@@ -21,8 +21,6 @@ package org.apache.poi.poifs.storage;
 
 import java.io.*;
 
-import java.util.*;
-
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
 import org.apache.poi.util.IOUtils;
@@ -30,7 +28,6 @@ import org.apache.poi.util.IntegerField;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LongField;
-import org.apache.poi.util.ShortField;
 
 /**
  * The block containing the archive header
@@ -41,6 +38,11 @@ import org.apache.poi.util.ShortField;
 public class HeaderBlockReader
     implements HeaderBlockConstants
 {
+    /**
+     * What big block size the file uses. Most files
+     *  use 512 bytes, but a few use 4096
+     */
+    private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
 
     // number of big block allocation table blocks (int)
     private IntegerField _bat_count;
@@ -69,20 +71,27 @@ public class HeaderBlockReader
     public HeaderBlockReader(final InputStream stream)
         throws IOException
     {
-        _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
-        int byte_count = IOUtils.readFully(stream, _data);
-
-        if (byte_count != POIFSConstants.BIG_BLOCK_SIZE)
-        {
-               if (byte_count == -1)
-                       //Cant have -1 bytes read in the error message!
-                       byte_count = 0;
-            String type = " byte" + ((byte_count == 1) ? ("")
-                                                       : ("s"));
-
-            throw new IOException("Unable to read entire header; "
-                                  + byte_count + type + " read; expected "
-                                  + POIFSConstants.BIG_BLOCK_SIZE + " bytes");
+       // At this point, we don't know how big our
+       //  block sizes are
+       // So, read the first 32 bytes to check, then
+       //  read the rest of the block
+       byte[] blockStart = new byte[32];
+       int bsCount = IOUtils.readFully(stream, blockStart);
+       if(bsCount != 32) {
+               alertShortRead(bsCount);
+       }
+       
+       // Figure out our block size
+       if(blockStart[30] == 12) {
+               bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE;
+       }
+        _data = new byte[ bigBlockSize ];
+        System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
+       
+       // Now we can read the rest of our header
+        int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
+        if (byte_count+bsCount != bigBlockSize) {
+               alertShortRead(byte_count);
         }
 
         // verify signature
@@ -110,13 +119,24 @@ public class HeaderBlockReader
         _xbat_start     = new IntegerField(_xbat_start_offset, _data);
         _xbat_count     = new IntegerField(_xbat_count_offset, _data);
     }
+    
+    private void alertShortRead(int read) throws IOException {
+       if (read == -1)
+               //Cant have -1 bytes read in the error message!
+               read = 0;
+        String type = " byte" + ((read == 1) ? ("")
+                                                   : ("s"));
+
+        throw new IOException("Unable to read entire header; "
+                              + read + type + " read; expected "
+                              + bigBlockSize + " bytes");
+    }
 
     /**
      * get start of Property Table
      *
      * @return the index of the first block of the Property Table
      */
-
     public int getPropertyStart()
     {
         return _property_start.get();
@@ -174,5 +194,12 @@ public class HeaderBlockReader
     {
         return _xbat_start.get();
     }
+    
+    /**
+     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+     */
+    public int getBigBlockSize() {
+       return bigBlockSize;
+    }
 }   // end public class HeaderBlockReader
 
index eed318fb552ae54ec2de5bce3c3891e0fe88c416..76ab219562007e692fee01b6b39f5553b6c11ee7 100644 (file)
@@ -37,19 +37,20 @@ public class RawDataBlockList
      * Constructor RawDataBlockList
      *
      * @param stream the InputStream from which the data will be read
+     * @param bigBlockSize The big block size, either 512 bytes or 4096 bytes
      *
      * @exception IOException on I/O errors, and if an incomplete
      *            block is read
      */
 
-    public RawDataBlockList(final InputStream stream)
+    public RawDataBlockList(final InputStream stream, int bigBlockSize)
         throws IOException
     {
         List blocks = new ArrayList();
 
         while (true)
         {
-            RawDataBlock block = new RawDataBlock(stream);
+            RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
 
             if (block.eof())
             {
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PercentEval.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PercentEval.java
new file mode 100755 (executable)
index 0000000..c698a4e
--- /dev/null
@@ -0,0 +1,71 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.formula.eval;
+
+import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+
+/**
+ * Implementation of Excel formula token '%'. <p/>
+ * @author Josh Micich
+ */
+public final class PercentEval extends NumericOperationEval {
+
+       private PercentPtg _delegate;
+
+       private static final ValueEvalToNumericXlator NUM_XLATOR = new ValueEvalToNumericXlator(
+                       (short) (ValueEvalToNumericXlator.BOOL_IS_PARSED
+                                       | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
+                                       | ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.REF_STRING_IS_PARSED));
+
+       public PercentEval(Ptg ptg) {
+               _delegate = (PercentPtg) ptg;
+       }
+
+       protected ValueEvalToNumericXlator getXlator() {
+               return NUM_XLATOR;
+       }
+
+       public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+               if (args.length != 1) {
+                       return ErrorEval.VALUE_INVALID;
+               }
+
+               ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+               if (ve instanceof NumericValueEval) {
+                       double d0 = ((NumericValueEval) ve).getNumberValue();
+                       return new NumberEval(d0 / 100);
+               }
+
+               if (ve instanceof BlankEval) {
+                       return NumberEval.ZERO;
+               }
+               if (ve instanceof ErrorEval) {
+                       return ve;
+               }
+               return ErrorEval.VALUE_INVALID;
+       }
+
+       public int getNumberOfOperands() {
+               return _delegate.getNumberOfOperands();
+       }
+
+       public int getType() {
+               return _delegate.getType();
+       }
+}
index 3fce3065579b1a31aed726021a308cfc65f061e9..58ab5b47aefb6bcab2d4e061d89acf64a1228275 100644 (file)
@@ -24,71 +24,40 @@ import java.util.Stack;
 
 import org.apache.poi.hssf.model.FormulaParser;
 import org.apache.poi.hssf.model.Workbook;
-import org.apache.poi.hssf.record.formula.AddPtg;
 import org.apache.poi.hssf.record.formula.Area3DPtg;
 import org.apache.poi.hssf.record.formula.AreaPtg;
 import org.apache.poi.hssf.record.formula.AttrPtg;
 import org.apache.poi.hssf.record.formula.BoolPtg;
-import org.apache.poi.hssf.record.formula.ConcatPtg;
 import org.apache.poi.hssf.record.formula.ControlPtg;
-import org.apache.poi.hssf.record.formula.DividePtg;
-import org.apache.poi.hssf.record.formula.EqualPtg;
-import org.apache.poi.hssf.record.formula.FuncPtg;
-import org.apache.poi.hssf.record.formula.FuncVarPtg;
-import org.apache.poi.hssf.record.formula.GreaterEqualPtg;
-import org.apache.poi.hssf.record.formula.GreaterThanPtg;
 import org.apache.poi.hssf.record.formula.IntPtg;
-import org.apache.poi.hssf.record.formula.LessEqualPtg;
-import org.apache.poi.hssf.record.formula.LessThanPtg;
 import org.apache.poi.hssf.record.formula.MemErrPtg;
 import org.apache.poi.hssf.record.formula.MissingArgPtg;
-import org.apache.poi.hssf.record.formula.MultiplyPtg;
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
-import org.apache.poi.hssf.record.formula.NotEqualPtg;
 import org.apache.poi.hssf.record.formula.NumberPtg;
 import org.apache.poi.hssf.record.formula.OperationPtg;
 import org.apache.poi.hssf.record.formula.ParenthesisPtg;
-import org.apache.poi.hssf.record.formula.PowerPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
 import org.apache.poi.hssf.record.formula.ReferencePtg;
 import org.apache.poi.hssf.record.formula.StringPtg;
-import org.apache.poi.hssf.record.formula.SubtractPtg;
-import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
-import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
 import org.apache.poi.hssf.record.formula.UnionPtg;
 import org.apache.poi.hssf.record.formula.UnknownPtg;
-import org.apache.poi.hssf.record.formula.eval.AddEval;
 import org.apache.poi.hssf.record.formula.eval.Area2DEval;
 import org.apache.poi.hssf.record.formula.eval.Area3DEval;
 import org.apache.poi.hssf.record.formula.eval.AreaEval;
 import org.apache.poi.hssf.record.formula.eval.BlankEval;
 import org.apache.poi.hssf.record.formula.eval.BoolEval;
-import org.apache.poi.hssf.record.formula.eval.ConcatEval;
-import org.apache.poi.hssf.record.formula.eval.DivideEval;
-import org.apache.poi.hssf.record.formula.eval.EqualEval;
 import org.apache.poi.hssf.record.formula.eval.ErrorEval;
 import org.apache.poi.hssf.record.formula.eval.Eval;
-import org.apache.poi.hssf.record.formula.eval.FuncVarEval;
 import org.apache.poi.hssf.record.formula.eval.FunctionEval;
-import org.apache.poi.hssf.record.formula.eval.GreaterEqualEval;
-import org.apache.poi.hssf.record.formula.eval.GreaterThanEval;
-import org.apache.poi.hssf.record.formula.eval.LessEqualEval;
-import org.apache.poi.hssf.record.formula.eval.LessThanEval;
-import org.apache.poi.hssf.record.formula.eval.MultiplyEval;
 import org.apache.poi.hssf.record.formula.eval.NameEval;
-import org.apache.poi.hssf.record.formula.eval.NotEqualEval;
 import org.apache.poi.hssf.record.formula.eval.NumberEval;
 import org.apache.poi.hssf.record.formula.eval.OperationEval;
-import org.apache.poi.hssf.record.formula.eval.PowerEval;
 import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
 import org.apache.poi.hssf.record.formula.eval.Ref3DEval;
 import org.apache.poi.hssf.record.formula.eval.RefEval;
 import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.SubtractEval;
-import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;
-import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
 import org.apache.poi.hssf.record.formula.eval.ValueEval;
 
 /**
@@ -98,8 +67,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
 public class HSSFFormulaEvaluator {
                 
     // params to lookup the right constructor using reflection
-    private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
-
     private static final Class[] VALUE_CONTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
 
     private static final Class[] AREA3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval[].class };
@@ -111,8 +78,6 @@ public class HSSFFormulaEvaluator {
     // Maps for mapping *Eval to *Ptg
     private static final Map VALUE_EVALS_MAP = new HashMap();
 
-    private static final Map OPERATION_EVALS_MAP = new HashMap();
-
     /*
      * Following is the mapping between the Ptg tokens returned 
      * by the FormulaParser and the *Eval classes that are used 
@@ -124,26 +89,6 @@ public class HSSFFormulaEvaluator {
         VALUE_EVALS_MAP.put(NumberPtg.class, NumberEval.class);
         VALUE_EVALS_MAP.put(StringPtg.class, StringEval.class);
 
-        OPERATION_EVALS_MAP.put(AddPtg.class, AddEval.class);
-        OPERATION_EVALS_MAP.put(ConcatPtg.class, ConcatEval.class);
-        OPERATION_EVALS_MAP.put(DividePtg.class, DivideEval.class);
-        OPERATION_EVALS_MAP.put(EqualPtg.class, EqualEval.class);
-        //OPERATION_EVALS_MAP.put(ExpPtg.class, ExpEval.class); // TODO: check
-        // this
-        OPERATION_EVALS_MAP.put(FuncPtg.class, FuncVarEval.class); // TODO:
-                                                                   // check this
-        OPERATION_EVALS_MAP.put(FuncVarPtg.class, FuncVarEval.class);
-        OPERATION_EVALS_MAP.put(GreaterEqualPtg.class, GreaterEqualEval.class);
-        OPERATION_EVALS_MAP.put(GreaterThanPtg.class, GreaterThanEval.class);
-        OPERATION_EVALS_MAP.put(LessEqualPtg.class, LessEqualEval.class);
-        OPERATION_EVALS_MAP.put(LessThanPtg.class, LessThanEval.class);
-        OPERATION_EVALS_MAP.put(MultiplyPtg.class, MultiplyEval.class);
-        OPERATION_EVALS_MAP.put(NotEqualPtg.class, NotEqualEval.class);
-        OPERATION_EVALS_MAP.put(PowerPtg.class, PowerEval.class);
-        OPERATION_EVALS_MAP.put(SubtractPtg.class, SubtractEval.class);
-        OPERATION_EVALS_MAP.put(UnaryMinusPtg.class, UnaryMinusEval.class);
-        OPERATION_EVALS_MAP.put(UnaryPlusPtg.class, UnaryPlusEval.class);
-
     }
 
     
@@ -402,7 +347,7 @@ public class HSSFFormulaEvaluator {
                 if (optg instanceof AttrPtg) { continue; }
                 if (optg instanceof UnionPtg) { continue; }
 
-                OperationEval operation = (OperationEval) getOperationEvalForPtg(optg);
+                OperationEval operation = OperationEvaluatorFactory.create(optg);
 
                 int numops = operation.getNumberOfOperands();
                 Eval[] ops = new Eval[numops];
@@ -557,25 +502,6 @@ public class HSSFFormulaEvaluator {
         return values;
     }
 
-    /**
-     * returns the OperationEval concrete impl instance corresponding
-     * to the suplied operationPtg
-     * @param ptg
-     */
-    protected static Eval getOperationEvalForPtg(OperationPtg ptg) {
-        Eval retval = null;
-
-        Class clazz = (Class) OPERATION_EVALS_MAP.get(ptg.getClass());
-        try {
-            Constructor constructor = clazz.getConstructor(OPERATION_CONSTRUCTOR_CLASS_ARRAY);
-            retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
-        }
-        catch (Exception e) {
-            throw new RuntimeException("Fatal Error: ", e);
-        }
-        return retval;
-    }
-
     /**
      * returns an appropriate Eval impl instance for the Ptg. The Ptg must be
      * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg,
diff --git a/src/scratchpad/src/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java b/src/scratchpad/src/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java
new file mode 100755 (executable)
index 0000000..1292009
--- /dev/null
@@ -0,0 +1,165 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.record.formula.AddPtg;
+import org.apache.poi.hssf.record.formula.ConcatPtg;
+import org.apache.poi.hssf.record.formula.DividePtg;
+import org.apache.poi.hssf.record.formula.EqualPtg;
+import org.apache.poi.hssf.record.formula.ExpPtg;
+import org.apache.poi.hssf.record.formula.FuncPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
+import org.apache.poi.hssf.record.formula.GreaterEqualPtg;
+import org.apache.poi.hssf.record.formula.GreaterThanPtg;
+import org.apache.poi.hssf.record.formula.LessEqualPtg;
+import org.apache.poi.hssf.record.formula.LessThanPtg;
+import org.apache.poi.hssf.record.formula.MultiplyPtg;
+import org.apache.poi.hssf.record.formula.NotEqualPtg;
+import org.apache.poi.hssf.record.formula.OperationPtg;
+import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.PowerPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.SubtractPtg;
+import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
+import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
+import org.apache.poi.hssf.record.formula.eval.AddEval;
+import org.apache.poi.hssf.record.formula.eval.ConcatEval;
+import org.apache.poi.hssf.record.formula.eval.DivideEval;
+import org.apache.poi.hssf.record.formula.eval.EqualEval;
+import org.apache.poi.hssf.record.formula.eval.FuncVarEval;
+import org.apache.poi.hssf.record.formula.eval.GreaterEqualEval;
+import org.apache.poi.hssf.record.formula.eval.GreaterThanEval;
+import org.apache.poi.hssf.record.formula.eval.LessEqualEval;
+import org.apache.poi.hssf.record.formula.eval.LessThanEval;
+import org.apache.poi.hssf.record.formula.eval.MultiplyEval;
+import org.apache.poi.hssf.record.formula.eval.NotEqualEval;
+import org.apache.poi.hssf.record.formula.eval.OperationEval;
+import org.apache.poi.hssf.record.formula.eval.PercentEval;
+import org.apache.poi.hssf.record.formula.eval.PowerEval;
+import org.apache.poi.hssf.record.formula.eval.SubtractEval;
+import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;
+import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
+
+/**
+ * This class creates <tt>OperationEval</tt> instances to help evaluate <tt>OperationPtg</tt>
+ * formula tokens.
+ * 
+ * @author Josh Micich
+ */
+final class OperationEvaluatorFactory {
+       private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
+       
+       private static final Map _constructorsByPtgClass = initialiseConstructorsMap();
+       
+       private OperationEvaluatorFactory() {
+               // no instances of this class
+       }
+       
+       private static Map initialiseConstructorsMap() {
+               Map m = new HashMap(32);
+               add(m, AddPtg.class, AddEval.class);
+               add(m, ConcatPtg.class, ConcatEval.class);
+               add(m, DividePtg.class, DivideEval.class);
+               add(m, EqualPtg.class, EqualEval.class);
+               add(m, FuncPtg.class, FuncVarEval.class);
+               add(m, FuncVarPtg.class, FuncVarEval.class);
+               add(m, GreaterEqualPtg.class, GreaterEqualEval.class);
+               add(m, GreaterThanPtg.class, GreaterThanEval.class);
+               add(m, LessEqualPtg.class, LessEqualEval.class);
+               add(m, LessThanPtg.class, LessThanEval.class);
+               add(m, MultiplyPtg.class, MultiplyEval.class);
+               add(m, NotEqualPtg.class, NotEqualEval.class);
+               add(m, PercentPtg.class, PercentEval.class);
+               add(m, PowerPtg.class, PowerEval.class);
+               add(m, SubtractPtg.class, SubtractEval.class);
+               add(m, UnaryMinusPtg.class, UnaryMinusEval.class);
+               add(m, UnaryPlusPtg.class, UnaryPlusEval.class);
+               return m;
+       }
+
+       private static void add(Map m, Class ptgClass, Class evalClass) {
+               
+               // perform some validation now, to keep later exception handlers simple
+               if(!Ptg.class.isAssignableFrom(ptgClass)) {
+                       throw new IllegalArgumentException("Expected Ptg subclass");
+               }
+               if(!OperationEval.class.isAssignableFrom(evalClass)) {
+                       throw new IllegalArgumentException("Expected OperationEval subclass");
+               }
+               if (!Modifier.isPublic(evalClass.getModifiers())) {
+                       throw new RuntimeException("Eval class must be public");
+               }
+               if (Modifier.isAbstract(evalClass.getModifiers())) {
+                       throw new RuntimeException("Eval class must not be abstract");
+               }
+               
+               Constructor constructor;
+               try {
+                       constructor = evalClass.getDeclaredConstructor(OPERATION_CONSTRUCTOR_CLASS_ARRAY);
+               } catch (NoSuchMethodException e) {
+                       throw new RuntimeException("Missing constructor");
+               }
+               if (!Modifier.isPublic(constructor.getModifiers())) {
+                       throw new RuntimeException("Eval constructor must be public");
+               }
+               m.put(ptgClass, constructor);
+       }
+       
+       /**
+        * returns the OperationEval concrete impl instance corresponding
+        * to the supplied operationPtg
+        */
+       public static OperationEval create(OperationPtg ptg) {
+               if(ptg == null) {
+                       throw new IllegalArgumentException("ptg must not be null");
+               }
+               
+               Class ptgClass = ptg.getClass();
+               
+               Constructor constructor = (Constructor) _constructorsByPtgClass.get(ptgClass);
+               if(constructor == null) {
+                       if(ptgClass == ExpPtg.class) {
+                               // ExpPtg is used for array formulas and shared formulas.
+                               // it is currently unsupported, and may not even get implemented here
+                               throw new RuntimeException("ExpPtg currently not supported");
+                       }
+                       throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")");
+               }
+               
+               Object result;
+               Object[] initargs = { ptg };
+               try {
+                       result = constructor.newInstance(initargs);
+               } catch (IllegalArgumentException e) {
+                       throw new RuntimeException(e);
+               } catch (InstantiationException e) {
+                       throw new RuntimeException(e);
+               } catch (IllegalAccessException e) {
+                       throw new RuntimeException(e);
+               } catch (InvocationTargetException e) {
+                       throw new RuntimeException(e);
+               }
+               return (OperationEval) result;
+       }
+}
index 593214b180976640ec0bc10814996aa249cc5da0..67c634d9f687b76f52d534e10e7920d7a97d0bd9 100644 (file)
@@ -90,7 +90,19 @@ public class TextPiece extends PropertyNode implements Comparable
 
    public void adjustForDelete(int start, int length)
    {
-
+          int myStart = getStart();
+          int myEnd = getEnd();
+          int end = start + length;
+
+          /* do we have to delete from this text piece? */
+          if (start <= myEnd && end >= myStart) {
+                  /* find where the deleted area overlaps with this text piece */
+                  int overlapStart = Math.max(myStart, start);
+                  int overlapEnd = Math.min(myEnd, end);
+                  ((StringBuffer)_buf).delete(overlapStart, overlapEnd);
+                  
+                  super.adjustForDelete(start, length);
+          }
    }
 
    public int characterLength()
index 60e00f32566c746294e7a5e2d38bfa5d2cd742ec..f2d9a615f812d8ce3c31e61c670aef0d75cec083 100644 (file)
@@ -494,6 +494,7 @@ public class Range
     int numSections = _sections.size();
     int numRuns = _characters.size();
     int numParagraphs = _paragraphs.size();
+    int numTextPieces = _text.size();
 
     for (int x = _charStart; x < numRuns; x++)
     {
@@ -512,6 +513,12 @@ public class Range
       SEPX sepx = (SEPX)_sections.get(x);
       sepx.adjustForDelete(_start, _end - _start);
     }
+    
+    for (int x = _textStart; x < numTextPieces; x++)
+    {
+       TextPiece piece = (TextPiece)_text.get(x);
+       piece.adjustForDelete(_start, _end - _start);
+    }
   }
 
   /**
index 3260c371c62f9680bcd83f6c3d57f93e936de109..5098c789a763580bc04d7e2ae8a5c98f96b3e92c 100755 (executable)
@@ -31,7 +31,9 @@ public class AllFormulaEvalTests {
                TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula.eval");
                result.addTestSuite(TestCircularReferences.class);
                result.addTestSuite(TestExternalFunction.class);
+               result.addTestSuite(TestFormulaBugs.class);
                result.addTestSuite(TestFormulasFromSpreadsheet.class);
+               result.addTestSuite(TestPercentEval.class);
                result.addTestSuite(TestUnaryPlusEval.class);
                return result;
        }
diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java
new file mode 100755 (executable)
index 0000000..617f5d0
--- /dev/null
@@ -0,0 +1,217 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.formula.eval;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
+
+/**
+ * Miscellaneous tests for bugzilla entries.<p/> The test name contains the
+ * bugzilla bug id.
+ * 
+ * 
+ * @author Josh Micich
+ */
+public final class TestFormulaBugs extends TestCase {
+
+       private static final String TEST_DATA_DIR_SYS_PROPERTY_NAME = "HSSF.testdata.path";
+
+       /**
+        * Opens a sample file from the standard HSSF test data directory
+        * 
+        * @return an open <tt>InputStream</tt> for the specified sample file
+        */
+       private static InputStream openSampleFileStream(String sampleFileName) {
+               // TODO - move this method somewhere common
+               String dataDirName = System
+                               .getProperty(TEST_DATA_DIR_SYS_PROPERTY_NAME);
+               if (dataDirName == null) {
+                       throw new RuntimeException("Must set system property '"
+                                       + TEST_DATA_DIR_SYS_PROPERTY_NAME
+                                       + "' before running tests");
+               }
+               File dataDir = new File(dataDirName);
+               if (!dataDir.exists()) {
+                       throw new RuntimeException("Data dir '" + dataDirName
+                                       + "' specified by system property '"
+                                       + TEST_DATA_DIR_SYS_PROPERTY_NAME + "' does not exist");
+               }
+               File f = new File(dataDir, sampleFileName);
+               if (!f.exists()) {
+                       throw new RuntimeException("Sample file '" + sampleFileName
+                                       + "' not found in data dir '" + dataDirName + "'");
+               }
+               InputStream is;
+               try {
+                       is = new FileInputStream(f);
+               } catch (FileNotFoundException e) {
+                       throw new RuntimeException(e);
+               }
+               return is;
+       }
+
+       /**
+        * Bug 27349 - VLOOKUP with reference to another sheet.<p/> This test was
+        * added <em>long</em> after the relevant functionality was fixed.
+        */
+       public void test27349() {
+               // 27349-vlookupAcrossSheets.xls is bugzilla/attachment.cgi?id=10622
+               InputStream is = openSampleFileStream("27349-vlookupAcrossSheets.xls");
+               HSSFWorkbook wb;
+               try {
+                       // original bug may have thrown exception here, or output warning to
+                       // stderr
+                       wb = new HSSFWorkbook(is);
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+
+               HSSFSheet sheet = wb.getSheetAt(0);
+               HSSFRow row = sheet.getRow(1);
+               HSSFCell cell = row.getCell(0);
+
+               // this definitely would have failed due to 27349
+               assertEquals("VLOOKUP(1,'DATA TABLE'!$A$8:'DATA TABLE'!$B$10,2)", cell
+                               .getCellFormula());
+
+               // We might as well evaluate the formula
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
+               fe.setCurrentRow(row);
+               CellValue cv = fe.evaluate(cell);
+
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(3.0, cv.getNumberValue(), 0.0);
+       }
+
+       /**
+        * Bug 27405 - isnumber() formula always evaluates to false in if statement<p/>
+        * 
+        * seems to be a duplicate of 24925
+        */
+       public void test27405() {
+
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("input");
+               // input row 0
+               HSSFRow row = sheet.createRow((short) 0);
+               HSSFCell cell = row.createCell((short) 0);
+               cell = row.createCell((short) 1);
+               cell.setCellValue(1); // B1
+               // input row 1
+               row = sheet.createRow((short) 1);
+               cell = row.createCell((short) 1);
+               cell.setCellValue(999); // B2
+
+               int rno = 4;
+               row = sheet.createRow(rno);
+               cell = row.createCell((short) 1); // B5
+               cell.setCellFormula("isnumber(b1)");
+               cell = row.createCell((short) 3); // D5
+               cell.setCellFormula("IF(ISNUMBER(b1),b1,b2)");
+
+               if (false) { // set true to check excel file manually
+                       // bug report mentions 'Editing the formula in excel "fixes" the problem.'
+                       try {
+                               FileOutputStream fileOut = new FileOutputStream("27405output.xls");
+                               wb.write(fileOut);
+                               fileOut.close();
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
+               
+               // use POI's evaluator as an extra sanity check
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
+               fe.setCurrentRow(row);
+               CellValue cv;
+               cv = fe.evaluate(cell);
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(1.0, cv.getNumberValue(), 0.0);
+               
+               cv = fe.evaluate(row.getCell(1));
+               assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, cv.getCellType());
+               assertEquals(true, cv.getBooleanValue());
+       }
+
+       /**
+        * Bug 42448 - Can't parse SUMPRODUCT(A!C7:A!C67, B8:B68) / B69 <p/>
+        */
+       public void test42448() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet1 = wb.createSheet("Sheet1");
+
+               HSSFRow row = sheet1.createRow(0);
+               HSSFCell cell = row.createCell((short) 0);
+
+               // it's important to create the referenced sheet first
+               HSSFSheet sheet2 = wb.createSheet("A"); // note name 'A'
+               // TODO - POI crashes if the formula is added before this sheet
+               // RuntimeException("Zero length string is an invalid sheet name")
+               // Excel doesn't crash but the formula doesn't work until it is
+               // re-entered
+
+               String inputFormula = "SUMPRODUCT(A!C7:A!C67, B8:B68) / B69"; // as per bug report
+               try {
+                       cell.setCellFormula(inputFormula); 
+               } catch (StringIndexOutOfBoundsException e) {
+                       throw new AssertionFailedError("Identified bug 42448");
+               }
+
+               assertEquals("SUMPRODUCT(A!C7:C67,B8:B68)/B69", cell.getCellFormula());
+
+               // might as well evaluate the sucker...
+
+               addCell(sheet2, 5, 2, 3.0); // A!C6
+               addCell(sheet2, 6, 2, 4.0); // A!C7
+               addCell(sheet2, 66, 2, 5.0); // A!C67
+               addCell(sheet2, 67, 2, 6.0); // A!C68
+
+               addCell(sheet1, 6, 1, 7.0); // B7
+               addCell(sheet1, 7, 1, 8.0); // B8
+               addCell(sheet1, 67, 1, 9.0); // B68
+               addCell(sheet1, 68, 1, 10.0); // B69
+
+               double expectedResult = (4.0 * 8.0 + 5.0 * 9.0) / 10.0;
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet1, wb);
+               fe.setCurrentRow(row);
+               CellValue cv = fe.evaluate(cell);
+
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(expectedResult, cv.getNumberValue(), 0.0);
+       }
+
+       private static void addCell(HSSFSheet sheet, int rowIx, int colIx,
+                       double value) {
+               sheet.createRow(rowIx).createCell((short) colIx).setCellValue(value);
+       }
+}
index f57221c9b0a94e090ab499fe1cb520b868010459..2d5408c76a6a602817750d2976d35bae2146fc71 100644 (file)
@@ -15,7 +15,6 @@
 * limitations under the License.
 */
 
-
 package org.apache.poi.hssf.record.formula.eval;
 
 import java.io.FileInputStream;
@@ -59,36 +58,36 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
                 * Name of the test spreadsheet (found in the standard test data folder)
                 */
                public final static String FILENAME = "FormulaEvalTestData.xls";
-           /**
-            * Row (zero-based) in the test spreadsheet where the operator examples start.
-            */
+               /**
+                * Row (zero-based) in the test spreadsheet where the operator examples start.
+                */
                public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
-           /**
-            * Row (zero-based) in the test spreadsheet where the function examples start.
-            */
-               public static final int START_FUNCTIONS_ROW_INDEX = 83; // Row '84
+               /**
+                * Row (zero-based) in the test spreadsheet where the function examples start.
+                */
+               public static final int START_FUNCTIONS_ROW_INDEX = 87; // Row '88
                /** 
                 * Index of the column that contains the function names
                 */
-           public static final short COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
+               public static final short COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
        
-           /**
-            * Used to indicate when there are no more functions left
-            */
+               /**
+                * Used to indicate when there are no more functions left
+                */
                public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
        
                /**
                 * Index of the column where the test values start (for each function)
                 */
-           public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
-           
-           /**
-            * Each function takes 4 rows in the test spreadsheet 
-            */
+               public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
+               
+               /**
+                * Each function takes 4 rows in the test spreadsheet 
+                */
                public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
        }
 
-    private HSSFWorkbook workbook;
+       private HSSFWorkbook workbook;
        private HSSFSheet sheet;
        // Note - multiple failures are aggregated before ending.  
        // If one or more functions fail, a single AssertionFailedError is thrown at the end
@@ -97,138 +96,138 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
        private int _evaluationFailureCount;
        private int _evaluationSuccessCount;
 
-    private static final HSSFCell getExpectedValueCell(HSSFRow row, short columnIndex) {
-       if (row == null) {
-               return null;
-       }
-       return row.getCell(columnIndex);
-    }
+       private static final HSSFCell getExpectedValueCell(HSSFRow row, short columnIndex) {
+               if (row == null) {
+                       return null;
+               }
+               return row.getCell(columnIndex);
+       }
 
 
-    private static void confirmExpectedResult(String msg, HSSFCell expected, HSSFFormulaEvaluator.CellValue actual) {
-        if (expected == null) {
+       private static void confirmExpectedResult(String msg, HSSFCell expected, HSSFFormulaEvaluator.CellValue actual) {
+               if (expected == null) {
                        throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
                }
                if(actual == null) {
                        throw new AssertionFailedError(msg + " - actual value was null");
                }
-        
+               
                if (expected.getCellType() == HSSFCell.CELL_TYPE_STRING) {
-                   String value = expected.getRichStringCellValue().getString();
-                   if (value.startsWith("#")) {
-                       // TODO - this code never called
-                       expected.setCellType(HSSFCell.CELL_TYPE_ERROR);
-                       // expected.setCellErrorValue(...?);
-                   }
+                       String value = expected.getRichStringCellValue().getString();
+                       if (value.startsWith("#")) {
+                               // TODO - this code never called
+                               expected.setCellType(HSSFCell.CELL_TYPE_ERROR);
+                               // expected.setCellErrorValue(...?);
+                       }
                }
                
                switch (expected.getCellType()) {
                        case HSSFCell.CELL_TYPE_BLANK:
-                           assertEquals(msg, HSSFCell.CELL_TYPE_BLANK, actual.getCellType());
-                           break;
+                               assertEquals(msg, HSSFCell.CELL_TYPE_BLANK, actual.getCellType());
+                               break;
                        case HSSFCell.CELL_TYPE_BOOLEAN:
-                           assertEquals(msg, HSSFCell.CELL_TYPE_BOOLEAN, actual.getCellType());
-                           assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
-                           break;
+                               assertEquals(msg, HSSFCell.CELL_TYPE_BOOLEAN, actual.getCellType());
+                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
+                               break;
                        case HSSFCell.CELL_TYPE_ERROR:
-                           assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType());
-                           if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
-                               assertEquals(msg, expected.getErrorCellValue(), actual.getErrorValue());
-                           }
-                           break;
+                               assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType());
+                               if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
+                                       assertEquals(msg, expected.getErrorCellValue(), actual.getErrorValue());
+                               }
+                               break;
                        case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
-                           throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
+                               throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
                        case HSSFCell.CELL_TYPE_NUMERIC:
-                           assertEquals(msg, HSSFCell.CELL_TYPE_NUMERIC, actual.getCellType());
-                           TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
-//                 double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
-//                 double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
-//                 assertTrue(msg, delta <= pctExpected);
-                           break;
+                               assertEquals(msg, HSSFCell.CELL_TYPE_NUMERIC, actual.getCellType());
+                               TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
+//                             double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
+//                             double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
+//                             assertTrue(msg, delta <= pctExpected);
+                               break;
                        case HSSFCell.CELL_TYPE_STRING:
-                           assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType());
-                           assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
-                           break;
+                               assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType());
+                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
+                               break;
                }
-    }
+       }
 
 
        protected void setUp() throws Exception {
-        if (workbook == null) {
-               String filePath = System.getProperty("HSSF.testdata.path")+ "/" + SS.FILENAME;
-            FileInputStream fin = new FileInputStream( filePath );
-            workbook = new HSSFWorkbook( fin );
-            sheet = workbook.getSheetAt( 0 );
-          }
-        _functionFailureCount = 0;
-        _functionSuccessCount = 0;
-        _evaluationFailureCount = 0;
-        _evaluationSuccessCount = 0;
-    }
-    
-    public void testFunctionsFromTestSpreadsheet() {
-        
-        processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
-        processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
-        // example for debugging individual functions/operators:
-//        processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
-//        processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
-        
-        // confirm results
-       String successMsg = "There were " 
-                       + _evaluationSuccessCount + " successful evaluation(s) and "
+               if (workbook == null) {
+                       String filePath = System.getProperty("HSSF.testdata.path")+ "/" + SS.FILENAME;
+                       FileInputStream fin = new FileInputStream( filePath );
+                       workbook = new HSSFWorkbook( fin );
+                       sheet = workbook.getSheetAt( 0 );
+                 }
+               _functionFailureCount = 0;
+               _functionSuccessCount = 0;
+               _evaluationFailureCount = 0;
+               _evaluationSuccessCount = 0;
+       }
+       
+       public void testFunctionsFromTestSpreadsheet() {
+               
+               processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
+               processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
+               // example for debugging individual functions/operators:
+//             processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
+//             processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
+               
+               // confirm results
+               String successMsg = "There were " 
+                               + _evaluationSuccessCount + " successful evaluation(s) and "
                                + _functionSuccessCount + " function(s) without error";
                if(_functionFailureCount > 0) {
                        String msg = _functionFailureCount + " function(s) failed in "
                        + _evaluationFailureCount + " evaluation(s).  " + successMsg;
-               throw new AssertionFailedError(msg);
-        }
+                       throw new AssertionFailedError(msg);
+               }
                if(false) { // normally no output for successful tests
                        System.out.println(getClass().getName() + ": " + successMsg);
                }
        }
 
-    /**
-     * @param startRowIndex row index in the spreadsheet where the first function/operator is found 
-     * @param testFocusFunctionName name of a single function/operator to test alone. 
-     * Typically pass <code>null</code> to test all functions
-     */
+       /**
+        * @param startRowIndex row index in the spreadsheet where the first function/operator is found 
+        * @param testFocusFunctionName name of a single function/operator to test alone. 
+        * Typically pass <code>null</code> to test all functions
+        */
        private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
  
                HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, workbook);
 
-        int rowIndex = startRowIndex;
-        while (true) {
-            HSSFRow r = sheet.getRow(rowIndex);
-            String targetFunctionName = getTargetFunctionName(r);
-               if(targetFunctionName == null) {
-                       throw new AssertionFailedError("Test spreadsheet cell empty on row (" 
-                                       + (rowIndex+1) + "). Expected function name or '"
-                                       + SS.FUNCTION_NAMES_END_SENTINEL + "'");
-               }
-               if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
-                       // found end of functions list
-                       break;
-               }
-               if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
-                       
-                       // expected results are on the row below
-                   HSSFRow expectedValuesRow = sheet.getRow(rowIndex + 1);
-                   if(expectedValuesRow == null) {
-                       int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
-                       throw new AssertionFailedError("Missing expected values row for function '" 
-                                       + targetFunctionName + " (row " + missingRowNum + ")"); 
-                   }
-                   switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
-                       case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
-                       case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
-                       default:
-                               throw new RuntimeException("unexpected result");
-                       case Result.NO_EVALUATIONS_FOUND: // do nothing
-                   }
-               }
-            rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
-        }
+               int rowIndex = startRowIndex;
+               while (true) {
+                       HSSFRow r = sheet.getRow(rowIndex);
+                       String targetFunctionName = getTargetFunctionName(r);
+                       if(targetFunctionName == null) {
+                               throw new AssertionFailedError("Test spreadsheet cell empty on row (" 
+                                               + (rowIndex+1) + "). Expected function name or '"
+                                               + SS.FUNCTION_NAMES_END_SENTINEL + "'");
+                       }
+                       if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
+                               // found end of functions list
+                               break;
+                       }
+                       if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
+                               
+                               // expected results are on the row below
+                               HSSFRow expectedValuesRow = sheet.getRow(rowIndex + 1);
+                               if(expectedValuesRow == null) {
+                                       int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
+                                       throw new AssertionFailedError("Missing expected values row for function '" 
+                                                       + targetFunctionName + " (row " + missingRowNum + ")"); 
+                               }
+                               switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
+                                       case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
+                                       case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
+                                       default:
+                                               throw new RuntimeException("unexpected result");
+                                       case Result.NO_EVALUATIONS_FOUND: // do nothing
+                               }
+                       }
+                       rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
+               }
        }
 
        /**
@@ -236,16 +235,16 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
         * @return a constant from the local Result class denoting whether there were any evaluation
         * cases, and whether they all succeeded.
         */
-    private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName, 
-               HSSFRow formulasRow, HSSFRow expectedValuesRow) {
-       
-        int result = Result.NO_EVALUATIONS_FOUND; // so far
-        short endcolnum = formulasRow.getLastCellNum();
-        evaluator.setCurrentRow(formulasRow);
+       private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName, 
+                       HSSFRow formulasRow, HSSFRow expectedValuesRow) {
+               
+               int result = Result.NO_EVALUATIONS_FOUND; // so far
+               short endcolnum = formulasRow.getLastCellNum();
+               evaluator.setCurrentRow(formulasRow);
 
-        // iterate across the row for all the evaluation cases
-        for (short colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
-            HSSFCell c = formulasRow.getCell(colnum);
+               // iterate across the row for all the evaluation cases
+               for (short colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
+                       HSSFCell c = formulasRow.getCell(colnum);
                        if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
                                continue;
                        }
@@ -265,13 +264,13 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
                                printShortStackTrace(System.err, e);
                                result = Result.SOME_EVALUATIONS_FAILED;
                        }
-        }
+               }
                return result;
        }
 
-    /**
-     * Useful to keep output concise when expecting many failures to be reported by this test case
-     */
+       /**
+        * Useful to keep output concise when expecting many failures to be reported by this test case
+        */
        private static void printShortStackTrace(PrintStream ps, AssertionFailedError e) {
                StackTraceElement[] stes = e.getStackTrace();
                
@@ -304,8 +303,8 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
        }
 
        /**
-     * @return <code>null</code> if cell is missing, empty or blank
-     */
+        * @return <code>null</code> if cell is missing, empty or blank
+        */
        private static String getTargetFunctionName(HSSFRow r) {
                if(r == null) {
                        System.err.println("Warning - given null row, can't figure out function name");
diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java
new file mode 100755 (executable)
index 0000000..be8cef1
--- /dev/null
@@ -0,0 +1,82 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
+
+/**
+ * Test for percent operator evaluator.
+ * 
+ * @author Josh Micich
+ */
+public final class TestPercentEval extends TestCase {
+       
+       private static void confirm(ValueEval arg, double expectedResult) {
+               Eval[] args = { 
+                       arg,    
+               };
+               
+               PercentEval opEval = new PercentEval(new PercentPtg());
+               double result = NumericFunctionInvoker.invoke(opEval, args, -1, (short)-1);
+               
+               assertEquals(expectedResult, result, 0);
+       }
+
+       public void testBasic() {
+               confirm(new NumberEval(5), 0.05);
+               confirm(new NumberEval(3000), 30.0);
+               confirm(new NumberEval(-150), -1.5);
+               confirm(new StringEval("0.2"), 0.002);
+               confirm(BoolEval.TRUE, 0.01);
+       }
+
+       public void testInSpreadSheet() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+               HSSFRow row = sheet.createRow(0);
+               HSSFCell cell = row.createCell((short)0);
+               cell.setCellFormula("B1%");
+               row.createCell((short)1).setCellValue(50.0);
+               
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
+               fe.setCurrentRow(row);
+               CellValue cv;
+               try {
+                       cv = fe.evaluate(cell);
+               } catch (RuntimeException e) {
+                       if(e.getCause() instanceof NullPointerException) {
+                               throw new AssertionFailedError("Identified bug 44608");
+                       }
+                       // else some other unexpected error
+                       throw e;
+               }
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(0.5, cv.getNumberValue(), 0.0);
+       }
+
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/Bug28627.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/Bug28627.doc
new file mode 100644 (file)
index 0000000..91b031d
Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hwpf/data/Bug28627.doc differ
index e82c4d13045f98f4277d6065a90fd59d807e087f..23681486f32b9945fa184a74237662faa02dfc99 100644 (file)
 */
 package org.apache.poi.hwpf.usermodel;
 
-import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileInputStream;
-import java.util.Iterator;
-import java.util.List;
+import java.io.FileOutputStream;
+
+import junit.framework.TestCase;
 
 import org.apache.poi.hwpf.HWPFDocument;
 import org.apache.poi.hwpf.model.StyleSheet;
-import org.apache.poi.hwpf.model.TextPiece;
-import org.apache.poi.hwpf.usermodel.Paragraph;
-import org.apache.poi.hwpf.usermodel.Range;
-import org.apache.poi.util.LittleEndian;
-
-import junit.framework.TestCase;
 
 /**
  * Test various problem documents
@@ -36,16 +31,18 @@ import junit.framework.TestCase;
  * @author Nick Burch (nick at torchbox dot com)
  */
 public class TestProblems extends TestCase {
+
        private String dirname = System.getProperty("HWPF.testdata.path");
        
     protected void setUp() throws Exception {
-    }                  
-    
+    }
+
     /**
      * ListEntry passed no ListTable
      */
     public void testListEntryNoListTable() throws Exception {
-       HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/ListEntryNoListTable.doc"));
+       HWPFDocument doc = new HWPFDocument(new FileInputStream(
+                       new File(dirname, "ListEntryNoListTable.doc")));
        
        Range r = doc.getRange();
        StyleSheet styleSheet = doc.getStyleSheet();
@@ -62,7 +59,8 @@ public class TestProblems extends TestCase {
         * AIOOB for TableSprmUncompressor.unCompressTAPOperation
         */
        public void testSprmAIOOB() throws Exception {
-       HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/AIOOB-Tap.doc"));
+       HWPFDocument doc = new HWPFDocument(new FileInputStream(
+                       new File(dirname, "AIOOB-Tap.doc")));
        
        Range r = doc.getRange();
        StyleSheet styleSheet = doc.getStyleSheet();
@@ -79,7 +77,8 @@ public class TestProblems extends TestCase {
         * Test for TableCell not skipping the last paragraph
         */
        public void testTableCellLastParagraph() throws Exception {
-       HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/Bug44292.doc"));
+       HWPFDocument doc = new HWPFDocument(new FileInputStream(
+                       new File(dirname, "Bug44292.doc")));
                Range r = doc.getRange();
                        
                //get the table
@@ -104,4 +103,39 @@ public class TestProblems extends TestCase {
                // Last cell should have one paragraph
                assertEquals(1, cell.numParagraphs());
        }
+
+       public void testRangeDelete() throws Exception {
+       HWPFDocument doc = new HWPFDocument(new FileInputStream(
+                       new File(dirname, "Bug28627.doc")));
+
+       Range range = doc.getRange();
+               int numParagraphs = range.numParagraphs();
+               
+               int totalLength = 0, deletedLength = 0;
+               
+               for (int i = 0; i < numParagraphs; i++) {
+                       Paragraph para = range.getParagraph(i);
+                       String text = para.text();
+
+                       totalLength += text.length();
+                       if (text.indexOf("{delete me}") > -1) {
+                               para.delete();
+                               deletedLength = text.length();
+                       }
+               }
+               
+               // check the text length after deletion
+               int newLength = 0;
+       range = doc.getRange();
+               numParagraphs = range.numParagraphs();
+               
+               for (int i = 0; i < numParagraphs; i++) {
+                       Paragraph para = range.getParagraph(i);
+                       String text = para.text();
+
+                       newLength += text.length();                     
+               }
+               
+               assertEquals(newLength, totalLength - deletedLength);
+       }
 }
diff --git a/src/testcases/org/apache/poi/hssf/data/27349-vlookupAcrossSheets.xls b/src/testcases/org/apache/poi/hssf/data/27349-vlookupAcrossSheets.xls
new file mode 100755 (executable)
index 0000000..c21d434
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/27349-vlookupAcrossSheets.xls differ
diff --git a/src/testcases/org/apache/poi/hssf/data/Bug44593.xls b/src/testcases/org/apache/poi/hssf/data/Bug44593.xls
new file mode 100644 (file)
index 0000000..84d1311
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/Bug44593.xls differ
index 6260d878bc89ada3ebe92c7fa615baa1c387cde3..aaaf958a9d2747503a773502b73b03707081e6b3 100644 (file)
Binary files a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls and b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls differ
index f922e75d8280aeacdee06f9479a404f9530a6e62..b79236ff08c138d6ae158218b193d188c95082ca 100644 (file)
@@ -844,4 +844,48 @@ public final class TestFormulaParser extends TestCase {
         }
         assertEquals("SUM(A32769:A32770)", cell.getCellFormula());
     }
+
+    public void testSpaceAtStartOfFormula() {
+        // Simulating cell formula of "= 4" (note space)
+        // The same Ptg array can be observed if an excel file is saved with that exact formula
+
+        AttrPtg spacePtg = AttrPtg.createSpace(AttrPtg.SpaceType.SPACE_BEFORE, 1);
+        Ptg[] ptgs = { spacePtg, new IntPtg(4), };
+        String formulaString;
+        try {
+            formulaString = FormulaParser.toFormulaString(null, ptgs);
+        } catch (IllegalStateException e) {
+            if(e.getMessage().equalsIgnoreCase("too much stuff left on the stack")) {
+                throw new AssertionFailedError("Identified bug 44609");
+            }
+            // else some unexpected error
+            throw e;
+        }
+        // FormulaParser strips spaces anyway
+        assertEquals("4", formulaString); 
+
+        ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, new AddPtg()};
+        formulaString = FormulaParser.toFormulaString(null, ptgs);
+        assertEquals("3+4", formulaString); 
+    }
+
+    /**
+     * Checks some internal error detecting logic ('stack underflow error' in toFormulaString)
+     */
+    public void testTooFewOperandArgs() {
+        // Simulating badly encoded cell formula of "=/1"
+        // Not sure if Excel could ever produce this
+        Ptg[] ptgs = { 
+                // Excel would probably have put tMissArg here
+                new IntPtg(1),
+                new DividePtg(),
+        };
+        try {
+            FormulaParser.toFormulaString(null, ptgs);
+            fail("Expected exception was not thrown");
+        } catch (IllegalStateException e) {
+            // expected during successful test
+            assertTrue(e.getMessage().startsWith("Too few arguments suppled to operation token"));
+        }
+    }
 }
index f9bb362c7b0b87743c5ac3da4a00009f3f739b17..f06f591c425241aaa0dc70bb12251b53e73b8324 100644 (file)
@@ -508,6 +508,30 @@ extends TestCase {
         }
         assertTrue("No Exceptions till here!", true);
     }
+
+       public void test28031() {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet = wb.createSheet();
+        wb.setSheetName(0, "Sheet1");
+
+        HSSFRow row = sheet.createRow(0);
+        HSSFCell cell = row.createCell((short)0);
+        String formulaText =
+                       "IF(ROUND(A2*B2*C2,2)>ROUND(B2*D2,2),ROUND(A2*B2*C2,2),ROUND(B2*D2,2))";
+        cell.setCellFormula(formulaText);
+
+        assertEquals(formulaText, cell.getCellFormula());
+        if(false) {
+            // this file can be inspected manually
+            try {
+                OutputStream os = new FileOutputStream("/tmp/output28031.xls");
+                wb.write(os);
+                os.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
        
        public void test33082() throws java.io.IOException {
               String filename = System.getProperty("HSSF.testdata.path");
@@ -1127,6 +1151,23 @@ extends TestCase {
         in.close();
         assertFalse(wb.isWriteProtected());
     }
+    
+    /**
+     * Some files were having problems with the DVRecord,
+     *  probably due to dropdowns
+     */
+    public void test44593() throws Exception {
+        FileInputStream in = new FileInputStream(new File(cwd, "Bug44593.xls"));
+        
+        // Used to blow up with an IllegalArgumentException
+        //  when creating a DVRecord
+        // Now won't, but no idea if this means we have
+        //  rubbish in the DVRecord or not...
+        HSSFWorkbook wb = new HSSFWorkbook(in);
+        in.close();
+        
+        assertEquals(2, wb.getNumberOfSheets());
+    }
 }
 
 
index 6c604d1b4d6bd10c13d38f5ae193939e3646245d..38d3b89295ab249b3abb26a98abc5a34692aa8dd 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -15,7 +14,6 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-        
 
 package org.apache.poi.hssf.usermodel;
 
@@ -24,12 +22,11 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.util.Date;
 import java.util.GregorianCalendar;
-import java.util.List;
 
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.model.Sheet;
-import org.apache.poi.hssf.record.HyperlinkRecord;
 import org.apache.poi.hssf.util.HSSFColor;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.TempFile;
@@ -41,12 +38,7 @@ import org.apache.poi.util.TempFile;
  * @author  Dan Sherman (dsherman at isisph.com)
  * @author Alex Jacoby (ajacoby at gmail.com)
  */
-
-public class TestHSSFCell
-extends TestCase {
-    public TestHSSFCell(String s) {
-        super(s);
-    }
+public final class TestHSSFCell extends TestCase {
 
     /**
      * test that Boolean and Error types (BoolErrRecord) are supported properly.
@@ -388,6 +380,17 @@ extends TestCase {
        assertEquals("Formula", "A1+B1", c.toString());
     }
     
+    public void testSetStringInFormulaCell_bug44606() {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFCell cell = wb.createSheet("Sheet1").createRow(0).createCell((short)0);
+        cell.setCellFormula("B1&C1");
+        try {
+            cell.setCellValue(new HSSFRichTextString("hello"));
+        } catch (ClassCastException e) {
+            throw new AssertionFailedError("Identified bug 44606");
+        }
+    }
+    
     public static void main(String [] args) {
         System.out
         .println("Testing org.apache.poi.hssf.usermodel.TestHSSFCell");
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFTextbox.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFTextbox.java
new file mode 100755 (executable)
index 0000000..f7ce61f
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+* Licensed to the Apache Software Foundation (ASF) under one or more\r
+* contributor license agreements.  See the NOTICE file distributed with\r
+* this work for additional information regarding copyright ownership.\r
+* The ASF licenses this file to You under the Apache License, Version 2.0\r
+* (the "License"); you may not use this file except in compliance with\r
+* the License.  You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+package org.apache.poi.hssf.usermodel;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import junit.framework.TestCase;\r
+\r
+/**\r
+ * Test <code>HSSFTextbox</code>.\r
+ *\r
+ * @author Yegor Kozlov (yegor at apache.org)\r
+ */\r
+public final class TestHSSFTextbox extends TestCase{\r
+\r
+    /**\r
+     * Test that accessors to horizontal and vertical alignment work properly\r
+     */\r
+    public void testAlignment() {\r
+        HSSFWorkbook wb = new HSSFWorkbook();\r
+        HSSFSheet sh1 = wb.createSheet();\r
+        HSSFPatriarch patriarch = sh1.createDrawingPatriarch();\r
+\r
+        HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor(0, 0, 0, 0, (short) 1, 1, (short) 6, 4));\r
+        HSSFRichTextString str = new HSSFRichTextString("Hello, World");\r
+        textbox.setString(str);\r
+        textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);\r
+        textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_CENTER);\r
+\r
+        assertEquals(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED, textbox.getHorizontalAlignment());\r
+        assertEquals(HSSFTextbox.VERTICAL_ALIGNMENT_CENTER, textbox.getVerticalAlignment());\r
+    }\r
+\r
+ }\r
index 895c40f70441ea923d5af1641fbe3e81c71151ec..008504fb00311010f755e8b74158dfec296fa909 100644 (file)
@@ -25,6 +25,7 @@ import java.util.*;
 
 import junit.framework.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.storage.BlockAllocationTableReader;
 import org.apache.poi.poifs.storage.RawDataBlockList;
 
@@ -2598,7 +2599,7 @@ public class TestPropertyTable
             ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF
         };
         RawDataBlockList data_blocks    =
-            new RawDataBlockList(new ByteArrayInputStream(raw_data_array));
+            new RawDataBlockList(new ByteArrayInputStream(raw_data_array), POIFSConstants.BIG_BLOCK_SIZE);
         int[]            bat_array      =
         {
             15
index ed3e8d925996dda7e8dd4373405b6c3200e34c20..21049ebf1816bdc9c76475031a4bda4c886f457e 100644 (file)
@@ -19,6 +19,8 @@
 
 package org.apache.poi.poifs.storage;
 
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
 
@@ -47,7 +49,7 @@ public class LocalRawDataBlockList
     public LocalRawDataBlockList()
         throws IOException
     {
-        super(new ByteArrayInputStream(new byte[ 0 ]));
+        super(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
         _list  = new ArrayList();
         _array = null;
     }
index ac6fc08c052a503013a8ad0a04ab267c5fc19a11..d151029762089e1634a46b4ff9fadddc9643bc93 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.poi.poifs.storage;
 
 import java.io.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.util.DummyPOILogger;
 import org.apache.poi.util.POILogFactory;
 
@@ -69,7 +70,7 @@ public class TestRawDataBlockList
         {
             data[ j ] = ( byte ) j;
         }
-        new RawDataBlockList(new ByteArrayInputStream(data));
+        new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
     }
 
     /**
@@ -81,7 +82,7 @@ public class TestRawDataBlockList
     public void testEmptyConstructor()
         throws IOException
     {
-        new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]));
+        new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
     }
 
     /**
@@ -108,7 +109,7 @@ public class TestRawDataBlockList
 
             // Check we logged the error
             logger.reset();
-            new RawDataBlockList(new ByteArrayInputStream(data));
+            new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
             assertEquals(1, logger.logged.size());
         }
     }
index bb2e3c4c0e63e5dac85a3ec6c161750afce63cc4..4d4254a91e4661fb02d83a065840518f8319cd30 100644 (file)
@@ -25,6 +25,7 @@ import java.util.*;
 
 import junit.framework.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.property.PropertyTable;
 import org.apache.poi.poifs.property.RootProperty;
 
@@ -2112,7 +2113,7 @@ public class TestSmallBlockTableReader
             ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF
         };
         RawDataBlockList data_blocks    =
-            new RawDataBlockList(new ByteArrayInputStream(raw_data_array));
+            new RawDataBlockList(new ByteArrayInputStream(raw_data_array), POIFSConstants.BIG_BLOCK_SIZE);
         int[]            bat_array      =
         {
             15