From 7cbb071a627502937657d01ef8a963b5a73e1853 Mon Sep 17 00:00:00 2001 From: Glen Stampoultzis Date: Sun, 20 Oct 2002 06:16:34 +0000 Subject: [PATCH] 'AI' record support. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352897 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/FormulaRecord.java | 8 +- .../hssf/record/LinkedDataFormulaField.java | 81 +++++- .../poi/hssf/record/LinkedDataRecord.java | 6 +- .../poi/hssf/record/formula/Area3DPtg.java | 265 ++++++++++-------- .../apache/poi/generator/FieldIterator.java | 4 +- .../org/apache/poi/generator/RecordUtil.java | 20 +- .../poi/hssf/record/TestLinkedDataRecord.java | 95 ++++++- 7 files changed, 331 insertions(+), 148 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index f790b605a..e8466a49e 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -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"); diff --git a/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java b/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java index ac3ced6db..c4ab2d69d 100644 --- a/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java +++ b/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java @@ -54,6 +54,12 @@ 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(); } } diff --git a/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java b/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java index a7a1f95ed..ddbd24900 100644 --- a/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java +++ b/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java @@ -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(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java index 5e4ed7f73..a428a0d5f 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java @@ -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() + { } - public Area3DPtg(byte[] data, int offset) + + 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); - } - - public boolean isFirstColRelative() - { - return colRelative.isSet(field_4_first_column); + return rowRelative.isSet( field_4_first_column ); } - public void setFirstColumn(short column) + public boolean isFirstColRelative() + { + return colRelative.isSet( field_4_first_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; - } } diff --git a/src/scratchpad/src/org/apache/poi/generator/FieldIterator.java b/src/scratchpad/src/org/apache/poi/generator/FieldIterator.java index 5e47276b2..70ba34020 100644 --- a/src/scratchpad/src/org/apache/poi/generator/FieldIterator.java +++ b/src/scratchpad/src/org/apache/poi/generator/FieldIterator.java @@ -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[]")) diff --git a/src/scratchpad/src/org/apache/poi/generator/RecordUtil.java b/src/scratchpad/src/org/apache/poi/generator/RecordUtil.java index 87c19e49c..548b904dc 100644 --- a/src/scratchpad/src/org/apache/poi/generator/RecordUtil.java +++ b/src/scratchpad/src/org/apache/poi/generator/RecordUtil.java @@ -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) diff --git a/src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java b/src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java index 442f63df5..81a74ad01 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java @@ -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);