Merged revisions 612484-612511,612513-612519,612521-613394,613397-613399,613402-614210,614212-614273,614275-614869,614871-614877,614879-614908,614910-615189,615191-615254,615256-615258,615260-615309,615311-615314,615316-615609,615611-615768,615770-615858,615860-617155,617157-617166,617168-617482,617484-617486,617488-617490,617492-617515,617517-617522,617524-617554,617556-617833,617835-618229,618231-618234,618236-618327,618329-618679,618681-618689,618691,618693-618939,618941-619000,619002-619309,619311-619381,619383-619501,619503-619508,619510-619847,619850,619852-619967,619969-620340,620342-620556,620558-620581,620583-627778,627780-627787,627789-627998,628000-628026,628028,628030-628032,628034,628036-628043,628045-628064,628066-628713,628715-629551,629553-629737,629739-629741,629743-629754,629756-629820,629822-629828,629830,629833-629836,629838-629848,629850-629864,629866-630159,630161-630163,630165-633113,633115-633117,633119-633125,633127-633150,633152-633168,633170-633204,633206-633504,633506-633546,633549-634317,634319-634370,634373-634616,634618,634620-634629,634631-636750,636752-636755,636757-636785,636787-636789,636791-637188,637190-637592,637594,637596-637597,637599,637602-637869,637871-638784,638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-640056,640058-642557 via svnmerge from

https://svn.apache.org/repos/asf/poi/trunk

........
  r639918 | josh | 2008-03-21 23:47:51 +0000 (Fri, 21 Mar 2008) | 1 line
  
  sort to int conversion sign extension fix
........
  r640711 | josh | 2008-03-25 06:18:33 +0000 (Tue, 25 Mar 2008) | 1 line
  
  Added class javadoc.  Patch 30311 from Dmtriy.
........
  r641157 | josh | 2008-03-26 05:29:08 +0000 (Wed, 26 Mar 2008) | 1 line
  
  more javadoc + clean-up from Dmitriy (bug 30311 att 21711)
........
  r641185 | josh | 2008-03-26 07:32:28 +0000 (Wed, 26 Mar 2008) | 1 line
  
  patch 44675 - made POI capable of recognising var-args functions.  Some related fixes.
........
  r641796 | nick | 2008-03-27 12:48:55 +0000 (Thu, 27 Mar 2008) | 1 line
  
  Patch from Raghu from bug #44652 - Improved handling of Pictures in Word Documents
........
  r641799 | nick | 2008-03-27 12:54:32 +0000 (Thu, 27 Mar 2008) | 1 line
  
  Fix typo, and point hwpf people at the new microsoft docs
........
  r641934 | nick | 2008-03-27 18:24:39 +0000 (Thu, 27 Mar 2008) | 1 line
  
  Add failing (but disabled) test from bug #44691
........
  r641964 | josh | 2008-03-27 20:03:29 +0000 (Thu, 27 Mar 2008) | 1 line
  
  fixes for ExternalNameRecord serialisation bug #44691
........
  r641967 | josh | 2008-03-27 20:15:13 +0000 (Thu, 27 Mar 2008) | 1 line
  
  annotated previous changelist(641964) with wrong buzilla number.  Previous changes were for bug #44695.
........
  r641996 | josh | 2008-03-27 21:54:21 +0000 (Thu, 27 Mar 2008) | 1 line
  
  (real) fix for  bug #44691. Modified Pmt.java to allow for 3 arguments.  Added TestPmt junit.
........
  r642231 | nick | 2008-03-28 13:35:37 +0000 (Fri, 28 Mar 2008) | 1 line
  
  Add test to show that bug #44693 is incorrect
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@642560 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-03-29 17:19:09 +00:00
parent 356410c13c
commit ddb5f1133f
40 changed files with 2797 additions and 1462 deletions

View File

@ -70,7 +70,7 @@ under the License.
<property name="forrest.home" value="${env.FORREST_HOME}"/> <property name="forrest.home" value="${env.FORREST_HOME}"/>
<!-- Main: --> <!-- Main: -->
<property name="main.resource1.dir" value="src/resources/fontmetrics"/> <property name="main.resource1.dir" value="src/resources/main"/>
<property name="main.src" location="src/java"/> <property name="main.src" location="src/java"/>
<property name="main.src.test" location="src/testcases"/> <property name="main.src.test" location="src/testcases"/>
<property name="main.documentation" value="src/documentation"/> <property name="main.documentation" value="src/documentation"/>

View File

@ -36,6 +36,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.1-beta1" date="2008-??-??"> <release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>
<action dev="POI-DEVELOPERS" type="fix">44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits</action> <action dev="POI-DEVELOPERS" type="fix">44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits</action>
<action dev="POI-DEVELOPERS" type="fix">44627 - Improve the thread safety of POILogFactory</action> <action dev="POI-DEVELOPERS" type="fix">44627 - Improve the thread safety of POILogFactory</action>
<action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action> <action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action>

View File

@ -33,8 +33,9 @@
<p>The purpose of this document is to give a brief high level overview of the <p>The purpose of this document is to give a brief high level overview of the
HWPF document format. This document does not go into in-depth technical HWPF document format. This document does not go into in-depth technical
detail and is only meant as a supplement to the Microsoft Word 97 Binary detail and is only meant as a supplement to the Microsoft Word 97-2007
File Format freely available at <link href="http://wotsit.org">Wotsit.org</link>.</p> Binary File Format freely available from
<link href="http://www.microsoft.com/interop/docs/officebinaryformats.mspx">Microsoft</link>.</p>
<p>The OLE file format is not discussed in this document. It is assumed that <p>The OLE file format is not discussed in this document. It is assumed that
the reader has a working knowledge of the POIFS API. </p> the reader has a working knowledge of the POIFS API. </p>

View File

@ -87,7 +87,7 @@
<li>anything else that seems reasonable</li> <li>anything else that seems reasonable</li>
</ul> </ul>
<p>When you start start coding, you will not yet have write access to the <p>When you start coding, you will not yet have write access to the
CVS repository. Please submit your patches to <link CVS repository. Please submit your patches to <link
href="http://issues.apache.org/">Bugzilla</link> and nag <link href="http://issues.apache.org/">Bugzilla</link> and nag <link
href="mailto:klute@apache.org">Rainer Klute</link> until he commits href="mailto:klute@apache.org">Rainer Klute</link> until he commits

View File

@ -33,6 +33,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.1-beta1" date="2008-??-??"> <release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>
<action dev="POI-DEVELOPERS" type="fix">44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits</action> <action dev="POI-DEVELOPERS" type="fix">44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits</action>
<action dev="POI-DEVELOPERS" type="fix">44627 - Improve the thread safety of POILogFactory</action> <action dev="POI-DEVELOPERS" type="fix">44627 - Improve the thread safety of POILogFactory</action>
<action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action> <action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action>

View File

@ -25,6 +25,8 @@ import java.util.regex.Pattern;
//import PTG's .. since we need everything, import * //import PTG's .. since we need everything, import *
import org.apache.poi.hssf.record.formula.*; import org.apache.poi.hssf.record.formula.*;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
@ -369,7 +371,23 @@ public final class FormulaParser {
*/ */
private AbstractFunctionPtg getFunction(String name, int numArgs, List argumentPointers) { private AbstractFunctionPtg getFunction(String name, int numArgs, List argumentPointers) {
AbstractFunctionPtg retval = new FuncVarPtg(name, (byte)numArgs); boolean isVarArgs;
int funcIx;
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase());
if(fm == null) {
// must be external function
isVarArgs = true;
funcIx = FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL;
} else {
isVarArgs = !fm.hasFixedArgsLength();
funcIx = fm.getIndex();
}
AbstractFunctionPtg retval;
if(isVarArgs) {
retval = new FuncVarPtg(name, (byte)numArgs);
} else {
retval = new FuncPtg(funcIx, (byte)numArgs);
}
if (!name.equals(AbstractFunctionPtg.FUNCTION_NAME_IF)) { if (!name.equals(AbstractFunctionPtg.FUNCTION_NAME_IF)) {
// early return for everything else besides IF() // early return for everything else besides IF()
return retval; return retval;
@ -969,6 +987,10 @@ end;
// tAttrSpace comes *before* the operand it applies to, which may be consistent // tAttrSpace comes *before* the operand it applies to, which may be consistent
// with how the formula text appears but is against the RPN ordering assumed here // with how the formula text appears but is against the RPN ordering assumed here
} }
if (attrPtg.isSemiVolatile()) {
// similar to tAttrSpace - RPN is violated
continue;
}
} }
final OperationPtg o = (OperationPtg) ptg; final OperationPtg o = (OperationPtg) ptg;
@ -979,7 +1001,7 @@ end;
if(stack.isEmpty()) { if(stack.isEmpty()) {
String msg = "Too few arguments suppled to operation token (" String msg = "Too few arguments suppled to operation token ("
+ o.getClass().getName() + "). Expected (" + nOperands + o.getClass().getName() + "). Expected (" + nOperands
+ ") operands but got (" + (nOperands - j + 1) + ")"; + ") operands but got (" + (nOperands - j - 1) + ")";
throw new IllegalStateException(msg); throw new IllegalStateException(msg);
} }
operands[j] = (String) stack.pop(); operands[j] = (String) stack.pop();

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.List;
import java.util.Stack; import java.util.Stack;
import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ptg;
@ -27,153 +26,160 @@ import org.apache.poi.util.StringUtil;
/** /**
* EXTERNALNAME<p/> * EXTERNALNAME<p/>
* *
* @author josh micich * @author Josh Micich
*/ */
public final class ExternalNameRecord extends Record { public final class ExternalNameRecord extends Record {
public final static short sid = 0x23; // as per BIFF8. (some old versions used 0x223) public final static short sid = 0x23; // as per BIFF8. (some old versions used 0x223)
private static final int OPT_BUILTIN_NAME = 0x0001;
private static final int OPT_AUTOMATIC_LINK = 0x0002;
private static final int OPT_PICTURE_LINK = 0x0004;
private static final int OPT_STD_DOCUMENT_NAME = 0x0008;
private static final int OPT_OLE_LINK = 0x0010;
// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;
private static final int OPT_BUILTIN_NAME = 0x0001; private short field_1_option_flag;
private static final int OPT_AUTOMATIC_LINK = 0x0002; private short field_2_index;
private static final int OPT_PICTURE_LINK = 0x0004; private short field_3_not_used;
private static final int OPT_STD_DOCUMENT_NAME = 0x0008; private String field_4_name;
private static final int OPT_OLE_LINK = 0x0010; private Ptg[] field_5_name_definition; // TODO - junits for name definition field
// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
private static final int OPT_ICONIFIED_PICTURE_LINK = 0x8000;
public ExternalNameRecord(RecordInputStream in) {
private short field_1_option_flag; super(in);
private short field_2_index; }
private short field_3_not_used;
private String field_4_name;
private Stack field_5_name_definition;
public ExternalNameRecord(RecordInputStream in) {
super(in);
}
/** /**
* Convenience Function to determine if the name is a built-in name * Convenience Function to determine if the name is a built-in name
*/ */
public boolean isBuiltInName() { public boolean isBuiltInName() {
return (field_1_option_flag & OPT_BUILTIN_NAME) != 0; return (field_1_option_flag & OPT_BUILTIN_NAME) != 0;
}
/**
* For OLE and DDE, links can be either 'automatic' or 'manual'
*/
public boolean isAutomaticLink() {
return (field_1_option_flag & OPT_AUTOMATIC_LINK) != 0;
}
/**
* only for OLE and DDE
*/
public boolean isPicureLink() {
return (field_1_option_flag & OPT_PICTURE_LINK) != 0;
}
/**
* DDE links only. If <code>true</code>, this denotes the 'StdDocumentName'
*/
public boolean isStdDocumentNameIdentifier() {
return (field_1_option_flag & OPT_STD_DOCUMENT_NAME) != 0;
}
public boolean isOLELink() {
return (field_1_option_flag & OPT_OLE_LINK) != 0;
}
public boolean isIconifiedPictureLink() {
return (field_1_option_flag & OPT_ICONIFIED_PICTURE_LINK) != 0;
}
/**
* @return the standard String representation of this name
*/
public String getText() {
return field_4_name;
} }
/**
* For OLE and DDE, links can be either 'automatic' or 'manual'
*/
public boolean isAutomaticLink() {
return (field_1_option_flag & OPT_AUTOMATIC_LINK) != 0;
}
/**
* only for OLE and DDE
*/
public boolean isPicureLink() {
return (field_1_option_flag & OPT_PICTURE_LINK) != 0;
}
/**
* DDE links only. If <code>true</code>, this denotes the 'StdDocumentName'
*/
public boolean isStdDocumentNameIdentifier() {
return (field_1_option_flag & OPT_STD_DOCUMENT_NAME) != 0;
}
public boolean isOLELink() {
return (field_1_option_flag & OPT_OLE_LINK) != 0;
}
public boolean isIconifiedPictureLink() {
return (field_1_option_flag & OPT_ICONIFIED_PICTURE_LINK) != 0;
}
/**
* @return the standard String representation of this name
*/
public String getText() {
return field_4_name;
}
/** /**
* called by constructor, should throw runtime exception in the event of a * called by constructor, should throw runtime exception in the event of a
* record passed with a differing ID. * record passed with a differing ID.
* *
* @param id alleged id for this record * @param id alleged id for this record
*/ */
protected void validateSid(short id) { protected void validateSid(short id) {
if (id != sid) { if (id != sid) {
throw new RecordFormatException("NOT A valid ExternalName RECORD"); throw new RecordFormatException("NOT A valid ExternalName RECORD");
} }
} }
private int getDataSize(){ private int getDataSize(){
return 2 + 2 + field_4_name.length() + 2 + getNameDefinitionSize(); return 3 * 2 // 3 short fields
} + 2 + field_4_name.length() // nameLen and name
+ 2 + getNameDefinitionSize(); // nameDefLen and nameDef
}
/** /**
* called by the class that is responsible for writing this sucker. * called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a * Subclasses should implement this so that their data is passed back in a
* byte array. * byte array.
* *
* @param offset to begin writing at * @param offset to begin writing at
* @param data byte array containing instance data * @param data byte array containing instance data
* @return number of bytes written * @return number of bytes written
*/ */
public int serialize( int offset, byte[] data ) { public int serialize( int offset, byte[] data ) {
// TODO - junit tests int dataSize = getDataSize();
int dataSize = getDataSize();
LittleEndian.putShort( data, 0 + offset, sid ); LittleEndian.putShort( data, 0 + offset, sid );
LittleEndian.putShort( data, 2 + offset, (short) dataSize ); LittleEndian.putShort( data, 2 + offset, (short) dataSize );
LittleEndian.putShort( data, 4 + offset, field_1_option_flag ); LittleEndian.putShort( data, 4 + offset, field_1_option_flag );
LittleEndian.putShort( data, 6 + offset, field_2_index ); LittleEndian.putShort( data, 6 + offset, field_2_index );
LittleEndian.putShort( data, 8 + offset, field_3_not_used ); LittleEndian.putShort( data, 8 + offset, field_3_not_used );
short nameLen = (short) field_4_name.length(); short nameLen = (short) field_4_name.length();
LittleEndian.putShort( data, 10 + offset, nameLen ); LittleEndian.putShort( data, 10 + offset, nameLen );
StringUtil.putCompressedUnicode( field_4_name, data, 10 + offset ); StringUtil.putCompressedUnicode( field_4_name, data, 12 + offset );
short defLen = (short) getNameDefinitionSize(); short defLen = (short) getNameDefinitionSize();
LittleEndian.putShort( data, 12 + nameLen + offset, defLen ); LittleEndian.putShort( data, 12 + nameLen + offset, defLen );
Ptg.serializePtgStack(field_5_name_definition, data, 12 + nameLen + offset ); Ptg.serializePtgStack(toStack(field_5_name_definition), data, 14 + nameLen + offset );
return dataSize + 4; return dataSize + 4;
} }
private int getNameDefinitionSize() { private int getNameDefinitionSize() {
int result = 0; int result = 0;
List list = field_5_name_definition; for (int i = 0; i < field_5_name_definition.length; i++) {
result += field_5_name_definition[i].getSize();
for (int k = 0; k < list.size(); k++) }
{ return result;
Ptg ptg = ( Ptg ) list.get(k); }
result += ptg.getSize();
}
return result;
}
public int getRecordSize(){ public int getRecordSize(){
return 6 + 2 + field_4_name.length() + 2 + getNameDefinitionSize(); return 4 + getDataSize();
} }
protected void fillFields(RecordInputStream in) { protected void fillFields(RecordInputStream in) {
field_1_option_flag = in.readShort(); field_1_option_flag = in.readShort();
field_2_index = in.readShort(); field_2_index = in.readShort();
field_3_not_used = in.readShort(); field_3_not_used = in.readShort();
short nameLength = in.readShort(); short nameLength = in.readShort();
field_4_name = in.readCompressedUnicode(nameLength); field_4_name = in.readCompressedUnicode(nameLength);
short formulaLen = in.readShort(); short formulaLen = in.readShort();
field_5_name_definition = Ptg.createParsedExpressionTokens(formulaLen, in); field_5_name_definition = toPtgArray(Ptg.createParsedExpressionTokens(formulaLen, in));
} }
public short getSid() { private static Ptg[] toPtgArray(Stack s) {
return sid; Ptg[] result = new Ptg[s.size()];
} s.toArray(result);
return result;
}
private static Stack toStack(Ptg[] ptgs) {
Stack result = new Stack();
for (int i = 0; i < ptgs.length; i++) {
result.push(ptgs[i]);
}
return result;
}
public String toString() { public short getSid() {
StringBuffer sb = new StringBuffer(); return sid;
sb.append(getClass().getName()).append(" [EXTERNALNAME "); }
sb.append(" ").append(field_4_name);
sb.append(" ix=").append(field_2_index); public String toString() {
sb.append("]"); StringBuffer sb = new StringBuffer();
return sb.toString(); sb.append(getClass().getName()).append(" [EXTERNALNAME ");
} sb.append(" ").append(field_4_name);
sb.append(" ix=").append(field_2_index);
sb.append("]");
return sb.toString();
}
} }

View File

@ -35,53 +35,54 @@ import org.apache.poi.util.POILogger;
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
* *
*/ */
public class CFRecordsAggregate extends Record public final class CFRecordsAggregate extends Record
{ {
public final static short sid = -2008; public final static short sid = -2008; // not a real BIFF record
private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class); private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
private CFHeaderRecord header; private CFHeaderRecord header;
// List of CFRuleRecord objects // List of CFRuleRecord objects
private List rules; private final List rules;
public CFRecordsAggregate() public CFRecordsAggregate()
{ {
header = null; header = null;
rules = new ArrayList(3); rules = new ArrayList(3);
} }
/** /**
* Create CFRecordsAggregate from a list of CF Records * Create CFRecordsAggregate from a list of CF Records
* @param recs - list of {@link Record} objects * @param recs - list of {@link Record} objects
* @param offset - position of {@link CFHeaderRecord} object in the list of Record objects * @param offset - position of {@link CFHeaderRecord} object in the list of Record objects
* @return CFRecordsAggregate object * @return CFRecordsAggregate object
*/ */
public static CFRecordsAggregate createCFAggregate(List recs, int offset) public static CFRecordsAggregate createCFAggregate(List recs, int pOffset)
{ {
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
int count = 0; int offset = pOffset;
Record rec = ( Record ) recs.get(offset++); CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
if (rec.getSid() == CFHeaderRecord.sid) Record rec = ( Record ) recs.get(offset++);
{
records.add(rec);
cfRecords.header = (CFHeaderRecord)rec;
int nRules = cfRecords.header.getNumberOfConditionalFormats(); if (rec.getSid() == CFHeaderRecord.sid)
int rulesCount = 0; {
while( offset<recs.size() && records.add(rec);
(rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid && cfRecords.header = (CFHeaderRecord)rec;
rec instanceof CFRuleRecord &&
rulesCount++ < nRules int nRules = cfRecords.header.getNumberOfConditionalFormats();
) int rulesCount = 0;
{ while( offset<recs.size() &&
records.add(rec); (rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
cfRecords.rules.add(rec); rec instanceof CFRuleRecord &&
} rulesCount++ < nRules
)
{
records.add(rec);
cfRecords.rules.add(rec);
}
if (nRules != cfRecords.rules.size()) if (nRules != cfRecords.rules.size())
{ {
@ -93,30 +94,30 @@ public class CFRecordsAggregate extends Record
cfRecords.header.setNumberOfConditionalFormats(nRules); cfRecords.header.setNumberOfConditionalFormats(nRules);
} }
} }
return cfRecords; return cfRecords;
} }
/** /**
* Create a deep clone of the record * Create a deep clone of the record
* @return * @return
*/ */
public CFRecordsAggregate cloneCFAggregate() public CFRecordsAggregate cloneCFAggregate()
{ {
ArrayList records = new ArrayList(this.rules.size()+1); ArrayList records = new ArrayList(this.rules.size()+1);
records.add(this.header.clone()); records.add(this.header.clone());
for (int i=0; i<this.rules.size();i++) for (int i=0; i<this.rules.size();i++)
{ {
Record rec = (Record)((Record)this.rules.get(i)).clone(); Record rec = (Record)((Record)this.rules.get(i)).clone();
records.add(rec); records.add(rec);
} }
return createCFAggregate(records, 0); return createCFAggregate(records, 0);
} }
/** You never fill an aggregate */ /** You never fill an aggregate */
protected void fillFields(RecordInputStream in) protected void fillFields(RecordInputStream in)
{ {
} }
@ -126,31 +127,31 @@ public class CFRecordsAggregate extends Record
return sid; return sid;
} }
/** /**
* called by the class that is responsible for writing this sucker. * called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a * Subclasses should implement this so that their data is passed back in a
* byte array. * byte array.
* *
* @param offset to begin writing at * @param offset to begin writing at
* @param data byte array containing instance data * @param data byte array containing instance data
* @return number of bytes written * @return number of bytes written
*/ */
public int serialize(int offset, byte[] data) public int serialize(int offset, byte[] data)
{ {
int pos = offset; int pos = offset;
if( header != null && rules.size()>0 ) if( header != null && rules.size()>0 )
{ {
header.setNumberOfConditionalFormats(rules.size()); header.setNumberOfConditionalFormats(rules.size());
pos += (( Record ) header).serialize(pos, data); pos += (( Record ) header).serialize(pos, data);
for(Iterator itr = rules.iterator(); itr.hasNext();) for(Iterator itr = rules.iterator(); itr.hasNext();)
{ {
pos += (( Record ) itr.next()).serialize(pos, data); pos += (( Record ) itr.next()).serialize(pos, data);
} }
} }
return pos - offset; return pos - offset;
} }
protected void validateSid(short id) protected void validateSid(short id)
@ -179,20 +180,20 @@ public class CFRecordsAggregate extends Record
*/ */
public int getRecordSize() public int getRecordSize()
{ {
int size = 0; int size = 0;
if( header != null) if( header != null)
{ {
size += header.getRecordSize(); size += header.getRecordSize();
} }
if( rules != null) if( rules != null)
{ {
for(Iterator irecs = rules.iterator(); irecs.hasNext(); ) for(Iterator irecs = rules.iterator(); irecs.hasNext(); )
{ {
size += (( Record ) irecs.next()).getRecordSize(); size += (( Record ) irecs.next()).getRecordSize();
} }
} }
return size; return size;
} }
/** /**
* String representation of CFRecordsAggregate * String representation of CFRecordsAggregate
@ -206,19 +207,15 @@ public class CFRecordsAggregate extends Record
{ {
buffer.append(header.toString()); buffer.append(header.toString());
} }
if( rules != null ) for(int i=0; i<rules.size(); i++)
{ {
for(int i=0; i<rules.size(); i++) CFRuleRecord cfRule = (CFRuleRecord)rules.get(i);
if(cfRule!=null)
{ {
CFRuleRecord cfRule = (CFRuleRecord)rules.get(i); buffer.append(cfRule.toString());
if(cfRule!=null)
{
buffer.append(cfRule.toString());
}
} }
} }
buffer.append("[/CF]\n"); buffer.append("[/CF]\n");
return buffer.toString(); return buffer.toString();
} }
} }

View File

@ -17,8 +17,9 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.BinaryTree;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/** /**
@ -37,8 +38,6 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
/** All external functions have function index 255 */ /** All external functions have function index 255 */
private static final short FUNCTION_INDEX_EXTERNAL = 255; private static final short FUNCTION_INDEX_EXTERNAL = 255;
private static BinaryTree map = produceHash();
protected static Object[][] functionData = produceFunctionData();
protected byte returnClass; protected byte returnClass;
protected byte[] paramClass; protected byte[] paramClass;
@ -46,14 +45,11 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
protected short field_2_fnc_index; protected short field_2_fnc_index;
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer sb = new StringBuffer(64);
buffer sb.append(getClass().getName()).append(" [");
.append("<FunctionPtg>").append("\n") sb.append(field_2_fnc_index).append(" ").append(field_1_num_args);
.append(" field_1_num_args=").append(field_1_num_args).append("\n") sb.append("]");
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n") return sb.toString();
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
} }
public int getType() { public int getType() {
@ -117,11 +113,19 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
* <code>false</code> if the name should be assumed to be an external function. * <code>false</code> if the name should be assumed to be an external function.
*/ */
public static final boolean isInternalFunctionName(String name) { public static final boolean isInternalFunctionName(String name) {
return map.containsValue(name.toUpperCase()); short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
return ix >= 0;
} }
protected String lookupName(short index) { protected String lookupName(short index) {
return ((String)map.get(new Integer(index))); if(index == FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL) {
return "#external#";
}
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(index);
if(fm == null) {
throw new RuntimeException("bad function index (" + index + ")");
}
return fm.getName();
} }
/** /**
@ -131,729 +135,11 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
* @return the standard worksheet function index if found, otherwise <tt>FUNCTION_INDEX_EXTERNAL</tt> * @return the standard worksheet function index if found, otherwise <tt>FUNCTION_INDEX_EXTERNAL</tt>
*/ */
protected static short lookupIndex(String name) { protected static short lookupIndex(String name) {
Integer index = (Integer) map.getKeyForValue(name.toUpperCase()); short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
if (index != null) return index.shortValue(); if (ix < 0) {
return FUNCTION_INDEX_EXTERNAL; return FUNCTION_INDEX_EXTERNAL;
} }
return ix;
/**
* Produces the function table hashmap
*/
private static BinaryTree produceHash() {
BinaryTree dmap = new BinaryTree();
dmap.put(new Integer(0),"COUNT");
dmap.put(new Integer(1),FUNCTION_NAME_IF);
dmap.put(new Integer(2),"ISNA");
dmap.put(new Integer(3),"ISERROR");
dmap.put(new Integer(4),"SUM");
dmap.put(new Integer(5),"AVERAGE");
dmap.put(new Integer(6),"MIN");
dmap.put(new Integer(7),"MAX");
dmap.put(new Integer(8),"ROW");
dmap.put(new Integer(9),"COLUMN");
dmap.put(new Integer(10),"NA");
dmap.put(new Integer(11),"NPV");
dmap.put(new Integer(12),"STDEV");
dmap.put(new Integer(13),"DOLLAR");
dmap.put(new Integer(14),"FIXED");
dmap.put(new Integer(15),"SIN");
dmap.put(new Integer(16),"COS");
dmap.put(new Integer(17),"TAN");
dmap.put(new Integer(18),"ATAN");
dmap.put(new Integer(19),"PI");
dmap.put(new Integer(20),"SQRT");
dmap.put(new Integer(21),"EXP");
dmap.put(new Integer(22),"LN");
dmap.put(new Integer(23),"LOG10");
dmap.put(new Integer(24),"ABS");
dmap.put(new Integer(25),"INT");
dmap.put(new Integer(26),"SIGN");
dmap.put(new Integer(27),"ROUND");
dmap.put(new Integer(28),"LOOKUP");
dmap.put(new Integer(29),"INDEX");
dmap.put(new Integer(30),"REPT");
dmap.put(new Integer(31),"MID");
dmap.put(new Integer(32),"LEN");
dmap.put(new Integer(33),"VALUE");
dmap.put(new Integer(34),"TRUE");
dmap.put(new Integer(35),"FALSE");
dmap.put(new Integer(36),"AND");
dmap.put(new Integer(37),"OR");
dmap.put(new Integer(38),"NOT");
dmap.put(new Integer(39),"MOD");
dmap.put(new Integer(40),"DCOUNT");
dmap.put(new Integer(41),"DSUM");
dmap.put(new Integer(42),"DAVERAGE");
dmap.put(new Integer(43),"DMIN");
dmap.put(new Integer(44),"DMAX");
dmap.put(new Integer(45),"DSTDEV");
dmap.put(new Integer(46),"VAR");
dmap.put(new Integer(47),"DVAR");
dmap.put(new Integer(48),"TEXT");
dmap.put(new Integer(49),"LINEST");
dmap.put(new Integer(50),"TREND");
dmap.put(new Integer(51),"LOGEST");
dmap.put(new Integer(52),"GROWTH");
dmap.put(new Integer(53),"GOTO");
dmap.put(new Integer(54),"HALT");
dmap.put(new Integer(56),"PV");
dmap.put(new Integer(57),"FV");
dmap.put(new Integer(58),"NPER");
dmap.put(new Integer(59),"PMT");
dmap.put(new Integer(60),"RATE");
dmap.put(new Integer(61),"MIRR");
dmap.put(new Integer(62),"IRR");
dmap.put(new Integer(63),"RAND");
dmap.put(new Integer(64),"MATCH");
dmap.put(new Integer(65),"DATE");
dmap.put(new Integer(66),"TIME");
dmap.put(new Integer(67),"DAY");
dmap.put(new Integer(68),"MONTH");
dmap.put(new Integer(69),"YEAR");
dmap.put(new Integer(70),"WEEKDAY");
dmap.put(new Integer(71),"HOUR");
dmap.put(new Integer(72),"MINUTE");
dmap.put(new Integer(73),"SECOND");
dmap.put(new Integer(74),"NOW");
dmap.put(new Integer(75),"AREAS");
dmap.put(new Integer(76),"ROWS");
dmap.put(new Integer(77),"COLUMNS");
dmap.put(new Integer(78),"OFFSET");
dmap.put(new Integer(79),"ABSREF");
dmap.put(new Integer(80),"RELREF");
dmap.put(new Integer(81),"ARGUMENT");
dmap.put(new Integer(82),"SEARCH");
dmap.put(new Integer(83),"TRANSPOSE");
dmap.put(new Integer(84),"ERROR");
dmap.put(new Integer(85),"STEP");
dmap.put(new Integer(86),"TYPE");
dmap.put(new Integer(87),"ECHO");
dmap.put(new Integer(88),"SETNAME");
dmap.put(new Integer(89),"CALLER");
dmap.put(new Integer(90),"DEREF");
dmap.put(new Integer(91),"WINDOWS");
dmap.put(new Integer(92),"SERIES");
dmap.put(new Integer(93),"DOCUMENTS");
dmap.put(new Integer(94),"ACTIVECELL");
dmap.put(new Integer(95),"SELECTION");
dmap.put(new Integer(96),"RESULT");
dmap.put(new Integer(97),"ATAN2");
dmap.put(new Integer(98),"ASIN");
dmap.put(new Integer(99),"ACOS");
dmap.put(new Integer(100),"CHOOSE");
dmap.put(new Integer(101),"HLOOKUP");
dmap.put(new Integer(102),"VLOOKUP");
dmap.put(new Integer(103),"LINKS");
dmap.put(new Integer(104),"INPUT");
dmap.put(new Integer(105),"ISREF");
dmap.put(new Integer(106),"GETFORMULA");
dmap.put(new Integer(107),"GETNAME");
dmap.put(new Integer(108),"SETVALUE");
dmap.put(new Integer(109),"LOG");
dmap.put(new Integer(110),"EXEC");
dmap.put(new Integer(111),"CHAR");
dmap.put(new Integer(112),"LOWER");
dmap.put(new Integer(113),"UPPER");
dmap.put(new Integer(114),"PROPER");
dmap.put(new Integer(115),"LEFT");
dmap.put(new Integer(116),"RIGHT");
dmap.put(new Integer(117),"EXACT");
dmap.put(new Integer(118),"TRIM");
dmap.put(new Integer(119),"REPLACE");
dmap.put(new Integer(120),"SUBSTITUTE");
dmap.put(new Integer(121),"CODE");
dmap.put(new Integer(122),"NAMES");
dmap.put(new Integer(123),"DIRECTORY");
dmap.put(new Integer(124),"FIND");
dmap.put(new Integer(125),"CELL");
dmap.put(new Integer(126),"ISERR");
dmap.put(new Integer(127),"ISTEXT");
dmap.put(new Integer(128),"ISNUMBER");
dmap.put(new Integer(129),"ISBLANK");
dmap.put(new Integer(130),"T");
dmap.put(new Integer(131),"N");
dmap.put(new Integer(132),"FOPEN");
dmap.put(new Integer(133),"FCLOSE");
dmap.put(new Integer(134),"FSIZE");
dmap.put(new Integer(135),"FREADLN");
dmap.put(new Integer(136),"FREAD");
dmap.put(new Integer(137),"FWRITELN");
dmap.put(new Integer(138),"FWRITE");
dmap.put(new Integer(139),"FPOS");
dmap.put(new Integer(140),"DATEVALUE");
dmap.put(new Integer(141),"TIMEVALUE");
dmap.put(new Integer(142),"SLN");
dmap.put(new Integer(143),"SYD");
dmap.put(new Integer(144),"DDB");
dmap.put(new Integer(145),"GETDEF");
dmap.put(new Integer(146),"REFTEXT");
dmap.put(new Integer(147),"TEXTREF");
dmap.put(new Integer(148),"INDIRECT");
dmap.put(new Integer(149),"REGISTER");
dmap.put(new Integer(150),"CALL");
dmap.put(new Integer(151),"ADDBAR");
dmap.put(new Integer(152),"ADDMENU");
dmap.put(new Integer(153),"ADDCOMMAND");
dmap.put(new Integer(154),"ENABLECOMMAND");
dmap.put(new Integer(155),"CHECKCOMMAND");
dmap.put(new Integer(156),"RENAMECOMMAND");
dmap.put(new Integer(157),"SHOWBAR");
dmap.put(new Integer(158),"DELETEMENU");
dmap.put(new Integer(159),"DELETECOMMAND");
dmap.put(new Integer(160),"GETCHARTITEM");
dmap.put(new Integer(161),"DIALOGBOX");
dmap.put(new Integer(162),"CLEAN");
dmap.put(new Integer(163),"MDETERM");
dmap.put(new Integer(164),"MINVERSE");
dmap.put(new Integer(165),"MMULT");
dmap.put(new Integer(166),"FILES");
dmap.put(new Integer(167),"IPMT");
dmap.put(new Integer(168),"PPMT");
dmap.put(new Integer(169),"COUNTA");
dmap.put(new Integer(170),"CANCELKEY");
dmap.put(new Integer(175),"INITIATE");
dmap.put(new Integer(176),"REQUEST");
dmap.put(new Integer(177),"POKE");
dmap.put(new Integer(178),"EXECUTE");
dmap.put(new Integer(179),"TERMINATE");
dmap.put(new Integer(180),"RESTART");
dmap.put(new Integer(181),"HELP");
dmap.put(new Integer(182),"GETBAR");
dmap.put(new Integer(183),"PRODUCT");
dmap.put(new Integer(184),"FACT");
dmap.put(new Integer(185),"GETCELL");
dmap.put(new Integer(186),"GETWORKSPACE");
dmap.put(new Integer(187),"GETWINDOW");
dmap.put(new Integer(188),"GETDOCUMENT");
dmap.put(new Integer(189),"DPRODUCT");
dmap.put(new Integer(190),"ISNONTEXT");
dmap.put(new Integer(191),"GETNOTE");
dmap.put(new Integer(192),"NOTE");
dmap.put(new Integer(193),"STDEVP");
dmap.put(new Integer(194),"VARP");
dmap.put(new Integer(195),"DSTDEVP");
dmap.put(new Integer(196),"DVARP");
dmap.put(new Integer(197),"TRUNC");
dmap.put(new Integer(198),"ISLOGICAL");
dmap.put(new Integer(199),"DCOUNTA");
dmap.put(new Integer(200),"DELETEBAR");
dmap.put(new Integer(201),"UNREGISTER");
dmap.put(new Integer(204),"USDOLLAR");
dmap.put(new Integer(205),"FINDB");
dmap.put(new Integer(206),"SEARCHB");
dmap.put(new Integer(207),"REPLACEB");
dmap.put(new Integer(208),"LEFTB");
dmap.put(new Integer(209),"RIGHTB");
dmap.put(new Integer(210),"MIDB");
dmap.put(new Integer(211),"LENB");
dmap.put(new Integer(212),"ROUNDUP");
dmap.put(new Integer(213),"ROUNDDOWN");
dmap.put(new Integer(214),"ASC");
dmap.put(new Integer(215),"DBCS");
dmap.put(new Integer(216),"RANK");
dmap.put(new Integer(219),"ADDRESS");
dmap.put(new Integer(220),"DAYS360");
dmap.put(new Integer(221),"TODAY");
dmap.put(new Integer(222),"VDB");
dmap.put(new Integer(227),"MEDIAN");
dmap.put(new Integer(228),"SUMPRODUCT");
dmap.put(new Integer(229),"SINH");
dmap.put(new Integer(230),"COSH");
dmap.put(new Integer(231),"TANH");
dmap.put(new Integer(232),"ASINH");
dmap.put(new Integer(233),"ACOSH");
dmap.put(new Integer(234),"ATANH");
dmap.put(new Integer(235),"DGET");
dmap.put(new Integer(236),"CREATEOBJECT");
dmap.put(new Integer(237),"VOLATILE");
dmap.put(new Integer(238),"LASTERROR");
dmap.put(new Integer(239),"CUSTOMUNDO");
dmap.put(new Integer(240),"CUSTOMREPEAT");
dmap.put(new Integer(241),"FORMULACONVERT");
dmap.put(new Integer(242),"GETLINKINFO");
dmap.put(new Integer(243),"TEXTBOX");
dmap.put(new Integer(244),"INFO");
dmap.put(new Integer(245),"GROUP");
dmap.put(new Integer(246),"GETOBJECT");
dmap.put(new Integer(247),"DB");
dmap.put(new Integer(248),"PAUSE");
dmap.put(new Integer(250),"RESUME");
dmap.put(new Integer(252),"FREQUENCY");
dmap.put(new Integer(253),"ADDTOOLBAR");
dmap.put(new Integer(254),"DELETETOOLBAR");
dmap.put(new Integer(FUNCTION_INDEX_EXTERNAL),"externalflag");
dmap.put(new Integer(256),"RESETTOOLBAR");
dmap.put(new Integer(257),"EVALUATE");
dmap.put(new Integer(258),"GETTOOLBAR");
dmap.put(new Integer(259),"GETTOOL");
dmap.put(new Integer(260),"SPELLINGCHECK");
dmap.put(new Integer(261),"ERROR.TYPE");
dmap.put(new Integer(262),"APPTITLE");
dmap.put(new Integer(263),"WINDOWTITLE");
dmap.put(new Integer(264),"SAVETOOLBAR");
dmap.put(new Integer(265),"ENABLETOOL");
dmap.put(new Integer(266),"PRESSTOOL");
dmap.put(new Integer(267),"REGISTERID");
dmap.put(new Integer(268),"GETWORKBOOK");
dmap.put(new Integer(269),"AVEDEV");
dmap.put(new Integer(270),"BETADIST");
dmap.put(new Integer(271),"GAMMALN");
dmap.put(new Integer(272),"BETAINV");
dmap.put(new Integer(273),"BINOMDIST");
dmap.put(new Integer(274),"CHIDIST");
dmap.put(new Integer(275),"CHIINV");
dmap.put(new Integer(276),"COMBIN");
dmap.put(new Integer(277),"CONFIDENCE");
dmap.put(new Integer(278),"CRITBINOM");
dmap.put(new Integer(279),"EVEN");
dmap.put(new Integer(280),"EXPONDIST");
dmap.put(new Integer(281),"FDIST");
dmap.put(new Integer(282),"FINV");
dmap.put(new Integer(283),"FISHER");
dmap.put(new Integer(284),"FISHERINV");
dmap.put(new Integer(285),"FLOOR");
dmap.put(new Integer(286),"GAMMADIST");
dmap.put(new Integer(287),"GAMMAINV");
dmap.put(new Integer(288),"CEILING");
dmap.put(new Integer(289),"HYPGEOMDIST");
dmap.put(new Integer(290),"LOGNORMDIST");
dmap.put(new Integer(291),"LOGINV");
dmap.put(new Integer(292),"NEGBINOMDIST");
dmap.put(new Integer(293),"NORMDIST");
dmap.put(new Integer(294),"NORMSDIST");
dmap.put(new Integer(295),"NORMINV");
dmap.put(new Integer(296),"NORMSINV");
dmap.put(new Integer(297),"STANDARDIZE");
dmap.put(new Integer(298),"ODD");
dmap.put(new Integer(299),"PERMUT");
dmap.put(new Integer(300),"POISSON");
dmap.put(new Integer(301),"TDIST");
dmap.put(new Integer(302),"WEIBULL");
dmap.put(new Integer(303),"SUMXMY2");
dmap.put(new Integer(304),"SUMX2MY2");
dmap.put(new Integer(305),"SUMX2PY2");
dmap.put(new Integer(306),"CHITEST");
dmap.put(new Integer(307),"CORREL");
dmap.put(new Integer(308),"COVAR");
dmap.put(new Integer(309),"FORECAST");
dmap.put(new Integer(310),"FTEST");
dmap.put(new Integer(311),"INTERCEPT");
dmap.put(new Integer(312),"PEARSON");
dmap.put(new Integer(313),"RSQ");
dmap.put(new Integer(314),"STEYX");
dmap.put(new Integer(315),"SLOPE");
dmap.put(new Integer(316),"TTEST");
dmap.put(new Integer(317),"PROB");
dmap.put(new Integer(318),"DEVSQ");
dmap.put(new Integer(319),"GEOMEAN");
dmap.put(new Integer(320),"HARMEAN");
dmap.put(new Integer(321),"SUMSQ");
dmap.put(new Integer(322),"KURT");
dmap.put(new Integer(323),"SKEW");
dmap.put(new Integer(324),"ZTEST");
dmap.put(new Integer(325),"LARGE");
dmap.put(new Integer(326),"SMALL");
dmap.put(new Integer(327),"QUARTILE");
dmap.put(new Integer(328),"PERCENTILE");
dmap.put(new Integer(329),"PERCENTRANK");
dmap.put(new Integer(330),"MODE");
dmap.put(new Integer(331),"TRIMMEAN");
dmap.put(new Integer(332),"TINV");
dmap.put(new Integer(334),"MOVIECOMMAND");
dmap.put(new Integer(335),"GETMOVIE");
dmap.put(new Integer(336),"CONCATENATE");
dmap.put(new Integer(337),"POWER");
dmap.put(new Integer(338),"PIVOTADDDATA");
dmap.put(new Integer(339),"GETPIVOTTABLE");
dmap.put(new Integer(340),"GETPIVOTFIELD");
dmap.put(new Integer(341),"GETPIVOTITEM");
dmap.put(new Integer(342),"RADIANS");
dmap.put(new Integer(343),"DEGREES");
dmap.put(new Integer(344),"SUBTOTAL");
dmap.put(new Integer(345),"SUMIF");
dmap.put(new Integer(346),"COUNTIF");
dmap.put(new Integer(347),"COUNTBLANK");
dmap.put(new Integer(348),"SCENARIOGET");
dmap.put(new Integer(349),"OPTIONSLISTSGET");
dmap.put(new Integer(350),"ISPMT");
dmap.put(new Integer(351),"DATEDIF");
dmap.put(new Integer(352),"DATESTRING");
dmap.put(new Integer(353),"NUMBERSTRING");
dmap.put(new Integer(354),"ROMAN");
dmap.put(new Integer(355),"OPENDIALOG");
dmap.put(new Integer(356),"SAVEDIALOG");
dmap.put(new Integer(357),"VIEWGET");
dmap.put(new Integer(358),"GETPIVOTDATA");
dmap.put(new Integer(359),"HYPERLINK");
dmap.put(new Integer(360),"PHONETIC");
dmap.put(new Integer(361),"AVERAGEA");
dmap.put(new Integer(362),"MAXA");
dmap.put(new Integer(363),"MINA");
dmap.put(new Integer(364),"STDEVPA");
dmap.put(new Integer(365),"VARPA");
dmap.put(new Integer(366),"STDEVA");
dmap.put(new Integer(367),"VARA");
return dmap;
}
private static Object[][] produceFunctionData() {
Object [][] functionData = new Object[368][3];
//return Class // Param Class //Num Params
functionData[0][0]=new Byte(Ptg.CLASS_VALUE);functionData[0][1]=new byte[] {Ptg.CLASS_REF};functionData[0][2]=new Integer(-1);
functionData[2][0]=new Byte(Ptg.CLASS_VALUE);functionData[2][1]=new byte[] {Ptg.CLASS_VALUE};functionData[2][2]=new Integer(1);
functionData[3][0]=new Byte(Ptg.CLASS_VALUE);functionData[3][1]=new byte[] {Ptg.CLASS_VALUE};functionData[3][2]=new Integer(1);
functionData[4][0]=new Byte(Ptg.CLASS_VALUE);functionData[4][1]=new byte[] {Ptg.CLASS_REF};functionData[4][2]=new Integer(-1);
functionData[5][0]=new Byte(Ptg.CLASS_VALUE);functionData[5][1]=new byte[] {Ptg.CLASS_REF};functionData[5][2]=new Integer(-1);
functionData[6][0]=new Byte(Ptg.CLASS_VALUE);functionData[6][1]=new byte[] {Ptg.CLASS_REF};functionData[6][2]=new Integer(-1);
functionData[7][0]=new Byte(Ptg.CLASS_VALUE);functionData[7][1]=new byte[] {Ptg.CLASS_REF};functionData[7][2]=new Integer(-1);
functionData[8][0]=new Byte(Ptg.CLASS_VALUE);functionData[8][1]=new byte[] {Ptg.CLASS_REF};functionData[8][2]=new Integer(-1);
functionData[9][0]=new Byte(Ptg.CLASS_VALUE);functionData[9][1]=new byte[] {Ptg.CLASS_REF};functionData[9][2]=new Integer(-1);
functionData[10][0]=new Byte(Ptg.CLASS_VALUE);functionData[10][1]=new byte[] {Ptg.CLASS_VALUE};functionData[10][2]=new Integer(0);
functionData[11][0]=new Byte(Ptg.CLASS_VALUE);functionData[11][1]=new byte[] {Ptg.CLASS_REF};functionData[11][2]=new Integer(-1);
functionData[12][0]=new Byte(Ptg.CLASS_VALUE);functionData[12][1]=new byte[] {Ptg.CLASS_REF};functionData[12][2]=new Integer(-1);
functionData[13][0]=new Byte(Ptg.CLASS_VALUE);functionData[13][1]=new byte[] {Ptg.CLASS_VALUE};functionData[13][2]=new Integer(-1);
functionData[14][0]=new Byte(Ptg.CLASS_VALUE);functionData[14][1]=new byte[] {Ptg.CLASS_VALUE};functionData[14][2]=new Integer(-1);
functionData[15][0]=new Byte(Ptg.CLASS_VALUE);functionData[15][1]=new byte[] {Ptg.CLASS_VALUE};functionData[15][2]=new Integer(1);
functionData[16][0]=new Byte(Ptg.CLASS_VALUE);functionData[16][1]=new byte[] {Ptg.CLASS_VALUE};functionData[16][2]=new Integer(1);
functionData[17][0]=new Byte(Ptg.CLASS_VALUE);functionData[17][1]=new byte[] {Ptg.CLASS_VALUE};functionData[17][2]=new Integer(1);
functionData[18][0]=new Byte(Ptg.CLASS_VALUE);functionData[18][1]=new byte[] {Ptg.CLASS_VALUE};functionData[18][2]=new Integer(1);
functionData[19][0]=new Byte(Ptg.CLASS_VALUE);functionData[19][1]=new byte[] {Ptg.CLASS_VALUE};functionData[19][2]=new Integer(0);
functionData[20][0]=new Byte(Ptg.CLASS_VALUE);functionData[20][1]=new byte[] {Ptg.CLASS_VALUE};functionData[20][2]=new Integer(1);
functionData[21][0]=new Byte(Ptg.CLASS_VALUE);functionData[21][1]=new byte[] {Ptg.CLASS_VALUE};functionData[21][2]=new Integer(1);
functionData[22][0]=new Byte(Ptg.CLASS_VALUE);functionData[22][1]=new byte[] {Ptg.CLASS_VALUE};functionData[22][2]=new Integer(1);
functionData[23][0]=new Byte(Ptg.CLASS_VALUE);functionData[23][1]=new byte[] {Ptg.CLASS_VALUE};functionData[23][2]=new Integer(1);
functionData[24][0]=new Byte(Ptg.CLASS_VALUE);functionData[24][1]=new byte[] {Ptg.CLASS_VALUE};functionData[24][2]=new Integer(1);
functionData[25][0]=new Byte(Ptg.CLASS_VALUE);functionData[25][1]=new byte[] {Ptg.CLASS_VALUE};functionData[25][2]=new Integer(1);
functionData[26][0]=new Byte(Ptg.CLASS_VALUE);functionData[26][1]=new byte[] {Ptg.CLASS_VALUE};functionData[26][2]=new Integer(1);
functionData[27][0]=new Byte(Ptg.CLASS_VALUE);functionData[27][1]=new byte[] {Ptg.CLASS_VALUE};functionData[27][2]=new Integer(2);
functionData[28][0]=new Byte(Ptg.CLASS_VALUE);functionData[28][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[28][2]=new Integer(-1);
functionData[29][0]=new Byte(Ptg.CLASS_VALUE);functionData[29][1]=new byte[] {Ptg.CLASS_REF};functionData[29][2]=new Integer(-1);
functionData[30][0]=new Byte(Ptg.CLASS_VALUE);functionData[30][1]=new byte[] {Ptg.CLASS_VALUE};functionData[30][2]=new Integer(2);
functionData[31][0]=new Byte(Ptg.CLASS_VALUE);functionData[31][1]=new byte[] {Ptg.CLASS_VALUE};functionData[31][2]=new Integer(3);
functionData[32][0]=new Byte(Ptg.CLASS_VALUE);functionData[32][1]=new byte[] {Ptg.CLASS_VALUE};functionData[32][2]=new Integer(1);
functionData[33][0]=new Byte(Ptg.CLASS_VALUE);functionData[33][1]=new byte[] {Ptg.CLASS_VALUE};functionData[33][2]=new Integer(1);
functionData[34][0]=new Byte(Ptg.CLASS_VALUE);functionData[34][1]=new byte[] {Ptg.CLASS_VALUE};functionData[34][2]=new Integer(0);
functionData[35][0]=new Byte(Ptg.CLASS_VALUE);functionData[35][1]=new byte[] {Ptg.CLASS_VALUE};functionData[35][2]=new Integer(0);
functionData[36][0]=new Byte(Ptg.CLASS_VALUE);functionData[36][1]=new byte[] {Ptg.CLASS_REF};functionData[36][2]=new Integer(-1);
functionData[37][0]=new Byte(Ptg.CLASS_VALUE);functionData[37][1]=new byte[] {Ptg.CLASS_REF};functionData[37][2]=new Integer(-1);
functionData[38][0]=new Byte(Ptg.CLASS_VALUE);functionData[38][1]=new byte[] {Ptg.CLASS_VALUE};functionData[38][2]=new Integer(1);
functionData[39][0]=new Byte(Ptg.CLASS_VALUE);functionData[39][1]=new byte[] {Ptg.CLASS_VALUE};functionData[39][2]=new Integer(2);
functionData[40][0]=new Byte(Ptg.CLASS_VALUE);functionData[40][1]=new byte[] {Ptg.CLASS_REF};functionData[40][2]=new Integer(3);
functionData[41][0]=new Byte(Ptg.CLASS_VALUE);functionData[41][1]=new byte[] {Ptg.CLASS_REF};functionData[41][2]=new Integer(3);
functionData[42][0]=new Byte(Ptg.CLASS_VALUE);functionData[42][1]=new byte[] {Ptg.CLASS_REF};functionData[42][2]=new Integer(3);
functionData[43][0]=new Byte(Ptg.CLASS_VALUE);functionData[43][1]=new byte[] {Ptg.CLASS_REF};functionData[43][2]=new Integer(3);
functionData[44][0]=new Byte(Ptg.CLASS_VALUE);functionData[44][1]=new byte[] {Ptg.CLASS_REF};functionData[44][2]=new Integer(3);
functionData[45][0]=new Byte(Ptg.CLASS_VALUE);functionData[45][1]=new byte[] {Ptg.CLASS_REF};functionData[45][2]=new Integer(3);
functionData[46][0]=new Byte(Ptg.CLASS_VALUE);functionData[46][1]=new byte[] {Ptg.CLASS_REF};functionData[46][2]=new Integer(-1);
functionData[47][0]=new Byte(Ptg.CLASS_VALUE);functionData[47][1]=new byte[] {Ptg.CLASS_REF};functionData[47][2]=new Integer(3);
functionData[48][0]=new Byte(Ptg.CLASS_VALUE);functionData[48][1]=new byte[] {Ptg.CLASS_VALUE};functionData[48][2]=new Integer(2);
functionData[49][0]=new Byte(Ptg.CLASS_VALUE);functionData[49][1]=new byte[] {Ptg.CLASS_REF};functionData[49][2]=new Integer(-1);
functionData[50][0]=new Byte(Ptg.CLASS_VALUE);functionData[50][1]=new byte[] {Ptg.CLASS_REF};functionData[50][2]=new Integer(-1);
functionData[51][0]=new Byte(Ptg.CLASS_VALUE);functionData[51][1]=new byte[] {Ptg.CLASS_REF};functionData[51][2]=new Integer(-1);
functionData[52][0]=new Byte(Ptg.CLASS_VALUE);functionData[52][1]=new byte[] {Ptg.CLASS_REF};functionData[52][2]=new Integer(-1);
functionData[56][0]=new Byte(Ptg.CLASS_VALUE);functionData[56][1]=new byte[] {Ptg.CLASS_VALUE};functionData[56][2]=new Integer(-1);
functionData[57][0]=new Byte(Ptg.CLASS_VALUE);functionData[57][1]=new byte[] {Ptg.CLASS_VALUE};functionData[57][2]=new Integer(-1);
functionData[58][0]=new Byte(Ptg.CLASS_VALUE);functionData[58][1]=new byte[] {Ptg.CLASS_VALUE};functionData[58][2]=new Integer(-1);
functionData[59][0]=new Byte(Ptg.CLASS_VALUE);functionData[59][1]=new byte[] {Ptg.CLASS_VALUE};functionData[59][2]=new Integer(-1);
functionData[60][0]=new Byte(Ptg.CLASS_VALUE);functionData[60][1]=new byte[] {Ptg.CLASS_VALUE};functionData[60][2]=new Integer(-1);
functionData[61][0]=new Byte(Ptg.CLASS_VALUE);functionData[61][1]=new byte[] {Ptg.CLASS_VALUE};functionData[61][2]=new Integer(3);
functionData[62][0]=new Byte(Ptg.CLASS_VALUE);functionData[62][1]=new byte[] {Ptg.CLASS_REF};functionData[62][2]=new Integer(-1);
functionData[63][0]=new Byte(Ptg.CLASS_VALUE);functionData[63][1]=new byte[] {Ptg.CLASS_REF};functionData[63][2]=new Integer(1);
functionData[64][0]=new Byte(Ptg.CLASS_VALUE);functionData[64][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[64][2]=new Integer(-1);
functionData[65][0]=new Byte(Ptg.CLASS_VALUE);functionData[65][1]=new byte[] {Ptg.CLASS_VALUE};functionData[65][2]=new Integer(3);
functionData[66][0]=new Byte(Ptg.CLASS_VALUE);functionData[66][1]=new byte[] {Ptg.CLASS_VALUE};functionData[66][2]=new Integer(3);
functionData[67][0]=new Byte(Ptg.CLASS_VALUE);functionData[67][1]=new byte[] {Ptg.CLASS_VALUE};functionData[67][2]=new Integer(1);
functionData[68][0]=new Byte(Ptg.CLASS_VALUE);functionData[68][1]=new byte[] {Ptg.CLASS_VALUE};functionData[68][2]=new Integer(1);
functionData[69][0]=new Byte(Ptg.CLASS_VALUE);functionData[69][1]=new byte[] {Ptg.CLASS_VALUE};functionData[69][2]=new Integer(1);
functionData[70][0]=new Byte(Ptg.CLASS_VALUE);functionData[70][1]=new byte[] {Ptg.CLASS_VALUE};functionData[70][2]=new Integer(-1);
functionData[71][0]=new Byte(Ptg.CLASS_VALUE);functionData[71][1]=new byte[] {Ptg.CLASS_VALUE};functionData[71][2]=new Integer(1);
functionData[72][0]=new Byte(Ptg.CLASS_VALUE);functionData[72][1]=new byte[] {Ptg.CLASS_VALUE};functionData[72][2]=new Integer(1);
functionData[73][0]=new Byte(Ptg.CLASS_VALUE);functionData[73][1]=new byte[] {Ptg.CLASS_VALUE};functionData[73][2]=new Integer(1);
functionData[74][0]=new Byte(Ptg.CLASS_VALUE);functionData[74][1]=new byte[] {Ptg.CLASS_REF};functionData[74][2]=new Integer(1);
functionData[75][0]=new Byte(Ptg.CLASS_VALUE);functionData[75][1]=new byte[] {Ptg.CLASS_REF};functionData[75][2]=new Integer(1);
functionData[76][0]=new Byte(Ptg.CLASS_VALUE);functionData[76][1]=new byte[] {Ptg.CLASS_REF};functionData[76][2]=new Integer(1);
functionData[77][0]=new Byte(Ptg.CLASS_VALUE);functionData[77][1]=new byte[] {Ptg.CLASS_REF};functionData[77][2]=new Integer(1);
functionData[78][0]=new Byte(Ptg.CLASS_VALUE);functionData[78][1]=new byte[] {Ptg.CLASS_VALUE};functionData[78][2]=new Integer(-1);
functionData[82][0]=new Byte(Ptg.CLASS_VALUE);functionData[82][1]=new byte[] {Ptg.CLASS_VALUE};functionData[82][2]=new Integer(-1);
functionData[83][0]=new Byte(Ptg.CLASS_VALUE);functionData[83][1]=new byte[] {Ptg.CLASS_VALUE};functionData[83][2]=new Integer(1);
functionData[86][0]=new Byte(Ptg.CLASS_VALUE);functionData[86][1]=new byte[] {Ptg.CLASS_VALUE};functionData[86][2]=new Integer(1);
functionData[97][0]=new Byte(Ptg.CLASS_VALUE);functionData[97][1]=new byte[] {Ptg.CLASS_VALUE};functionData[97][2]=new Integer(2);
functionData[98][0]=new Byte(Ptg.CLASS_VALUE);functionData[98][1]=new byte[] {Ptg.CLASS_VALUE};functionData[98][2]=new Integer(1);
functionData[99][0]=new Byte(Ptg.CLASS_VALUE);functionData[99][1]=new byte[] {Ptg.CLASS_VALUE};functionData[99][2]=new Integer(1);
functionData[101][0]=new Byte(Ptg.CLASS_VALUE);functionData[101][1]=new byte[] {Ptg.CLASS_REF};functionData[101][2]=new Integer(-1);
functionData[102][0]=new Byte(Ptg.CLASS_VALUE);functionData[102][1]=new byte[] {Ptg.CLASS_REF};functionData[102][2]=new Integer(-1);
functionData[105][0]=new Byte(Ptg.CLASS_VALUE);functionData[105][1]=new byte[] {Ptg.CLASS_REF};functionData[105][2]=new Integer(1);
functionData[109][0]=new Byte(Ptg.CLASS_VALUE);functionData[109][1]=new byte[] {Ptg.CLASS_VALUE};functionData[109][2]=new Integer(-1);
functionData[111][0]=new Byte(Ptg.CLASS_VALUE);functionData[111][1]=new byte[] {Ptg.CLASS_VALUE};functionData[111][2]=new Integer(1);
functionData[112][0]=new Byte(Ptg.CLASS_VALUE);functionData[112][1]=new byte[] {Ptg.CLASS_VALUE};functionData[112][2]=new Integer(1);
functionData[113][0]=new Byte(Ptg.CLASS_VALUE);functionData[113][1]=new byte[] {Ptg.CLASS_VALUE};functionData[113][2]=new Integer(1);
functionData[114][0]=new Byte(Ptg.CLASS_VALUE);functionData[114][1]=new byte[] {Ptg.CLASS_VALUE};functionData[114][2]=new Integer(1);
functionData[115][0]=new Byte(Ptg.CLASS_VALUE);functionData[115][1]=new byte[] {Ptg.CLASS_VALUE};functionData[115][2]=new Integer(-1);
functionData[116][0]=new Byte(Ptg.CLASS_VALUE);functionData[116][1]=new byte[] {Ptg.CLASS_VALUE};functionData[116][2]=new Integer(-1);
functionData[117][0]=new Byte(Ptg.CLASS_VALUE);functionData[117][1]=new byte[] {Ptg.CLASS_VALUE};functionData[117][2]=new Integer(2);
functionData[118][0]=new Byte(Ptg.CLASS_VALUE);functionData[118][1]=new byte[] {Ptg.CLASS_VALUE};functionData[118][2]=new Integer(1);
functionData[119][0]=new Byte(Ptg.CLASS_VALUE);functionData[119][1]=new byte[] {Ptg.CLASS_VALUE};functionData[119][2]=new Integer(4);
functionData[120][0]=new Byte(Ptg.CLASS_VALUE);functionData[120][1]=new byte[] {Ptg.CLASS_VALUE};functionData[120][2]=new Integer(-1);
functionData[121][0]=new Byte(Ptg.CLASS_VALUE);functionData[121][1]=new byte[] {Ptg.CLASS_VALUE};functionData[121][2]=new Integer(1);
functionData[124][0]=new Byte(Ptg.CLASS_VALUE);functionData[124][1]=new byte[] {Ptg.CLASS_VALUE};functionData[124][2]=new Integer(-1);
functionData[125][0]=new Byte(Ptg.CLASS_VALUE);functionData[125][1]=new byte[] {Ptg.CLASS_VALUE};functionData[125][2]=new Integer(-1);
functionData[126][0]=new Byte(Ptg.CLASS_VALUE);functionData[126][1]=new byte[] {Ptg.CLASS_VALUE};functionData[126][2]=new Integer(1);
functionData[127][0]=new Byte(Ptg.CLASS_VALUE);functionData[127][1]=new byte[] {Ptg.CLASS_VALUE};functionData[127][2]=new Integer(1);
functionData[128][0]=new Byte(Ptg.CLASS_VALUE);functionData[128][1]=new byte[] {Ptg.CLASS_VALUE};functionData[128][2]=new Integer(1);
functionData[129][0]=new Byte(Ptg.CLASS_VALUE);functionData[129][1]=new byte[] {Ptg.CLASS_VALUE};functionData[129][2]=new Integer(1);
functionData[130][0]=new Byte(Ptg.CLASS_VALUE);functionData[130][1]=new byte[] {Ptg.CLASS_REF};functionData[130][2]=new Integer(1);
functionData[131][0]=new Byte(Ptg.CLASS_VALUE);functionData[131][1]=new byte[] {Ptg.CLASS_REF};functionData[131][2]=new Integer(1);
functionData[140][0]=new Byte(Ptg.CLASS_VALUE);functionData[140][1]=new byte[] {Ptg.CLASS_VALUE};functionData[140][2]=new Integer(1);
functionData[141][0]=new Byte(Ptg.CLASS_VALUE);functionData[141][1]=new byte[] {Ptg.CLASS_VALUE};functionData[141][2]=new Integer(1);
functionData[142][0]=new Byte(Ptg.CLASS_VALUE);functionData[142][1]=new byte[] {Ptg.CLASS_VALUE};functionData[142][2]=new Integer(3);
functionData[148][0]=new Byte(Ptg.CLASS_VALUE);functionData[148][1]=new byte[] {Ptg.CLASS_VALUE};functionData[148][2]=new Integer(-1);
functionData[150][0]=new Byte(Ptg.CLASS_VALUE);functionData[150][1]=new byte[] {Ptg.CLASS_VALUE};functionData[150][2]=new Integer(-1);
functionData[162][0]=new Byte(Ptg.CLASS_VALUE);functionData[162][1]=new byte[] {Ptg.CLASS_VALUE};functionData[162][2]=new Integer(1);
functionData[163][0]=new Byte(Ptg.CLASS_VALUE);functionData[163][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[163][2]=new Integer(1);
functionData[164][0]=new Byte(Ptg.CLASS_VALUE);functionData[164][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[164][2]=new Integer(1);
functionData[165][0]=new Byte(Ptg.CLASS_VALUE);functionData[165][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[165][2]=new Integer(2);
functionData[166][0]=new Byte(Ptg.CLASS_VALUE);functionData[166][1]=new byte[] {Ptg.CLASS_VALUE};functionData[166][2]=new Integer(-1);
functionData[167][0]=new Byte(Ptg.CLASS_VALUE);functionData[167][1]=new byte[] {Ptg.CLASS_VALUE};functionData[167][2]=new Integer(-1);
functionData[168][0]=new Byte(Ptg.CLASS_VALUE);functionData[168][1]=new byte[] {Ptg.CLASS_REF};functionData[168][2]=new Integer(-1);
functionData[183][0]=new Byte(Ptg.CLASS_VALUE);functionData[183][1]=new byte[] {Ptg.CLASS_REF};functionData[183][2]=new Integer(-1);
functionData[184][0]=new Byte(Ptg.CLASS_VALUE);functionData[184][1]=new byte[] {Ptg.CLASS_VALUE};functionData[184][2]=new Integer(1);
functionData[189][0]=new Byte(Ptg.CLASS_VALUE);functionData[189][1]=new byte[] {Ptg.CLASS_REF};functionData[189][2]=new Integer(3);
functionData[190][0]=new Byte(Ptg.CLASS_VALUE);functionData[190][1]=new byte[] {Ptg.CLASS_VALUE};functionData[190][2]=new Integer(1);
functionData[193][0]=new Byte(Ptg.CLASS_VALUE);functionData[193][1]=new byte[] {Ptg.CLASS_REF};functionData[193][2]=new Integer(-1);
functionData[194][0]=new Byte(Ptg.CLASS_VALUE);functionData[194][1]=new byte[] {Ptg.CLASS_REF};functionData[194][2]=new Integer(-1);
functionData[195][0]=new Byte(Ptg.CLASS_VALUE);functionData[195][1]=new byte[] {Ptg.CLASS_REF};functionData[195][2]=new Integer(3);
functionData[196][0]=new Byte(Ptg.CLASS_VALUE);functionData[196][1]=new byte[] {Ptg.CLASS_REF};functionData[196][2]=new Integer(3);
functionData[197][0]=new Byte(Ptg.CLASS_VALUE);functionData[197][1]=new byte[] {Ptg.CLASS_VALUE};functionData[197][2]=new Integer(-1);
functionData[198][0]=new Byte(Ptg.CLASS_VALUE);functionData[198][1]=new byte[] {Ptg.CLASS_VALUE};functionData[198][2]=new Integer(1);
functionData[199][0]=new Byte(Ptg.CLASS_VALUE);functionData[199][1]=new byte[] {Ptg.CLASS_REF};functionData[199][2]=new Integer(3);
functionData[204][0]=new Byte(Ptg.CLASS_VALUE);functionData[204][1]=new byte[] {Ptg.CLASS_VALUE};functionData[204][2]=new Integer(-1);
functionData[205][0]=new Byte(Ptg.CLASS_VALUE);functionData[205][1]=new byte[] {Ptg.CLASS_VALUE};functionData[205][2]=new Integer(-1);
functionData[206][0]=new Byte(Ptg.CLASS_VALUE);functionData[206][1]=new byte[] {Ptg.CLASS_VALUE};functionData[206][2]=new Integer(-1);
functionData[207][0]=new Byte(Ptg.CLASS_VALUE);functionData[207][1]=new byte[] {Ptg.CLASS_VALUE};functionData[207][2]=new Integer(3);
functionData[208][0]=new Byte(Ptg.CLASS_VALUE);functionData[208][1]=new byte[] {Ptg.CLASS_VALUE};functionData[208][2]=new Integer(1);
functionData[209][0]=new Byte(Ptg.CLASS_VALUE);functionData[209][1]=new byte[] {Ptg.CLASS_VALUE};functionData[209][2]=new Integer(2);
functionData[210][0]=new Byte(Ptg.CLASS_VALUE);functionData[210][1]=new byte[] {Ptg.CLASS_VALUE};functionData[210][2]=new Integer(2);
functionData[211][0]=new Byte(Ptg.CLASS_VALUE);functionData[211][1]=new byte[] {Ptg.CLASS_VALUE};functionData[211][2]=new Integer(1);
functionData[212][0]=new Byte(Ptg.CLASS_VALUE);functionData[212][1]=new byte[] {Ptg.CLASS_VALUE};functionData[212][2]=new Integer(2);
functionData[213][0]=new Byte(Ptg.CLASS_VALUE);functionData[213][1]=new byte[] {Ptg.CLASS_REF};functionData[213][2]=new Integer(2);
functionData[214][0]=new Byte(Ptg.CLASS_VALUE);functionData[214][1]=new byte[] {Ptg.CLASS_VALUE};functionData[214][2]=new Integer(-1);
functionData[221][0]=new Byte(Ptg.CLASS_VALUE);functionData[221][1]=new byte[] {Ptg.CLASS_REF};functionData[221][2]=new Integer(1);
functionData[222][0]=new Byte(Ptg.CLASS_VALUE);functionData[222][1]=new byte[] {Ptg.CLASS_VALUE};functionData[222][2]=new Integer(-1);
functionData[227][0]=new Byte(Ptg.CLASS_VALUE);functionData[227][1]=new byte[] {Ptg.CLASS_REF};functionData[227][2]=new Integer(-1);
functionData[228][0]=new Byte(Ptg.CLASS_VALUE);functionData[228][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[228][2]=new Integer(-1);
functionData[229][0]=new Byte(Ptg.CLASS_VALUE);functionData[229][1]=new byte[] {Ptg.CLASS_VALUE};functionData[229][2]=new Integer(1);
functionData[230][0]=new Byte(Ptg.CLASS_VALUE);functionData[230][1]=new byte[] {Ptg.CLASS_VALUE};functionData[230][2]=new Integer(1);
functionData[231][0]=new Byte(Ptg.CLASS_VALUE);functionData[231][1]=new byte[] {Ptg.CLASS_VALUE};functionData[231][2]=new Integer(1);
functionData[232][0]=new Byte(Ptg.CLASS_VALUE);functionData[232][1]=new byte[] {Ptg.CLASS_VALUE};functionData[232][2]=new Integer(1);
functionData[233][0]=new Byte(Ptg.CLASS_VALUE);functionData[233][1]=new byte[] {Ptg.CLASS_VALUE};functionData[233][2]=new Integer(1);
functionData[234][0]=new Byte(Ptg.CLASS_VALUE);functionData[234][1]=new byte[] {Ptg.CLASS_VALUE};functionData[234][2]=new Integer(1);
functionData[235][0]=new Byte(Ptg.CLASS_VALUE);functionData[235][1]=new byte[] {Ptg.CLASS_REF};functionData[235][2]=new Integer(3);
functionData[244][0]=new Byte(Ptg.CLASS_VALUE);functionData[244][1]=new byte[] {Ptg.CLASS_VALUE};functionData[244][2]=new Integer(2);
functionData[252][0]=new Byte(Ptg.CLASS_VALUE);functionData[252][1]=new byte[] {Ptg.CLASS_REF};functionData[252][2]=new Integer(2);
functionData[261][0]=new Byte(Ptg.CLASS_VALUE);functionData[261][1]=new byte[] {Ptg.CLASS_VALUE};functionData[261][2]=new Integer(1);
functionData[269][0]=new Byte(Ptg.CLASS_VALUE);functionData[269][1]=new byte[] {Ptg.CLASS_REF};functionData[269][2]=new Integer(-1);
functionData[270][0]=new Byte(Ptg.CLASS_VALUE);functionData[270][1]=new byte[] {Ptg.CLASS_VALUE};functionData[270][2]=new Integer(-1);
functionData[271][0]=new Byte(Ptg.CLASS_VALUE);functionData[271][1]=new byte[] {Ptg.CLASS_VALUE};functionData[271][2]=new Integer(1);
functionData[272][0]=new Byte(Ptg.CLASS_VALUE);functionData[272][1]=new byte[] {Ptg.CLASS_VALUE};functionData[272][2]=new Integer(-1);
functionData[273][0]=new Byte(Ptg.CLASS_VALUE);functionData[273][1]=new byte[] {Ptg.CLASS_VALUE};functionData[273][2]=new Integer(4);
functionData[274][0]=new Byte(Ptg.CLASS_VALUE);functionData[274][1]=new byte[] {Ptg.CLASS_VALUE};functionData[274][2]=new Integer(2);
functionData[275][0]=new Byte(Ptg.CLASS_VALUE);functionData[275][1]=new byte[] {Ptg.CLASS_VALUE};functionData[275][2]=new Integer(2);
functionData[276][0]=new Byte(Ptg.CLASS_VALUE);functionData[276][1]=new byte[] {Ptg.CLASS_VALUE};functionData[276][2]=new Integer(2);
functionData[277][0]=new Byte(Ptg.CLASS_VALUE);functionData[277][1]=new byte[] {Ptg.CLASS_VALUE};functionData[277][2]=new Integer(3);
functionData[278][0]=new Byte(Ptg.CLASS_VALUE);functionData[278][1]=new byte[] {Ptg.CLASS_VALUE};functionData[278][2]=new Integer(3);
functionData[279][0]=new Byte(Ptg.CLASS_VALUE);functionData[279][1]=new byte[] {Ptg.CLASS_VALUE};functionData[279][2]=new Integer(1);
functionData[280][0]=new Byte(Ptg.CLASS_VALUE);functionData[280][1]=new byte[] {Ptg.CLASS_VALUE};functionData[280][2]=new Integer(3);
functionData[281][0]=new Byte(Ptg.CLASS_VALUE);functionData[281][1]=new byte[] {Ptg.CLASS_VALUE};functionData[281][2]=new Integer(3);
functionData[282][0]=new Byte(Ptg.CLASS_VALUE);functionData[282][1]=new byte[] {Ptg.CLASS_VALUE};functionData[282][2]=new Integer(3);
functionData[283][0]=new Byte(Ptg.CLASS_VALUE);functionData[283][1]=new byte[] {Ptg.CLASS_VALUE};functionData[283][2]=new Integer(1);
functionData[284][0]=new Byte(Ptg.CLASS_VALUE);functionData[284][1]=new byte[] {Ptg.CLASS_VALUE};functionData[284][2]=new Integer(1);
functionData[285][0]=new Byte(Ptg.CLASS_VALUE);functionData[285][1]=new byte[] {Ptg.CLASS_VALUE};functionData[285][2]=new Integer(2);
functionData[286][0]=new Byte(Ptg.CLASS_VALUE);functionData[286][1]=new byte[] {Ptg.CLASS_VALUE};functionData[286][2]=new Integer(4);
functionData[287][0]=new Byte(Ptg.CLASS_VALUE);functionData[287][1]=new byte[] {Ptg.CLASS_VALUE};functionData[287][2]=new Integer(3);
functionData[288][0]=new Byte(Ptg.CLASS_VALUE);functionData[288][1]=new byte[] {Ptg.CLASS_VALUE};functionData[288][2]=new Integer(2);
functionData[289][0]=new Byte(Ptg.CLASS_VALUE);functionData[289][1]=new byte[] {Ptg.CLASS_VALUE};functionData[289][2]=new Integer(4);
functionData[290][0]=new Byte(Ptg.CLASS_VALUE);functionData[290][1]=new byte[] {Ptg.CLASS_VALUE};functionData[290][2]=new Integer(3);
functionData[291][0]=new Byte(Ptg.CLASS_VALUE);functionData[291][1]=new byte[] {Ptg.CLASS_VALUE};functionData[291][2]=new Integer(3);
functionData[292][0]=new Byte(Ptg.CLASS_VALUE);functionData[292][1]=new byte[] {Ptg.CLASS_VALUE};functionData[292][2]=new Integer(3);
functionData[293][0]=new Byte(Ptg.CLASS_VALUE);functionData[293][1]=new byte[] {Ptg.CLASS_VALUE};functionData[293][2]=new Integer(4);
functionData[294][0]=new Byte(Ptg.CLASS_VALUE);functionData[294][1]=new byte[] {Ptg.CLASS_VALUE};functionData[294][2]=new Integer(1);
functionData[295][0]=new Byte(Ptg.CLASS_VALUE);functionData[295][1]=new byte[] {Ptg.CLASS_VALUE};functionData[295][2]=new Integer(3);
functionData[296][0]=new Byte(Ptg.CLASS_VALUE);functionData[296][1]=new byte[] {Ptg.CLASS_VALUE};functionData[296][2]=new Integer(1);
functionData[297][0]=new Byte(Ptg.CLASS_VALUE);functionData[297][1]=new byte[] {Ptg.CLASS_VALUE};functionData[297][2]=new Integer(3);
functionData[298][0]=new Byte(Ptg.CLASS_VALUE);functionData[298][1]=new byte[] {Ptg.CLASS_VALUE};functionData[298][2]=new Integer(1);
functionData[299][0]=new Byte(Ptg.CLASS_VALUE);functionData[299][1]=new byte[] {Ptg.CLASS_VALUE};functionData[299][2]=new Integer(2);
functionData[300][0]=new Byte(Ptg.CLASS_VALUE);functionData[300][1]=new byte[] {Ptg.CLASS_VALUE};functionData[300][2]=new Integer(3);
functionData[301][0]=new Byte(Ptg.CLASS_VALUE);functionData[301][1]=new byte[] {Ptg.CLASS_VALUE};functionData[301][2]=new Integer(3);
functionData[302][0]=new Byte(Ptg.CLASS_VALUE);functionData[302][1]=new byte[] {Ptg.CLASS_VALUE};functionData[302][2]=new Integer(4);
functionData[303][0]=new Byte(Ptg.CLASS_VALUE);functionData[303][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[303][2]=new Integer(2);
functionData[304][0]=new Byte(Ptg.CLASS_VALUE);functionData[304][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[304][2]=new Integer(2);
functionData[305][0]=new Byte(Ptg.CLASS_VALUE);functionData[305][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[305][2]=new Integer(2);
functionData[306][0]=new Byte(Ptg.CLASS_VALUE);functionData[306][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[306][2]=new Integer(2);
functionData[307][0]=new Byte(Ptg.CLASS_VALUE);functionData[307][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[307][2]=new Integer(2);
functionData[308][0]=new Byte(Ptg.CLASS_VALUE);functionData[308][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[308][2]=new Integer(2);
functionData[309][0]=new Byte(Ptg.CLASS_VALUE);functionData[309][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[309][2]=new Integer(3);
functionData[310][0]=new Byte(Ptg.CLASS_VALUE);functionData[310][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[310][2]=new Integer(2);
functionData[311][0]=new Byte(Ptg.CLASS_VALUE);functionData[311][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[311][2]=new Integer(2);
functionData[312][0]=new Byte(Ptg.CLASS_VALUE);functionData[312][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[312][2]=new Integer(2);
functionData[313][0]=new Byte(Ptg.CLASS_VALUE);functionData[313][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[313][2]=new Integer(2);
functionData[314][0]=new Byte(Ptg.CLASS_VALUE);functionData[314][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[314][2]=new Integer(2);
functionData[315][0]=new Byte(Ptg.CLASS_VALUE);functionData[315][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[315][2]=new Integer(2);
functionData[316][0]=new Byte(Ptg.CLASS_VALUE);functionData[316][1]=new byte[] {Ptg.CLASS_VALUE};functionData[316][2]=new Integer(4);
functionData[317][0]=new Byte(Ptg.CLASS_VALUE);functionData[317][1]=new byte[] {Ptg.CLASS_VALUE};functionData[317][2]=new Integer(-1);
functionData[318][0]=new Byte(Ptg.CLASS_VALUE);functionData[318][1]=new byte[] {Ptg.CLASS_REF};functionData[318][2]=new Integer(-1);
functionData[319][0]=new Byte(Ptg.CLASS_VALUE);functionData[319][1]=new byte[] {Ptg.CLASS_REF};functionData[319][2]=new Integer(-1);
functionData[320][0]=new Byte(Ptg.CLASS_VALUE);functionData[320][1]=new byte[] {Ptg.CLASS_REF};functionData[320][2]=new Integer(-1);
functionData[321][0]=new Byte(Ptg.CLASS_VALUE);functionData[321][1]=new byte[] {Ptg.CLASS_REF};functionData[321][2]=new Integer(-1);
functionData[322][0]=new Byte(Ptg.CLASS_VALUE);functionData[322][1]=new byte[] {Ptg.CLASS_REF};functionData[322][2]=new Integer(-1);
functionData[323][0]=new Byte(Ptg.CLASS_VALUE);functionData[323][1]=new byte[] {Ptg.CLASS_REF};functionData[323][2]=new Integer(-1);
functionData[324][0]=new Byte(Ptg.CLASS_VALUE);functionData[324][1]=new byte[] {Ptg.CLASS_VALUE};functionData[324][2]=new Integer(-1);
functionData[325][0]=new Byte(Ptg.CLASS_VALUE);functionData[325][1]=new byte[] {Ptg.CLASS_VALUE};functionData[325][2]=new Integer(2);
functionData[326][0]=new Byte(Ptg.CLASS_VALUE);functionData[326][1]=new byte[] {Ptg.CLASS_VALUE};functionData[326][2]=new Integer(2);
functionData[327][0]=new Byte(Ptg.CLASS_VALUE);functionData[327][1]=new byte[] {Ptg.CLASS_VALUE};functionData[327][2]=new Integer(2);
functionData[328][0]=new Byte(Ptg.CLASS_VALUE);functionData[328][1]=new byte[] {Ptg.CLASS_VALUE};functionData[328][2]=new Integer(2);
functionData[329][0]=new Byte(Ptg.CLASS_VALUE);functionData[329][1]=new byte[] {Ptg.CLASS_VALUE};functionData[329][2]=new Integer(-1);
functionData[330][0]=new Byte(Ptg.CLASS_VALUE);functionData[330][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[330][2]=new Integer(-1);
functionData[331][0]=new Byte(Ptg.CLASS_VALUE);functionData[331][1]=new byte[] {Ptg.CLASS_VALUE};functionData[331][2]=new Integer(2);
functionData[332][0]=new Byte(Ptg.CLASS_VALUE);functionData[332][1]=new byte[] {Ptg.CLASS_VALUE};functionData[332][2]=new Integer(2);
functionData[336][0]=new Byte(Ptg.CLASS_VALUE);functionData[336][1]=new byte[] {Ptg.CLASS_VALUE};functionData[336][2]=new Integer(-1);
functionData[337][0]=new Byte(Ptg.CLASS_VALUE);functionData[337][1]=new byte[] {Ptg.CLASS_VALUE};functionData[337][2]=new Integer(2);
functionData[342][0]=new Byte(Ptg.CLASS_VALUE);functionData[342][1]=new byte[] {Ptg.CLASS_VALUE};functionData[342][2]=new Integer(1);
functionData[343][0]=new Byte(Ptg.CLASS_VALUE);functionData[343][1]=new byte[] {Ptg.CLASS_VALUE};functionData[343][2]=new Integer(1);
functionData[344][0]=new Byte(Ptg.CLASS_VALUE);functionData[344][1]=new byte[] {Ptg.CLASS_REF};functionData[344][2]=new Integer(-1);
functionData[345][0]=new Byte(Ptg.CLASS_VALUE);functionData[345][1]=new byte[] {Ptg.CLASS_REF};functionData[345][2]=new Integer(-1);
functionData[346][0]=new Byte(Ptg.CLASS_VALUE);functionData[346][1]=new byte[] {Ptg.CLASS_VALUE};functionData[346][2]=new Integer(2);
functionData[347][0]=new Byte(Ptg.CLASS_VALUE);functionData[347][1]=new byte[] {Ptg.CLASS_REF};functionData[347][2]=new Integer(1);
functionData[350][0]=new Byte(Ptg.CLASS_VALUE);functionData[350][1]=new byte[] {Ptg.CLASS_VALUE};functionData[350][2]=new Integer(4);
functionData[352][0]=new Byte(Ptg.CLASS_VALUE);functionData[352][1]=new byte[] {Ptg.CLASS_VALUE};functionData[352][2]=new Integer(1);
functionData[354][0]=new Byte(Ptg.CLASS_VALUE);functionData[354][1]=new byte[] {Ptg.CLASS_VALUE};functionData[354][2]=new Integer(-1);
functionData[358][0]=new Byte(Ptg.CLASS_VALUE);functionData[358][1]=new byte[] {Ptg.CLASS_VALUE};functionData[358][2]=new Integer(2);
functionData[359][0]=new Byte(Ptg.CLASS_VALUE);functionData[359][1]=new byte[] {Ptg.CLASS_VALUE};functionData[359][2]=new Integer(-1);
functionData[360][0]=new Byte(Ptg.CLASS_VALUE);functionData[360][1]=new byte[] {Ptg.CLASS_REF};functionData[360][2]=new Integer(1);
functionData[361][0]=new Byte(Ptg.CLASS_VALUE);functionData[361][1]=new byte[] {Ptg.CLASS_REF};functionData[361][2]=new Integer(-1);
functionData[362][0]=new Byte(Ptg.CLASS_VALUE);functionData[362][1]=new byte[] {Ptg.CLASS_REF};functionData[362][2]=new Integer(-1);
functionData[363][0]=new Byte(Ptg.CLASS_VALUE);functionData[363][1]=new byte[] {Ptg.CLASS_REF};functionData[363][2]=new Integer(-1);
functionData[364][0]=new Byte(Ptg.CLASS_VALUE);functionData[364][1]=new byte[] {Ptg.CLASS_REF};functionData[364][2]=new Integer(-1);
functionData[365][0]=new Byte(Ptg.CLASS_VALUE);functionData[365][1]=new byte[] {Ptg.CLASS_REF};functionData[365][2]=new Integer(-1);
functionData[366][0]=new Byte(Ptg.CLASS_VALUE);functionData[366][1]=new byte[] {Ptg.CLASS_REF};functionData[366][2]=new Integer(-1);
functionData[367][0]=new Byte(Ptg.CLASS_VALUE);functionData[367][1]=new byte[] {Ptg.CLASS_REF};functionData[367][2]=new Integer(-1);
return functionData;
} }
public byte getDefaultOperandClass() { public byte getDefaultOperandClass() {

View File

@ -15,17 +15,18 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/** /**
* @author aviks * @author aviks
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
* @author Danny Mui (dmui at apache dot org) (Leftover handling) * @author Danny Mui (dmui at apache dot org) (Leftover handling)
*/ */
public class FuncPtg extends AbstractFunctionPtg{ public final class FuncPtg extends AbstractFunctionPtg {
public final static byte sid = 0x21; public final static byte sid = 0x21;
public final static int SIZE = 3; public final static int SIZE = 3;
@ -50,34 +51,24 @@ public class FuncPtg extends AbstractFunctionPtg{
//field_1_num_args = data[ offset + 0 ]; //field_1_num_args = data[ offset + 0 ];
field_2_fnc_index = in.readShort(); field_2_fnc_index = in.readShort();
/* FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if (data.length - offset > 2) { //save left overs if there are any if(fm == null) {
leftOvers = new byte[2]; throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
System.arraycopy(data, offset+1, leftOvers, 0, leftOvers.length);
} }
*/ numParams = fm.getMinParams();
try {
numParams = ( (Integer)functionData[field_2_fnc_index][2]).intValue();
} catch (NullPointerException npe) {
numParams=0;
}
} }
public FuncPtg(int functionIndex, int numberOfParameters) { public FuncPtg(int functionIndex, int numberOfParameters) {
field_2_fnc_index = (short) functionIndex; field_2_fnc_index = (short) functionIndex;
numParams = numberOfParameters; numParams = numberOfParameters;
paramClass = new byte[] { Ptg.CLASS_VALUE, }; // TODO
} }
public void writeBytes(byte[] array, int offset) { public void writeBytes(byte[] array, int offset) {
array[offset+0]= (byte) (sid + ptgClass); array[offset+0]= (byte) (sid + ptgClass);
//array[offset+1]=field_1_num_args;
LittleEndian.putShort(array,offset+1,field_2_fnc_index); LittleEndian.putShort(array,offset+1,field_2_fnc_index);
/**if (leftOvers != null) {
System.arraycopy(leftOvers, 0, array, offset+2, leftOvers.length);
}**/
} }
public int getNumberOfOperands() { public int getNumberOfOperands() {
return numParams; return numParams;
} }
@ -94,13 +85,11 @@ public class FuncPtg extends AbstractFunctionPtg{
} }
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer sb = new StringBuffer(64);
buffer sb.append(getClass().getName()).append(" [");
.append("<FunctionPtg>").append("\n") sb.append(lookupName(field_2_fnc_index));
.append(" numArgs(internal)=").append(this.numParams).append("\n") sb.append(" nArgs=").append(numParams);
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n") sb.append("]");
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n") return sb.toString();
.append("</FunctionPtg>");
return buffer.toString();
} }
} }

View File

@ -19,12 +19,14 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/** /**
* *
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
*/ */
public class FuncVarPtg extends AbstractFunctionPtg{ public final class FuncVarPtg extends AbstractFunctionPtg{
public final static byte sid = 0x22; public final static byte sid = 0x22;
private final static int SIZE = 4; private final static int SIZE = 4;
@ -47,10 +49,12 @@ public class FuncVarPtg extends AbstractFunctionPtg{
public FuncVarPtg(String pName, byte pNumOperands) { public FuncVarPtg(String pName, byte pNumOperands) {
field_1_num_args = pNumOperands; field_1_num_args = pNumOperands;
field_2_fnc_index = lookupIndex(pName); field_2_fnc_index = lookupIndex(pName);
try{ FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
returnClass = ( (Byte) functionData[field_2_fnc_index][0]).byteValue(); if(fm == null) {
paramClass = (byte[]) functionData[field_2_fnc_index][1]; // Happens only as a result of a call to FormulaParser.parse(), with a non-built-in function name
} catch (NullPointerException npe ) { returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
} else {
returnClass = Ptg.CLASS_VALUE; returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE}; paramClass = new byte[] {Ptg.CLASS_VALUE};
} }
@ -79,15 +83,11 @@ public class FuncVarPtg extends AbstractFunctionPtg{
} }
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer sb = new StringBuffer(64);
buffer sb.append(getClass().getName()).append(" [");
.append("<FunctionVarPtg>").append("\n") sb.append(lookupName(field_2_fnc_index));
.append(" field_1_num_args=").append(field_1_num_args).append("\n") sb.append(" nArgs=").append(field_1_num_args);
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n") sb.append("]");
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n") return sb.toString();
.append("</FunctionPtg>");
return buffer.toString();
} }
} }

View File

@ -0,0 +1,89 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
* <tt>FunctionMetadataRegistry</tt>.
*
* @author Josh Micich
*/
final class FunctionDataBuilder {
private int _maxFunctionIndex;
private final Map _functionDataByName;
private final Map _functionDataByIndex;
/** stores indexes of all functions with footnotes (i.e. whose definitions might change) */
private final Set _mutatingFunctionIndexes;
public FunctionDataBuilder(int sizeEstimate) {
_maxFunctionIndex = -1;
_functionDataByName = new HashMap(sizeEstimate * 3 / 2);
_functionDataByIndex = new HashMap(sizeEstimate * 3 / 2);
_mutatingFunctionIndexes = new HashSet();
}
public void add(int functionIndex, String functionName, int minParams, int maxParams, boolean hasFootnote) {
FunctionMetadata fm = new FunctionMetadata(functionIndex, functionName, minParams, maxParams);
Integer indexKey = new Integer(functionIndex);
if(functionIndex > _maxFunctionIndex) {
_maxFunctionIndex = functionIndex;
}
// allow function definitions to change only if both previous and the new items have footnotes
FunctionMetadata prevFM;
prevFM = (FunctionMetadata) _functionDataByName.get(functionName);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function name '" + functionName + "'");
}
_functionDataByIndex.remove(new Integer(prevFM.getIndex()));
}
prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")");
}
_functionDataByName.remove(prevFM.getName());
}
if(hasFootnote) {
_mutatingFunctionIndexes.add(indexKey);
}
_functionDataByIndex.put(indexKey, fm);
_functionDataByName.put(functionName, fm);
}
public FunctionMetadataRegistry build() {
FunctionMetadata[] jumbledArray = new FunctionMetadata[_functionDataByName.size()];
_functionDataByName.values().toArray(jumbledArray);
FunctionMetadata[] fdIndexArray = new FunctionMetadata[_maxFunctionIndex+1];
for (int i = 0; i < jumbledArray.length; i++) {
FunctionMetadata fd = jumbledArray[i];
fdIndexArray[fd.getIndex()] = fd;
}
return new FunctionMetadataRegistry(fdIndexArray, _functionDataByName);
}
}

View File

@ -0,0 +1,58 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
/**
*
* @author Josh Micich
*/
public final class FunctionMetadata {
private final int _index;
private final String _name;
private final int _minParams;
private final int _maxParams;
/* package */ FunctionMetadata(int index, String name, int minParams, int maxParams) {
_index = index;
_name = name;
_minParams = minParams;
_maxParams = maxParams;
}
public int getIndex() {
return _index;
}
public String getName() {
return _name;
}
public int getMinParams() {
return _minParams;
}
public int getMaxParams() {
return _maxParams;
}
public boolean hasFixedArgsLength() {
return _minParams == _maxParams;
}
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(_index).append(" ").append(_name);
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,129 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt>
*
* @author Josh Micich
*/
final class FunctionMetadataReader {
private static final String METADATA_FILE_NAME = "functionMetadata.txt";
private static final Pattern TAB_DELIM_PATTERN = Pattern.compile("\t");
private static final String[] DIGIT_ENDING_FUNCTION_NAMES = {
// Digits at the end of a function might be due to a left-over footnote marker.
// except in these cases
"LOG10", "ATAN2", "DAYS360", "SUMXMY2", "SUMX2MY2", "SUMX2PY2",
};
private static final Set DIGIT_ENDING_FUNCTION_NAMES_SET = new HashSet(Arrays.asList(DIGIT_ENDING_FUNCTION_NAMES));
public static FunctionMetadataRegistry createRegistry() {
InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
if(is == null) {
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
FunctionDataBuilder fdb = new FunctionDataBuilder(400);
try {
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
if (line.length() < 1 || line.charAt(0) == '#') {
continue;
}
String trimLine = line.trim();
if (trimLine.length() < 1) {
continue;
}
processLine(fdb, line);
}
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return fdb.build();
}
private static void processLine(FunctionDataBuilder fdb, String line) {
String[] parts = TAB_DELIM_PATTERN.split(line, -2);
if(parts.length != 8) {
throw new RuntimeException("Bad line format '" + line + "' - expected 8 data fields");
}
int functionIndex = parseInt(parts[0]);
String functionName = parts[1];
int minParams = parseInt(parts[2]);
int maxParams = parseInt(parts[3]);
// 4 returnClass
// 5 parameterClasses
// 6 isVolatile
boolean hasNote = parts[7].length() > 0;
validateFunctionName(functionName);
// TODO - make POI use returnClass, parameterClasses, isVolatile
fdb.add(functionIndex, functionName, minParams, maxParams, hasNote);
}
/**
* Makes sure that footnote digits from the original OOO document have not been accidentally
* left behind
*/
private static void validateFunctionName(String functionName) {
int len = functionName.length();
int ix = len - 1;
if (!Character.isDigit(functionName.charAt(ix))) {
return;
}
while(ix >= 0) {
if (!Character.isDigit(functionName.charAt(ix))) {
break;
}
ix--;
}
if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) {
return;
}
throw new RuntimeException("Invalid function name '" + functionName
+ "' (is footnote number incorrectly appended)");
}
private static int parseInt(String valStr) {
try {
return Integer.parseInt(valStr);
} catch (NumberFormatException e) {
throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
}
}
}

View File

@ -0,0 +1,82 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import java.util.Map;
import java.util.Set;
public final class FunctionMetadataRegistry {
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
*/
public static final String FUNCTION_NAME_IF = "IF";
public static final short FUNCTION_INDEX_EXTERNAL = 255;
private static FunctionMetadataRegistry _instance;
private final FunctionMetadata[] _functionDataByIndex;
private final Map _functionDataByName;
private static FunctionMetadataRegistry getInstance() {
if (_instance == null) {
_instance = FunctionMetadataReader.createRegistry();
// _instance = POIFunctionMetadataCreator.createInstance();
}
return _instance;
}
/* package */ FunctionMetadataRegistry(FunctionMetadata[] functionDataByIndex, Map functionDataByName) {
_functionDataByIndex = functionDataByIndex;
_functionDataByName = functionDataByName;
}
/* package */ Set getAllFunctionNames() {
return _functionDataByName.keySet();
}
public static FunctionMetadata getFunctionByIndex(int index) {
return getInstance().getFunctionByIndexInternal(index);
}
private FunctionMetadata getFunctionByIndexInternal(int index) {
return _functionDataByIndex[index];
}
/**
* Resolves a built-in function index.
* @param name uppercase function name
* @return a negative value if the function name is not found.
* This typically occurs for external functions.
*/
public static short lookupIndexByName(String name) {
FunctionMetadata fd = getInstance().getFunctionByNameInternal(name);
if (fd == null) {
return -1;
}
return (short) fd.getIndex();
}
private FunctionMetadata getFunctionByNameInternal(String name) {
return (FunctionMetadata) _functionDataByName.get(name);
}
public static FunctionMetadata getFunctionByName(String name) {
return getInstance().getFunctionByNameInternal(name);
}
}

View File

@ -25,23 +25,88 @@ import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.cf.CellRange; import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.Region; import org.apache.poi.hssf.util.Region;
public class HSSFConditionalFormatting /**
* HSSFConditionalFormatting class encapsulates all settings of Conditional Formatting.
*
* The class can be used
*
* <UL>
* <LI>
* to make a copy HSSFConditionalFormatting settings.
* </LI>
*
*
* For example:
* <PRE>
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
* newSheet.addConditionalFormatting(cf);
* </PRE>
*
* <LI>
* or to modify existing Conditional Formatting settings (formatting regions and/or rules).
* </LI>
* </UL>
*
* Use {@link HSSFSheet#getConditionalFormattingAt(int)} to get access to an instance of this class.
* <P>
* To create a new Conditional Formatting set use the following approach:
*
* <PRE>
* // Create pattern with red background
* HSSFPatternFormatting patternFormatting = new HSSFPatternFormatting();
* patternFormatting.setFillBackgroundColor(HSSFColor.RED.index);
*
* Region [] regions =
* {
* // Define a region containing first column
* new Region(1,(short)1,-1,(short)1)
* };
*
* HSSFConditionalFormattingRule[] rules =
* {
* // Define a Conditional Formatting rule, which triggers formatting
* // when cell's value is greater or equal than 100.0 and
* // applies patternFormatting defined above.
*
* sheet.createConditionalFormattingRule(
* HSSFConditionalFormattingRule.COMPARISON_OPERATOR_GE,
* "100.0", // 1st formula
* null, // 2nd formula is not used for comparison operator GE
* null, // do not override Font Formatting
* null, // do not override Border Formatting
* patternFormatting
* )
* };
*
* // Apply Conditional Formatting rules defined above to the regions
* sheet.addConditionalFormatting(regions, rules);
* </PRE>
*
* @author Dmitriy Kumshayev
*/
public final class HSSFConditionalFormatting
{ {
HSSFSheet sheet; private final HSSFSheet sheet;
CFRecordsAggregate cfAggregate; private final CFRecordsAggregate cfAggregate;
protected HSSFConditionalFormatting(HSSFSheet sheet) HSSFConditionalFormatting(HSSFSheet sheet) {
{ this(sheet, new CFRecordsAggregate());
this.sheet = sheet;
this.cfAggregate = new CFRecordsAggregate();
} }
protected HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate) HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
{ {
if(sheet == null) {
throw new IllegalArgumentException("sheet must not be null");
}
if(cfAggregate == null) {
throw new IllegalArgumentException("cfAggregate must not be null");
}
this.sheet = sheet; this.sheet = sheet;
this.cfAggregate = cfAggregate; this.cfAggregate = cfAggregate;
} }
CFRecordsAggregate getCFRecordsAggregate() {
return cfAggregate;
}
public void setFormattingRegions(Region[] regions) public void setFormattingRegions(Region[] regions)
{ {
@ -52,35 +117,65 @@ public class HSSFConditionalFormatting
} }
} }
/**
* @return array of <tt>Region</tt>s. never <code>null</code>
*/
public Region[] getFormattingRegions() public Region[] getFormattingRegions()
{ {
CFHeaderRecord cfh = cfAggregate.getHeader(); CFHeaderRecord cfh = cfAggregate.getHeader();
List cellRanges = cfh.getCellRanges(); List cellRanges = cfh.getCellRanges();
if (cellRanges != null) return toRegionArray(cellRanges);
{
return toRegionArray(cellRanges);
}
return null;
} }
public void setConditionalFormat(int idx, HSSFConditionalFormattingRule cfRule) /**
* set a Conditional Formatting rule at position idx.
* Excel allows to create up to 3 Conditional Formatting rules.
* This method can be useful to modify existing Conditional Formatting rules.
*
* @param idx position of the rule. Should be between 0 and 2.
* @param cfRule - Conditional Formatting rule
*/
public void setRule(int idx, HSSFConditionalFormattingRule cfRule)
{ {
if (idx < 0 || idx > 2) {
throw new IllegalArgumentException("idx must be between 0 and 2 but was ("
+ idx + ")");
}
cfAggregate.getRules().set(idx, cfRule); cfAggregate.getRules().set(idx, cfRule);
} }
public void addConditionalFormat(HSSFConditionalFormattingRule cfRule) /**
* add a Conditional Formatting rule.
* Excel allows to create up to 3 Conditional Formatting rules.
* @param cfRule - Conditional Formatting rule
*/
public void addRule(HSSFConditionalFormattingRule cfRule)
{ {
cfAggregate.getRules().add(cfRule); cfAggregate.getRules().add(cfRule);
} }
public HSSFConditionalFormattingRule getConditionalFormat(int idx) /**
* get a Conditional Formatting rule at position idx.
* @param idx
* @return a Conditional Formatting rule at position idx.
*/
public HSSFConditionalFormattingRule getRule(int idx)
{ {
CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx); CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx);
return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord); return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord);
} }
/**
* @return number of Conditional Formatting rules.
*/
public int getNumbOfRules()
{
return cfAggregate.getRules().size();
}
/** /**
* Do all possible cell merges between cells of the list so that:<br> * Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list * <li>if a cell range is completely inside of another cell range, it gets removed from the list
@ -192,10 +287,6 @@ public class HSSFConditionalFormatting
public String toString() public String toString()
{ {
if(cfAggregate!=null) return cfAggregate.toString();
{
return cfAggregate.toString();
}
return null;
} }
} }

View File

@ -308,9 +308,9 @@ public class HSSFRow
* @param cellnum 0 based column number * @param cellnum 0 based column number
* @return HSSFCell representing that column or null if undefined. * @return HSSFCell representing that column or null if undefined.
*/ */
public HSSFCell getCell(short cellnum) public HSSFCell getCell(short cellnum) {
{ int ushortCellNum = cellnum & 0x0000FFFF; // avoid sign extension
return getCell((int)cellnum); return getCell(ushortCellNum);
} }
/** /**
* Get the hssfcell representing a given column (logical cell) * Get the hssfcell representing a given column (logical cell)

View File

@ -15,11 +15,6 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
/*
* HSSFSheet.java
*
* Created on September 30, 2001, 3:40 PM
*/
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.awt.font.FontRenderContext; import java.awt.font.FontRenderContext;
@ -616,7 +611,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
*/ */
public void setForceFormulaRecalculation(boolean value) public void setForceFormulaRecalculation(boolean value)
{ {
sheet.setUncalced(value); sheet.setUncalced(value);
} }
/** /**
* Whether a record must be inserted or not at generation to indicate that * Whether a record must be inserted or not at generation to indicate that
@ -625,7 +620,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
*/ */
public boolean getForceFormulaRecalculation() public boolean getForceFormulaRecalculation()
{ {
return sheet.getUncalced(); return sheet.getUncalced();
} }
@ -1015,45 +1010,45 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
getSheet().setMargin( margin, size ); getSheet().setMargin( margin, size );
} }
/** /**
* Answer whether protection is enabled or disabled * Answer whether protection is enabled or disabled
* @return true => protection enabled; false => protection disabled * @return true => protection enabled; false => protection disabled
*/ */
public boolean getProtect() { public boolean getProtect() {
return getSheet().isProtected()[0]; return getSheet().isProtected()[0];
} }
/** /**
* @return hashed password * @return hashed password
*/ */
public short getPassword() { public short getPassword() {
return getSheet().getPassword().getPassword(); return getSheet().getPassword().getPassword();
} }
/** /**
* Answer whether object protection is enabled or disabled * Answer whether object protection is enabled or disabled
* @return true => protection enabled; false => protection disabled * @return true => protection enabled; false => protection disabled
*/ */
public boolean getObjectProtect() { public boolean getObjectProtect() {
return getSheet().isProtected()[1]; return getSheet().isProtected()[1];
} }
/** /**
* Answer whether scenario protection is enabled or disabled * Answer whether scenario protection is enabled or disabled
* @return true => protection enabled; false => protection disabled * @return true => protection enabled; false => protection disabled
*/ */
public boolean getScenarioProtect() { public boolean getScenarioProtect() {
return getSheet().isProtected()[2]; return getSheet().isProtected()[2];
} }
/** /**
* Sets the protection on enabled or disabled * Sets the protection on enabled or disabled
* @param protect true => protection enabled; false => protection disabled * @param protect true => protection enabled; false => protection disabled
* @deprecated use protectSheet(String, boolean, boolean) * @deprecated use protectSheet(String, boolean, boolean)
*/ */
public void setProtect(boolean protect) { public void setProtect(boolean protect) {
getSheet().getProtect().setProtect(protect); getSheet().getProtect().setProtect(protect);
} }
/** /**
* Sets the protection enabled as well as the password * Sets the protection enabled as well as the password
@ -1091,7 +1086,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
*/ */
public short getTopRow() public short getTopRow()
{ {
return sheet.getTopRow(); return sheet.getTopRow();
} }
/** /**
@ -1101,7 +1096,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
*/ */
public short getLeftCol() public short getLeftCol()
{ {
return sheet.getLeftCol(); return sheet.getLeftCol();
} }
/** /**
@ -1115,49 +1110,49 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
this.sheet.setLeftCol((short)leftcol); this.sheet.setLeftCol((short)leftcol);
} }
/** /**
* Shifts the merged regions left or right depending on mode * Shifts the merged regions left or right depending on mode
* <p> * <p>
* TODO: MODE , this is only row specific * TODO: MODE , this is only row specific
* @param startRow * @param startRow
* @param endRow * @param endRow
* @param n * @param n
* @param isRow * @param isRow
*/ */
protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) { protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
List shiftedRegions = new ArrayList(); List shiftedRegions = new ArrayList();
//move merged regions completely if they fall within the new region boundaries when they are shifted //move merged regions completely if they fall within the new region boundaries when they are shifted
for (int i = 0; i < this.getNumMergedRegions(); i++) { for (int i = 0; i < this.getNumMergedRegions(); i++) {
Region merged = this.getMergedRegionAt(i); Region merged = this.getMergedRegionAt(i);
boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow); boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow);
boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow); boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow);
//dont check if it's not within the shifted area //dont check if it's not within the shifted area
if (! (inStart && inEnd)) continue; if (! (inStart && inEnd)) continue;
//only shift if the region outside the shifted rows is not merged too //only shift if the region outside the shifted rows is not merged too
if (!merged.contains(startRow-1, (short)0) && !merged.contains(endRow+1, (short)0)){ if (!merged.contains(startRow-1, (short)0) && !merged.contains(endRow+1, (short)0)){
merged.setRowFrom(merged.getRowFrom()+n); merged.setRowFrom(merged.getRowFrom()+n);
merged.setRowTo(merged.getRowTo()+n); merged.setRowTo(merged.getRowTo()+n);
//have to remove/add it back //have to remove/add it back
shiftedRegions.add(merged); shiftedRegions.add(merged);
this.removeMergedRegion(i); this.removeMergedRegion(i);
i = i -1; // we have to back up now since we removed one i = i -1; // we have to back up now since we removed one
} }
} }
//readd so it doesn't get shifted again //readd so it doesn't get shifted again
Iterator iterator = shiftedRegions.iterator(); Iterator iterator = shiftedRegions.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Region region = (Region)iterator.next(); Region region = (Region)iterator.next();
this.addMergedRegion(region); this.addMergedRegion(region);
} }
} }
/** /**
* Shifts rows between startRow and endRow n number of rows. * Shifts rows between startRow and endRow n number of rows.
@ -1174,7 +1169,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param n the number of rows to shift * @param n the number of rows to shift
*/ */
public void shiftRows( int startRow, int endRow, int n ) { public void shiftRows( int startRow, int endRow, int n ) {
shiftRows(startRow, endRow, n, false, false); shiftRows(startRow, endRow, n, false, false);
} }
/** /**
@ -1224,23 +1219,23 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
// Removes the cells before over writting them. // Removes the cells before over writting them.
for ( short col = row2Replace.getFirstCellNum(); col <= row2Replace.getLastCellNum(); col++ ) for ( short col = row2Replace.getFirstCellNum(); col <= row2Replace.getLastCellNum(); col++ )
{ {
cell = row2Replace.getCell( col ); cell = row2Replace.getCell( col );
if ( cell != null ) if ( cell != null )
row2Replace.removeCell( cell ); row2Replace.removeCell( cell );
} }
if (row == null) continue; // Nothing to do for this row if (row == null) continue; // Nothing to do for this row
else { else {
if (copyRowHeight) { if (copyRowHeight) {
row2Replace.setHeight(row.getHeight()); row2Replace.setHeight(row.getHeight());
} }
if (resetOriginalRowHeight) { if (resetOriginalRowHeight) {
row.setHeight((short)0xff); row.setHeight((short)0xff);
} }
} }
for ( short col = row.getFirstCellNum(); col <= row.getLastCellNum(); col++ ) for ( short col = row.getFirstCellNum(); col <= row.getLastCellNum(); col++ )
{ {
cell = row.getCell( col ); cell = row.getCell( col );
@ -1273,44 +1268,44 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* to point to the new location of moved rows * to point to the new location of moved rows
*/ */
private void updateFormulasAfterShift(int startRow, int endRow, int n) { private void updateFormulasAfterShift(int startRow, int endRow, int n) {
// Need to look at every cell on the sheet // Need to look at every cell on the sheet
// Not just those that were moved // Not just those that were moved
Iterator ri = rowIterator(); Iterator ri = rowIterator();
while(ri.hasNext()) { while(ri.hasNext()) {
HSSFRow r = (HSSFRow)ri.next(); HSSFRow r = (HSSFRow)ri.next();
Iterator ci = r.cellIterator(); Iterator ci = r.cellIterator();
while(ci.hasNext()) { while(ci.hasNext()) {
HSSFCell c = (HSSFCell)ci.next(); HSSFCell c = (HSSFCell)ci.next();
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
// Since it's a formula cell, process the // Since it's a formula cell, process the
// formula string, and look to see if // formula string, and look to see if
// it contains any references // it contains any references
FormulaParser fp = new FormulaParser(c.getCellFormula(), workbook.getWorkbook()); FormulaParser fp = new FormulaParser(c.getCellFormula(), workbook.getWorkbook());
fp.parse(); fp.parse();
// Look for references, and update if needed // Look for references, and update if needed
Ptg[] ptgs = fp.getRPNPtg(); Ptg[] ptgs = fp.getRPNPtg();
boolean changed = false; boolean changed = false;
for(int i=0; i<ptgs.length; i++) { for(int i=0; i<ptgs.length; i++) {
if(ptgs[i] instanceof ReferencePtg) { if(ptgs[i] instanceof ReferencePtg) {
ReferencePtg rptg = (ReferencePtg)ptgs[i]; ReferencePtg rptg = (ReferencePtg)ptgs[i];
if(startRow <= rptg.getRowAsInt() && if(startRow <= rptg.getRowAsInt() &&
rptg.getRowAsInt() <= endRow) { rptg.getRowAsInt() <= endRow) {
// References a row that moved // References a row that moved
rptg.setRow(rptg.getRowAsInt() + n); rptg.setRow(rptg.getRowAsInt() + n);
changed = true; changed = true;
} }
} }
} }
// If any references were changed, then // If any references were changed, then
// re-create the formula string // re-create the formula string
if(changed) { if(changed) {
c.setCellFormula( c.setCellFormula(
fp.toFormulaString(ptgs) fp.toFormulaString(ptgs)
); );
} }
} }
} }
} }
} }
@ -1385,7 +1380,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return whether gridlines are displayed * @return whether gridlines are displayed
*/ */
public boolean isDisplayGridlines() { public boolean isDisplayGridlines() {
return sheet.isDisplayGridlines(); return sheet.isDisplayGridlines();
} }
/** /**
@ -1401,7 +1396,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return whether formulas are displayed * @return whether formulas are displayed
*/ */
public boolean isDisplayFormulas() { public boolean isDisplayFormulas() {
return sheet.isDisplayFormulas(); return sheet.isDisplayFormulas();
} }
/** /**
@ -1417,7 +1412,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return whether RowColHeadings are displayed * @return whether RowColHeadings are displayed
*/ */
public boolean isDisplayRowColHeadings() { public boolean isDisplayRowColHeadings() {
return sheet.isDisplayRowColHeadings(); return sheet.isDisplayRowColHeadings();
} }
/** /**
@ -1425,8 +1420,8 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param row FIXME: Document this! * @param row FIXME: Document this!
*/ */
public void setRowBreak(int row) { public void setRowBreak(int row) {
validateRow(row); validateRow(row);
sheet.setRowBreak(row, (short)0, (short)255); sheet.setRowBreak(row, (short)0, (short)255);
} }
/** /**
@ -1435,7 +1430,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return FIXME: Document this! * @return FIXME: Document this!
*/ */
public boolean isRowBroken(int row) { public boolean isRowBroken(int row) {
return sheet.isRowBroken(row); return sheet.isRowBroken(row);
} }
/** /**
@ -1443,7 +1438,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param row * @param row
*/ */
public void removeRowBreak(int row) { public void removeRowBreak(int row) {
sheet.removeRowBreak(row); sheet.removeRowBreak(row);
} }
/** /**
@ -1451,19 +1446,19 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return all the horizontal page breaks, or null if there are no row page breaks * @return all the horizontal page breaks, or null if there are no row page breaks
*/ */
public int[] getRowBreaks(){ public int[] getRowBreaks(){
//we can probably cache this information, but this should be a sparsely used function //we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumRowBreaks(); int count = sheet.getNumRowBreaks();
if (count > 0) { if (count > 0) {
int[] returnValue = new int[count]; int[] returnValue = new int[count];
Iterator iterator = sheet.getRowBreaks(); Iterator iterator = sheet.getRowBreaks();
int i = 0; int i = 0;
while (iterator.hasNext()) { while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = (int)breakItem.main; returnValue[i++] = (int)breakItem.main;
} }
return returnValue; return returnValue;
} }
return null; return null;
} }
/** /**
@ -1471,19 +1466,19 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return all the vertical page breaks, or null if there are no column page breaks * @return all the vertical page breaks, or null if there are no column page breaks
*/ */
public short[] getColumnBreaks(){ public short[] getColumnBreaks(){
//we can probably cache this information, but this should be a sparsely used function //we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumColumnBreaks(); int count = sheet.getNumColumnBreaks();
if (count > 0) { if (count > 0) {
short[] returnValue = new short[count]; short[] returnValue = new short[count];
Iterator iterator = sheet.getColumnBreaks(); Iterator iterator = sheet.getColumnBreaks();
int i = 0; int i = 0;
while (iterator.hasNext()) { while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = breakItem.main; returnValue[i++] = breakItem.main;
} }
return returnValue; return returnValue;
} }
return null; return null;
} }
@ -1492,8 +1487,8 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param column * @param column
*/ */
public void setColumnBreak(short column) { public void setColumnBreak(short column) {
validateColumn(column); validateColumn(column);
sheet.setColumnBreak(column, (short)0, (short)65535); sheet.setColumnBreak(column, (short)0, (short)65535);
} }
/** /**
@ -1502,7 +1497,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return FIXME: Document this! * @return FIXME: Document this!
*/ */
public boolean isColumnBroken(short column) { public boolean isColumnBroken(short column) {
return sheet.isColumnBroken(column); return sheet.isColumnBroken(column);
} }
/** /**
@ -1510,7 +1505,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param column * @param column
*/ */
public void removeColumnBreak(short column) { public void removeColumnBreak(short column) {
sheet.removeColumnBreak(column); sheet.removeColumnBreak(column);
} }
/** /**
@ -1518,8 +1513,8 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param row * @param row
*/ */
protected void validateRow(int row) { protected void validateRow(int row) {
if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535"); if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535");
if (row < 0) throw new IllegalArgumentException("Minumum row number is 0"); if (row < 0) throw new IllegalArgumentException("Minumum row number is 0");
} }
/** /**
@ -1527,8 +1522,8 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param column * @param column
*/ */
protected void validateColumn(short column) { protected void validateColumn(short column) {
if (column > 255) throw new IllegalArgumentException("Maximum column number is 255"); if (column > 255) throw new IllegalArgumentException("Maximum column number is 255");
if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); if (column < 0) throw new IllegalArgumentException("Minimum column number is 0");
} }
/** /**
@ -1587,23 +1582,23 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* start from scratch! * start from scratch!
*/ */
public HSSFPatriarch getDrawingPatriarch() { public HSSFPatriarch getDrawingPatriarch() {
book.findDrawingGroup(); book.findDrawingGroup();
// If there's now no drawing manager, then there's // If there's now no drawing manager, then there's
// no drawing escher records on the workbook // no drawing escher records on the workbook
if(book.getDrawingManager() == null) { if(book.getDrawingManager() == null) {
return null; return null;
} }
int found = sheet.aggregateDrawingRecords( int found = sheet.aggregateDrawingRecords(
book.getDrawingManager(), false book.getDrawingManager(), false
); );
if(found == -1) { if(found == -1) {
// Workbook has drawing stuff, but this sheet doesn't // Workbook has drawing stuff, but this sheet doesn't
return null; return null;
} }
// Grab our aggregate record, and wire it up // Grab our aggregate record, and wire it up
EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid); EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
HSSFPatriarch patriarch = new HSSFPatriarch(this, agg); HSSFPatriarch patriarch = new HSSFPatriarch(this, agg);
agg.setPatriarch(patriarch); agg.setPatriarch(patriarch);
@ -1666,7 +1661,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param style the style to set * @param style the style to set
*/ */
public void setDefaultColumnStyle(short column, CellStyle style) { public void setDefaultColumnStyle(short column, CellStyle style) {
sheet.setColumn(column, new Short(((HSSFCellStyle) style).getIndex()), null, null, null, null); sheet.setColumn(column, new Short(((HSSFCellStyle) style).getIndex()), null, null, null, null);
} }
/** /**
@ -1814,7 +1809,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
/** /**
* Copy text attributes from the supplied HSSFFont to Java2D AttributedString * Copy text attributes from the supplied HSSFFont to Java2D AttributedString
*/ */
private void copyAttributes(HSSFFont font, AttributedString str, int startIdx, int endIdx){ private void copyAttributes(HSSFFont font, AttributedString str, int startIdx, int endIdx) {
str.addAttribute(TextAttribute.FAMILY, font.getFontName(), startIdx, endIdx); str.addAttribute(TextAttribute.FAMILY, font.getFontName(), startIdx, endIdx);
str.addAttribute(TextAttribute.SIZE, new Float(font.getFontHeightInPoints())); str.addAttribute(TextAttribute.SIZE, new Float(font.getFontHeightInPoints()));
if (font.getBoldweight() == HSSFFont.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx); if (font.getBoldweight() == HSSFFont.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx);
@ -1852,14 +1847,14 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* formatting rules such as font format, border format and pattern format * formatting rules such as font format, border format and pattern format
* *
* @param comparisonOperation - one of the following values: <p> * @param comparisonOperation - one of the following values: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p> * </p>
* @param formula1 - formula for the valued, compared with the cell * @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with * @param formula2 - second formula (only used with
@ -1872,19 +1867,19 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* *
*/ */
public HSSFConditionalFormattingRule createConditionalFormattingRule( public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation, byte comparisonOperation,
String formula1, String formula1,
String formula2, String formula2,
HSSFFontFormatting fontFmt, HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt, HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt) HSSFPatternFormatting patternFmt)
{ {
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook); HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt); cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt); cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt); cf.setPatternFormatting(patternFmt);
cf.setCellComparisonCondition(comparisonOperation, formula1, formula2); cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
return cf; return cf;
} }
/** /**
@ -1894,14 +1889,14 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* The formatting rules are applied by Excel when the value of the formula not equal to 0. * The formatting rules are applied by Excel when the value of the formula not equal to 0.
* *
* @param comparisonOperation - one of the following values: <p> * @param comparisonOperation - one of the following values: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li> * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p> * </p>
* @param formula1 - formula for the valued, compared with the cell * @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with * @param formula2 - second formula (only used with
@ -1914,17 +1909,17 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* *
*/ */
public HSSFConditionalFormattingRule createConditionalFormattingRule( public HSSFConditionalFormattingRule createConditionalFormattingRule(
String formula, String formula,
HSSFFontFormatting fontFmt, HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt, HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt) HSSFPatternFormatting patternFmt)
{ {
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook); HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt); cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt); cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt); cf.setPatternFormatting(patternFmt);
cf.setFormulaCondition(formula); cf.setFormulaCondition(formula);
return cf; return cf;
} }
/** /**
@ -1941,9 +1936,9 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
*/ */
public int addConditionalFormatting( HSSFConditionalFormatting cf ) public int addConditionalFormatting( HSSFConditionalFormatting cf )
{ {
HSSFConditionalFormatting cfClone = new HSSFConditionalFormatting(this,cf.cfAggregate.cloneCFAggregate()); CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
cfClone.sheet=this;
return sheet.addConditionalFormatting(cfClone.cfAggregate); return sheet.addConditionalFormatting(cfraClone);
} }
/** /**
@ -1957,49 +1952,48 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules ) public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules )
{ {
HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this); HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
cf.setFormattingRegions(regions); cf.setFormattingRegions(regions);
if( cfRules != null ) if( cfRules != null )
{ {
for( int i=0; i!= cfRules.length; i++ ) for( int i=0; i!= cfRules.length; i++ )
{ {
cf.addConditionalFormat(cfRules[i]); cf.addRule(cfRules[i]);
} }
} }
return sheet.addConditionalFormatting(cf.cfAggregate); return sheet.addConditionalFormatting(cf.getCFRecordsAggregate());
} }
/** /**
* gets Conditional Formatting object at a particular index * gets Conditional Formatting object at a particular index
* @param index of the Conditional Formatting object to fetch * @param index of the Conditional Formatting object to fetch
* @return Conditional Formatting object * @return Conditional Formatting object
*/ */
public HSSFConditionalFormatting getConditionalFormattingAt(int index) public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{ {
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index); CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null ) if( cf != null )
{ {
return new HSSFConditionalFormatting(this,cf); return new HSSFConditionalFormatting(this,cf);
} }
return null; return null;
} }
/** /**
* @return number of Conditional Formatting objects of the sheet * @return number of Conditional Formatting objects of the sheet
*/ */
public int getNumConditionalFormattings() public int getNumConditionalFormattings()
{ {
return sheet.getNumConditionalFormattings(); return sheet.getNumConditionalFormattings();
} }
/**
* removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove
*/
public void removeConditionalFormatting(int index)
{
sheet.removeConditionalFormatting(index);
}
/**
* removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove
*/
public void removeConditionalFormatting(int index)
{
sheet.removeConditionalFormatting(index);
}
} }

View File

@ -0,0 +1,283 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
# Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
#
#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
# Built-In Sheet Functions in BIFF2
0 COUNT 0 30 V R
1 IF 2 3 R V R R
2 ISNA 1 1 V V
3 ISERROR 1 1 V V
4 SUM 0 30 V R
5 AVERAGE 1 30 V R
6 MIN 1 30 V R
7 MAX 1 30 V R
8 ROW 0 1 V R
9 COLUMN 0 1 V R
10 NA 0 0 V
11 NPV 2 30 V V R
12 STDEV 1 30 V R
13 DOLLAR 1 2 V V V
14 FIXED 2 2 V V V x
15 SIN 1 1 V V
16 COS 1 1 V V
17 TAN 1 1 V V
18 ARCTAN 1 1 V V
19 PI 0 0 V
20 SQRT 1 1 V V
21 EXP 1 1 V V
22 LN 1 1 V V
23 LOG10 1 1 V V
24 ABS 1 1 V V
25 INT 1 1 V V
26 SIGN 1 1 V V
27 ROUND 2 2 V V V
28 LOOKUP 2 3 V V R R
29 INDEX 2 4 R R V V V
30 REPT 2 2 V V V
31 MID 3 3 V V V V
32 LEN 1 1 V V
33 VALUE 1 1 V V
34 TRUE 0 0 V
35 FALSE 0 0 V
36 AND 1 30 V R
37 OR 1 30 V R
38 NOT 1 1 V V
39 MOD 2 2 V V V
40 DCOUNT 3 3 V R R R
41 DSUM 3 3 V R R R
42 DAVERAGE 3 3 V R R R
43 DMIN 3 3 V R R R
44 DMAX 3 3 V R R R
45 DSTDEV 3 3 V R R R
46 VAR 1 30 V R
47 DVAR 3 3 V R R R
48 TEXT 2 2 V V V
49 LINEST 1 2 A R R x
50 TREND 1 3 A R R R x
51 LOGEST 1 2 A R R x
52 GROWTH 1 3 A R R R x
56 PV 3 5 V V V V V V
# Built-In Sheet Functions in BIFF2
57 FV 3 5 V V V V V V
58 NPER 3 5 V V V V V V
59 PMT 3 5 V V V V V V
60 RATE 3 6 V V V V V V V
61 MIRR 3 3 V R V V
62 IRR 1 2 V R V
63 RAND 0 0 V x
64 MATCH 2 3 V V R R
65 DATE 3 3 V V V V
66 TIME 3 3 V V V V
67 DAY 1 1 V V
68 MONTH 1 1 V V
69 YEAR 1 1 V V
70 WEEKDAY 1 1 V V x
71 HOUR 1 1 V V
72 MINUTE 1 1 V V
73 SECOND 1 1 V V
74 NOW 0 0 V x
75 AREAS 1 1 V R
76 ROWS 1 1 V R
77 COLUMNS 1 1 V R
78 OFFSET 3 5 R R V V V V x
82 SEARCH 2 3 V V V V
83 TRANSPOSE 1 1 A A
86 TYPE 1 1 V V
97 ATAN2 2 2 V V V
98 ASIN 1 1 V V
99 ACOS 1 1 V V
100 CHOOSE 2 30 R V R
101 HLOOKUP 3 3 V V R R x
102 VLOOKUP 3 3 V V R R x
105 ISREF 1 1 V R
109 LOG 1 2 V V V
111 CHAR 1 1 V V
112 LOWER 1 1 V V
113 UPPER 1 1 V V
114 PROPER 1 1 V V
115 LEFT 1 2 V V V
116 RIGHT 1 2 V V V
117 EXACT 2 2 V V V
118 TRIM 1 1 V V
119 REPLACE 4 4 V V V V V
120 SUBSTITUTE 3 4 V V V V V
121 CODE 1 1 V V
124 FIND 2 3 V V V V
125 CELL 1 2 V V R x
126 ISERR 1 1 V V
127 ISTEXT 1 1 V V
128 ISNUMBER 1 1 V V
129 ISBLANK 1 1 V V
130 T 1 1 V R
131 N 1 1 V R
140 DATEVALUE 1 1 V V
141 TIMEVALUE 1 1 V V
142 SLN 3 3 V V V V
143 SYD 4 4 V V V V V
144 DDB 4 5 V V V V V V
148 INDIRECT 1 2 R V V x
162 CLEAN 1 1 V V
163 MDETERM 1 1 V A
164 MINVERSE 1 1 A A
165 MMULT 2 2 A A A
167 IPMT 4 6 V V V V V V V
168 PPMT 4 6 V V V V V V V
169 COUNTA 0 30 V R
183 PRODUCT 0 30 V R
184 FACT 1 1 V V
191 DPRODUCT 3 3 V R R R
192 ISNONTEXT 1 1 V V
193 STDEVP 1 30 V R
194 VARP 1 30 V R
195 DSTDEVP 3 3 V R R R
196 DVARP 3 3 V R R R
197 TRUNC 1 1 V V x
198 ISLOGICAL 1 1 V V
199 DCOUNTA 3 3 V R R R
# New Built-In Sheet Functions in BIFF3
49 LINEST 1 4 A R R V V x
50 TREND 1 4 A R R R V x
51 LOGEST 1 4 A R R V V x
52 GROWTH 1 4 A R R R V x
197 TRUNC 1 2 V V V x
204 YEN 1 2 V V V x
205 FINDB 2 3 V V V V
206 SEARCHB 2 3 V V V V
207 REPLACEB 4 4 V V V V V
208 LEFTB 1 2 V V V
209 RIGHTB 1 2 V V V
210 MIDB 3 3 V V V V
211 LENB 1 1 V V
212 ROUNDUP 2 2 V V V
213 ROUNDDOWN 2 2 V V V
214 ASC 1 1 V V
215 JIS 1 1 V V x
219 ADDRESS 2 5 V V V V V V
220 DAYS360 2 2 V V V x
221 TODAY 0 0 V x
222 VDB 5 7 V V V V V V V V
227 MEDIAN 1 30 V R …
228 SUMPRODUCT 1 30 V A …
229 SINH 1 1 V V
230 COSH 1 1 V V
231 TANH 1 1 V V
232 ASINH 1 1 V V
233 ACOSH 1 1 V V
234 ATANH 1 1 V V
235 DGET 3 3 V R R R
244 INFO 1 1 V V
# New Built-In Sheet Functions in BIFF4
14 FIXED 2 3 V V V V x
216 RANK 2 3 V V R V
247 DB 4 5 V V V V V V
252 FREQUENCY 2 2 A R R
261 ERROR.TYPE 1 1 V V
269 AVEDEV 1 30 V R …
270 BETADIST 3 5 V V V V V V
271 GAMMALN 1 1 V V
272 BETAINV 3 5 V V V V V V
273 BINOMDIST 4 4 V V V V V
274 CHIDIST 2 2 V V V
275 CHIINV 2 2 V V V
276 COMBIN 2 2 V V V
277 CONFIDENCE 3 3 V V V V
278 CRITBINOM 3 3 V V V V
279 EVEN 1 1 V V
280 EXPONDIST 3 3 V V V V
281 FDIST 3 3 V V V V
282 FINV 3 3 V V V V
283 FISHER 1 1 V V
284 FISHERINV 1 1 V V
285 FLOOR 2 2 V V V
286 GAMMADIST 4 4 V V V V V
287 GAMMAINV 3 3 V V V V
288 CEILING 2 2 V V V
289 HYPGEOMDIST 4 4 V V V V V
290 LOGNORMDIST 3 3 V V V V
291 LOGINV 3 3 V V V V
292 NEGBINOMDIST 3 3 V V V V
293 NORMDIST 4 4 V V V V V
294 NORMSDIST 1 1 V V
295 NORMINV 3 3 V V V V
296 NORMSINV 1 1 V V
297 STANDARDIZE 3 3 V V V V
298 ODD 1 1 V V
299 PERMUT 2 2 V V V
300 POISSON 3 3 V V V V
301 TDIST 3 3 V V V V
302 WEIBULL 4 4 V V V V V
303 SUMXMY2 2 2 V A A
304 SUMX2MY2 2 2 V A A
305 SUMX2PY2 2 2 V A A
306 CHITEST 2 2 V A A
307 CORREL 2 2 V A A
308 COVAR 2 2 V A A
309 FORECAST 3 3 V V A A
310 FTEST 2 2 V A A
311 INTERCEPT 2 2 V A A
312 PEARSON 2 2 V A A
313 RSQ 2 2 V A A
314 STEYX 2 2 V A A
315 SLOPE 2 2 V A A
316 TTEST 4 4 V A A V V
317 PROB 3 4 V A A V V
318 DEVSQ 1 30 V R …
319 GEOMEAN 1 30 V R …
320 HARMEAN 1 30 V R …
321 SUMSQ 0 30 V R …
322 KURT 1 30 V R …
323 SKEW 1 30 V R …
324 ZTEST 2 3 V R V V
325 LARGE 2 2 V R V
326 SMALL 2 2 V R V
327 QUARTILE 2 2 V R V
328 PERCENTILE 2 2 V R V
329 PERCENTRANK 2 3 V R V V
330 MODE 1 30 V A
331 TRIMMEAN 2 2 V R V
332 TINV 2 2 V V V
# New Built-In Sheet Functions in BIFF5
70 WEEKDAY 1 2 V V V x
101 HLOOKUP 3 4 V V R R V x
102 VLOOKUP 3 4 V V R R V x
220 DAYS360 2 3 V V V V x
336 CONCATENATE 0 30 V V
337 POWER 2 2 V V V
342 RADIANS 1 1 V V
343 DEGREES 1 1 V V
344 SUBTOTAL 2 30 V V R
345 SUMIF 2 3 V R V R
346 COUNTIF 2 2 V R V
347 COUNTBLANK 1 1 V R
350 ISPMT 4 4 V V V V V
351 DATEDIF 3 3 V V V V
352 DATESTRING 1 1 V V
353 NUMBERSTRING 2 2 V V V
354 ROMAN 1 2 V V V
# New Built-In Sheet Functions in BIFF8
358 GETPIVOTDATA 2 30
359 HYPERLINK 1 2 V V V
360 PHONETIC 1 1 V R
361 AVERAGEA 1 30 V R …
362 MAXA 1 30 V R …
363 MINA 1 30 V R …
364 STDEVPA 1 30 V R …
365 VARPA 1 30 V R …
366 STDEVA 1 30 V R …
367 VARA 1 30 V R …

View File

@ -0,0 +1,287 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
# Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
#
#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
#
# + some manual edits !
# Built-In Sheet Functions in BIFF2
0 COUNT 0 30 V R
1 IF 2 3 R V R R
2 ISNA 1 1 V V
3 ISERROR 1 1 V V
4 SUM 0 30 V R
5 AVERAGE 1 30 V R
6 MIN 1 30 V R
7 MAX 1 30 V R
8 ROW 0 1 V R
9 COLUMN 0 1 V R
10 NA 0 0 V
11 NPV 2 30 V V R
12 STDEV 1 30 V R
13 DOLLAR 1 2 V V V
14 FIXED 2 2 V V V x
15 SIN 1 1 V V
16 COS 1 1 V V
17 TAN 1 1 V V
18 ATAN 1 1 V V
19 PI 0 0 V
20 SQRT 1 1 V V
21 EXP 1 1 V V
22 LN 1 1 V V
23 LOG10 1 1 V V
24 ABS 1 1 V V
25 INT 1 1 V V
26 SIGN 1 1 V V
27 ROUND 2 2 V V V
28 LOOKUP 2 3 V V R R
29 INDEX 2 4 R R V V V
30 REPT 2 2 V V V
31 MID 3 3 V V V V
32 LEN 1 1 V V
33 VALUE 1 1 V V
34 TRUE 0 0 V
35 FALSE 0 0 V
36 AND 1 30 V R
37 OR 1 30 V R
38 NOT 1 1 V V
39 MOD 2 2 V V V
40 DCOUNT 3 3 V R R R
41 DSUM 3 3 V R R R
42 DAVERAGE 3 3 V R R R
43 DMIN 3 3 V R R R
44 DMAX 3 3 V R R R
45 DSTDEV 3 3 V R R R
46 VAR 1 30 V R
47 DVAR 3 3 V R R R
48 TEXT 2 2 V V V
49 LINEST 1 2 A R R x
50 TREND 1 3 A R R R x
51 LOGEST 1 2 A R R x
52 GROWTH 1 3 A R R R x
56 PV 3 5 V V V V V V
# Built-In Sheet Functions in BIFF2
57 FV 3 5 V V V V V V
58 NPER 3 5 V V V V V V
59 PMT 3 5 V V V V V V
60 RATE 3 6 V V V V V V V
61 MIRR 3 3 V R V V
62 IRR 1 2 V R V
63 RAND 0 0 V x
64 MATCH 2 3 V V R R
65 DATE 3 3 V V V V
66 TIME 3 3 V V V V
67 DAY 1 1 V V
68 MONTH 1 1 V V
69 YEAR 1 1 V V
70 WEEKDAY 1 1 V V x
71 HOUR 1 1 V V
72 MINUTE 1 1 V V
73 SECOND 1 1 V V
74 NOW 0 0 V x
75 AREAS 1 1 V R
76 ROWS 1 1 V R
77 COLUMNS 1 1 V R
78 OFFSET 3 5 R R V V V V x
82 SEARCH 2 3 V V V V
83 TRANSPOSE 1 1 A A
86 TYPE 1 1 V V
97 ATAN2 2 2 V V V
98 ASIN 1 1 V V
99 ACOS 1 1 V V
100 CHOOSE 2 30 R V R
101 HLOOKUP 3 3 V V R R x
102 VLOOKUP 3 3 V V R R x
105 ISREF 1 1 V R
109 LOG 1 2 V V V
111 CHAR 1 1 V V
112 LOWER 1 1 V V
113 UPPER 1 1 V V
114 PROPER 1 1 V V
115 LEFT 1 2 V V V
116 RIGHT 1 2 V V V
117 EXACT 2 2 V V V
118 TRIM 1 1 V V
119 REPLACE 4 4 V V V V V
120 SUBSTITUTE 3 4 V V V V V
121 CODE 1 1 V V
124 FIND 2 3 V V V V
125 CELL 1 2 V V R x
126 ISERR 1 1 V V
127 ISTEXT 1 1 V V
128 ISNUMBER 1 1 V V
129 ISBLANK 1 1 V V
130 T 1 1 V R
131 N 1 1 V R
140 DATEVALUE 1 1 V V
141 TIMEVALUE 1 1 V V
142 SLN 3 3 V V V V
143 SYD 4 4 V V V V V
144 DDB 4 5 V V V V V V
148 INDIRECT 1 2 R V V x
162 CLEAN 1 1 V V
163 MDETERM 1 1 V A
164 MINVERSE 1 1 A A
165 MMULT 2 2 A A A
167 IPMT 4 6 V V V V V V V
168 PPMT 4 6 V V V V V V V
169 COUNTA 0 30 V R
183 PRODUCT 0 30 V R
184 FACT 1 1 V V
190 ISNONTEXT 1 1 V V
191 DPRODUCT 3 3 V R R R
193 STDEVP 1 30 V R
194 VARP 1 30 V R
195 DSTDEVP 3 3 V R R R
196 DVARP 3 3 V R R R
197 TRUNC 1 1 V V x
198 ISLOGICAL 1 1 V V
199 DCOUNTA 3 3 V R R R
# New Built-In Sheet Functions in BIFF3
49 LINEST 1 4 A R R V V x
50 TREND 1 4 A R R R V x
51 LOGEST 1 4 A R R V V x
52 GROWTH 1 4 A R R R V x
197 TRUNC 1 2 V V V x
204 YEN 1 2 V V V x
205 FINDB 2 3 V V V V
206 SEARCHB 2 3 V V V V
207 REPLACEB 4 4 V V V V V
208 LEFTB 1 2 V V V
209 RIGHTB 1 2 V V V
210 MIDB 3 3 V V V V
211 LENB 1 1 V V
212 ROUNDUP 2 2 V V V
213 ROUNDDOWN 2 2 V V V
214 ASC 1 1 V V
215 JIS 1 1 V V x
219 ADDRESS 2 5 V V V V V V
220 DAYS360 2 2 V V V x
221 TODAY 0 0 V x
222 VDB 5 7 V V V V V V V V
227 MEDIAN 1 30 V R …
228 SUMPRODUCT 1 30 V A …
229 SINH 1 1 V V
230 COSH 1 1 V V
231 TANH 1 1 V V
232 ASINH 1 1 V V
233 ACOSH 1 1 V V
234 ATANH 1 1 V V
235 DGET 3 3 V R R R
244 INFO 1 1 V V
# New Built-In Sheet Functions in BIFF4
14 FIXED 2 3 V V V V x
204 USDOLLAR 1 1 V V x
215 DBCS 1 1 V V x
216 RANK 2 3 V V R V
247 DB 4 5 V V V V V V
252 FREQUENCY 2 2 A R R
261 ERROR.TYPE 1 1 V V
269 AVEDEV 1 30 V R …
270 BETADIST 3 5 V V V V V V
271 GAMMALN 1 1 V V
272 BETAINV 3 5 V V V V V V
273 BINOMDIST 4 4 V V V V V
274 CHIDIST 2 2 V V V
275 CHIINV 2 2 V V V
276 COMBIN 2 2 V V V
277 CONFIDENCE 3 3 V V V V
278 CRITBINOM 3 3 V V V V
279 EVEN 1 1 V V
280 EXPONDIST 3 3 V V V V
281 FDIST 3 3 V V V V
282 FINV 3 3 V V V V
283 FISHER 1 1 V V
284 FISHERINV 1 1 V V
285 FLOOR 2 2 V V V
286 GAMMADIST 4 4 V V V V V
287 GAMMAINV 3 3 V V V V
288 CEILING 2 2 V V V
289 HYPGEOMDIST 4 4 V V V V V
290 LOGNORMDIST 3 3 V V V V
291 LOGINV 3 3 V V V V
292 NEGBINOMDIST 3 3 V V V V
293 NORMDIST 4 4 V V V V V
294 NORMSDIST 1 1 V V
295 NORMINV 3 3 V V V V
296 NORMSINV 1 1 V V
297 STANDARDIZE 3 3 V V V V
298 ODD 1 1 V V
299 PERMUT 2 2 V V V
300 POISSON 3 3 V V V V
301 TDIST 3 3 V V V V
302 WEIBULL 4 4 V V V V V
303 SUMXMY2 2 2 V A A
304 SUMX2MY2 2 2 V A A
305 SUMX2PY2 2 2 V A A
306 CHITEST 2 2 V A A
307 CORREL 2 2 V A A
308 COVAR 2 2 V A A
309 FORECAST 3 3 V V A A
310 FTEST 2 2 V A A
311 INTERCEPT 2 2 V A A
312 PEARSON 2 2 V A A
313 RSQ 2 2 V A A
314 STEYX 2 2 V A A
315 SLOPE 2 2 V A A
316 TTEST 4 4 V A A V V
317 PROB 3 4 V A A V V
318 DEVSQ 1 30 V R …
319 GEOMEAN 1 30 V R …
320 HARMEAN 1 30 V R …
321 SUMSQ 0 30 V R …
322 KURT 1 30 V R …
323 SKEW 1 30 V R …
324 ZTEST 2 3 V R V V
325 LARGE 2 2 V R V
326 SMALL 2 2 V R V
327 QUARTILE 2 2 V R V
328 PERCENTILE 2 2 V R V
329 PERCENTRANK 2 3 V R V V
330 MODE 1 30 V A
331 TRIMMEAN 2 2 V R V
332 TINV 2 2 V V V
# New Built-In Sheet Functions in BIFF5
70 WEEKDAY 1 2 V V V x
101 HLOOKUP 3 4 V V R R V x
102 VLOOKUP 3 4 V V R R V x
220 DAYS360 2 3 V V V V x
336 CONCATENATE 0 30 V V
337 POWER 2 2 V V V
342 RADIANS 1 1 V V
343 DEGREES 1 1 V V
344 SUBTOTAL 2 30 V V R
345 SUMIF 2 3 V R V R
346 COUNTIF 2 2 V R V
347 COUNTBLANK 1 1 V R
350 ISPMT 4 4 V V V V V
351 DATEDIF 3 3 V V V V
352 DATESTRING 1 1 V V
353 NUMBERSTRING 2 2 V V V
354 ROMAN 1 2 V V V
# New Built-In Sheet Functions in BIFF8
358 GETPIVOTDATA 2 30
359 HYPERLINK 1 2 V V V
360 PHONETIC 1 1 V R
361 AVERAGEA 1 30 V R …
362 MAXA 1 30 V R …
363 MINA 1 30 V R …
364 STDEVPA 1 30 V R …
365 VARPA 1 30 V R …
366 STDEVA 1 30 V R …
367 VARA 1 30 V R …

View File

@ -14,61 +14,78 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Created on May 15, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval; import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
public class Pmt extends FinanceFunction { /**
* Implementation for the PMT() Excel function.<p/>
*
* <b>Syntax:</b><br/>
* <b>PMT</b>(<b>rate</b>, <b>nper</b>, <b>pv</b>, fv, type)<p/>
*
* Returns the constant repayment amount required for a loan assuming a constant interest rate.<p/>
*
* <b>rate</b> the loan interest rate.<br/>
* <b>nper</b> the number of loan repayments.<br/>
* <b>pv</b> the present value of the future payments (or principle).<br/>
* <b>fv</b> the future value (default zero) surplus cash at the end of the loan lifetime.<br/>
* <b>type</b> whether payments are due at the beginning(1) or end(0 - default) of each payment period.<br/>
*
*/
public final class Pmt extends FinanceFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
double rate = 0, fv = 0, nper = 0, pv = 0, d = 0;
boolean type = false;
ValueEval retval = null;
ValueEval ve = null;
switch (operands.length) { if(args.length < 3 || args.length > 5) {
default: return ErrorEval.VALUE_INVALID;
retval = ErrorEval.VALUE_INVALID; }
break;
case 5:
ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol);
if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; }
type = ((BoolEval) ve).getBooleanValue();
case 4:
ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[1], srcRow, srcCol); try {
if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue(); // evaluate first three (always present) args
else { retval = ErrorEval.VALUE_INVALID; break; } double rate = evalArg(args[0], srcRow, srcCol);
double nper = evalArg(args[1], srcRow, srcCol);
double pv = evalArg(args[2], srcRow, srcCol);
double fv = 0;
boolean arePaymentsAtPeriodBeginning = false;
ve = singleOperandEvaluate(operands[2], srcRow, srcCol); switch (args.length) {
if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue(); case 5:
else { retval = ErrorEval.VALUE_INVALID; break; } ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol);
if (ve instanceof ErrorEval) {
return ve;
}
arePaymentsAtPeriodBeginning = ((BoolEval) ve).getBooleanValue();
case 4:
fv = evalArg(args[3], srcRow, srcCol);
}
double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning);
if (Double.isNaN(d)) {
return (ValueEval) ErrorEval.VALUE_INVALID;
}
if (Double.isInfinite(d)) {
return (ValueEval) ErrorEval.NUM_ERROR;
}
return new NumberEval(d);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
ve = singleOperandEvaluate(operands[3], srcRow, srcCol); private double evalArg(Eval arg, int srcRow, short srcCol) throws EvaluationException {
if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue(); ValueEval ve = singleOperandEvaluate(arg, srcRow, srcCol);
else { retval = ErrorEval.VALUE_INVALID; break; } if(ve instanceof ErrorEval) {
} throw new EvaluationException((ErrorEval) ve);
}
if (retval == null) { if (ve instanceof NumericValueEval) {
d = FinanceLib.pmt(rate, nper, pv, fv, type); return ((NumericValueEval) ve).getNumberValue();
retval = (Double.isNaN(d)) }
? (ValueEval) ErrorEval.VALUE_INVALID throw new EvaluationException(ErrorEval.VALUE_INVALID);
: (Double.isInfinite(d)) }
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -190,7 +190,7 @@ public class HWPFDocument extends POIDocument
} }
// read in the pictures stream // read in the pictures stream
_pictures = new PicturesTable(_dataStream); _pictures = new PicturesTable(this, _dataStream);
// get the start of text in the main stream // get the start of text in the main stream
int fcMin = _fib.getFcMin(); int fcMin = _fib.getFcMin();

View File

@ -19,8 +19,10 @@
package org.apache.poi.hwpf.model; package org.apache.poi.hwpf.model;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.CharacterRun; import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Picture; import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.Range;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
@ -53,6 +55,7 @@ public class PicturesTable
static final int BLOCK_TYPE_OFFSET = 0xE; static final int BLOCK_TYPE_OFFSET = 0xE;
static final int MM_MODE_TYPE_OFFSET = 0x6; static final int MM_MODE_TYPE_OFFSET = 0x6;
private HWPFDocument _document;
private byte[] _dataStream; private byte[] _dataStream;
/** @link dependency /** @link dependency
@ -61,10 +64,12 @@ public class PicturesTable
/** /**
* *
* @param document
* @param _dataStream * @param _dataStream
*/ */
public PicturesTable(byte[] _dataStream) public PicturesTable(HWPFDocument _document, byte[] _dataStream)
{ {
this._document = _document;
this._dataStream = _dataStream; this._dataStream = _dataStream;
} }
@ -119,23 +124,24 @@ public class PicturesTable
} }
/** /**
* Not all documents have all the images concatenated in the data stream
* although MS claims so. The best approach is to scan all character runs.
*
* @return a list of Picture objects found in current document * @return a list of Picture objects found in current document
*/ */
public List getAllPictures() { public List getAllPictures() {
ArrayList pictures = new ArrayList(); ArrayList pictures = new ArrayList();
int pos = 0; Range range = _document.getRange();
boolean atEnd = false; for (int i = 0; i < range.numCharacterRuns(); i++) {
CharacterRun run = range.getCharacterRun(i);
while(pos<_dataStream.length && !atEnd) { String text = run.text();
if (isBlockContainsImage(pos)) { int j = text.charAt(0);
pictures.add(new Picture(pos, _dataStream, false)); Picture picture = extractPicture(run, false);
} if (picture != null) {
pictures.add(picture);
int skipOn = LittleEndian.getInt(_dataStream, pos); }
if(skipOn <= 0) { atEnd = true; } }
pos += skipOn;
}
return pictures; return pictures;
} }

View File

@ -15,7 +15,6 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import junit.framework.Test; import junit.framework.Test;
@ -41,6 +40,7 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestMid.class); result.addTestSuite(TestMid.class);
result.addTestSuite(TestMathX.class); result.addTestSuite(TestMathX.class);
result.addTestSuite(TestMatch.class); result.addTestSuite(TestMatch.class);
result.addTestSuite(TestPmt.class);
result.addTestSuite(TestOffset.class); result.addTestSuite(TestOffset.class);
result.addTestSuite(TestRowCol.class); result.addTestSuite(TestRowCol.class);
result.addTestSuite(TestSumproduct.class); result.addTestSuite(TestSumproduct.class);
@ -50,5 +50,4 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestXYNumericFunction.class); result.addTestSuite(TestXYNumericFunction.class);
return result; return result;
} }
} }

View File

@ -0,0 +1,87 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.functions;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
/**
*
* @author Josh Micich
*/
public final class TestPmt extends TestCase {
private static void confirm(double expected, NumberEval ne) {
// only asserting accuracy to 4 fractional digits
assertEquals(expected, ne.getNumberValue(), 0.00005);
}
private static Eval invoke(Eval[] args) {
return new Pmt().evaluate(args, -1, (short)-1);
}
/**
* Invocation when not expecting an error result
*/
private static NumberEval invokeNormal(Eval[] args) {
Eval ev = invoke(args);
if(ev instanceof ErrorEval) {
throw new AssertionFailedError("Normal evaluation failed with error code: "
+ ev.toString());
}
return (NumberEval) ev;
}
private static void confirm(double expected, double rate, double nper, double pv, double fv, boolean isBeginning) {
Eval[] args = {
new NumberEval(rate),
new NumberEval(nper),
new NumberEval(pv),
new NumberEval(fv),
new NumberEval(isBeginning ? 1 : 0),
};
confirm(expected, invokeNormal(args));
}
public void testBasic() {
confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
}
public void test3args() {
Eval[] args = {
new NumberEval(0.005),
new NumberEval(24),
new NumberEval(1000),
};
Eval ev = invoke(args);
if(ev instanceof ErrorEval) {
ErrorEval err = (ErrorEval) ev;
if(err.getErrorCode() == HSSFErrorConstants.ERROR_VALUE) {
throw new AssertionFailedError("Identified bug 44691");
}
}
confirm(-44.3206, invokeNormal(args));
}
}

View File

@ -17,18 +17,15 @@
package org.apache.poi.hwpf.usermodel; package org.apache.poi.hwpf.usermodel;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.TextPiece;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.util.LittleEndian;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.util.LittleEndian;
/** /**
* Test the picture handling * Test the picture handling
* *
@ -118,6 +115,12 @@ public class TestPictures extends TestCase {
* emf image, with a crazy offset * emf image, with a crazy offset
*/ */
public void testEmfComplexImage() throws Exception { public void testEmfComplexImage() throws Exception {
/*
Commenting out this test case temporarily. The file emf_2003_image does not contain any
pictures. Instead it has an office drawing object. Need to rewrite this test after
revisiting the implementation of office drawing objects.
HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/emf_2003_image.doc")); HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/emf_2003_image.doc"));
List pics = doc.getPicturesTable().getAllPictures(); List pics = doc.getPicturesTable().getAllPictures();
@ -137,8 +140,16 @@ public class TestPictures extends TestCase {
assertEquals(4, pic.getSize()); assertEquals(4, pic.getSize());
assertEquals(0x80000000l, LittleEndian.getUInt(pic.getContent())); assertEquals(0x80000000l, LittleEndian.getUInt(pic.getContent()));
assertEquals(0x80000000l, LittleEndian.getUInt(pic.getRawContent())); assertEquals(0x80000000l, LittleEndian.getUInt(pic.getRawContent()));
*/
} }
public void testPicturesWithTable() throws Exception {
HWPFDocument doc = new HWPFDocument(new FileInputStream(
new File(dirname, "Bug44603.doc")));
List pics = doc.getPicturesTable().getAllPictures();
assertEquals(pics.size(), 2);
}
private byte[] loadImage(String filename) throws Exception { private byte[] loadImage(String filename) throws Exception {
ByteArrayOutputStream b = new ByteArrayOutputStream(); ByteArrayOutputStream b = new ByteArrayOutputStream();

Binary file not shown.

View File

@ -293,7 +293,7 @@ public final class TestFormulaParser extends TestCase {
assertEquals("FOO", tname.toFormulaString(w)); assertEquals("FOO", tname.toFormulaString(w));
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1]; AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertEquals("externalflag", tfunc.getName()); assertTrue(tfunc.isExternalFunction());
} }
public void testEmbeddedSlash() { public void testEmbeddedSlash() {
@ -888,4 +888,17 @@ public final class TestFormulaParser extends TestCase {
assertTrue(e.getMessage().startsWith("Too few arguments suppled to operation token")); assertTrue(e.getMessage().startsWith("Too few arguments suppled to operation token"));
} }
} }
public void testFuncPtgSelection() {
Workbook book = Workbook.createWorkbook();
Ptg[] ptgs;
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
assertEquals(3, ptgs.length);
if(FuncVarPtg.class == ptgs[2].getClass()) {
throw new AssertionFailedError("Identified bug 44675");
}
assertEquals(FuncPtg.class, ptgs[2].getClass());
ptgs = FormulaParser.parse("sin(1)", book);
assertEquals(2, ptgs.length);
assertEquals(FuncPtg.class, ptgs[1].getClass());
}
} }

View File

@ -15,7 +15,6 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.formula.AllFormulaTests; import org.apache.poi.hssf.record.formula.AllFormulaTests;
@ -28,10 +27,10 @@ import junit.framework.TestSuite;
* *
* @author Josh Micich * @author Josh Micich
*/ */
public class AllRecordTests { public final class AllRecordTests {
public static Test suite() { public static Test suite() {
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record"); TestSuite result = new TestSuite(AllRecordTests.class.getName());
result.addTest(AllFormulaTests.suite()); result.addTest(AllFormulaTests.suite());
@ -56,6 +55,7 @@ public class AllRecordTests {
result.addTestSuite(TestEmbeddedObjectRefSubRecord.class); result.addTestSuite(TestEmbeddedObjectRefSubRecord.class);
result.addTestSuite(TestEndSubRecord.class); result.addTestSuite(TestEndSubRecord.class);
result.addTestSuite(TestEscherAggregate.class); result.addTestSuite(TestEscherAggregate.class);
result.addTestSuite(TestExternalNameRecord.class);
result.addTestSuite(TestFontBasisRecord.class); result.addTestSuite(TestFontBasisRecord.class);
result.addTestSuite(TestFontIndexRecord.class); result.addTestSuite(TestFontIndexRecord.class);
result.addTestSuite(TestFormulaRecord.class); result.addTestSuite(TestFormulaRecord.class);

View File

@ -0,0 +1,55 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
*
* @author Josh Micich
*/
public final class TestExternalNameRecord extends TestCase {
private static final byte[] dataFDS = {
0, 0, 0, 0, 0, 0, 3, 0, 70, 68, 83, 0, 0,
};
private static ExternalNameRecord createSimpleENR() {
return new ExternalNameRecord(new TestcaseRecordInputStream((short)0x0023, dataFDS));
}
public void testBasicDeserializeReserialize() {
ExternalNameRecord enr = createSimpleENR();
assertEquals( "FDS", enr.getText());
try {
TestcaseRecordInputStream.confirmRecordEncoding(0x0023, dataFDS, enr.serialize());
} catch (ArrayIndexOutOfBoundsException e) {
if(e.getMessage().equals("15")) {
throw new AssertionFailedError("Identified bug 44695");
}
}
}
public void testBasicSize() {
ExternalNameRecord enr = createSimpleENR();
if(enr.getRecordSize() == 13) {
throw new AssertionFailedError("Identified bug 44695");
}
assertEquals(17, enr.getRecordSize());
}
}

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -28,12 +30,12 @@ import junit.framework.TestSuite;
public class AllFormulaTests { public class AllFormulaTests {
public static Test suite() { public static Test suite() {
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula"); TestSuite result = new TestSuite(AllFormulaTests.class.getName());
result.addTestSuite(TestArea3DPtg.class); result.addTestSuite(TestArea3DPtg.class);
result.addTestSuite(TestAreaErrPtg.class); result.addTestSuite(TestAreaErrPtg.class);
result.addTestSuite(TestAreaPtg.class); result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestErrPtg.class); result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class); result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestFuncPtg.class); result.addTestSuite(TestFuncPtg.class);
result.addTestSuite(TestIntersectionPtg.class); result.addTestSuite(TestIntersectionPtg.class);
result.addTestSuite(TestPercentPtg.class); result.addTestSuite(TestPercentPtg.class);
@ -42,6 +44,7 @@ public class AllFormulaTests {
result.addTestSuite(TestReferencePtg.class); result.addTestSuite(TestReferencePtg.class);
result.addTestSuite(TestSheetNameFormatter.class); result.addTestSuite(TestSheetNameFormatter.class);
result.addTestSuite(TestUnionPtg.class); result.addTestSuite(TestUnionPtg.class);
result.addTest(AllFormulaFunctionTests.suite());
return result; return result;
} }
} }

View File

@ -0,0 +1,37 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Collects all tests for this package.
*
* @author Josh Micich
*/
public class AllFormulaFunctionTests {
public static Test suite() {
TestSuite result = new TestSuite(AllFormulaFunctionTests.class.getName());
result.addTestSuite(TestFunctionMetadataRegistry.class);
result.addTestSuite(TestParseMissingBuiltInFuncs.class);
result.addTestSuite(TestReadMissingBuiltInFuncs.class);
return result;
}
}

View File

@ -0,0 +1,503 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.zip.CRC32;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* This class is not used during normal POI run-time but is used at development time to generate
* the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the
* intention of this class is to make it easier to maintain the metadata, by extracting it from
* a reliable source.
*
* @author Josh Micich
*/
public class ExcelFileFormatDocFunctionExtractor {
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
private static final class FunctionData {
private final int _index;
private final boolean _hasFootnote;
private final String _name;
private final int _minParams;
private final int _maxParams;
private final String _returnClass;
private final String _paramClasses;
private final boolean _isVolatile;
public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, boolean isVolatile) {
_index = funcIx;
_hasFootnote = hasFootnote;
_name = funcName;
_minParams = minParams;
_maxParams = maxParams;
_returnClass = returnClass;
_paramClasses = paramClasses;
_isVolatile = isVolatile;
}
public int getIndex() {
return _index;
}
public String getName() {
return _name;
}
public boolean hasFootnote() {
return _hasFootnote;
}
public String formatAsDataLine() {
return _index + "\t" + _name + "\t" + _minParams + "\t"
+ _maxParams + "\t" + _returnClass + "\t" + _paramClasses
+ "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote);
}
private static String checkMark(boolean b) {
return b ? "x" : "";
}
}
private static final class FunctionDataCollector {
private final Map _allFunctionsByIndex;
private final Map _allFunctionsByName;
private final Set _groupFunctionIndexes;
private final Set _groupFunctionNames;
private final PrintStream _ps;
public FunctionDataCollector(PrintStream ps) {
_ps = ps;
_allFunctionsByIndex = new HashMap();
_allFunctionsByName = new HashMap();
_groupFunctionIndexes = new HashSet();
_groupFunctionNames = new HashSet();
}
public void addFuntion(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, String volatileFlagStr) {
boolean isVolatile = volatileFlagStr.length() > 0;
Integer funcIxKey = new Integer(funcIx);
if(!_groupFunctionIndexes.add(funcIxKey)) {
throw new RuntimeException("Duplicate function index (" + funcIx + ")");
}
if(!_groupFunctionNames.add(funcName)) {
throw new RuntimeException("Duplicate function name '" + funcName + "'");
}
checkRedefinedFunction(hasFootnote, funcName, funcIxKey);
FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName,
minParams, maxParams, returnClass, paramClasses, isVolatile);
_allFunctionsByIndex.put(funcIxKey, fd);
_allFunctionsByName.put(funcName, fd);
}
private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) {
FunctionData fdPrev;
fdPrev = (FunctionData) _allFunctionsByIndex.get(funcIxKey);
if(fdPrev != null) {
if(fdPrev.hasFootnote() && hasNote) {
// func def can change if both have a foot-note
_allFunctionsByName.remove(fdPrev.getName());
} else {
throw new RuntimeException("changing function definition without foot-note");
}
}
fdPrev = (FunctionData) _allFunctionsByName.get(funcName);
if(fdPrev != null) {
if(fdPrev.hasFootnote() && hasNote) {
// func def can change if both have a foot-note
_allFunctionsByIndex.remove(new Integer(fdPrev.getIndex()));
} else {
throw new RuntimeException("changing function definition without foot-note");
}
}
}
public void endTableGroup(String headingText) {
Integer[] keys = new Integer[_groupFunctionIndexes.size()];
_groupFunctionIndexes.toArray(keys);
_groupFunctionIndexes.clear();
_groupFunctionNames.clear();
Arrays.sort(keys);
_ps.println("# " + headingText);
for (int i = 0; i < keys.length; i++) {
FunctionData fd = (FunctionData) _allFunctionsByIndex.get(keys[i]);
_ps.println(fd.formatAsDataLine());
}
}
}
/**
* To avoid drag-in - parse XML using only JDK.
*/
private static class EFFDocHandler implements ContentHandler {
private static final String[] HEADING_PATH_NAMES = {
"office:document-content", "office:body", "office:text", "text:h",
};
private static final String[] TABLE_BASE_PATH_NAMES = {
"office:document-content", "office:body", "office:text", "table:table",
};
private static final String[] TABLE_ROW_RELPATH_NAMES = {
"table:table-row",
};
private static final String[] TABLE_CELL_RELPATH_NAMES = {
"table:table-row", "table:table-cell", "text:p",
};
private static final String[] NOTE_REF_RELPATH_NAMES = {
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
};
private final Stack _elemNameStack;
/** <code>true</code> only when parsing the target tables */
private boolean _isInsideTable;
private final List _rowData;
private final StringBuffer _textNodeBuffer;
private final List _rowNoteFlags;
private boolean _cellHasNote;
private final FunctionDataCollector _fdc;
private String _lastHeadingText;
public EFFDocHandler(FunctionDataCollector fdc) {
_fdc = fdc;
_elemNameStack = new Stack();
_isInsideTable = false;
_rowData = new ArrayList();
_textNodeBuffer = new StringBuffer();
_rowNoteFlags = new ArrayList();
}
private boolean matchesTargetPath() {
return matchesPath(0, TABLE_BASE_PATH_NAMES);
}
private boolean matchesRelPath(String[] pathNames) {
return matchesPath(TABLE_BASE_PATH_NAMES.length, pathNames);
}
private boolean matchesPath(int baseStackIndex, String[] pathNames) {
if(_elemNameStack.size() != baseStackIndex + pathNames.length) {
return false;
}
for (int i = 0; i < pathNames.length; i++) {
if(!_elemNameStack.get(baseStackIndex + i).equals(pathNames[i])) {
return false;
}
}
return true;
}
public void characters(char[] ch, int start, int length) {
// only 2 text nodes where text is collected:
if(matchesRelPath(TABLE_CELL_RELPATH_NAMES) || matchesPath(0, HEADING_PATH_NAMES)) {
_textNodeBuffer.append(ch, start, length);
}
}
public void endElement(String namespaceURI, String localName, String name) {
String expectedName = (String) _elemNameStack.peek();
if(expectedName != name) {
throw new RuntimeException("close tag mismatch");
}
if(matchesPath(0, HEADING_PATH_NAMES)) {
_lastHeadingText = _textNodeBuffer.toString().trim();
_textNodeBuffer.setLength(0);
}
if(_isInsideTable) {
if(matchesTargetPath()) {
_fdc.endTableGroup(_lastHeadingText);
_isInsideTable = false;
} else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
String[] cellData = new String[_rowData.size()];
_rowData.toArray(cellData);
_rowData.clear();
Boolean[] noteFlags = new Boolean[_rowNoteFlags.size()];
_rowNoteFlags.toArray(noteFlags);
_rowNoteFlags.clear();
processTableRow(cellData, noteFlags);
} else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
_rowData.add(_textNodeBuffer.toString().trim());
_rowNoteFlags.add(Boolean.valueOf(_cellHasNote));
_textNodeBuffer.setLength(0);
}
}
_elemNameStack.pop();
}
private void processTableRow(String[] cellData, Boolean[] noteFlags) {
// each table row of the document contains data for two functions
if(cellData.length != 15) {
throw new RuntimeException("Bad table row size");
}
processFunction(cellData, noteFlags, 0);
processFunction(cellData, noteFlags, 8);
}
public void processFunction(String[] cellData, Boolean[] noteFlags, int i) {
String funcIxStr = cellData[i + 0];
if (funcIxStr.length() < 1) {
// empty (happens on the right hand side when there is an odd number of functions)
return;
}
int funcIx = parseInt(funcIxStr);
boolean hasFootnote = noteFlags[i + 1].booleanValue();
String funcName = cellData[i + 1];
int minParams = parseInt(cellData[i + 2]);
int maxParams = parseInt(cellData[i + 3]);
String returnClass = cellData[i + 4];
String paramClasses = cellData[i + 5];
String volatileFlagStr = cellData[i + 6];
_fdc.addFuntion(funcIx, hasFootnote, funcName, minParams, maxParams, returnClass, paramClasses, volatileFlagStr);
}
private static int parseInt(String valStr) {
try {
return Integer.parseInt(valStr);
} catch (NumberFormatException e) {
throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
}
}
public void startElement(String namespaceURI, String localName, String name, Attributes atts) {
_elemNameStack.add(name);
if(matchesTargetPath()) {
String tableName = atts.getValue("table:name");
if(tableName.startsWith("tab_fml_func") && !tableName.equals("tab_fml_func0")) {
_isInsideTable = true;
}
return;
}
if(matchesPath(0, HEADING_PATH_NAMES)) {
_textNodeBuffer.setLength(0);
} else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
_rowData.clear();
_rowNoteFlags.clear();
} else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
_textNodeBuffer.setLength(0);
_cellHasNote = false;
} else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) {
_cellHasNote = true;
}
}
public void endDocument() {
// do nothing
}
public void endPrefixMapping(String prefix) {
// do nothing
}
public void ignorableWhitespace(char[] ch, int start, int length) {
// do nothing
}
public void processingInstruction(String target, String data) {
// do nothing
}
public void setDocumentLocator(Locator locator) {
// do nothing
}
public void skippedEntity(String name) {
// do nothing
}
public void startDocument() {
// do nothing
}
public void startPrefixMapping(String prefix, String uri) {
// do nothing
}
}
private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) {
System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
XMLReader xr;
try {
xr = XMLReaderFactory.createXMLReader();
} catch (SAXException e) {
throw new RuntimeException(e);
}
xr.setContentHandler(new EFFDocHandler(fdc));
InputSource inSrc = new InputSource(is);
try {
xr.parse(inSrc);
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
private static void processFile(File effDocFile, File outFile) {
OutputStream os;
try {
os = new FileOutputStream(outFile);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
PrintStream ps = new PrintStream(os);
outputLicenseHeader(ps);
Class genClass = ExcelFileFormatDocFunctionExtractor.class;
ps.println("# Created by (" + genClass.getName() + ")");
// identify the source file
ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'");
ps.println(" (size=" + effDocFile.length() + ", crc=" + getFileCRC(effDocFile) + ")");
ps.println("#");
ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )");
ps.println("");
try {
ZipFile zf = new ZipFile(effDocFile);
InputStream is = zf.getInputStream(zf.getEntry("content.xml"));
extractFunctionData(new FunctionDataCollector(ps), is);
zf.close();
} catch (ZipException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
ps.close();
}
private static void outputLicenseHeader(PrintStream ps) {
String[] lines= {
"Licensed to the Apache Software Foundation (ASF) under one or more",
"contributor license agreements. See the NOTICE file distributed with",
"this work for additional information regarding copyright ownership.",
"The ASF licenses this file to You 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.",
};
for (int i = 0; i < lines.length; i++) {
ps.print("# ");
ps.println(lines[i]);
}
ps.println();
}
/**
* Helps identify the source file
*/
private static String getFileCRC(File f) {
CRC32 crc = new CRC32();
byte[]buf = new byte[2048];
try {
InputStream is = new FileInputStream(f);
while(true) {
int bytesRead = is.read(buf);
if(bytesRead<1) {
break;
}
crc.update(buf, 0, bytesRead);
}
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
}
private static File getSourceFile() {
if (true) {
File dir = new File("c:/josh/ref-docs");
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
return effDocFile;
}
URL url;
try {
url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
File result;
byte[]buf = new byte[2048];
try {
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
System.out.println("downloading " + url.toExternalForm());
result = File.createTempFile("excelfileformat", "odt");
OutputStream os = new FileOutputStream(result);
while(true) {
int bytesRead = is.read(buf);
if(bytesRead<1) {
break;
}
os.write(buf, 0, bytesRead);
}
is.close();
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("file downloaded ok");
return result;
}
public static void main(String[] args) {
File effDocFile = getSourceFile();
if(!effDocFile.exists()) {
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
}
File outFile = new File("functionMetadata-asGenerated.txt");
processFile(effDocFile, outFile);
}
}

View File

@ -0,0 +1,43 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import junit.framework.TestCase;
/**
*
* @author Josh Micich
*/
public final class TestFunctionMetadataRegistry extends TestCase {
public void testWellKnownFunctions() {
confirmFunction(0, "COUNT");
confirmFunction(1, "IF");
}
private static void confirmFunction(int index, String funcName) {
FunctionMetadata fm;
fm = FunctionMetadataRegistry.getFunctionByIndex(index);
assertNotNull(fm);
assertEquals(funcName, fm.getName());
fm = FunctionMetadataRegistry.getFunctionByName(funcName);
assertNotNull(fm);
assertEquals(index, fm.getIndex());
}
}

View File

@ -0,0 +1,79 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.Ptg;
/**
* @author Josh Micich
*/
public final class TestParseMissingBuiltInFuncs extends TestCase {
private static Ptg[] parse(String formula) {
Workbook book = Workbook.createWorkbook();
return FormulaParser.parse(formula, book);
}
private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) {
Ptg[] ptgs = parse(formula);
Ptg ptgF = ptgs[ptgs.length-1]; // func is last RPN token in all these formulas
if(!(ptgF instanceof AbstractFunctionPtg)) {
throw new RuntimeException("function token missing");
}
AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
if(func.getFunctionIndex() == 255) {
throw new AssertionFailedError("Failed to recognise built-in function in formula '"
+ formula + "'");
}
assertEquals(expPtgArraySize, ptgs.length);
assertEquals(funcIx, func.getFunctionIndex());
Class expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class;
assertEquals(expCls, ptgF.getClass());
}
public void testDatedif() {
int expSize = 4; // NB would be 5 if POI added tAttrVolatile properly
confirmFunc("DATEDIF(NOW(),NOW(),\"d\")", expSize, false, 351);
}
public void testDdb() {
confirmFunc("DDB(1,1,1,1,1)", 6, true, 144);
}
public void testAtan() {
confirmFunc("ATAN(1)", 2, false, 18);
}
public void testUsdollar() {
confirmFunc("USDOLLAR(1)", 2, false, 204);
}
public void testDBCS() {
confirmFunc("DBCS(\"abc\")", 2, false, 215);
}
public void testIsnontext() {
confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190);
}
}

View File

@ -0,0 +1,142 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.function;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests reading from a sample spreadsheet some built-in functions that were not properly
* registered in POI as bug #44675 (March 2008).
*
* @author Josh Micich
*/
public final class TestReadMissingBuiltInFuncs extends TestCase {
private HSSFSheet sht;
protected void setUp() {
String cwd = System.getProperty("HSSF.testdata.path");
HSSFWorkbook wb;
try {
InputStream is = new FileInputStream(new File(cwd, "missingFuncs44675.xls"));
wb = new HSSFWorkbook(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
sht = wb.getSheetAt(0);
}
public void testDatedif() {
String formula;
try {
formula = getCellFormula(0);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("Too few arguments")) {
if(e.getMessage().indexOf("AttrPtg") > 0) {
throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
}
throw afe("NOW() registered with 1 arg instead of 0");
}
if(e.getMessage().startsWith("too much stuff")) {
throw afe("DATEDIF() not registered");
}
// some other unexpected error
throw e;
}
assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
}
public void testDdb() {
String formula = getCellFormula(1);
if("externalflag(1,1,1,1,1)".equals(formula)) {
throw afe("DDB() not registered");
}
assertEquals("DDB(1,1,1,1,1)", formula);
}
public void testAtan() {
String formula = getCellFormula(2);
if(formula.equals("ARCTAN(1)")) {
throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
}
assertEquals("ATAN(1)", formula);
}
public void testUsdollar() {
String formula = getCellFormula(3);
if(formula.equals("YEN(1)")) {
throw afe("func ix 204 registered as YEN() instead of USDOLLAR()");
}
assertEquals("USDOLLAR(1)", formula);
}
public void testDBCS() {
String formula;
try {
formula = getCellFormula(4);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("too much stuff")) {
throw afe("DBCS() not registered");
}
// some other unexpected error
throw e;
} catch (NegativeArraySizeException e) {
throw afe("found err- DBCS() registered with -1 args");
}
if(formula.equals("JIS(\"abc\")")) {
throw afe("func ix 215 registered as JIS() instead of DBCS()");
}
assertEquals("DBCS(\"abc\")", formula);
}
public void testIsnontext() {
String formula;
try {
formula = getCellFormula(5);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("too much stuff")) {
throw afe("ISNONTEXT() registered with wrong index");
}
// some other unexpected error
throw e;
}
assertEquals("ISNONTEXT(\"abc\")", formula);
}
private String getCellFormula(int rowIx) {
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
if (false) {
System.err.println(result);
}
return result;
}
private static AssertionFailedError afe(String msg) {
return new AssertionFailedError(msg);
}
}

View File

@ -1218,6 +1218,30 @@ extends TestCase {
assertEquals(1, wb.getNumberOfSheets()); assertEquals(1, wb.getNumberOfSheets());
} }
/**
* User reported the wrong number of rows from the
* iterator, but we can't replicate that
*/
public void test44693() throws Exception {
FileInputStream in = new FileInputStream(new File(cwd, "44693.xls"));
HSSFWorkbook wb = new HSSFWorkbook(in);
HSSFSheet s = wb.getSheetAt(0);
// Rows are 1 to 713
assertEquals(0, s.getFirstRowNum());
assertEquals(712, s.getLastRowNum());
assertEquals(713, s.getPhysicalNumberOfRows());
// Now check the iterator
int rowsSeen = 0;
for(Iterator i = s.rowIterator(); i.hasNext(); ) {
HSSFRow r = (HSSFRow)i.next();
rowsSeen++;
}
assertEquals(713, rowsSeen);
}
} }