'AI' record support.

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352897 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Glen Stampoultzis 2002-10-20 06:16:34 +00:00
parent 69d107008d
commit 7cbb071a62
7 changed files with 331 additions and 148 deletions

View File

@ -145,7 +145,7 @@ public class FormulaRecord
field_6_zero = LittleEndian.getInt(data, 16 + offset); field_6_zero = LittleEndian.getInt(data, 16 + offset);
field_7_expression_len = LittleEndian.getShort(data, 20 + offset); field_7_expression_len = LittleEndian.getShort(data, 20 + offset);
field_8_parsed_expr = getParsedExpressionTokens(data, size, field_8_parsed_expr = getParsedExpressionTokens(data, size,
offset); 22 + offset);
} catch (java.lang.UnsupportedOperationException uoe) { } catch (java.lang.UnsupportedOperationException uoe) {
field_8_parsed_expr = null; field_8_parsed_expr = null;
@ -164,7 +164,7 @@ public class FormulaRecord
int offset) int offset)
{ {
Stack stack = new Stack(); Stack stack = new Stack();
int pos = 22 + offset; int pos = offset;
while (pos < size) while (pos < size)
{ {
@ -329,7 +329,7 @@ public class FormulaRecord
public List getParsedExpression() public List getParsedExpression()
{ {
return ( List ) field_8_parsed_expr; return field_8_parsed_expr;
} }
/** /**
@ -555,7 +555,7 @@ public class FormulaRecord
buffer.append("Formula ") buffer.append("Formula ")
.append(k) .append(k)
.append("=") .append("=")
.append(((Ptg)field_8_parsed_expr.get(k)).toString()) .append(field_8_parsed_expr.get(k).toString())
.append("\n") .append("\n")
.append(((Ptg)field_8_parsed_expr.get(k)).toDebugString()) .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString())
.append("\n"); .append("\n");

View File

@ -54,6 +54,12 @@
package org.apache.poi.hssf.record; 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 * Not implemented yet. May commit it anyway just so people can see
* where I'm heading. * where I'm heading.
@ -63,29 +69,92 @@ package org.apache.poi.hssf.record;
public class LinkedDataFormulaField public class LinkedDataFormulaField
implements CustomField implements CustomField
{ {
Stack formulaTokens = new Stack();
public int getSize() 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 ) 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 ) 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() 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();
} }
} }

View File

@ -84,7 +84,7 @@ public class LinkedDataRecord
private short field_3_options; private short field_3_options;
private BitField customNumberFormat = new BitField(0x1); private BitField customNumberFormat = new BitField(0x1);
private short field_4_indexNumberFmtRecord; private short field_4_indexNumberFmtRecord;
private LinkedDataFormulaField field_5_formulaOfLink = new org.apache.poi.hssf.record.LinkedDataFormulaField(); private LinkedDataFormulaField field_5_formulaOfLink;
public LinkedDataRecord() public LinkedDataRecord()
@ -145,7 +145,7 @@ public class LinkedDataRecord
field_3_options = LittleEndian.getShort(data, pos + 0x2 + offset); field_3_options = LittleEndian.getShort(data, pos + 0x2 + offset);
field_4_indexNumberFmtRecord = LittleEndian.getShort(data, pos + 0x4 + offset); field_4_indexNumberFmtRecord = LittleEndian.getShort(data, pos + 0x4 + offset);
field_5_formulaOfLink = new org.apache.poi.hssf.record.LinkedDataFormulaField(); 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; data[ 5 + offset + pos ] = field_2_referenceType;
LittleEndian.putShort(data, 6 + offset + pos, field_3_options); LittleEndian.putShort(data, 6 + offset + pos, field_3_options);
LittleEndian.putShort(data, 8 + offset + pos, field_4_indexNumberFmtRecord); 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(); return getRecordSize();
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
* The Apache Software License, Version 1.1 * The Apache Software License, Version 1.1
* *
@ -76,71 +75,75 @@ import org.apache.poi.util.BitField;
public class Area3DPtg extends Ptg public class Area3DPtg extends Ptg
{ {
public final static byte sid = 0x3b; public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg private final static int SIZE = 11; // 10 + 1 for Ptg
private short field_1_index_extern_sheet; private short field_1_index_extern_sheet;
private short field_2_first_row; private short field_2_first_row;
private short field_3_last_row; private short field_3_last_row;
private short field_4_first_column; private short field_4_first_column;
private short field_5_last_column; private short field_5_last_column;
private BitField rowRelative = new BitField(0x8000); private BitField rowRelative = new BitField( 0x8000 );
private BitField colRelative = new BitField(0x4000); private BitField colRelative = new BitField( 0x4000 );
/** Creates new AreaPtg */ /** Creates new AreaPtg */
public Area3DPtg() {} 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( 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++; offset++;
field_1_index_extern_sheet = LittleEndian.getShort(data, 0 + offset); field_1_index_extern_sheet = LittleEndian.getShort( data, 0 + offset );
field_2_first_row = LittleEndian.getShort(data, 2 + offset); field_2_first_row = LittleEndian.getShort( data, 2 + offset );
field_3_last_row = LittleEndian.getShort(data, 4 + offset); field_3_last_row = LittleEndian.getShort( data, 4 + offset );
field_4_first_column = LittleEndian.getShort(data, 6 + offset); field_4_first_column = LittleEndian.getShort( data, 6 + offset );
field_5_last_column = LittleEndian.getShort(data, 8 + offset); field_5_last_column = LittleEndian.getShort( data, 8 + offset );
} }
public String toString() public String toString()
{ {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("AreaPtg\n"); buffer.append( "AreaPtg\n" );
buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n"); buffer.append( "Index to Extern Sheet = " + getExternSheetIndex() ).append( "\n" );
buffer.append("firstRow = " + getFirstRow()).append("\n"); buffer.append( "firstRow = " + getFirstRow() ).append( "\n" );
buffer.append("lastRow = " + getLastRow()).append("\n"); buffer.append( "lastRow = " + getLastRow() ).append( "\n" );
buffer.append("firstCol = " + getFirstColumn()).append("\n"); buffer.append( "firstCol = " + getFirstColumn() ).append( "\n" );
buffer.append("lastCol = " + getLastColumn()).append("\n"); buffer.append( "lastCol = " + getLastColumn() ).append( "\n" );
buffer.append("firstColRel= " buffer.append( "firstColRel= "
+ isFirstRowRelative()).append("\n"); + isFirstRowRelative() ).append( "\n" );
buffer.append("lastColRowRel = " buffer.append( "lastColRowRel = "
+ isLastRowRelative()).append("\n"); + isLastRowRelative() ).append( "\n" );
buffer.append("firstColRel = " + isFirstColRelative()).append("\n"); buffer.append( "firstColRel = " + isFirstColRelative() ).append( "\n" );
buffer.append("lastColRel = " + isLastColRelative()).append("\n"); buffer.append( "lastColRel = " + isLastColRelative() ).append( "\n" );
return buffer.toString(); return buffer.toString();
} }
public void writeBytes(byte [] array, int offset) public void writeBytes( byte[] array, int offset )
{ {
array[ 0 + offset ] = (byte) (sid + ptgClass); array[0 + offset] = (byte) ( sid + ptgClass );
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex()); LittleEndian.putShort( array, 1 + offset, getExternSheetIndex() );
LittleEndian.putShort(array, 3 + offset , getFirstRow()); LittleEndian.putShort( array, 3 + offset, getFirstRow() );
LittleEndian.putShort(array, 5 + offset , getLastRow()); LittleEndian.putShort( array, 5 + offset, getLastRow() );
LittleEndian.putShort(array, 7 + offset , getFirstColumnRaw()); LittleEndian.putShort( array, 7 + offset, getFirstColumnRaw() );
LittleEndian.putShort(array, 9 + offset , getLastColumnRaw()); LittleEndian.putShort( array, 9 + offset, getLastColumnRaw() );
} }
public int getSize() public int getSize()
@ -148,11 +151,13 @@ public class Area3DPtg extends Ptg
return SIZE; return SIZE;
} }
public short getExternSheetIndex(){ public short getExternSheetIndex()
{
return field_1_index_extern_sheet; return field_1_index_extern_sheet;
} }
public void setExternSheetIndex(short index){ public void setExternSheetIndex( short index )
{
field_1_index_extern_sheet = index; field_1_index_extern_sheet = index;
} }
@ -161,7 +166,7 @@ public class Area3DPtg extends Ptg
return field_2_first_row; return field_2_first_row;
} }
public void setFirstRow(short row) public void setFirstRow( short row )
{ {
field_2_first_row = row; field_2_first_row = row;
} }
@ -171,14 +176,14 @@ public class Area3DPtg extends Ptg
return field_3_last_row; return field_3_last_row;
} }
public void setLastRow(short row) public void setLastRow( short row )
{ {
field_3_last_row = row; field_3_last_row = row;
} }
public short getFirstColumn() public short getFirstColumn()
{ {
return ( short ) (field_4_first_column & 0xFF); return (short) ( field_4_first_column & 0xFF );
} }
public short getFirstColumnRaw() public short getFirstColumnRaw()
@ -188,28 +193,28 @@ public class Area3DPtg extends Ptg
public boolean isFirstRowRelative() 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);
} }
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 &= 0xFF00;
field_4_first_column |= column & 0xFF; field_4_first_column |= column & 0xFF;
} }
public void setFirstColumnRaw(short column) public void setFirstColumnRaw( short column )
{ {
field_4_first_column = column; field_4_first_column = column;
} }
public short getLastColumn() public short getLastColumn()
{ {
return ( short ) (field_5_last_column & 0xFF); return (short) ( field_5_last_column & 0xFF );
} }
public short getLastColumnRaw() public short getLastColumnRaw()
@ -217,56 +222,61 @@ public class Area3DPtg extends Ptg
return field_5_last_column; 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() 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 &= 0xFF00;
field_5_last_column |= column & 0xFF; field_5_last_column |= column & 0xFF;
} }
public void setLastColumnRaw(short column) public void setLastColumnRaw( short column )
{ {
field_5_last_column = column; field_5_last_column = column;
} }
/** /**
* sets the first row to relative or not * sets the first row to relative or not
* @param isRelative or not. * @param isRelative or not.
*/ */
public void setFirstRowRelative(boolean rel) { public void setFirstRowRelative( boolean rel )
field_4_first_column=rowRelative.setShortBoolean(field_4_first_column,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) { public void setFirstColRelative( boolean rel )
field_4_first_column=colRelative.setShortBoolean(field_4_first_column,rel); {
field_4_first_column = colRelative.setShortBoolean( field_4_first_column, rel );
} }
/** /**
* set whether the last row is relative or not * set whether the last row is relative or not
* @param last row relative * @param last row relative
*/ */
public void setLastRowRelative(boolean rel) { public void setLastRowRelative( boolean rel )
field_5_last_column=rowRelative.setShortBoolean(field_5_last_column,rel); {
field_5_last_column = rowRelative.setShortBoolean( field_5_last_column, rel );
} }
/** /**
* set whether the last column should be relative or not * set whether the last column should be relative or not
*/ */
public void setLastColRelative(boolean rel) { public void setLastColRelative( boolean rel )
field_5_last_column=colRelative.setShortBoolean(field_5_last_column,rel); {
field_5_last_column = colRelative.setShortBoolean( field_5_last_column, rel );
} }
/*public String getArea(){ /*public String getArea(){
RangeAddress ra = new RangeAddress( getFirstColumn(),getFirstRow() + 1, getLastColumn(), getLastRow() + 1); RangeAddress ra = new RangeAddress( getFirstColumn(),getFirstRow() + 1, getLastColumn(), getLastRow() + 1);
@ -275,44 +285,77 @@ public class Area3DPtg extends Ptg
return result; return result;
}*/ }*/
public void setArea(String ref){ public void setArea( String ref )
RangeAddress ra = new RangeAddress(ref); {
RangeAddress ra = new RangeAddress( ref );
String from = ra.getFromCell(); String from = ra.getFromCell();
String to = ra.getToCell(); String to = ra.getToCell();
setFirstColumn((short) (ra.getXPosition(from) -1)); setFirstColumn( (short) ( ra.getXPosition( from ) - 1 ) );
setFirstRow((short) (ra.getYPosition(from) -1)); setFirstRow( (short) ( ra.getYPosition( from ) - 1 ) );
setLastColumn((short) (ra.getXPosition(to) -1)); setLastColumn( (short) ( ra.getXPosition( to ) - 1 ) );
setLastRow((short) (ra.getYPosition(to) -1)); setLastRow( (short) ( ra.getYPosition( to ) - 1 ) );
} }
public String toFormulaString(SheetReferences refs) public String toFormulaString( SheetReferences refs )
{ {
StringBuffer retval = new StringBuffer(); StringBuffer retval = new StringBuffer();
if (refs != null) { if ( refs != null )
retval.append(refs.getSheetName(this.field_1_index_extern_sheet)); {
retval.append('!'); retval.append( refs.getSheetName( this.field_1_index_extern_sheet ) );
retval.append( '!' );
} }
retval.append((new CellReference(getFirstRow(),getFirstColumn(),!isFirstRowRelative(),!isFirstColRelative())).toString()); retval.append( ( new CellReference( getFirstRow(), getFirstColumn(), !isFirstRowRelative(), !isFirstColRelative() ) ).toString() );
retval.append(':'); retval.append( ':' );
retval.append((new CellReference(getLastRow(),getLastColumn(),!isLastRowRelative(),!isLastColRelative())).toString()); retval.append( ( new CellReference( getLastRow(), getLastColumn(), !isLastRowRelative(), !isLastColRelative() ) ).toString() );
return retval.toString(); return retval.toString();
} }
public byte getDefaultOperandClass() { public byte getDefaultOperandClass()
return Ptg.CLASS_REF; {
} 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;
}
} }

View File

@ -122,7 +122,7 @@ public class FieldIterator
result.append( "();\n"); result.append( "();\n");
result.append( " pos += " ); result.append( " pos += " );
result.append(RecordUtil.getFieldName(position, name, 0)) result.append(RecordUtil.getFieldName(position, name, 0))
.append(".fillField(data,size,pos + ") .append(".fillField(data,size,pos + offset + ")
.append(offset) .append(offset)
.append(")"); .append(")");
return result.toString(); return result.toString();
@ -143,7 +143,7 @@ public class FieldIterator
String result = ""; String result = "";
if (type.startsWith("custom:")) 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")) else if (javaType.equals("short"))
result = "LittleEndian.putShort(data, " + (offset+4) + " + offset + pos, " + javaFieldName + ");"; result = "LittleEndian.putShort(data, " + (offset+4) + " + offset + pos, " + javaFieldName + ");";
else if (javaType.equals("short[]")) else if (javaType.equals("short[]"))

View File

@ -120,15 +120,17 @@ public class RecordUtil
public static String initializeText(String size, String type) public static String initializeText(String size, String type)
{ {
if (type.startsWith("custom:")) // Removed because of wierdo initialization sequence in constructors.
{ // if (type.startsWith("custom:"))
String javaType = type.substring( 7 ); // {
return " = new " + javaType + "()"; // String javaType = type.substring( 7 );
} // return " = new " + javaType + "()";
else // }
{ // else
return ""; // {
} // return "";
// }
return "";
} }
private static void toIdentifier(String name, StringBuffer fieldName) private static void toIdentifier(String name, StringBuffer fieldName)

View File

@ -58,6 +58,9 @@ package org.apache.poi.hssf.record;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.Area3DPtg;
import java.util.Stack;
/** /**
* Tests the serialization and deserialization of the LinkedDataRecord * 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 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 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 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) Offset 0xf9c (3996)
@ -94,6 +99,20 @@ recordid = 0x1051, size =8
.formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@95fd19 ) .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@95fd19 )
[/AI] [/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) Offset 0xfa8 (4008)
rectype = 0x1051, recsize = 0x13 rectype = 0x1051, recsize = 0x13
@ -111,6 +130,20 @@ recordid = 0x1051, size =19
.formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@11b9fb1 ) .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@11b9fb1 )
[/AI] [/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) Offset 0xfbf (4031)
rectype = 0x1051, recsize = 0x13 rectype = 0x1051, recsize = 0x13
@ -128,6 +161,9 @@ recordid = 0x1051, size =19
.formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@913fe2 ) .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@913fe2 )
[/AI] [/AI]
This third link type does not seem to be documented and does not appear to
contain any useful information anyway.
============================================ ============================================
Offset 0xfd6 (4054) Offset 0xfd6 (4054)
rectype = 0x1051, recsize = 0x8 rectype = 0x1051, recsize = 0x8
@ -147,11 +183,17 @@ recordid = 0x1051, size =8
*/ */
byte[] data = new byte[]{ byte[] data = new byte[]{
(byte) 0x00, (byte)0x01, // link type
(byte) 0x01, (byte)0x02, // reference type
(byte) 0x00, (byte) 0x00, (byte)0x00,(byte)0x00, // options
(byte)0x00,(byte)0x00, (byte)0x00,(byte)0x00, // index number format record
(byte)0x00,(byte)0x00 // not supported (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) public TestLinkedDataRecord(String name)
@ -164,14 +206,27 @@ recordid = 0x1051, size =8
{ {
LinkedDataRecord record = new LinkedDataRecord((short)0x1051, (short)data.length, data); LinkedDataRecord record = new LinkedDataRecord((short)0x1051, (short)data.length, data);
assertEquals( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT, record.getLinkType()); assertEquals( LinkedDataRecord.LINK_TYPE_VALUES, record.getLinkType());
assertEquals( LinkedDataRecord.REFERENCE_TYPE_DIRECT, record.getReferenceType()); assertEquals( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET, record.getReferenceType());
assertEquals( 0, record.getOptions()); assertEquals( 0, record.getOptions());
assertEquals( false, record.isCustomNumberFormat() ); assertEquals( false, record.isCustomNumberFormat() );
assertEquals( 0, record.getIndexNumberFmtRecord()); 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); record.validateSid((short)0x1051);
@ -180,12 +235,26 @@ recordid = 0x1051, size =8
public void testStore() public void testStore()
{ {
LinkedDataRecord record = new LinkedDataRecord(); LinkedDataRecord record = new LinkedDataRecord();
record.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT ); record.setLinkType( LinkedDataRecord.LINK_TYPE_VALUES );
record.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT ); record.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET );
record.setOptions( (short)0 ); record.setOptions( (short)0 );
record.setCustomNumberFormat( false ); record.setCustomNumberFormat( false );
record.setIndexNumberFmtRecord( (short)0 ); 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(); byte [] recordBytes = record.serialize();
assertEquals(recordBytes.length - 4, data.length); assertEquals(recordBytes.length - 4, data.length);