diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java index d1abd2cf3c..9cc2389c78 100644 --- a/src/java/org/apache/poi/hssf/model/Workbook.java +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -1738,15 +1738,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 @@ -1754,10 +1756,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; } diff --git a/src/java/org/apache/poi/hssf/record/NameRecord.java b/src/java/org/apache/poi/hssf/record/NameRecord.java index 09bf2a416d..01fe777dfc 100644 --- a/src/java/org/apache/poi/hssf/record/NameRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameRecord.java @@ -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(); diff --git a/src/java/org/apache/poi/hssf/record/StyleRecord.java b/src/java/org/apache/poi/hssf/record/StyleRecord.java index c4f8ee35cc..d6bb482e5c 100644 --- a/src/java/org/apache/poi/hssf/record/StyleRecord.java +++ b/src/java/org/apache/poi/hssf/record/StyleRecord.java @@ -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

* Description: Describes a builtin to the gui or user defined style

* REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

* @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; } diff --git a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java index 9a7575c21e..e3eb40e201 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java @@ -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; } diff --git a/src/java/org/apache/poi/hssf/record/formula/NamePtg.java b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java index 57c6dccb59..3786cdd694 100644 --- a/src/java/org/apache/poi/hssf/record/formula/NamePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java @@ -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; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/StringPtg.java b/src/java/org/apache/poi/hssf/record/formula/StringPtg.java index 022fffd83c..a66861914e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/StringPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/StringPtg.java @@ -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 index 0000000000..3b26ed1e90 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 index 0000000000..48cec0192a --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -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 + * . + */ + +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()); + + } + +} + + +