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 fb33f585f5
commit 8aa0c858c6
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}"/>
<!-- 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.test" location="src/testcases"/>
<property name="main.documentation" value="src/documentation"/>

View File

@ -36,6 +36,7 @@
<!-- Don't forget to update status.xml too! -->
<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">44627 - Improve the thread safety of POILogFactory</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
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
File Format freely available at <link href="http://wotsit.org">Wotsit.org</link>.</p>
detail and is only meant as a supplement to the Microsoft Word 97-2007
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
the reader has a working knowledge of the POIFS API. </p>

View File

@ -87,7 +87,7 @@
<li>anything else that seems reasonable</li>
</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
href="http://issues.apache.org/">Bugzilla</link> and nag <link
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! -->
<changes>
<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">44627 - Improve the thread safety of POILogFactory</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 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) {
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)) {
// early return for everything else besides IF()
return retval;
@ -969,6 +987,10 @@ end;
// 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
}
if (attrPtg.isSemiVolatile()) {
// similar to tAttrSpace - RPN is violated
continue;
}
}
final OperationPtg o = (OperationPtg) ptg;
@ -979,7 +1001,7 @@ end;
if(stack.isEmpty()) {
String msg = "Too few arguments suppled to operation token ("
+ o.getClass().getName() + "). Expected (" + nOperands
+ ") operands but got (" + (nOperands - j + 1) + ")";
+ ") operands but got (" + (nOperands - j - 1) + ")";
throw new IllegalStateException(msg);
}
operands[j] = (String) stack.pop();

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record;
import java.util.List;
import java.util.Stack;
import org.apache.poi.hssf.record.formula.Ptg;
@ -27,153 +26,160 @@ import org.apache.poi.util.StringUtil;
/**
* EXTERNALNAME<p/>
*
* @author josh micich
* @author Josh Micich
*/
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 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 short field_1_option_flag;
private short field_2_index;
private short field_3_not_used;
private String field_4_name;
private Ptg[] field_5_name_definition; // TODO - junits for name definition field
private short field_1_option_flag;
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);
}
public ExternalNameRecord(RecordInputStream in) {
super(in);
}
/**
* Convenience Function to determine if the name is a built-in name
*/
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
* record passed with a differing ID.
*
* @param id alleged id for this record
*/
protected void validateSid(short id) {
if (id != sid) {
throw new RecordFormatException("NOT A valid ExternalName RECORD");
}
}
/**
* called by constructor, should throw runtime exception in the event of a
* record passed with a differing ID.
*
* @param id alleged id for this record
*/
protected void validateSid(short id) {
if (id != sid) {
throw new RecordFormatException("NOT A valid ExternalName RECORD");
}
}
private int getDataSize(){
return 2 + 2 + field_4_name.length() + 2 + getNameDefinitionSize();
}
private int getDataSize(){
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.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize( int offset, byte[] data ) {
// TODO - junit tests
int dataSize = getDataSize();
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize( int offset, byte[] data ) {
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, 4 + offset, field_1_option_flag );
LittleEndian.putShort( data, 6 + offset, field_2_index );
LittleEndian.putShort( data, 8 + offset, field_3_not_used );
short nameLen = (short) field_4_name.length();
LittleEndian.putShort( data, 4 + offset, field_1_option_flag );
LittleEndian.putShort( data, 6 + offset, field_2_index );
LittleEndian.putShort( data, 8 + offset, field_3_not_used );
short nameLen = (short) field_4_name.length();
LittleEndian.putShort( data, 10 + offset, nameLen );
StringUtil.putCompressedUnicode( field_4_name, data, 10 + offset );
short defLen = (short) getNameDefinitionSize();
LittleEndian.putShort( data, 12 + nameLen + offset, defLen );
Ptg.serializePtgStack(field_5_name_definition, data, 12 + nameLen + offset );
StringUtil.putCompressedUnicode( field_4_name, data, 12 + offset );
short defLen = (short) getNameDefinitionSize();
LittleEndian.putShort( data, 12 + nameLen + offset, defLen );
Ptg.serializePtgStack(toStack(field_5_name_definition), data, 14 + nameLen + offset );
return dataSize + 4;
}
}
private int getNameDefinitionSize() {
int result = 0;
List list = field_5_name_definition;
for (int k = 0; k < list.size(); k++)
{
Ptg ptg = ( Ptg ) list.get(k);
result += ptg.getSize();
}
return result;
}
private int getNameDefinitionSize() {
int result = 0;
for (int i = 0; i < field_5_name_definition.length; i++) {
result += field_5_name_definition[i].getSize();
}
return result;
}
public int getRecordSize(){
return 6 + 2 + field_4_name.length() + 2 + getNameDefinitionSize();
}
public int getRecordSize(){
return 4 + getDataSize();
}
protected void fillFields(RecordInputStream in) {
field_1_option_flag = in.readShort();
field_2_index = in.readShort();
field_3_not_used = in.readShort();
short nameLength = in.readShort();
field_4_name = in.readCompressedUnicode(nameLength);
short formulaLen = in.readShort();
field_5_name_definition = Ptg.createParsedExpressionTokens(formulaLen, in);
}
protected void fillFields(RecordInputStream in) {
field_1_option_flag = in.readShort();
field_2_index = in.readShort();
field_3_not_used = in.readShort();
short nameLength = in.readShort();
field_4_name = in.readCompressedUnicode(nameLength);
short formulaLen = in.readShort();
field_5_name_definition = toPtgArray(Ptg.createParsedExpressionTokens(formulaLen, in));
}
public short getSid() {
return sid;
}
private static Ptg[] toPtgArray(Stack s) {
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 short getSid() {
return sid;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append(" [EXTERNALNAME ");
sb.append(" ").append(field_4_name);
sb.append(" ix=").append(field_2_index);
sb.append("]");
return sb.toString();
}
public String toString() {
StringBuffer sb = new StringBuffer();
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,54 +35,55 @@ import org.apache.poi.util.POILogger;
* @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 CFHeaderRecord header;
private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
private CFHeaderRecord header;
// List of CFRuleRecord objects
private final List rules;
public CFRecordsAggregate()
{
header = null;
rules = new ArrayList(3);
}
/**
* Create CFRecordsAggregate from a list of CF Records
* @param recs - list of {@link Record} objects
* @param offset - position of {@link CFHeaderRecord} object in the list of Record objects
* @return CFRecordsAggregate object
*/
public static CFRecordsAggregate createCFAggregate(List recs, int pOffset)
{
int offset = pOffset;
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
Record rec = ( Record ) recs.get(offset++);
if (rec.getSid() == CFHeaderRecord.sid)
{
records.add(rec);
cfRecords.header = (CFHeaderRecord)rec;
int nRules = cfRecords.header.getNumberOfConditionalFormats();
int rulesCount = 0;
while( offset<recs.size() &&
(rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
rec instanceof CFRuleRecord &&
rulesCount++ < nRules
)
{
records.add(rec);
cfRecords.rules.add(rec);
}
// List of CFRuleRecord objects
private List rules;
public CFRecordsAggregate()
{
header = null;
rules = new ArrayList(3);
}
/**
* Create CFRecordsAggregate from a list of CF Records
* @param recs - list of {@link Record} objects
* @param offset - position of {@link CFHeaderRecord} object in the list of Record objects
* @return CFRecordsAggregate object
*/
public static CFRecordsAggregate createCFAggregate(List recs, int offset)
{
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
int count = 0;
Record rec = ( Record ) recs.get(offset++);
if (rec.getSid() == CFHeaderRecord.sid)
{
records.add(rec);
cfRecords.header = (CFHeaderRecord)rec;
int nRules = cfRecords.header.getNumberOfConditionalFormats();
int rulesCount = 0;
while( offset<recs.size() &&
(rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
rec instanceof CFRuleRecord &&
rulesCount++ < nRules
)
{
records.add(rec);
cfRecords.rules.add(rec);
}
if (nRules != cfRecords.rules.size())
{
if (log.check(POILogger.DEBUG))
@ -93,66 +94,66 @@ public class CFRecordsAggregate extends Record
cfRecords.header.setNumberOfConditionalFormats(nRules);
}
}
return cfRecords;
}
/**
* Create a deep clone of the record
* @return
*/
public CFRecordsAggregate cloneCFAggregate()
{
ArrayList records = new ArrayList(this.rules.size()+1);
records.add(this.header.clone());
for (int i=0; i<this.rules.size();i++)
{
Record rec = (Record)((Record)this.rules.get(i)).clone();
records.add(rec);
}
return createCFAggregate(records, 0);
}
/** You never fill an aggregate */
}
return cfRecords;
}
/**
* Create a deep clone of the record
* @return
*/
public CFRecordsAggregate cloneCFAggregate()
{
ArrayList records = new ArrayList(this.rules.size()+1);
records.add(this.header.clone());
for (int i=0; i<this.rules.size();i++)
{
Record rec = (Record)((Record)this.rules.get(i)).clone();
records.add(rec);
}
return createCFAggregate(records, 0);
}
/** You never fill an aggregate */
protected void fillFields(RecordInputStream in)
{
}
public short getSid()
{
return sid;
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize(int offset, byte[] data)
{
int pos = offset;
int pos = offset;
if( header != null && rules.size()>0 )
{
header.setNumberOfConditionalFormats(rules.size());
pos += (( Record ) header).serialize(pos, data);
pos += (( Record ) header).serialize(pos, data);
for(Iterator itr = rules.iterator(); itr.hasNext();)
{
pos += (( Record ) itr.next()).serialize(pos, data);
}
for(Iterator itr = rules.iterator(); itr.hasNext();)
{
pos += (( Record ) itr.next()).serialize(pos, data);
}
}
return pos - offset;
return pos - offset;
}
protected void validateSid(short id)
{
// do nothing here
@ -179,21 +180,21 @@ public class CFRecordsAggregate extends Record
*/
public int getRecordSize()
{
int size = 0;
if( header != null)
{
size += header.getRecordSize();
}
if( rules != null)
{
for(Iterator irecs = rules.iterator(); irecs.hasNext(); )
{
size += (( Record ) irecs.next()).getRecordSize();
}
}
return size;
}
int size = 0;
if( header != null)
{
size += header.getRecordSize();
}
if( rules != null)
{
for(Iterator irecs = rules.iterator(); irecs.hasNext(); )
{
size += (( Record ) irecs.next()).getRecordSize();
}
}
return size;
}
/**
* String representation of CFRecordsAggregate
*/
@ -206,19 +207,15 @@ public class CFRecordsAggregate extends Record
{
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);
if(cfRule!=null)
{
buffer.append(cfRule.toString());
}
buffer.append(cfRule.toString());
}
}
buffer.append("[/CF]\n");
return buffer.toString();
}
}

View File

@ -17,8 +17,9 @@
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.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/**
@ -29,7 +30,7 @@ import org.apache.poi.hssf.model.Workbook;
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public abstract class AbstractFunctionPtg extends OperationPtg {
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
*/
@ -37,8 +38,6 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
/** All external functions have function index 255 */
private static final short FUNCTION_INDEX_EXTERNAL = 255;
private static BinaryTree map = produceHash();
protected static Object[][] functionData = produceFunctionData();
protected byte returnClass;
protected byte[] paramClass;
@ -46,14 +45,11 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
protected short field_2_fnc_index;
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("<FunctionPtg>").append("\n")
.append(" field_1_num_args=").append(field_1_num_args).append("\n")
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n")
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(field_2_fnc_index).append(" ").append(field_1_num_args);
sb.append("]");
return sb.toString();
}
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.
*/
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) {
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>
*/
protected static short lookupIndex(String name) {
Integer index = (Integer) map.getKeyForValue(name.toUpperCase());
if (index != null) return index.shortValue();
return FUNCTION_INDEX_EXTERNAL;
}
/**
* 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;
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
if (ix < 0) {
return FUNCTION_INDEX_EXTERNAL;
}
return ix;
}
public byte getDefaultOperandClass() {

View File

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

View File

@ -19,12 +19,14 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
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)
*/
public class FuncVarPtg extends AbstractFunctionPtg{
public final class FuncVarPtg extends AbstractFunctionPtg{
public final static byte sid = 0x22;
private final static int SIZE = 4;
@ -47,10 +49,12 @@ public class FuncVarPtg extends AbstractFunctionPtg{
public FuncVarPtg(String pName, byte pNumOperands) {
field_1_num_args = pNumOperands;
field_2_fnc_index = lookupIndex(pName);
try{
returnClass = ( (Byte) functionData[field_2_fnc_index][0]).byteValue();
paramClass = (byte[]) functionData[field_2_fnc_index][1];
} catch (NullPointerException npe ) {
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if(fm == null) {
// Happens only as a result of a call to FormulaParser.parse(), with a non-built-in function name
returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
} else {
returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
}
@ -79,15 +83,11 @@ public class FuncVarPtg extends AbstractFunctionPtg{
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("<FunctionVarPtg>").append("\n")
.append(" field_1_num_args=").append(field_1_num_args).append("\n")
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n")
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(lookupName(field_2_fnc_index));
sb.append(" nArgs=").append(field_1_num_args);
sb.append("]");
return sb.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.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;
CFRecordsAggregate cfAggregate;
protected HSSFConditionalFormatting(HSSFSheet sheet)
{
this.sheet = sheet;
this.cfAggregate = new CFRecordsAggregate();
private final HSSFSheet sheet;
private final CFRecordsAggregate cfAggregate;
HSSFConditionalFormatting(HSSFSheet sheet) {
this(sheet, 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.cfAggregate = cfAggregate;
}
CFRecordsAggregate getCFRecordsAggregate() {
return cfAggregate;
}
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()
{
CFHeaderRecord cfh = cfAggregate.getHeader();
List cellRanges = cfh.getCellRanges();
if (cellRanges != null)
{
return toRegionArray(cellRanges);
}
return null;
return toRegionArray(cellRanges);
}
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);
}
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);
}
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);
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>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
@ -91,11 +186,11 @@ public class HSSFConditionalFormatting
private static List mergeCellRanges(List cellRangeList)
{
boolean merged = false;
do
{
merged = false;
if( cellRangeList.size()>1 )
{
for( int i=0; i<cellRangeList.size(); i++)
@ -104,7 +199,7 @@ public class HSSFConditionalFormatting
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRange range2 = (CellRange)cellRangeList.get(j);
switch(range1.intersect(range2))
{
case CellRange.NO_INTERSECTION:
@ -147,10 +242,10 @@ public class HSSFConditionalFormatting
}
}
while( merged );
return cellRangeList;
}
/**
* Convert a List of CellRange objects to an array of regions
*
@ -161,7 +256,7 @@ public class HSSFConditionalFormatting
{
int size = cellRanges.size();
Region[] regions = new Region[size];
for (int i = 0; i != size; i++)
{
CellRange cr = (CellRange) cellRanges.get(i);
@ -170,7 +265,7 @@ public class HSSFConditionalFormatting
}
return regions;
}
/**
* Convert array of regions to a List of CellRange objects
*
@ -192,10 +287,6 @@ public class HSSFConditionalFormatting
public String toString()
{
if(cfAggregate!=null)
{
return cfAggregate.toString();
}
return null;
return cfAggregate.toString();
}
}

View File

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

View File

@ -15,11 +15,6 @@
limitations under the License.
==================================================================== */
/*
* HSSFSheet.java
*
* Created on September 30, 2001, 3:40 PM
*/
package org.apache.poi.hssf.usermodel;
import java.awt.font.FontRenderContext;
@ -374,7 +369,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
{
return lastrow;
}
/**
* Creates a data validation object
* @param obj_validation The Data validation object settings
@ -610,25 +605,25 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
}
/**
* 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
* formula must be recalculated when workbook is opened.
* @param value true if an uncalced record must be inserted or not at generation
*/
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
* formula must be recalculated when workbook is opened.
* @return true if an uncalced record must be inserted or not at generation
*/
public boolean getForceFormulaRecalculation()
{
return sheet.getUncalced();
return sheet.getUncalced();
}
/**
* determines whether the output is vertically centered on the page.
* @param value true to vertically center, false otherwise.
@ -728,13 +723,13 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
return rows.values().iterator();
}
/**
* Alias for {@link #rowIterator()} to allow
* Alias for {@link #rowIterator()} to allow
* foreach loops
*/
public Iterator iterator() {
return rowIterator();
}
/**
* used internally in the API to get the low level Sheet record represented by this
@ -1015,45 +1010,45 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
getSheet().setMargin( margin, size );
}
/**
* Answer whether protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getProtect() {
return getSheet().isProtected()[0];
}
/**
* Answer whether protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getProtect() {
return getSheet().isProtected()[0];
}
/**
* @return hashed password
*/
public short getPassword() {
return getSheet().getPassword().getPassword();
}
/**
* @return hashed password
*/
public short getPassword() {
return getSheet().getPassword().getPassword();
}
/**
* Answer whether object protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getObjectProtect() {
return getSheet().isProtected()[1];
}
/**
* Answer whether object protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getObjectProtect() {
return getSheet().isProtected()[1];
}
/**
* Answer whether scenario protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getScenarioProtect() {
return getSheet().isProtected()[2];
}
/**
* Answer whether scenario protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getScenarioProtect() {
return getSheet().isProtected()[2];
}
/**
* Sets the protection on enabled or disabled
* @param protect true => protection enabled; false => protection disabled
/**
* Sets the protection on enabled or disabled
* @param protect true => protection enabled; false => protection disabled
* @deprecated use protectSheet(String, boolean, boolean)
*/
public void setProtect(boolean protect) {
getSheet().getProtect().setProtect(protect);
}
*/
public void setProtect(boolean protect) {
getSheet().getProtect().setProtect(protect);
}
/**
* Sets the protection enabled as well as the password
@ -1083,29 +1078,29 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
sclRecord.setDenominator((short)denominator);
getSheet().setSCLRecord(sclRecord);
}
/**
* The top row in the visible view when the sheet is
* first viewed after opening it in a viewer
* The top row in the visible view when the sheet is
* first viewed after opening it in a viewer
* @return short indicating the rownum (0 based) of the top row
*/
public short getTopRow()
public short getTopRow()
{
return sheet.getTopRow();
return sheet.getTopRow();
}
/**
* The left col in the visible view when the sheet is
* first viewed after opening it in a viewer
* The left col in the visible view when the sheet is
* first viewed after opening it in a viewer
* @return short indicating the rownum (0 based) of the top row
*/
public short getLeftCol()
public short getLeftCol()
{
return sheet.getLeftCol();
return sheet.getLeftCol();
}
/**
* Sets desktop window pane display area, when the
* Sets desktop window pane display area, when the
* file is first opened in a viewer.
* @param toprow the top row to show in desktop window pane
* @param leftcol the left column to show in desktop window pane
@ -1115,49 +1110,49 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
this.sheet.setLeftCol((short)leftcol);
}
/**
* Shifts the merged regions left or right depending on mode
* <p>
* TODO: MODE , this is only row specific
* @param startRow
* @param endRow
* @param n
* @param isRow
*/
protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
List shiftedRegions = new ArrayList();
//move merged regions completely if they fall within the new region boundaries when they are shifted
for (int i = 0; i < this.getNumMergedRegions(); i++) {
Region merged = this.getMergedRegionAt(i);
/**
* Shifts the merged regions left or right depending on mode
* <p>
* TODO: MODE , this is only row specific
* @param startRow
* @param endRow
* @param n
* @param isRow
*/
protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
List shiftedRegions = new ArrayList();
//move merged regions completely if they fall within the new region boundaries when they are shifted
for (int i = 0; i < this.getNumMergedRegions(); i++) {
Region merged = this.getMergedRegionAt(i);
boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow);
boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow);
boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow);
boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow);
//dont check if it's not within the shifted area
if (! (inStart && inEnd)) continue;
//dont check if it's not within the shifted area
if (! (inStart && inEnd)) continue;
//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)){
merged.setRowFrom(merged.getRowFrom()+n);
merged.setRowTo(merged.getRowTo()+n);
//have to remove/add it back
shiftedRegions.add(merged);
this.removeMergedRegion(i);
i = i -1; // we have to back up now since we removed one
//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)){
merged.setRowFrom(merged.getRowFrom()+n);
merged.setRowTo(merged.getRowTo()+n);
//have to remove/add it back
shiftedRegions.add(merged);
this.removeMergedRegion(i);
i = i -1; // we have to back up now since we removed one
}
}
}
}
//readd so it doesn't get shifted again
Iterator iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
Region region = (Region)iterator.next();
//readd so it doesn't get shifted again
Iterator iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
Region region = (Region)iterator.next();
this.addMergedRegion(region);
}
this.addMergedRegion(region);
}
}
}
/**
* 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
*/
public void shiftRows( int startRow, int endRow, int n ) {
shiftRows(startRow, endRow, n, false, false);
shiftRows(startRow, endRow, n, false, false);
}
/**
@ -1211,7 +1206,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
shiftMerged(startRow, endRow, n, true);
sheet.shiftRowBreaks(startRow, endRow, n);
for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc )
{
HSSFRow row = getRow( rowNum );
@ -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++ )
{
cell = row2Replace.getCell( col );
if ( cell != null )
row2Replace.removeCell( cell );
}
if (row == null) continue; // Nothing to do for this row
else {
if (copyRowHeight) {
row2Replace.setHeight(row.getHeight());
}
if (row == null) continue; // Nothing to do for this row
else {
if (copyRowHeight) {
row2Replace.setHeight(row.getHeight());
}
if (resetOriginalRowHeight) {
row.setHeight((short)0xff);
}
}
if (resetOriginalRowHeight) {
row.setHeight((short)0xff);
}
}
for ( short col = row.getFirstCellNum(); col <= row.getLastCellNum(); col++ )
{
cell = row.getCell( col );
@ -1262,55 +1257,55 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
}
if ( endRow == lastrow || endRow + n > lastrow ) lastrow = Math.min( endRow + n, 65535 );
if ( startRow == firstrow || startRow + n < firstrow ) firstrow = Math.max( startRow + n, 0 );
// Update any formulas on this sheet that point to
// rows which have been moved
updateFormulasAfterShift(startRow, endRow, n);
}
/**
* Called by shiftRows to update formulas on this sheet
* to point to the new location of moved rows
*/
private void updateFormulasAfterShift(int startRow, int endRow, int n) {
// Need to look at every cell on the sheet
// Not just those that were moved
// Need to look at every cell on the sheet
// Not just those that were moved
Iterator ri = rowIterator();
while(ri.hasNext()) {
HSSFRow r = (HSSFRow)ri.next();
Iterator ci = r.cellIterator();
while(ci.hasNext()) {
HSSFCell c = (HSSFCell)ci.next();
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
// Since it's a formula cell, process the
// formula string, and look to see if
// it contains any references
FormulaParser fp = new FormulaParser(c.getCellFormula(), workbook.getWorkbook());
fp.parse();
// Look for references, and update if needed
Ptg[] ptgs = fp.getRPNPtg();
boolean changed = false;
for(int i=0; i<ptgs.length; i++) {
if(ptgs[i] instanceof ReferencePtg) {
ReferencePtg rptg = (ReferencePtg)ptgs[i];
if(startRow <= rptg.getRowAsInt() &&
rptg.getRowAsInt() <= endRow) {
// References a row that moved
rptg.setRow(rptg.getRowAsInt() + n);
changed = true;
}
}
}
// If any references were changed, then
// re-create the formula string
if(changed) {
c.setCellFormula(
fp.toFormulaString(ptgs)
);
}
}
}
HSSFRow r = (HSSFRow)ri.next();
Iterator ci = r.cellIterator();
while(ci.hasNext()) {
HSSFCell c = (HSSFCell)ci.next();
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
// Since it's a formula cell, process the
// formula string, and look to see if
// it contains any references
FormulaParser fp = new FormulaParser(c.getCellFormula(), workbook.getWorkbook());
fp.parse();
// Look for references, and update if needed
Ptg[] ptgs = fp.getRPNPtg();
boolean changed = false;
for(int i=0; i<ptgs.length; i++) {
if(ptgs[i] instanceof ReferencePtg) {
ReferencePtg rptg = (ReferencePtg)ptgs[i];
if(startRow <= rptg.getRowAsInt() &&
rptg.getRowAsInt() <= endRow) {
// References a row that moved
rptg.setRow(rptg.getRowAsInt() + n);
changed = true;
}
}
}
// If any references were changed, then
// re-create the formula string
if(changed) {
c.setCellFormula(
fp.toFormulaString(ptgs)
);
}
}
}
}
}
@ -1363,7 +1358,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
{
getSheet().createSplitPane( xSplitPos, ySplitPos, topRow, leftmostColumn, activePane );
}
/**
* Returns the information regarding the currently configured pane (split or freeze).
* @return null if no pane configured, or the pane information.
@ -1385,7 +1380,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return whether gridlines are displayed
*/
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
*/
public boolean isDisplayFormulas() {
return sheet.isDisplayFormulas();
return sheet.isDisplayFormulas();
}
/**
@ -1417,16 +1412,16 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return whether RowColHeadings are displayed
*/
public boolean isDisplayRowColHeadings() {
return sheet.isDisplayRowColHeadings();
return sheet.isDisplayRowColHeadings();
}
/**
* Sets a page break at the indicated row
* @param row FIXME: Document this!
*/
public void setRowBreak(int row) {
validateRow(row);
sheet.setRowBreak(row, (short)0, (short)255);
validateRow(row);
sheet.setRowBreak(row, (short)0, (short)255);
}
/**
@ -1435,35 +1430,35 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return FIXME: Document this!
*/
public boolean isRowBroken(int row) {
return sheet.isRowBroken(row);
return sheet.isRowBroken(row);
}
/**
* Removes the page break at the indicated row
* @param row
*/
public void removeRowBreak(int row) {
sheet.removeRowBreak(row);
sheet.removeRowBreak(row);
}
/**
* Retrieves all the horizontal page breaks
* @return all the horizontal page breaks, or null if there are no row page breaks
*/
public int[] getRowBreaks(){
//we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumRowBreaks();
if (count > 0) {
int[] returnValue = new int[count];
Iterator iterator = sheet.getRowBreaks();
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = (int)breakItem.main;
}
return returnValue;
}
return null;
//we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumRowBreaks();
if (count > 0) {
int[] returnValue = new int[count];
Iterator iterator = sheet.getRowBreaks();
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = (int)breakItem.main;
}
return returnValue;
}
return null;
}
/**
@ -1471,29 +1466,29 @@ 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
*/
public short[] getColumnBreaks(){
//we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumColumnBreaks();
if (count > 0) {
short[] returnValue = new short[count];
Iterator iterator = sheet.getColumnBreaks();
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = breakItem.main;
}
return returnValue;
}
return null;
//we can probably cache this information, but this should be a sparsely used function
int count = sheet.getNumColumnBreaks();
if (count > 0) {
short[] returnValue = new short[count];
Iterator iterator = sheet.getColumnBreaks();
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = breakItem.main;
}
return returnValue;
}
return null;
}
/**
* Sets a page break at the indicated column
* @param column
*/
public void setColumnBreak(short column) {
validateColumn(column);
sheet.setColumnBreak(column, (short)0, (short)65535);
validateColumn(column);
sheet.setColumnBreak(column, (short)0, (short)65535);
}
/**
@ -1502,33 +1497,33 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @return FIXME: Document this!
*/
public boolean isColumnBroken(short column) {
return sheet.isColumnBroken(column);
return sheet.isColumnBroken(column);
}
/**
* Removes a page break at the indicated column
* @param column
*/
public void removeColumnBreak(short column) {
sheet.removeColumnBreak(column);
sheet.removeColumnBreak(column);
}
/**
* Runs a bounds check for row numbers
* @param row
*/
protected void validateRow(int row) {
if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535");
if (row < 0) throw new IllegalArgumentException("Minumum row number is 0");
if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535");
if (row < 0) throw new IllegalArgumentException("Minumum row number is 0");
}
/**
* Runs a bounds check for column numbers
* @param column
*/
protected void validateColumn(short column) {
if (column > 255) throw new IllegalArgumentException("Maximum column number is 255");
if (column < 0) throw new IllegalArgumentException("Minimum column number is 0");
if (column > 255) throw new IllegalArgumentException("Maximum column number is 255");
if (column < 0) throw new IllegalArgumentException("Minimum column number is 0");
}
/**
@ -1573,7 +1568,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
agg.setPatriarch(patriarch);
return patriarch;
}
/**
* Returns the top-level drawing patriach, if there is
* one.
@ -1587,32 +1582,32 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* start from scratch!
*/
public HSSFPatriarch getDrawingPatriarch() {
book.findDrawingGroup();
// If there's now no drawing manager, then there's
// no drawing escher records on the workbook
if(book.getDrawingManager() == null) {
return null;
}
int found = sheet.aggregateDrawingRecords(
book.getDrawingManager(), false
);
if(found == -1) {
// Workbook has drawing stuff, but this sheet doesn't
return null;
}
// Grab our aggregate record, and wire it up
book.findDrawingGroup();
// If there's now no drawing manager, then there's
// no drawing escher records on the workbook
if(book.getDrawingManager() == null) {
return null;
}
int found = sheet.aggregateDrawingRecords(
book.getDrawingManager(), false
);
if(found == -1) {
// Workbook has drawing stuff, but this sheet doesn't
return null;
}
// Grab our aggregate record, and wire it up
EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
HSSFPatriarch patriarch = new HSSFPatriarch(this, agg);
agg.setPatriarch(patriarch);
// Have it process the records into high level objects
// as best it can do (this step may eat anything
// that isn't supported, you were warned...)
agg.convertRecordsToUserModel();
// Return what we could cope with
return patriarch;
}
@ -1666,7 +1661,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @param style the style to set
*/
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);
}
/**
@ -1687,13 +1682,13 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* '0' looks to be a good choice.
*/
char defaultChar = '0';
/**
* This is the multiple that the font height is scaled by when determining the
* boundary of rotated text.
*/
double fontHeightMultiple = 2.0;
FontRenderContext frc = new FontRenderContext(null, true, true);
HSSFWorkbook wb = new HSSFWorkbook(book);
@ -1814,7 +1809,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
/**
* 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.SIZE, new Float(font.getFontHeightInPoints()));
if (font.getBoldweight() == HSSFFont.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx);
@ -1847,86 +1842,86 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
/**
* A factory method allowing to create a conditional formatting rule
* with a cell comparison operator and
* A factory method allowing to create a conditional formatting rule
* with a cell comparison operator and
* formatting rules such as font format, border format and pattern format
*
*
* @param comparisonOperation - one of the following values: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules
* @param bordFmt - border formatting rules
* @param patternFmt - pattern formatting rules
* @return
*
*
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation,
String formula1,
String formula2,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
byte comparisonOperation,
String formula1,
String formula2,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
{
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
return cf;
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
return cf;
}
/**
* A factory method allowing to create a conditional formatting rule with a formula
* A factory method allowing to create a conditional formatting rule with a formula
* and formatting rules such as font format, border format and pattern format. <br>
*
* 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>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules
* @param bordFmt - border formatting rules
* @param patternFmt - pattern formatting rules
* @return
*
*
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
String formula,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
String formula,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
{
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setFormulaCondition(formula);
return cf;
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setFormulaCondition(formula);
return cf;
}
/**
* Adds a copy of HSSFConditionalFormatting object to the sheet
* <p>This method could be used to copy HSSFConditionalFormatting object
@ -1934,72 +1929,71 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* <pre>
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
* newSheet.addConditionalFormatting(cf);
* </pre>
*
* </pre>
*
* @param cf HSSFConditionalFormatting object
* @return index of the new Conditional Formatting object
*/
public int addConditionalFormatting( HSSFConditionalFormatting cf )
{
HSSFConditionalFormatting cfClone = new HSSFConditionalFormatting(this,cf.cfAggregate.cloneCFAggregate());
cfClone.sheet=this;
return sheet.addConditionalFormatting(cfClone.cfAggregate);
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
return sheet.addConditionalFormatting(cfraClone);
}
/**
* Allows to add a new Conditional Formatting set to the sheet.
*
* @param regions - list of rectangular regions to apply conditional formatting rules
*
* @param regions - list of rectangular regions to apply conditional formatting rules
* @param cfRules - set of up to three conditional formatting rules
*
*
* @return index of the newly created Conditional Formatting object
*/
public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules )
{
HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
cf.setFormattingRegions(regions);
if( cfRules != null )
{
for( int i=0; i!= cfRules.length; i++ )
{
cf.addConditionalFormat(cfRules[i]);
}
}
return sheet.addConditionalFormatting(cf.cfAggregate);
HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
cf.setFormattingRegions(regions);
if( cfRules != null )
{
for( int i=0; i!= cfRules.length; i++ )
{
cf.addRule(cfRules[i]);
}
}
return sheet.addConditionalFormatting(cf.getCFRecordsAggregate());
}
/**
* gets Conditional Formatting object at a particular index
* @param index of the Conditional Formatting object to fetch
* @return Conditional Formatting object
*/
public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null )
{
return new HSSFConditionalFormatting(this,cf);
}
return null;
}
/**
* @return number of Conditional Formatting objects of the sheet
*/
public int getNumConditionalFormattings()
{
return sheet.getNumConditionalFormattings();
}
/**
* gets Conditional Formatting object at a particular index
* @param index of the Conditional Formatting object to fetch
* @return Conditional Formatting object
*/
/**
* removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove
*/
public void removeConditionalFormatting(int index)
{
sheet.removeConditionalFormatting(index);
}
public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null )
{
return new HSSFConditionalFormatting(this,cf);
}
return null;
}
/**
* @return number of Conditional Formatting objects of the sheet
*/
public int 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);
}
}

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
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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.ErrorEval;
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.NumericValueEval;
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) {
double rate = 0, fv = 0, nper = 0, pv = 0, d = 0;
boolean type = false;
ValueEval retval = null;
ValueEval ve = null;
switch (operands.length) {
default:
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);
if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[2], srcRow, srcCol);
if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[3], srcRow, srcCol);
if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
}
if (retval == null) {
d = FinanceLib.pmt(rate, nper, pv, fv, type);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: (Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
if(args.length < 3 || args.length > 5) {
return ErrorEval.VALUE_INVALID;
}
try {
// evaluate first three (always present) args
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;
switch (args.length) {
case 5:
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();
}
}
private double evalArg(Eval arg, int srcRow, short srcCol) throws EvaluationException {
ValueEval ve = singleOperandEvaluate(arg, srcRow, srcCol);
if(ve instanceof ErrorEval) {
throw new EvaluationException((ErrorEval) ve);
}
if (ve instanceof NumericValueEval) {
return ((NumericValueEval) ve).getNumberValue();
}
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
}

View File

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

View File

@ -19,8 +19,10 @@
package org.apache.poi.hwpf.model;
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.Picture;
import org.apache.poi.hwpf.usermodel.Range;
import java.util.List;
import java.util.ArrayList;
@ -53,6 +55,7 @@ public class PicturesTable
static final int BLOCK_TYPE_OFFSET = 0xE;
static final int MM_MODE_TYPE_OFFSET = 0x6;
private HWPFDocument _document;
private byte[] _dataStream;
/** @link dependency
@ -61,10 +64,12 @@ public class PicturesTable
/**
*
* @param document
* @param _dataStream
*/
public PicturesTable(byte[] _dataStream)
public PicturesTable(HWPFDocument _document, byte[] _dataStream)
{
this._document = _document;
this._dataStream = _dataStream;
}
@ -119,24 +124,25 @@ 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
*/
public List getAllPictures() {
ArrayList pictures = new ArrayList();
int pos = 0;
boolean atEnd = false;
while(pos<_dataStream.length && !atEnd) {
if (isBlockContainsImage(pos)) {
pictures.add(new Picture(pos, _dataStream, false));
}
int skipOn = LittleEndian.getInt(_dataStream, pos);
if(skipOn <= 0) { atEnd = true; }
pos += skipOn;
}
Range range = _document.getRange();
for (int i = 0; i < range.numCharacterRuns(); i++) {
CharacterRun run = range.getCharacterRun(i);
String text = run.text();
int j = text.charAt(0);
Picture picture = extractPicture(run, false);
if (picture != null) {
pictures.add(picture);
}
}
return pictures;
}

View File

@ -14,7 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula.functions;
@ -41,6 +40,7 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestMid.class);
result.addTestSuite(TestMathX.class);
result.addTestSuite(TestMatch.class);
result.addTestSuite(TestPmt.class);
result.addTestSuite(TestOffset.class);
result.addTestSuite(TestRowCol.class);
result.addTestSuite(TestSumproduct.class);
@ -50,5 +50,4 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestXYNumericFunction.class);
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;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
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 org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.util.LittleEndian;
/**
* Test the picture handling
*
@ -118,6 +115,12 @@ public class TestPictures extends TestCase {
* emf image, with a crazy offset
*/
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"));
List pics = doc.getPicturesTable().getAllPictures();
@ -137,9 +140,17 @@ public class TestPictures extends TestCase {
assertEquals(4, pic.getSize());
assertEquals(0x80000000l, LittleEndian.getUInt(pic.getContent()));
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 {
ByteArrayOutputStream b = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(dirname + "/" + filename);

Binary file not shown.

View File

@ -293,7 +293,7 @@ public final class TestFormulaParser extends TestCase {
assertEquals("FOO", tname.toFormulaString(w));
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertEquals("externalflag", tfunc.getName());
assertTrue(tfunc.isExternalFunction());
}
public void testEmbeddedSlash() {
@ -888,4 +888,17 @@ public final class TestFormulaParser extends TestCase {
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

@ -14,7 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
@ -28,10 +27,10 @@ import junit.framework.TestSuite;
*
* @author Josh Micich
*/
public class AllRecordTests {
public final class AllRecordTests {
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());
@ -56,6 +55,7 @@ public class AllRecordTests {
result.addTestSuite(TestEmbeddedObjectRefSubRecord.class);
result.addTestSuite(TestEndSubRecord.class);
result.addTestSuite(TestEscherAggregate.class);
result.addTestSuite(TestExternalNameRecord.class);
result.addTestSuite(TestFontBasisRecord.class);
result.addTestSuite(TestFontIndexRecord.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;
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
import junit.framework.Test;
import junit.framework.TestSuite;
@ -28,12 +30,12 @@ import junit.framework.TestSuite;
public class AllFormulaTests {
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(TestAreaErrPtg.class);
result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestFuncPtg.class);
result.addTestSuite(TestIntersectionPtg.class);
result.addTestSuite(TestPercentPtg.class);
@ -42,6 +44,7 @@ public class AllFormulaTests {
result.addTestSuite(TestReferencePtg.class);
result.addTestSuite(TestSheetNameFormatter.class);
result.addTestSuite(TestUnionPtg.class);
result.addTest(AllFormulaFunctionTests.suite());
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());
}
/**
* 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);
}
}