]> source.dussan.org Git - poi.git/commitdiff
bug 15228 and related fixes:
authorAvik Sengupta <avik@apache.org>
Fri, 25 Jul 2003 18:22:20 +0000 (18:22 +0000)
committerAvik Sengupta <avik@apache.org>
Fri, 25 Jul 2003 18:22:20 +0000 (18:22 +0000)
1. Correct structure of NamePtg
2. Correct Unicode handling of strings in StyleRecord and StringPtg
3. Workaround for SheetReferences
4. Ensure correct handling in NameRecord if we cant parse PTGs
5. Ensure correct order of String and SharFormula records
6. Testcase!

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

src/java/org/apache/poi/hssf/model/Workbook.java
src/java/org/apache/poi/hssf/record/NameRecord.java
src/java/org/apache/poi/hssf/record/StyleRecord.java
src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
src/java/org/apache/poi/hssf/record/formula/NamePtg.java
src/java/org/apache/poi/hssf/record/formula/StringPtg.java
src/testcases/org/apache/poi/hssf/data/15228.xls [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java [new file with mode: 0644]

index b86f60887c0247aae049c6393440c262493c31d1..da1aa129e9a6ac5e5ffd1070070536c7d0716c35 100644 (file)
@@ -1729,15 +1729,17 @@ public class Workbook implements Model {
     }
 
     public SheetReferences getSheetReferences() {
-       SheetReferences refs = new SheetReferences();
-
-       if (externSheet != null) {
-          for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) {
-              String sheetName = findSheetNameFromExternSheet((short)k);
-              refs.addSheetReference(sheetName, k);
-          }
-       }
-       return refs;
+        SheetReferences refs = new SheetReferences();
+        
+        if (externSheet != null) {
+            for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) {
+                
+                String sheetName = findSheetNameFromExternSheet((short)k);
+                refs.addSheetReference(sheetName, k);
+                
+            }
+        }
+        return refs;
     }
 
     /** finds the sheet name by his extern sheet index
@@ -1745,10 +1747,12 @@ public class Workbook implements Model {
      * @return sheet name
      */
     public String findSheetNameFromExternSheet(short num){
-        String result;
+        String result="";
 
         short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook();
-        result = getSheetName(indexToSheet);
+        if (indexToSheet>-1) { //error check, bail out gracefully!
+            result = getSheetName(indexToSheet);
+        }
 
         return result;
     }
index 09bf2a416dae07f840aef48ab92a255bf4e9e6d3..01fe777dfc717abb4ee563301083ff643ae6384a 100644 (file)
@@ -794,6 +794,8 @@ public class NameRecord extends Record {
                 pos += ptg.getSize();
                 sizeCounter += ptg.getSize();
                 stack.push(ptg);
+                field_13_raw_name_definition=new byte[size];
+                System.arraycopy(data,offset,field_13_raw_name_definition,0,size);
             }
         } catch (java.lang.UnsupportedOperationException uoe) {
             System.err.println("[WARNING] Unknown Ptg "
@@ -880,7 +882,7 @@ public class NameRecord extends Record {
             .append("\n");
         buffer.append("    .unused                   = ").append( field_5_index_to_sheet )
             .append("\n");
-        buffer.append("    .( 0 = Global name, otherwise index to sheet (one-based) ) = ").append( field_6_equals_to_index_to_sheet )
+        buffer.append("    .index to sheet (1-based, 0=Global)           = ").append( field_6_equals_to_index_to_sheet )
             .append("\n");
         buffer.append("    .Length of menu text (character count)        = ").append( field_7_length_custom_menu )
             .append("\n");
@@ -906,6 +908,7 @@ public class NameRecord extends Record {
             .append("\n");
         buffer.append("    .Status bar text (Unicode string without length field)  = ").append( field_17_status_bar_text )
             .append("\n");
+        buffer.append(org.apache.poi.util.HexDump.dump(this.field_13_raw_name_definition,0,0));
         buffer.append("[/NAME]\n");
         
         return buffer.toString();
index c4f8ee35cc6bbc00b6990c6ae5d5ab6421d7db72..d6bb482e5cddc21bf770553ca1fcbe1dcbe77a87 100644 (file)
@@ -57,12 +57,14 @@ package org.apache.poi.hssf.record;
 
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
+import org.apache.poi.util.BitField;
 
 /**
  * Title:        Style Record<P>
  * Description:  Describes a builtin to the gui or user defined style<P>
  * REFERENCE:  PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
  * @author Andrew C. Oliver (acoliver at apache dot org)
+ * @author aviks : string fixes for UserDefined Style
  * @version 2.0-pre
  */
 
@@ -81,8 +83,10 @@ public class StyleRecord
     private byte              field_3_outline_style_level;
 
     // only for user defined styles
-    private byte              field_2_name_length;
-    private String            field_3_name;
+    private short              field_2_name_length; //OO doc says 16 bit length, so we believe
+    private byte               field_3_string_options;
+    private BitField fHighByte;
+    private String             field_4_name;
 
     public StyleRecord()
     {
@@ -125,17 +129,24 @@ public class StyleRecord
 
     protected void fillFields(byte [] data, short size, int offset)
     {
+        fHighByte = new BitField(0x01); //have to init here, since we are being called
+                                        //from super, and class level init hasnt been done. 
         field_1_xf_index = LittleEndian.getShort(data, 0 + offset);
-        if (getType() == 1)
+        if (getType() == STYLE_BUILT_IN)
         {
             field_2_builtin_style       = data[ 2 + offset ];
             field_3_outline_style_level = data[ 3 + offset ];
         }
-        else if (getType() == 0)
+        else if (getType() == STYLE_USER_DEFINED)
         {
-            field_2_name_length = data[ 2 + offset ];
-            field_3_name        = StringUtil.getFromCompressedUnicode(data, 3 + offset,
-                                             LittleEndian.ubyteToInt(field_2_name_length));
+            field_2_name_length = LittleEndian.getShort(data, 2 + offset );
+            field_3_string_options = data[4+offset];
+            
+            if (fHighByte.isSet(field_3_string_options)) {
+                field_4_name= StringUtil.getFromUnicode(data,offset+5,field_2_name_length);
+            }else {
+                field_4_name=StringUtil.getFromCompressedUnicode(data,offset+5,field_2_name_length);
+            }
         }
 
         // todo sanity check exception to make sure we're one or the other
@@ -199,7 +210,8 @@ public class StyleRecord
 
     public void setName(String name)
     {
-        field_3_name = name;
+        field_4_name = name;
+        //TODO set name length and string options
     }
 
     // end user defined
@@ -273,7 +285,7 @@ public class StyleRecord
      * @see #getName()
      */
 
-    public byte getNameLength()
+    public short getNameLength()
     {
         return field_2_name_length;
     }
@@ -286,7 +298,7 @@ public class StyleRecord
 
     public String getName()
     {
-        return field_3_name;
+        return field_4_name;
     }
 
     // end user defined
@@ -361,7 +373,7 @@ public class StyleRecord
         else
         {
             LittleEndian.putShort(data, 2 + offset,
-                                  (( short ) (0x03 + getNameLength())));
+                                  (( short ) (getRecordSize()-4)));
         }
         LittleEndian.putShort(data, 4 + offset, getIndex());
         if (getType() == STYLE_BUILT_IN)
@@ -371,8 +383,9 @@ public class StyleRecord
         }
         else
         {
-            data[ 6 + offset ] = getNameLength();
-            StringUtil.putCompressedUnicode(getName(), data, 7 + offset);
+            LittleEndian.putShort(data, 6 + offset , getNameLength());
+            data[8+offset]=this.field_3_string_options;
+            StringUtil.putCompressedUnicode(getName(), data, 9 + offset);
         }
         return getRecordSize();
     }
@@ -387,7 +400,11 @@ public class StyleRecord
         }
         else
         {
-            retval = 7 + getNameLength();
+             if (fHighByte.isSet(field_3_string_options))  {
+                 retval= 9+2*getNameLength();
+             }else {
+                retval = 9 + getNameLength();
+             }
         }
         return retval;
     }
index 9a7575c21ee41395179ccf4e2a345d322f375da7..e3eb40e2014fdedcaa5c449c15812ffac994c5dd 100644 (file)
@@ -119,14 +119,14 @@ public class FormulaRecordAggregate
     {
         int pos = offset;
         pos += formulaRecord.serialize(pos, data);
-        if (stringRecord != null)
-        {
-            pos += stringRecord.serialize(pos, data);
-        }
         if (this.getSharedFormulaRecord() != null) 
         {
                        pos += getSharedFormulaRecord().serialize(pos, data);
         }      
+         if (stringRecord != null)
+        {
+            pos += stringRecord.serialize(pos, data);
+        }
         return pos - offset;
         
     }
index 57c6dccb5964047a634ef33faaf45262aa6069cf..3786cdd69468cec62c0e733a588179f80747c30f 100644 (file)
@@ -73,10 +73,10 @@ public class NamePtg
     extends Ptg
 {
     public final static short sid  = 0x23;
-    private final static int  SIZE = 7;
-    private short             field_1_ixti;   // unknown function
-    private short             field_2_label_index;
-    private short             field_3_zero;   // reserved must be 0
+    private final static int  SIZE = 5;
+    private short             field_1_label_index;
+    private short             field_2_zero;   // reserved must be 0
+    boolean xtra=false;
 
 
     private NamePtg() {
@@ -95,13 +95,17 @@ public class NamePtg
     public NamePtg(byte [] data, int offset)
     {
         offset++;
-        field_1_ixti        = LittleEndian.getShort(data, offset);
-        field_2_label_index = LittleEndian.getShort(data, offset + 2);
-        field_3_zero        = LittleEndian.getShort(data, offset + 4);
+        //field_1_ixti        = LittleEndian.getShort(data, offset);
+        field_1_label_index = LittleEndian.getShort(data, offset );
+        field_2_zero        = LittleEndian.getShort(data, offset + 2);
+        //if (data[offset+6]==0) xtra=true;
     }
 
     public void writeBytes(byte [] array, int offset)
     {
+        array[offset+0]= (byte) (sid + ptgClass);
+        LittleEndian.putShort(array,offset+1,field_1_label_index);
+        LittleEndian.putShort(array,offset+3, field_2_zero);
     }
 
     public int getSize()
@@ -111,17 +115,15 @@ public class NamePtg
 
     public String toFormulaString(SheetReferences refs)
     {
-        return "NO IDEA - NAME";
+        return "NAMED RANGE";
     }
     
     public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
 
     public Object clone() {
       NamePtg ptg = new NamePtg();
-      ptg.field_1_ixti = field_1_ixti;
-      ptg.field_2_label_index = field_2_label_index;
-      ptg.field_3_zero = field_3_zero;
-      ptg.setClass(ptgClass);
+      ptg.field_1_label_index = field_1_label_index;
+      ptg.field_2_zero = field_2_zero;
       return ptg;
     }
 }
index 022fffd83c0ae9beb9667198519874b1b57fe3f6..a66861914ed8fa348ced601de6c95507224fecfd 100644 (file)
@@ -55,8 +55,9 @@
 package org.apache.poi.hssf.record.formula;
 
 import org.apache.poi.util.LittleEndian;
-
+import org.apache.poi.util.BitField;
 import org.apache.poi.hssf.util.SheetReferences;
+import org.apache.poi.util.StringUtil;
 
 /**
  * Number
@@ -70,7 +71,12 @@ public class StringPtg
 {
     public final static int  SIZE = 9;
     public final static byte sid  = 0x17;
-    private String            field_1_value;
+    //NOTE: OO doc says 16bit lenght, but BiffViewer says 8
+    // Book says something totally different, so dont look there!
+    byte field_1_length;
+    byte field_2_options;
+    BitField fHighByte = new BitField(0x01);
+    private String            field_3_string;
 
     private StringPtg() {
       //Required for clone methods
@@ -79,7 +85,16 @@ public class StringPtg
     /** Create a StringPtg from a byte array read from disk */
     public StringPtg(byte [] data, int offset)
     {
-        setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2]));
+        offset++;
+        field_1_length = data[offset];
+        field_2_options = data[offset+1];
+        if (fHighByte.isSet(field_2_options)) {
+            field_3_string= StringUtil.getFromUnicode(data,offset+2,field_1_length);
+        }else {
+            field_3_string=StringUtil.getFromCompressedUnicode(data,offset+2,field_1_length);
+        }
+                                
+        //setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2]));
     }
 
     /** Create a StringPtg from a string representation of  the number
@@ -88,32 +103,46 @@ public class StringPtg
      *  @param value : String representation of a floating point number
      */
     public StringPtg(String value) {
-        setValue(value);
+        if (value.length() >255) {
+            throw new IllegalArgumentException("String literals in formulas cant be bigger than 255 characters ASCII");
+        }
+        this.field_2_options=0;
+        this.fHighByte.setBoolean(field_2_options, false);
+        this.field_3_string=value;
+        this.field_1_length=(byte)value.length(); //for the moment, we support only ASCII strings in formulas we create
     }
 
-
+    /*
     public void setValue(String value)
     {
         field_1_value = value;
-    }
+    }*/
 
 
     public String getValue()
     {
-        return field_1_value;
+        return field_3_string;
     }
 
     public void writeBytes(byte [] array, int offset)
     {
         array[ offset + 0 ] = sid;
-        array[ offset + 1 ] = (byte)(getValue().length() % 256);
-        array[ offset + 2 ] = (byte)(getValue().length() / 256);
-        System.arraycopy(getValue().getBytes(), 0, array, offset + 3, getValue().length());
+        array[ offset + 1 ] = field_1_length;
+        array[ offset + 2 ] = field_2_options;
+        if (fHighByte.isSet(field_2_options)) {
+            StringUtil.putUncompressedUnicode(getValue(),array,offset+3);
+        }else {
+            StringUtil.putCompressedUnicode(getValue(),array,offset+3);
+        }
     }
 
     public int getSize()
     {
-        return field_1_value.length() + 3;
+        if (fHighByte.isSet(field_2_options)) {
+            return 2*field_1_length+3;
+        }else {
+            return field_1_length+3;
+        }
     }
 
     public String toFormulaString(SheetReferences refs)
@@ -126,7 +155,9 @@ public class StringPtg
 
    public Object clone() {
      StringPtg ptg = new StringPtg();
-     ptg.field_1_value = field_1_value;
+     ptg.field_1_length = field_1_length;
+     ptg.field_2_options=field_2_options;
+     ptg.field_3_string=field_3_string;
      return ptg;
    }
 
diff --git a/src/testcases/org/apache/poi/hssf/data/15228.xls b/src/testcases/org/apache/poi/hssf/data/15228.xls
new file mode 100644 (file)
index 0000000..3b26ed1
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/15228.xls differ
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
new file mode 100644 (file)
index 0000000..48cec01
--- /dev/null
@@ -0,0 +1,98 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003, 2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache POI" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache POI", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.poi.hssf.usermodel;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+
+
+/**
+ * @author Avik Sengupta
+ */
+
+public class TestBugs
+extends TestCase {
+    public TestBugs(String s) {
+        super(s);
+    }
+    
+          public void test15228()
+        throws java.io.IOException
+    {
+         String readFilename = System.getProperty("HSSF.testdata.path");
+          FileInputStream in = new FileInputStream(readFilename+File.separator+"15228.xls");
+          HSSFWorkbook wb = new HSSFWorkbook(in);
+          HSSFSheet s = wb.getSheetAt(0);
+          HSSFRow r = s.createRow(0);
+          HSSFCell c = r.createCell((short)0);
+          c.setCellValue(10);
+          File file = File.createTempFile("test15228",".xls");
+          FileOutputStream out    = new FileOutputStream(file);
+          wb.write(out);
+          assertTrue("No exception thrown", true); 
+          assertTrue("File Should Exist", file.exists());
+            
+    }
+    
+}
+    
+
+