]> source.dussan.org Git - poi.git/commitdiff
'AI' record support.
authorGlen Stampoultzis <glens@apache.org>
Sun, 20 Oct 2002 06:16:34 +0000 (06:16 +0000)
committerGlen Stampoultzis <glens@apache.org>
Sun, 20 Oct 2002 06:16:34 +0000 (06:16 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352897 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/FormulaRecord.java
src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
src/java/org/apache/poi/hssf/record/LinkedDataRecord.java
src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
src/scratchpad/src/org/apache/poi/generator/FieldIterator.java
src/scratchpad/src/org/apache/poi/generator/RecordUtil.java
src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java

index f790b605a016716e2b005de7caa149206ce30bdd..e8466a49ee50cb63ea2ab0ff55b9eb8853c5886b 100644 (file)
@@ -145,7 +145,7 @@ public class FormulaRecord
         field_6_zero           = LittleEndian.getInt(data, 16 + offset);
         field_7_expression_len = LittleEndian.getShort(data, 20 + offset);
         field_8_parsed_expr    = getParsedExpressionTokens(data, size,
-                                 offset);
+                                 22 + offset);
         
         } catch (java.lang.UnsupportedOperationException uoe)  {
             field_8_parsed_expr = null;
@@ -164,7 +164,7 @@ public class FormulaRecord
                                             int offset)
     {
         Stack stack = new Stack();
-        int   pos   = 22 + offset;
+        int   pos   = offset;
 
         while (pos < size)
         {
@@ -329,7 +329,7 @@ public class FormulaRecord
 
     public List getParsedExpression()
     {
-        return ( List ) field_8_parsed_expr;
+        return field_8_parsed_expr;
     }
 
     /**
@@ -555,7 +555,7 @@ public class FormulaRecord
                 buffer.append("Formula ")
                 .append(k)
                 .append("=")
-                .append(((Ptg)field_8_parsed_expr.get(k)).toString())
+                .append(field_8_parsed_expr.get(k).toString())
                 .append("\n")
                 .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString())
                 .append("\n");                
index ac3ced6dbbdae79cb42b5259dc4eab43159434d5..c4ab2d69dcda6baee66cdcbbde9fbfc0cb647946 100644 (file)
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.util.LittleEndian;
+
+import java.util.Stack;
+import java.util.Iterator;
+
 /**
  * Not implemented yet. May commit it anyway just so people can see
  * where I'm heading.
@@ -63,29 +69,92 @@ package org.apache.poi.hssf.record;
 public class LinkedDataFormulaField
         implements CustomField
 {
+    Stack formulaTokens = new Stack();
+
     public int getSize()
     {
-        return 2;
+        int size = 0;
+        for ( Iterator iterator = formulaTokens.iterator(); iterator.hasNext(); )
+        {
+            Ptg token = (Ptg) iterator.next();
+            size += token.getSize();
+        }
+        return size + 2;
     }
 
     public int fillField( byte[] data, short size, int offset )
     {
-        return 0;
+        short tokenSize = LittleEndian.getShort(data, offset);
+        formulaTokens = getParsedExpressionTokens(data, size, offset + 2);
+
+        return tokenSize + 2;
     }
 
-    public void toString( StringBuffer str )
+    public void toString( StringBuffer buffer )
     {
-        str.append("todo");
+        for ( int k = 0; k < formulaTokens.size(); k++ )
+        {
+            buffer.append( "Formula " )
+                    .append( k )
+                    .append( "=" )
+                    .append( formulaTokens.get( k ).toString() )
+                    .append( "\n" )
+                    .append( ( (Ptg) formulaTokens.get( k ) ).toDebugString() )
+                    .append( "\n" );
+        }
     }
 
     public int serializeField( int offset, byte[] data )
     {
-        return 0;
+        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();
+        }
+        return size;
     }
 
     public Object clone()
     {
-        return this;
+        try
+        {
+            // todo: clone tokens? or are they immutable?
+            return super.clone();
+        }
+        catch ( CloneNotSupportedException e )
+        {
+            // should not happen
+            return null;
+        }
+    }
+
+    private Stack getParsedExpressionTokens( byte[] data, short size,
+                                             int offset )
+    {
+        Stack stack = new Stack();
+        int pos = offset;
+
+        while ( pos < size )
+        {
+            Ptg ptg = Ptg.createPtg( data, pos );
+            pos += ptg.getSize();
+            stack.push( ptg );
+        }
+        return stack;
+    }
+
+    public void setFormulaTokens( Stack formulaTokens )
+    {
+        this.formulaTokens = (Stack) formulaTokens.clone();
+    }
+
+    public Stack getFormulaTokens()
+    {
+        return (Stack)this.formulaTokens.clone();
     }
 
 }
index a7a1f95edd05bb972fe146c444dbe124c500dae8..ddbd249004feef38c24b0ea0e57a5d836135b697 100644 (file)
@@ -84,7 +84,7 @@ public class LinkedDataRecord
     private  short      field_3_options;
     private  BitField   customNumberFormat                          = new BitField(0x1);
     private  short      field_4_indexNumberFmtRecord;
-    private  LinkedDataFormulaField field_5_formulaOfLink = new org.apache.poi.hssf.record.LinkedDataFormulaField();
+    private  LinkedDataFormulaField field_5_formulaOfLink;
 
 
     public LinkedDataRecord()
@@ -145,7 +145,7 @@ public class LinkedDataRecord
         field_3_options                = LittleEndian.getShort(data, pos + 0x2 + offset);
         field_4_indexNumberFmtRecord   = LittleEndian.getShort(data, pos + 0x4 + offset);
         field_5_formulaOfLink = new org.apache.poi.hssf.record.LinkedDataFormulaField();
-        pos += field_5_formulaOfLink.fillField(data,size,pos + 6);
+        pos += field_5_formulaOfLink.fillField(data,size,pos + offset + 6);
 
     }
 
@@ -190,7 +190,7 @@ public class LinkedDataRecord
         data[ 5 + offset + pos ] = field_2_referenceType;
         LittleEndian.putShort(data, 6 + offset + pos, field_3_options);
         LittleEndian.putShort(data, 8 + offset + pos, field_4_indexNumberFmtRecord);
-        pos += field_5_formulaOfLink.serializeField( pos + offset, data );
+        pos += field_5_formulaOfLink.serializeField( pos + 10 + offset, data );
 
         return getRecordSize();
     }
index 5e4ed7f738cf2a63c60f2dbb35f6c9c6e99ec8dc..a428a0d5fd54ad379e7d7d29ec5dc99e13d4a4d9 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
  * The Apache Software License, Version 1.1
  *
@@ -76,71 +75,75 @@ import org.apache.poi.util.BitField;
 
 public class Area3DPtg extends Ptg
 {
-    public final static byte sid  = 0x3b;
-    private final static int  SIZE = 11; // 10 + 1 for Ptg
-    private short             field_1_index_extern_sheet;
-    private short             field_2_first_row;
-    private short             field_3_last_row;
-    private short             field_4_first_column;
-    private short             field_5_last_column;
-    
-    private BitField         rowRelative = new BitField(0x8000);
-    private BitField         colRelative = new BitField(0x4000);
+    public final static byte sid = 0x3b;
+    private final static int SIZE = 11; // 10 + 1 for Ptg
+    private short field_1_index_extern_sheet;
+    private short field_2_first_row;
+    private short field_3_last_row;
+    private short field_4_first_column;
+    private short field_5_last_column;
+
+    private BitField rowRelative = new BitField( 0x8000 );
+    private BitField colRelative = new BitField( 0x4000 );
 
     /** Creates new AreaPtg */
-    public Area3DPtg() {}
-   
-   public Area3DPtg(String arearef, short externIdx) {
-        AreaReference ar = new AreaReference(arearef);
-        
-        setFirstRow((short)ar.getCells()[0].getRow());
-        setFirstColumn((short)ar.getCells()[0].getCol());
-        setLastRow((short)ar.getCells()[1].getRow());
-        setLastColumn((short)ar.getCells()[1].getCol());
-        setFirstColRelative(!ar.getCells()[0].isColAbsolute());
-        setLastColRelative(!ar.getCells()[1].isColAbsolute());
-        setFirstRowRelative(!ar.getCells()[0].isRowAbsolute());
-        setLastRowRelative(!ar.getCells()[1].isRowAbsolute());
-        setExternSheetIndex(externIdx);
-        
-    }
-    public Area3DPtg(byte[] data, int offset)
+    public Area3DPtg()
+    {
+    }
+
+    public Area3DPtg( String arearef, short externIdx )
+    {
+        AreaReference ar = new AreaReference( arearef );
+
+        setFirstRow( (short) ar.getCells()[0].getRow() );
+        setFirstColumn( (short) ar.getCells()[0].getCol() );
+        setLastRow( (short) ar.getCells()[1].getRow() );
+        setLastColumn( (short) ar.getCells()[1].getCol() );
+        setFirstColRelative( !ar.getCells()[0].isColAbsolute() );
+        setLastColRelative( !ar.getCells()[1].isColAbsolute() );
+        setFirstRowRelative( !ar.getCells()[0].isRowAbsolute() );
+        setLastRowRelative( !ar.getCells()[1].isRowAbsolute() );
+        setExternSheetIndex( externIdx );
+
+    }
+
+    public Area3DPtg( byte[] data, int offset )
     {
         offset++;
-        field_1_index_extern_sheet = LittleEndian.getShort(data, 0 + offset);
-        field_2_first_row          = LittleEndian.getShort(data, 2 + offset);
-        field_3_last_row           = LittleEndian.getShort(data, 4 + offset);
-        field_4_first_column       = LittleEndian.getShort(data, 6 + offset);
-        field_5_last_column        = LittleEndian.getShort(data, 8 + offset);
+        field_1_index_extern_sheet = LittleEndian.getShort( data, 0 + offset );
+        field_2_first_row = LittleEndian.getShort( data, 2 + offset );
+        field_3_last_row = LittleEndian.getShort( data, 4 + offset );
+        field_4_first_column = LittleEndian.getShort( data, 6 + offset );
+        field_5_last_column = LittleEndian.getShort( data, 8 + offset );
     }
 
     public String toString()
     {
         StringBuffer buffer = new StringBuffer();
 
-        buffer.append("AreaPtg\n");
-        buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n");
-        buffer.append("firstRow = " + getFirstRow()).append("\n");
-        buffer.append("lastRow  = " + getLastRow()).append("\n");
-        buffer.append("firstCol = " + getFirstColumn()).append("\n");
-        buffer.append("lastCol  = " + getLastColumn()).append("\n");
-        buffer.append("firstColRel= "
-                      + isFirstRowRelative()).append("\n");
-        buffer.append("lastColRowRel = "
-                      + isLastRowRelative()).append("\n");
-        buffer.append("firstColRel   = " + isFirstColRelative()).append("\n");
-        buffer.append("lastColRel    = " + isLastColRelative()).append("\n");
+        buffer.append( "AreaPtg\n" );
+        buffer.append( "Index to Extern Sheet = " + getExternSheetIndex() ).append( "\n" );
+        buffer.append( "firstRow = " + getFirstRow() ).append( "\n" );
+        buffer.append( "lastRow  = " + getLastRow() ).append( "\n" );
+        buffer.append( "firstCol = " + getFirstColumn() ).append( "\n" );
+        buffer.append( "lastCol  = " + getLastColumn() ).append( "\n" );
+        buffer.append( "firstColRel= "
+                + isFirstRowRelative() ).append( "\n" );
+        buffer.append( "lastColRowRel = "
+                + isLastRowRelative() ).append( "\n" );
+        buffer.append( "firstColRel   = " + isFirstColRelative() ).append( "\n" );
+        buffer.append( "lastColRel    = " + isLastColRelative() ).append( "\n" );
         return buffer.toString();
     }
 
-    public void writeBytes(byte [] array, int offset)
+    public void writeBytes( byte[] array, int offset )
     {
-        array[ 0 + offset ] = (byte) (sid + ptgClass);
-        LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
-        LittleEndian.putShort(array, 3 + offset , getFirstRow());
-        LittleEndian.putShort(array, 5 + offset , getLastRow());
-        LittleEndian.putShort(array, 7 + offset , getFirstColumnRaw());
-        LittleEndian.putShort(array, 9 + offset , getLastColumnRaw());
+        array[0 + offset] = (byte) ( sid + ptgClass );
+        LittleEndian.putShort( array, 1 + offset, getExternSheetIndex() );
+        LittleEndian.putShort( array, 3 + offset, getFirstRow() );
+        LittleEndian.putShort( array, 5 + offset, getLastRow() );
+        LittleEndian.putShort( array, 7 + offset, getFirstColumnRaw() );
+        LittleEndian.putShort( array, 9 + offset, getLastColumnRaw() );
     }
 
     public int getSize()
@@ -148,11 +151,13 @@ public class Area3DPtg extends Ptg
         return SIZE;
     }
 
-    public short getExternSheetIndex(){
+    public short getExternSheetIndex()
+    {
         return field_1_index_extern_sheet;
     }
 
-    public void setExternSheetIndex(short index){
+    public void setExternSheetIndex( short index )
+    {
         field_1_index_extern_sheet = index;
     }
 
@@ -161,7 +166,7 @@ public class Area3DPtg extends Ptg
         return field_2_first_row;
     }
 
-    public void setFirstRow(short row)
+    public void setFirstRow( short row )
     {
         field_2_first_row = row;
     }
@@ -171,14 +176,14 @@ public class Area3DPtg extends Ptg
         return field_3_last_row;
     }
 
-    public void setLastRow(short row)
+    public void setLastRow( short row )
     {
         field_3_last_row = row;
     }
 
     public short getFirstColumn()
     {
-        return ( short ) (field_4_first_column & 0xFF);
+        return (short) ( field_4_first_column & 0xFF );
     }
 
     public short getFirstColumnRaw()
@@ -188,28 +193,28 @@ public class Area3DPtg extends Ptg
 
     public boolean isFirstRowRelative()
     {
-        return rowRelative.isSet(field_4_first_column);
+        return rowRelative.isSet( field_4_first_column );
     }
-    
+
     public boolean isFirstColRelative()
     {
-        return colRelative.isSet(field_4_first_column);
+        return colRelative.isSet( field_4_first_column );
     }
 
-    public void setFirstColumn(short column)
+    public void setFirstColumn( short column )
     {
         field_4_first_column &= 0xFF00;
         field_4_first_column |= column & 0xFF;
     }
 
-    public void setFirstColumnRaw(short column)
+    public void setFirstColumnRaw( short column )
     {
         field_4_first_column = column;
     }
 
     public short getLastColumn()
     {
-        return ( short ) (field_5_last_column & 0xFF);
+        return (short) ( field_5_last_column & 0xFF );
     }
 
     public short getLastColumnRaw()
@@ -217,56 +222,61 @@ public class Area3DPtg extends Ptg
         return field_5_last_column;
     }
 
-     public boolean isLastRowRelative()
+    public boolean isLastRowRelative()
     {
-        return rowRelative.isSet(field_5_last_column);
+        return rowRelative.isSet( field_5_last_column );
     }
+
     public boolean isLastColRelative()
     {
-        return colRelative.isSet(field_5_last_column);
+        return colRelative.isSet( field_5_last_column );
     }
-    
-    public void setLastColumn(short column)
+
+    public void setLastColumn( short column )
     {
         field_5_last_column &= 0xFF00;
         field_5_last_column |= column & 0xFF;
     }
 
-    public void setLastColumnRaw(short column)
+    public void setLastColumnRaw( short column )
     {
         field_5_last_column = column;
     }
-    
-        /**
+
+    /**
      * sets the first row to relative or not
      * @param isRelative or not.
      */
-    public void setFirstRowRelative(boolean rel) {
-        field_4_first_column=rowRelative.setShortBoolean(field_4_first_column,rel);
+    public void setFirstRowRelative( boolean rel )
+    {
+        field_4_first_column = rowRelative.setShortBoolean( field_4_first_column, rel );
     }
 
     /**
-     * set whether the first column is relative 
+     * set whether the first column is relative
      */
-    public void setFirstColRelative(boolean rel) {
-        field_4_first_column=colRelative.setShortBoolean(field_4_first_column,rel);
+    public void setFirstColRelative( boolean rel )
+    {
+        field_4_first_column = colRelative.setShortBoolean( field_4_first_column, rel );
     }
-    
+
     /**
      * set whether the last row is relative or not
      * @param last row relative
      */
-    public void setLastRowRelative(boolean rel) {
-        field_5_last_column=rowRelative.setShortBoolean(field_5_last_column,rel);
+    public void setLastRowRelative( boolean rel )
+    {
+        field_5_last_column = rowRelative.setShortBoolean( field_5_last_column, rel );
     }
-    
+
     /**
      * set whether the last column should be relative or not
      */
-    public void setLastColRelative(boolean rel) {
-        field_5_last_column=colRelative.setShortBoolean(field_5_last_column,rel);
+    public void setLastColRelative( boolean rel )
+    {
+        field_5_last_column = colRelative.setShortBoolean( field_5_last_column, rel );
     }
-    
+
 
     /*public String getArea(){
         RangeAddress ra = new RangeAddress( getFirstColumn(),getFirstRow() + 1, getLastColumn(), getLastRow() + 1);
@@ -275,44 +285,77 @@ public class Area3DPtg extends Ptg
         return result;
     }*/
 
-    public void setArea(String ref){
-        RangeAddress ra = new RangeAddress(ref);
+    public void setArea( String ref )
+    {
+        RangeAddress ra = new RangeAddress( ref );
 
         String from = ra.getFromCell();
-        String to   = ra.getToCell();
+        String to = ra.getToCell();
 
-        setFirstColumn((short) (ra.getXPosition(from) -1));
-        setFirstRow((short) (ra.getYPosition(from) -1));
-        setLastColumn((short) (ra.getXPosition(to) -1));
-        setLastRow((short) (ra.getYPosition(to) -1));
+        setFirstColumn( (short) ( ra.getXPosition( from ) - 1 ) );
+        setFirstRow( (short) ( ra.getYPosition( from ) - 1 ) );
+        setLastColumn( (short) ( ra.getXPosition( to ) - 1 ) );
+        setLastRow( (short) ( ra.getYPosition( to ) - 1 ) );
 
     }
 
-    public String toFormulaString(SheetReferences refs)
+    public String toFormulaString( SheetReferences refs )
     {
         StringBuffer retval = new StringBuffer();
-        if (refs != null) {
-            retval.append(refs.getSheetName(this.field_1_index_extern_sheet));
-            retval.append('!');
+        if ( refs != null )
+        {
+            retval.append( refs.getSheetName( this.field_1_index_extern_sheet ) );
+            retval.append( '!' );
         }
-        retval.append((new CellReference(getFirstRow(),getFirstColumn(),!isFirstRowRelative(),!isFirstColRelative())).toString()); 
-        retval.append(':');
-        retval.append((new CellReference(getLastRow(),getLastColumn(),!isLastRowRelative(),!isLastColRelative())).toString());
+        retval.append( ( new CellReference( getFirstRow(), getFirstColumn(), !isFirstRowRelative(), !isFirstColRelative() ) ).toString() );
+        retval.append( ':' );
+        retval.append( ( new CellReference( getLastRow(), getLastColumn(), !isLastRowRelative(), !isLastColRelative() ) ).toString() );
         return retval.toString();
     }
 
-   public byte getDefaultOperandClass() {
-       return Ptg.CLASS_REF;
-   }
+    public byte getDefaultOperandClass()
+    {
+        return Ptg.CLASS_REF;
+    }
+
+    public Object clone()
+    {
+        Area3DPtg ptg = new Area3DPtg();
+        ptg.field_1_index_extern_sheet = field_1_index_extern_sheet;
+        ptg.field_2_first_row = field_2_first_row;
+        ptg.field_3_last_row = field_3_last_row;
+        ptg.field_4_first_column = field_4_first_column;
+        ptg.field_5_last_column = field_5_last_column;
+        return ptg;
+    }
+
+
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( !( o instanceof Area3DPtg ) ) return false;
+
+        final Area3DPtg area3DPtg = (Area3DPtg) o;
+
+        if ( field_1_index_extern_sheet != area3DPtg.field_1_index_extern_sheet ) return false;
+        if ( field_2_first_row != area3DPtg.field_2_first_row ) return false;
+        if ( field_3_last_row != area3DPtg.field_3_last_row ) return false;
+        if ( field_4_first_column != area3DPtg.field_4_first_column ) return false;
+        if ( field_5_last_column != area3DPtg.field_5_last_column ) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        int result;
+        result = (int) field_1_index_extern_sheet;
+        result = 29 * result + (int) field_2_first_row;
+        result = 29 * result + (int) field_3_last_row;
+        result = 29 * result + (int) field_4_first_column;
+        result = 29 * result + (int) field_5_last_column;
+        return result;
+    }
 
-   public Object clone() {
-     Area3DPtg ptg = new Area3DPtg();
-     ptg.field_1_index_extern_sheet = field_1_index_extern_sheet;
-     ptg.field_2_first_row = field_2_first_row;
-     ptg.field_3_last_row = field_3_last_row;
-     ptg.field_4_first_column = field_4_first_column;
-     ptg.field_5_last_column = field_5_last_column;
-     return ptg;
-   }
 
 }
index 5e47276b296b9ad2fb6d62ded91e89a271ccc6dd..70ba340207ec19dc6d3e7f7d59c59f7578302d73 100644 (file)
@@ -122,7 +122,7 @@ public class FieldIterator
             result.append( "();\n");
             result.append( "        pos += " );
             result.append(RecordUtil.getFieldName(position, name, 0))
-                    .append(".fillField(data,size,pos + ")
+                    .append(".fillField(data,size,pos + offset + ")
                     .append(offset)
                     .append(")");
             return result.toString();
@@ -143,7 +143,7 @@ public class FieldIterator
 
         String result = "";
         if (type.startsWith("custom:"))
-            result = "pos += " + javaFieldName + ".serializeField( pos + offset, data );";
+            result = "pos += " + javaFieldName + ".serializeField( pos + " + (offset+4) + " + offset, data );";
         else if (javaType.equals("short"))
             result = "LittleEndian.putShort(data, " + (offset+4) + " + offset + pos, " + javaFieldName + ");";
         else if (javaType.equals("short[]"))
index 87c19e49c7462e7180aa9512135e227c294675cd..548b904dc4c6ac316c391f721e1504e42ba49d78 100644 (file)
@@ -120,15 +120,17 @@ public class RecordUtil
 
     public static String initializeText(String size, String type)
     {
-        if (type.startsWith("custom:"))
-        {
-            String javaType = type.substring( 7 );
-            return " = new " + javaType + "()";
-        }
-        else
-        {
-            return "";
-        }
+        // Removed because of wierdo initialization sequence in constructors.
+//        if (type.startsWith("custom:"))
+//        {
+//            String javaType = type.substring( 7 );
+//            return " = new " + javaType + "()";
+//        }
+//        else
+//        {
+//            return "";
+//        }
+        return "";
     }
 
     private static void toIdentifier(String name, StringBuffer fieldName)
index 442f63df58a3bf1ee033b11e140b0baca66462d8..81a74ad018ab7c20d781ed97b45987132a455fc7 100644 (file)
@@ -58,6 +58,9 @@ package org.apache.poi.hssf.record;
 
 
 import junit.framework.TestCase;
+import org.apache.poi.hssf.record.formula.Area3DPtg;
+
+import java.util.Stack;
 
 /**
  * Tests the serialization and deserialization of the LinkedDataRecord
@@ -71,12 +74,14 @@ public class TestLinkedDataRecord
 {
 
 /*
-    Records that would appear in a simple bar chart
+    The records below are records that would appear in a simple bar chart
 
     The first record links to the series title (linkType = 0).   It's
     reference type is 1 which means that it links directly to data entered
     into the forumula bar.  There seems to be no reference to any data
-    however.  The formulaOfLink field contains two 0 bytes.
+    however.  The formulaOfLink field contains two 0 bytes.  This probably
+    means that there is no particular heading set.
+
 
 ============================================
 Offset 0xf9c (3996)
@@ -94,6 +99,20 @@ recordid = 0x1051, size =8
 .formulaOfLink        =  (org.apache.poi.hssf.record.LinkedDataFormulaField@95fd19 )
 [/AI]
 
+
+    The second record links to the series data (linkType=1).  The
+    referenceType = 2 which means it's linked to the worksheet.
+    It links using a formula.  The formula value is
+    0B 00 3B 00 00 00 00 1E 00 01 00 01 00.
+
+    0B 00   11 bytes length
+    3B (tArea3d) Rectangular area
+        00 00 index to REF entry in extern sheet
+        00 00 index to first row
+        1E 00 index to last row
+        01 00 index to first column and relative flags
+        01 00 index to last column and relative flags
+
 ============================================
 Offset 0xfa8 (4008)
 rectype = 0x1051, recsize = 0x13
@@ -111,6 +130,20 @@ recordid = 0x1051, size =19
 .formulaOfLink        =  (org.apache.poi.hssf.record.LinkedDataFormulaField@11b9fb1 )
 [/AI]
 
+    The third record links to the series categories (linkType=2).  The
+    reference type of 2 means that it's linked to the worksheet.
+    It links using a formula.  The formula value is
+    0B 00 3B 00 00 00 00 1E 00 01 00 01 00
+
+    0B 00   11 bytes in length
+        3B (tArea3d) Rectangular area
+        00 00 index to REF entry in extern sheet
+        00 00  index to first row
+        00 1F  index to last row
+        00 00 index to first column and relative flags
+        00 00 index to last column and relative flags
+
+
 ============================================
 Offset 0xfbf (4031)
 rectype = 0x1051, recsize = 0x13
@@ -128,6 +161,9 @@ recordid = 0x1051, size =19
 .formulaOfLink        =  (org.apache.poi.hssf.record.LinkedDataFormulaField@913fe2 )
 [/AI]
 
+This third link type does not seem to be documented and does not appear to
+contain any useful information anyway.
+
 ============================================
 Offset 0xfd6 (4054)
 rectype = 0x1051, recsize = 0x8
@@ -147,11 +183,17 @@ recordid = 0x1051, size =8
 */
 
     byte[] data = new byte[]{
-        (byte) 0x00,
-        (byte) 0x01,
-        (byte) 0x00, (byte) 0x00,
-        (byte)0x00,(byte)0x00,
-        (byte)0x00,(byte)0x00          // not supported
+        (byte)0x01,                 // link type
+        (byte)0x02,                 // reference type
+        (byte)0x00,(byte)0x00,      // options
+        (byte)0x00,(byte)0x00,      // index number format record
+        (byte)0x0B,(byte)0x00,      // 11 bytes length
+        (byte)0x3B,                 // formula of link
+        (byte)0x00,(byte)0x00,          // index to ref entry in extern sheet
+        (byte)0x00,(byte)0x00,          // index to first row
+        (byte)0x00,(byte)0x1F,          // index to last row
+        (byte)0x00,(byte)0x00,          // index to first column and relative flags
+        (byte)0x00,(byte)0x00,          // index to last column and relative flags
     };
 
     public TestLinkedDataRecord(String name)
@@ -164,14 +206,27 @@ recordid = 0x1051, size =8
     {
 
         LinkedDataRecord record = new LinkedDataRecord((short)0x1051, (short)data.length, data);
-        assertEquals( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT, record.getLinkType());
-        assertEquals( LinkedDataRecord.REFERENCE_TYPE_DIRECT, record.getReferenceType());
+        assertEquals( LinkedDataRecord.LINK_TYPE_VALUES, record.getLinkType());
+        assertEquals( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET, record.getReferenceType());
         assertEquals( 0, record.getOptions());
         assertEquals( false, record.isCustomNumberFormat() );
         assertEquals( 0, record.getIndexNumberFmtRecord());
 
+        Area3DPtg ptg = new Area3DPtg();
+        ptg.setExternSheetIndex((short)0);
+        ptg.setFirstColumn((short)0);
+        ptg.setLastColumn((short)0);
+        ptg.setFirstRow((short)0);
+        ptg.setLastRow((short)7936);
+        ptg.setFirstColRelative(false);
+        ptg.setLastColRelative(false);
+        ptg.setFirstRowRelative(false);
+        ptg.setLastRowRelative(false);
+        Stack s = new Stack();
+        s.push(ptg);
+        assertEquals( s, record.getFormulaOfLink().getFormulaTokens() );
 
-        assertEquals( 12, record.getRecordSize() );
+        assertEquals( data.length + 4, record.getRecordSize() );
 
         record.validateSid((short)0x1051);
 
@@ -180,12 +235,26 @@ recordid = 0x1051, size =8
     public void testStore()
     {
         LinkedDataRecord record = new LinkedDataRecord();
-        record.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT );
-        record.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT );
+        record.setLinkType( LinkedDataRecord.LINK_TYPE_VALUES );
+        record.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET );
         record.setOptions( (short)0 );
         record.setCustomNumberFormat( false );
         record.setIndexNumberFmtRecord( (short)0 );
-
+        Area3DPtg ptg = new Area3DPtg();
+        ptg.setExternSheetIndex((short)0);
+        ptg.setFirstColumn((short)0);
+        ptg.setLastColumn((short)0);
+        ptg.setFirstRow((short)0);
+        ptg.setLastRow((short)7936);
+        ptg.setFirstColRelative(false);
+        ptg.setLastColRelative(false);
+        ptg.setFirstRowRelative(false);
+        ptg.setLastRowRelative(false);
+        Stack s = new Stack();
+        s.push(ptg);
+        LinkedDataFormulaField formulaOfLink = new LinkedDataFormulaField();
+        formulaOfLink.setFormulaTokens(s);
+        record.setFormulaOfLink(formulaOfLink );
 
         byte [] recordBytes = record.serialize();
         assertEquals(recordBytes.length - 4, data.length);