diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index ea8c9183d..61994208d 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -2,7 +2,7 @@ /* ==================================================================== * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights + * Copyright (c) 2002, 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,11 +60,11 @@ */ package org.apache.poi.hssf.record; -import java.util.Stack; import java.util.List; +import java.util.Stack; +import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.util.LittleEndian; -import org.apache.poi.hssf.record.formula.*; /** * Formula Record. @@ -94,6 +94,10 @@ public class FormulaRecord private short field_7_expression_len; private Stack field_8_parsed_expr; + /** + * Since the NaN support seems sketchy (different constants) we'll store and spit it out directly + */ + private byte[] value_data; private byte[] all_data; //if formula support is not enabled then //we'll just store/reserialize @@ -141,7 +145,13 @@ public class FormulaRecord field_2_column = LittleEndian.getShort(data, 2 + offset); field_3_xf = LittleEndian.getShort(data, 4 + offset); field_4_value = LittleEndian.getDouble(data, 6 + offset); - field_5_options = LittleEndian.getShort(data, 14 + offset); + field_5_options = LittleEndian.getShort(data, 14 + offset); + + if (Double.isNaN(field_4_value)) { + value_data = new byte[8]; + System.arraycopy(data, offset+6, value_data, 0, 8); + } + field_6_zero = LittleEndian.getInt(data, 16 + offset); field_7_expression_len = LittleEndian.getShort(data, 20 + offset); field_8_parsed_expr = getParsedExpressionTokens(data, size, @@ -371,9 +381,19 @@ public class FormulaRecord LittleEndian.putShort(data, 4 + offset, ( short ) getRow()); LittleEndian.putShort(data, 6 + offset, getColumn()); LittleEndian.putShort(data, 8 + offset, getXFIndex()); - LittleEndian.putDouble(data, 10 + offset, field_4_value); + + //only reserialize if the value is still NaN and we have old nan data + if (Double.isNaN(this.getValue()) && value_data != null) { + System.arraycopy(value_data,0,data,10 + offset,value_data.length); + } else { + LittleEndian.putDouble(data, 10 + offset, field_4_value); + } + LittleEndian.putShort(data, 18 + offset, getOptions()); - LittleEndian.putInt(data, 20 + offset, field_6_zero); + + //when writing the chn field (offset 20), it's supposed to be 0 but ignored on read + //Microsoft Excel Developer's Kit Page 318 + LittleEndian.putInt(data, 20 + offset, 0); LittleEndian.putShort(data, 24 + offset, getExpressionLength()); serializePtgs(data, 26+offset); } else { diff --git a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java index fa340d722..5d7e02b4b 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java @@ -2,7 +2,7 @@ /* ==================================================================== * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights + * Copyright (c) 2002, 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,6 +87,40 @@ public class TestFormulaRecord assertEquals(record.getXFIndex(),(short)4); } + /** + * Make sure a NAN value is preserved + * This formula record is a representation of =1/0 at row 0, column 0 + */ + public void testCheckNanPreserve() { + byte[] formulaByte = new byte[29]; + for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0; + formulaByte[4] = (byte)0x0F; + formulaByte[6] = (byte)0x02; + formulaByte[8] = (byte)0x07; + formulaByte[12] = (byte)0xFF; + formulaByte[13] = (byte)0xFF; + formulaByte[18] = (byte)0xE0; + formulaByte[19] = (byte)0xFC; + formulaByte[20] = (byte)0x07; + formulaByte[22] = (byte)0x1E; + formulaByte[23] = (byte)0x01; + formulaByte[25] = (byte)0x1E; + formulaByte[28] = (byte)0x06; + + FormulaRecord record = new FormulaRecord(FormulaRecord.sid, (short)29, formulaByte); + assertEquals("Row", 0, record.getRow()); + assertEquals("Column", 0, record.getColumn()); + assertTrue("Value is not NaN", Double.isNaN(record.getValue())); + + byte[] output = record.serialize(); + assertEquals("Output size", 33, output.length); //includes sid+recordlength + + for (int i = 5; i < 13;i++) { + assertEquals("FormulaByte NaN doesn't match", formulaByte[i], output[i+4]); + } + + } + public static void main(String [] ignored_args) { String filename = System.getProperty("HSSF.testdata.path");