diff --git a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java index f71d5ca7f1..1b22e3604a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java @@ -4,14 +4,23 @@ import org.apache.poi.util.LittleEndian; /** * * @author Jason Height (jheight at chariot dot net dot au) + * @author Danny Mui (dmui at apache dot org) (Leftover handling) */ public class FuncPtg extends AbstractFunctionPtg{ public final static byte sid = 0x21; private int numParams=0; + + /** + * FuncPtgs are defined to be 4 bytes but the actual FuncPtg uses only 2 bytes. + * If we have leftOvers that are read from the file we should serialize them back out. + *

+ * If the leftovers are removed, a prompt "Warning: Data may have been lost occurs in Excel" + */ + protected byte[] leftOvers = null; private FuncPtg() { - //Required for clone methods + //Required for clone methods } /**Creates new function pointer from a byte array @@ -21,17 +30,28 @@ public class FuncPtg extends AbstractFunctionPtg{ offset++; //field_1_num_args = data[ offset + 0 ]; field_2_fnc_index = LittleEndian.getShort(data,offset + 0 ); + + + if (data.length - offset > 2) { //save left overs if there are any + leftOvers = new byte[2]; + System.arraycopy(data, offset+1, leftOvers, 0, leftOvers.length); + } + try { numParams = ( (Integer)functionData[field_2_fnc_index][2]).intValue(); } catch (NullPointerException npe) { numParams=0; } + } public void writeBytes(byte[] array, int offset) { array[offset+0]= (byte) (sid + ptgClass); //array[offset+1]=field_1_num_args; LittleEndian.putShort(array,offset+1,field_2_fnc_index); + if (leftOvers != null) { + System.arraycopy(leftOvers, 0, array, offset+2, leftOvers.length); + } } public int getNumberOfOperands() { diff --git a/src/testcases/org/apache/poi/hssf/HSSFTests.java b/src/testcases/org/apache/poi/hssf/HSSFTests.java index ca43bfdb3a..c1bbff421b 100644 --- a/src/testcases/org/apache/poi/hssf/HSSFTests.java +++ b/src/testcases/org/apache/poi/hssf/HSSFTests.java @@ -50,6 +50,7 @@ import org.apache.poi.hssf.record.TestTickRecord; import org.apache.poi.hssf.record.TestUnitsRecord; import org.apache.poi.hssf.record.TestValueRangeRecord; import org.apache.poi.hssf.record.aggregates.TestRowRecordsAggregate; +import org.apache.poi.hssf.record.formula.TestFuncPtg; import org.apache.poi.hssf.usermodel.TestCellStyle; import org.apache.poi.hssf.usermodel.TestFormulas; import org.apache.poi.hssf.usermodel.TestHSSFCell; @@ -149,6 +150,9 @@ public class HSSFTests suite.addTest(new TestSuite(TestRKUtil.class)); suite.addTest(new TestSuite(TestSheetReferences.class)); + //not a real junit guru so i'm just adding it here + suite.addTest(new TestSuite(TestFuncPtg.class)); + //$JUnit-END$ return suite; } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java new file mode 100755 index 0000000000..b25e11cf69 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java @@ -0,0 +1,101 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 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.record.formula; + +import junit.framework.TestCase; + + + +/** + * Make sure the FuncPtg performs as expected + * @author Danny Mui (dmui at apache dot org) + */ +public class TestFuncPtg extends TestCase { + + public TestFuncPtg(String name) { + super(name); + + } + + public static void main(java.lang.String[] args) { + + junit.textui.TestRunner.run(TestFuncPtg.class); + } + + + /** + * Make sure the left overs are re-serialized on excel file reads to avoid + * the "Warning: Data may have been lost" prompt in excel. + *

+ * This ptg represents a LEN function extracted from excel + */ + public void testLeftOvers() { + byte[] fakeData = new byte[4]; + + fakeData[0] = (byte)0x41; + fakeData[1] = (byte)0x20; //function index + fakeData[2] = (byte)0; //leftovers begin + fakeData[3] = (byte)8; + + FuncPtg ptg = new FuncPtg(fakeData, 0); + + assertEquals("Len formula index is not 32(20H)",(int)0x20, ptg.getFunctionIndex()); + assertEquals("Number of operands in the len formula",1, ptg.getNumberOfOperands()); + assertEquals("first leftover byte is not 0", (byte)0, ptg.leftOvers[0]); + assertEquals("second leftover byte is not 8", (byte)8, ptg.leftOvers[1]); + + } + +}