You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by jh...@apache.org on 2006/01/21 06:41:41 UTC

svn commit: r370987 - in /jakarta/poi/trunk/src: java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/record/formula/ testcases/org/apache/poi/hssf/data/ testcases/org/apache/poi/hssf/usermodel/

Author: jheight
Date: Fri Jan 20 21:40:07 2006
New Revision: 370987

URL: http://svn.apache.org/viewcvs?rev=370987&view=rev
Log:
Bug37630: SQUASHED! Array Ptgs now implemented (at least the read and write functionality. No means to modify (yet!))

Added:
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java
    jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/data/37630.xls   (with props)
Modified:
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/FormulaRecord.java
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java
    jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
    jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java

Modified: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/FormulaRecord.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/FormulaRecord.java?rev=370987&r1=370986&r2=370987&view=diff
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/FormulaRecord.java (original)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/FormulaRecord.java Fri Jan 20 21:40:07 2006
@@ -100,26 +100,12 @@
         
           field_6_zero           = in.readInt();
           field_7_expression_len = in.readShort();
-          field_8_parsed_expr    = getParsedExpressionTokens(in, field_7_expression_len);
+          field_8_parsed_expr    = Ptg.createParsedExpressionTokens(field_7_expression_len, in);
         } catch (java.lang.UnsupportedOperationException uoe)  {
           throw new RecordFormatException(uoe.toString());
         }
     }
 
-    private Stack getParsedExpressionTokens(RecordInputStream in, short size)
-    {
-        Stack stack = new Stack();
-        int   pos   = 0;
-
-        while (pos < size)
-        {
-            Ptg ptg = Ptg.createPtg(in);
-            pos += ptg.getSize();
-            stack.push(ptg);
-        }
-        return stack;
-    }
-
     //public void setRow(short row)
     public void setRow(int row)
     {
@@ -330,7 +316,7 @@
         //Microsoft Excel Developer's Kit Page 318
         LittleEndian.putInt(data, 20 + offset, 0);
         LittleEndian.putShort(data, 24 + offset, getExpressionLength());
-        serializePtgs(data, 26+offset);
+        Ptg.serializePtgStack(field_8_parsed_expr, data, 26+offset);
         } else {
             System.arraycopy(all_data,0,data,offset,all_data.length);
         }
@@ -366,19 +352,6 @@
             retval += ptg.getSize();
         }
         return retval;
-    }
-
-    private void serializePtgs(byte [] data, int offset)
-    {
-        int pos = offset;
-
-        for (int k = 0; k < field_8_parsed_expr.size(); k++)
-        {
-            Ptg ptg = ( Ptg ) field_8_parsed_expr.get(k);
-
-            ptg.writeBytes(data, pos);
-            pos += ptg.getSize();
-        }
     }
 
     public boolean isBefore(CellValueRecordInterface i)

Modified: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java?rev=370987&r1=370986&r2=370987&view=diff
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java (original)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java Fri Jan 20 21:40:07 2006
@@ -49,7 +49,7 @@
     public int fillField( RecordInputStream in )
     {
         short tokenSize = in.readShort();
-        formulaTokens = getParsedExpressionTokens(tokenSize, in);
+        formulaTokens = Ptg.createParsedExpressionTokens(tokenSize, in);
 
         return tokenSize + 2;
     }
@@ -80,12 +80,7 @@
         int size = getSize();
         LittleEndian.putShort(data, offset, (short)(size - 2));
         int pos = offset + 2;
-        for ( Iterator iterator = formulaTokens.iterator(); iterator.hasNext(); )
-        {
-            Ptg ptg = (Ptg) iterator.next();
-            ptg.writeBytes(data, pos);
-            pos += ptg.getSize();
-        }
+        pos += Ptg.serializePtgStack(formulaTokens, data, pos);
         return size;
     }
 
@@ -101,19 +96,6 @@
             // should not happen
             return null;
         }
-    }
-
-    private Stack getParsedExpressionTokens(short size,  RecordInputStream in )
-    {
-        Stack stack = new Stack();
-        int pos = 0;
-        while ( pos < size )
-        {
-            Ptg ptg = Ptg.createPtg( in );
-            pos += ptg.getSize();
-            stack.push( ptg );
-        }
-        return stack;
     }
 
     public void setFormulaTokens( Stack formulaTokens )

Modified: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java?rev=370987&r1=370986&r2=370987&view=diff
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java (original)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java Fri Jan 20 21:40:07 2006
@@ -331,7 +331,7 @@
     /** get the definition length
      * @return definition length
      */
-    public short getDefinitionTextLength(){
+    public short getDefinitionLength(){
         return field_4_length_name_definition;
     }
 
@@ -488,7 +488,7 @@
             throw new RecordFormatException("NOT A valid Name RECORD");
         }
     }
-
+    
     /**
      * called by the class that is responsible for writing this sucker.
      * Subclasses should implement this so that their data is passed back in a
@@ -501,11 +501,13 @@
     public int serialize( int offset, byte[] data )
     {
         LittleEndian.putShort( data, 0 + offset, sid );
+        short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
+        LittleEndian.putShort( data, 2 + offset, size );
         // size defined below
         LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
         data[6 + offset] = getKeyboardShortcut();
         data[7 + offset] = getNameTextLength();
-        LittleEndian.putShort( data, 8 + offset, getDefinitionTextLength() );
+        LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
         LittleEndian.putShort( data, 10 + offset, getUnused() );
         LittleEndian.putShort( data, 12 + offset, getEqualsToIndexToSheet() );
         data[14 + offset] = getCustomMenuLength();
@@ -525,8 +527,7 @@
             return 20 + field_13_raw_name_definition.length;
         }
         else
-        {     */
-            LittleEndian.putShort( data, 2 + offset, (short) ( 15 + getTextsLength() ) );
+        {     */            
             
 			int start_of_name_definition = 19 + field_3_length_name_text;
 
@@ -539,7 +540,7 @@
 			}
 
 
-				serializePtgs( data, start_of_name_definition + offset );
+			Ptg.serializePtgStack(field_13_name_definition,  data, start_of_name_definition + offset );
 
 
             int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
@@ -558,37 +559,39 @@
         /* } */
     }
 
-    private void serializePtgs(byte [] data, int offset) {
-        int pos = offset;
-
-        for (int k = 0; k < field_13_name_definition.size(); k++) {
-            Ptg ptg = ( Ptg ) field_13_name_definition.get(k);
-
-            ptg.writeBytes(data, pos);
-            pos += ptg.getSize();
-        }
-    }
-
-
     /** gets the length of all texts
      * @return total length
      */
     public int getTextsLength(){
         int result;
 
-        result = getNameTextLength() + getDefinitionTextLength() + getDescriptionTextLength() +
+        result = getNameTextLength() + getDescriptionTextLength() +
         getHelpTopicLength() + getStatusBarLength();
 
 
         return result;
     }
+    
+    private int getNameDefinitionSize() {
+    	int result = 0;
+        List list   = field_13_name_definition;
+        
+        for (int k = 0; k < list.size(); k++)
+        {
+        	Ptg ptg = ( Ptg ) list.get(k);
+        	
+        	result += ptg.getSize();
+        }
+        return result;    
+    }
 
     /** returns the record size
      */
     public int getRecordSize(){
         int result;
 
-        result = 19 + getTextsLength();
+        result = 19 + getTextsLength() + getNameDefinitionSize();
+        
 
         return result;
     }
@@ -733,7 +736,7 @@
           }
 			}
             
-        field_13_name_definition = getParsedExpressionTokens(in, field_4_length_name_definition);
+        field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in);
     
         //Who says that this can only ever be compressed unicode???
         field_14_custom_menu_text       = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu));
@@ -745,23 +748,6 @@
         field_17_status_bar_text        = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text));
         /*} */
     }
-
-    private Stack getParsedExpressionTokens(RecordInputStream in, short size) {
-        Stack stack = new Stack();
-        int   sizeCounter   = 0;
-        try {
-            while (sizeCounter < size) {
-                Ptg ptg = Ptg.createPtg(in);
-
-                sizeCounter += ptg.getSize();
-                stack.push(ptg);
-            }
-        } catch (java.lang.UnsupportedOperationException uoe) {
-           throw new RecordFormatException(uoe.toString());
-        }
-        return stack;
-    }
-
 
     /**
      * return the non static version of the id for this record.

Added: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java?rev=370987&view=auto
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java (added)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java Fri Jan 20 21:40:07 2006
@@ -0,0 +1,246 @@
+/* ====================================================================
+   Copyright 2003-2004   Apache Software Foundation
+
+   Licensed 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;
+
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.StringUtil;
+
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.RecordFormatException;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.UnicodeString;
+
+/**
+ * ArrayPtg - handles arrays
+ * 
+ * The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
+ * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
+ * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
+ * held after this. So Ptg.createParsedExpression keeps track of the number of 
+ * ArrayPtg elements and need to parse the data upto the FORMULA record size.
+ *  
+ * @author Jason Height (jheight at chariot dot net dot au)
+ */
+
+public class ArrayPtg extends Ptg
+{
+    public final static byte sid  = 0x20;
+    protected byte field_1_reserved;
+    protected byte field_2_reserved;
+    protected byte field_3_reserved;
+    protected byte field_4_reserved;
+    protected byte field_5_reserved;
+    protected byte field_6_reserved;
+    protected byte field_7_reserved;
+    
+    
+    protected short  token_1_columns;
+    protected short token_2_rows;
+    protected Object[][] token_3_arrayValues;
+
+    protected ArrayPtg() {
+      //Required for clone methods
+    }
+
+    public ArrayPtg(RecordInputStream in)
+    {
+    	field_1_reserved = in.readByte();
+    	field_2_reserved = in.readByte();
+    	field_3_reserved = in.readByte();
+    	field_4_reserved = in.readByte();
+    	field_5_reserved = in.readByte();
+    	field_6_reserved = in.readByte();
+    	field_7_reserved = in.readByte();
+    }
+    
+    /** Read in the actual token (array) values. This occurs AFTER the last
+     * Ptg in the expression.
+     */
+    public void readTokenValues(RecordInputStream in) {    	
+        token_1_columns = (short)(0x00ff & in.readByte());
+        token_2_rows = in.readShort();
+        
+        //The token_1_columns and token_2_rows do not follow the documentation.
+        //The number of physical rows and columns is actually +1 of these values.
+        //Which is not explicitly documented.
+        token_1_columns++;
+        token_2_rows++;        
+        
+        token_3_arrayValues = new Object[token_1_columns][token_2_rows];
+        
+        for (int x=0;x<token_1_columns;x++) {
+        	for (int y=0;y<token_2_rows;y++) {
+        		byte grbit = in.readByte();
+        		if (grbit == 0x01) {
+        			token_3_arrayValues[x][y] = Double.valueOf(in.readDouble());
+        		} else if (grbit == 0x02) {
+        			//Ignore the doco, it is actually a unicode string with all the
+        			//trimmings ie 16 bit size, option byte etc
+        			token_3_arrayValues[x][y] = in.readUnicodeString();
+        		} else throw new RecordFormatException("Unknown grbit '"+grbit+"'");
+        	}
+        }
+
+    }
+
+    public String toString()
+    {
+        StringBuffer buffer = new StringBuffer("[ArrayPtg]\n");
+
+        buffer.append("columns = ").append(getColumnCount()).append("\n");
+        buffer.append("rows = ").append(getRowCount()).append("\n");
+        for (int x=0;x<getColumnCount();x++) {
+        	for (int y=0;y<getRowCount();y++) {
+        		Object o = token_3_arrayValues[x][y];
+       			buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); 
+        	}
+        }
+        return buffer.toString();
+    }
+
+    public void writeBytes(byte [] array, int offset)
+    {
+        array[offset++] = (byte) (sid + ptgClass);
+        array[offset++] = field_1_reserved;
+        array[offset++] = field_2_reserved;
+        array[offset++] = field_3_reserved;
+        array[offset++] = field_4_reserved;
+        array[offset++] = field_5_reserved;
+        array[offset++] = field_6_reserved;
+        array[offset++] = field_7_reserved;
+        
+    }
+    public int writeTokenValueBytes(byte [] array, int offset) {
+    	int pos = 0;
+    	array[pos + offset] = (byte)(token_1_columns-1);
+        pos++;
+        LittleEndian.putShort(array, pos+offset, (short)(token_2_rows-1));
+        pos += 2;
+        for (int x=0;x<getColumnCount();x++) {
+        	for (int y=0;y<getRowCount();y++) {
+        		Object o = token_3_arrayValues[x][y];
+        		if (o instanceof Double) {
+        			array[pos+offset] = 0x01;
+        			pos++;
+        			LittleEndian.putDouble(array, pos+offset, ((Double)o).doubleValue());
+        			pos+=8;
+        		} else if (o instanceof UnicodeString) {
+        			array[pos+offset] = 0x02;
+        			pos++;        			
+        			UnicodeString s = (UnicodeString)o;
+        			//JMH TBD Handle string continuation. Id do it now but its 4am.
+        	        UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
+        	        s.serialize(stats, pos + offset, array);
+        	        pos += stats.recordSize; 
+        		} else throw new RuntimeException("Coding error");
+        	}
+        }
+        return pos;
+    }
+
+    public void setRowCount(short row)
+    {
+        token_2_rows = row;
+    }
+
+    public short getRowCount()
+    {
+        return token_2_rows;
+    }
+
+    public void setColumnCount(short col)
+    {
+        token_1_columns = (byte)col;
+    }
+
+    public short getColumnCount()
+    {
+        return token_1_columns;
+    }
+
+    /** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
+    public int getSize()
+    {
+    	int size = 1+7+1+2;
+        for (int x=0;x<getColumnCount();x++) {
+        	for (int y=0;y<getRowCount();y++) {
+        		Object o = token_3_arrayValues[x][y];
+        		if (o instanceof UnicodeString) {
+        			size++;
+        	        UnicodeString.UnicodeRecordStats rs = new UnicodeString.UnicodeRecordStats();
+                    ((UnicodeString)o).getRecordSize(rs);        			
+        			size += rs.recordSize;
+        		} else if (o instanceof Double) {
+        			size += 9;
+        		}
+        	}
+        }
+        return size;
+    }
+
+    public String toFormulaString(Workbook book)
+    {
+    	StringBuffer b = new StringBuffer();
+    	b.append("{");
+        for (int x=0;x<getColumnCount();x++) {
+          	for (int y=0;y<getRowCount();y++) {
+          		Object o = token_3_arrayValues[x][y];
+        		if (o instanceof String) {
+        			b.append((String)o);
+        		} else if (o instanceof Double) {
+        			b.append(((Double)o).doubleValue());
+        		}
+        		if (y != getRowCount())
+        			b.append(",");
+          	}
+          	if (x != getColumnCount())
+          		b.append(";");
+          }
+        b.append("}");
+        return b.toString();
+    }
+    
+    public byte getDefaultOperandClass() {
+        return Ptg.CLASS_ARRAY;
+    }
+    
+    public Object clone() {
+      ArrayPtg ptg = new ArrayPtg();
+      ptg.field_1_reserved = field_1_reserved;
+      ptg.field_2_reserved = field_2_reserved;
+      ptg.field_3_reserved = field_3_reserved;
+      ptg.field_4_reserved = field_4_reserved;
+      ptg.field_5_reserved = field_5_reserved;
+      ptg.field_6_reserved = field_6_reserved;
+      ptg.field_7_reserved = field_7_reserved;
+      
+      ptg.token_1_columns = token_1_columns;
+      ptg.token_2_rows = token_2_rows;
+      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
+      for (int x=0;x<getColumnCount();x++) {
+      	for (int y=0;y<getRowCount();y++) {
+      		ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
+      	}
+      }      
+      ptg.setClass(ptgClass);
+      return ptg;
+    }
+}

Added: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java?rev=370987&view=auto
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java (added)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java Fri Jan 20 21:40:07 2006
@@ -0,0 +1,72 @@
+/* ====================================================================
+   Copyright 2003-2004   Apache Software Foundation
+
+   Licensed 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;
+
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.StringUtil;
+
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.RecordFormatException;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.UnicodeString;
+
+/**
+ * ArrayPtgA - handles arrays
+ *  
+ * @author Jason Height (jheight at chariot dot net dot au)
+ */
+
+public class ArrayPtgA extends ArrayPtg
+{
+    public final static byte sid  = 0x60;
+
+    protected ArrayPtgA() {
+    	super();
+      //Required for clone methods
+    }
+
+    public ArrayPtgA(RecordInputStream in)
+    {
+    	super(in);
+    }
+        
+    public Object clone() {
+      ArrayPtgA ptg = new ArrayPtgA();
+      ptg.field_1_reserved = field_1_reserved;
+      ptg.field_2_reserved = field_2_reserved;
+      ptg.field_3_reserved = field_3_reserved;
+      ptg.field_4_reserved = field_4_reserved;
+      ptg.field_5_reserved = field_5_reserved;
+      ptg.field_6_reserved = field_6_reserved;
+      ptg.field_7_reserved = field_7_reserved;
+      
+      ptg.token_1_columns = token_1_columns;
+      ptg.token_2_rows = token_2_rows;
+      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
+      for (int x=0;x<getColumnCount();x++) {
+      	for (int y=0;y<getRowCount();y++) {
+      		ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
+      	}
+      }      
+      ptg.setClass(ptgClass);
+      return ptg;
+    }
+}

Added: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java?rev=370987&view=auto
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java (added)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java Fri Jan 20 21:40:07 2006
@@ -0,0 +1,77 @@
+/* ====================================================================
+   Copyright 2003-2004   Apache Software Foundation
+
+   Licensed 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;
+
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.StringUtil;
+
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.RecordFormatException;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.UnicodeString;
+
+/**
+ * ArrayPtg - handles arrays
+ * 
+ * The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
+ * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
+ * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
+ * held after this. So Ptg.createParsedExpression keeps track of the number of 
+ * ArrayPtg elements and need to parse the data upto the FORMULA record size.
+ *  
+ * @author Jason Height (jheight at chariot dot net dot au)
+ */
+
+public class ArrayPtgV extends ArrayPtg
+{
+    public final static byte sid  = 0x40;
+
+    protected ArrayPtgV() {
+      //Required for clone methods
+    }
+
+    public ArrayPtgV(RecordInputStream in)
+    {
+    	super(in);
+    }
+    
+    public Object clone() {
+      ArrayPtgV ptg = new ArrayPtgV();
+      ptg.field_1_reserved = field_1_reserved;
+      ptg.field_2_reserved = field_2_reserved;
+      ptg.field_3_reserved = field_3_reserved;
+      ptg.field_4_reserved = field_4_reserved;
+      ptg.field_5_reserved = field_5_reserved;
+      ptg.field_6_reserved = field_6_reserved;
+      ptg.field_7_reserved = field_7_reserved;
+      
+      ptg.token_1_columns = token_1_columns;
+      ptg.token_2_rows = token_2_rows;
+      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
+      for (int x=0;x<getColumnCount();x++) {
+      	for (int y=0;y<getRowCount();y++) {
+      		ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
+      	}
+      }      
+      ptg.setClass(ptgClass);
+      return ptg;
+    }
+}

Modified: jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java?rev=370987&r1=370986&r2=370987&view=diff
==============================================================================
--- jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java (original)
+++ jakarta/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java Fri Jan 20 21:40:07 2006
@@ -18,6 +18,7 @@
 
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Stack;
 
 import org.apache.poi.hssf.model.Workbook;
 import org.apache.poi.hssf.record.RecordInputStream;
@@ -85,8 +86,33 @@
         return retval;
     }
     */
+
+    public static Stack createParsedExpressionTokens(short size,  RecordInputStream in )
+    {
+        Stack stack = new Stack();
+        int pos = 0;
+        List arrayPtgs = null;
+        while ( pos < size )
+        {
+            Ptg ptg = Ptg.createPtg( in );
+            if (ptg instanceof ArrayPtg) {
+            	if (arrayPtgs == null)
+            		arrayPtgs = new ArrayList(5);
+            	arrayPtgs.add(ptg);
+            	pos += 8;
+            } else pos += ptg.getSize();
+            stack.push( ptg );
+        }
+        if (arrayPtgs != null) {
+        	for (int i=0;i<arrayPtgs.size();i++) {
+        		ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
+        		p.readTokenValues(in);
+        	}
+        }
+        return stack;
+    }
     
-    public static Ptg createPtg(RecordInputStream in)
+    private static Ptg createPtg(RecordInputStream in)
     {
         byte id     = in.readByte();
         Ptg  retval = null;
@@ -157,6 +183,16 @@
             case ConcatPtg.sid :
                 retval = new ConcatPtg(in);
                 break;
+                
+            case ArrayPtg.sid:
+            	retval = new ArrayPtg(in);
+            	break;
+            case ArrayPtgV.sid:
+            	retval = new ArrayPtgV(in);
+            	break;            	
+            case ArrayPtgA.sid:            	
+            	retval = new ArrayPtgA(in);
+            	break;
 
             case AreaPtg.sid :
                 retval = new AreaPtg(in);
@@ -303,6 +339,34 @@
             retval.setClass(CLASS_REF);
        return retval;
         
+    }
+    
+    public static int serializePtgStack(Stack expression, byte[] array, int offset) {
+    	int pos = 0;
+    	int size = 0;
+    	if (expression != null)
+    		size = expression.size();
+
+    	List arrayPtgs = null;
+    	
+    	for (int k = 0; k < size; k++) {
+    		Ptg ptg = ( Ptg ) expression.get(k);
+    		
+    		ptg.writeBytes(array, pos + offset);
+    		if (ptg instanceof ArrayPtg) {
+    		  if (arrayPtgs == null)
+    			  arrayPtgs = new ArrayList(5);
+    		  arrayPtgs.add(ptg);
+    		  pos += 8;
+    		} else pos += ptg.getSize();
+    	}
+    	if (arrayPtgs != null) {
+    		for (int i=0;i<arrayPtgs.size();i++) {
+    			ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
+    			pos += p.writeTokenValueBytes(array, pos + offset);
+    		}
+    	}
+    	return pos;
     }
 
     public abstract int getSize();

Added: jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/data/37630.xls
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/data/37630.xls?rev=370987&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/data/37630.xls
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java?rev=370987&r1=370986&r2=370987&view=diff
==============================================================================
--- jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (original)
+++ jakarta/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java Fri Jan 20 21:40:07 2006
@@ -522,6 +522,22 @@
 	       HSSFWorkbook wb = new HSSFWorkbook(in);
 	       assertTrue("Read book fine!" , true);
 	}
+	
+	/** Error when reading then writing ArrayValues in NameRecord's*/
+	public void test37630() throws java.io.IOException {
+	       String filename = System.getProperty("HSSF.testdata.path");
+	       filename=filename+"/37630.xls";
+	       FileInputStream in = new FileInputStream(filename);
+	       HSSFWorkbook wb = new HSSFWorkbook(in);
+           File file = TempFile.createTempFile("test37630",".xls");
+	       FileOutputStream out    = new FileOutputStream(file);
+	       wb.write(out);
+	       
+	       assertTrue("Read book fine!" , true);
+	}
+	
+	
+	
 
 }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: poi-dev-unsubscribe@jakarta.apache.org
Mailing List:    http://jakarta.apache.org/site/mail2.html#poi
The Apache Jakarta POI Project: http://jakarta.apache.org/poi/