merged with trunk r670185
git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_3_1_FINAL@670186 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6a0a80a25d
commit
2b835e6c19
|
@ -135,7 +135,7 @@ under the License.
|
|||
<property name="mavendist.poi.dir" location="build/maven-dist/poi"/>
|
||||
<property name="mavendist.oap.dir" location="build/maven-dist/org.apache.poi"/>
|
||||
<property name="jar.name" value="poi"/>
|
||||
<property name="version.id" value="3.1-beta2"/>
|
||||
<property name="version.id" value="3.1-beta3"/>
|
||||
<property name="halt.on.test.failure" value="true"/>
|
||||
<property name="jdk.version.source" value="1.3"
|
||||
description="JDK version of source code"/>
|
||||
|
@ -170,6 +170,7 @@ under the License.
|
|||
<path id="examples.classpath">
|
||||
<path refid="main.classpath"/>
|
||||
<pathelement location="${main.output.dir}"/>
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
</path>
|
||||
|
||||
|
||||
|
|
|
@ -10,14 +10,6 @@ Common Public License Version 1.0:
|
|||
http://www.opensource.org/licenses/cpl.php
|
||||
See http://www.junit.org/
|
||||
|
||||
A single data file of the POI component HDGF is based on VSDump,
|
||||
and is under the GNU General Public Licence version 3 (GPL v3):
|
||||
http://gplv3.fsf.org/
|
||||
Since this is a data file, and has no compiled version (the original
|
||||
file is distributed in both source and binary versions), there should
|
||||
be little difference in licencing requirements compared to the ASL.
|
||||
See http://www.gnome.ru/projects/vsdump_en.html
|
||||
|
||||
|
||||
The Office Open XML experimental support had additional dependencies,
|
||||
with their own licensing:
|
||||
|
|
|
@ -36,6 +36,34 @@
|
|||
</devs>
|
||||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">30978 - Fixed re-serialization of tRefErr3d and tAreaErr3d</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45234 - Removed incorrect shared formula conversion in CFRuleRecord</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45001 - Improved HWPF Range.replaceText()</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Support custom image renderers in HSLF</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Correctly increment the reference count of a blip when a picture is inserted</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45110 - Fixed TextShape.resizeToFitText() to properly resize TextShape</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45091 - Fixed serialization of RefN~ tokens. Simplified Ptg class hierarchy</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45133 - Fixed OBJ Record (5Dh) to pad the sub-record data to a 4-byte boundary</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45145 - Fixed Sheet to always enforce RowRecordsAggregate before ValueRecordsAggregate</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45087 - Correctly detect date formats like [Black]YYYY as being date based</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45060 - Improved token class transformation during formula parsing</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45043 - Support for getting excel cell comments when extracting text</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45025 - improved FormulaParser parse error messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45066 - fixed sheet encoding size mismatch problems</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45001 - Partial fix for HWPF Range.insertBefore() and Range.delete() with unicode characters</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44977 - Support for AM/PM in excel date formats</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Support for specifying a policy to HSSF on missing / blank cells when fetching</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44937 - Partial support for extracting Escher images from HWPF files</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44824 - Avoid an infinite loop when reading some HWPF pictures</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44898 - Correctly handle short last blocks in POIFS</action>
|
||||
</release>
|
||||
<release version="3.1-beta2" date="2008-05-26">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
</header>
|
||||
|
||||
<body>
|
||||
<section><title>POI 3.1-BETA1 Released (2008-04028)</title>
|
||||
<section><title>POI 3.1-BETA2 Released (2008-05-28)</title>
|
||||
<p>
|
||||
The POI team is pleased to announce the release of 3.1 BETA1 which is one of the final steps before 3.1 FINAL.
|
||||
The POI team is pleased to announce the release of 3.1 BETA2 which is one of the final steps before 3.1 FINAL.
|
||||
The status of this release is a beta, meaning that we encourage users to try it out.
|
||||
If you find any bugs, please report them to the POI <link href="https://issues.apache.org/bugzilla/buglist.cgi?product=POI">bug database</link> or to
|
||||
the <link href="./mailinglists.html">POI Developer List</link>.
|
||||
|
@ -45,7 +45,7 @@
|
|||
</p>
|
||||
<p>
|
||||
The release is also available from the central Maven repository
|
||||
under Group ID "org.apache.poi" and Version "3.1-beta1".
|
||||
under Group ID "org.apache.poi" and Version "3.1-beta2".
|
||||
</p>
|
||||
</section>
|
||||
<section><title>POI 3.0.2 Released</title>
|
||||
|
|
|
@ -33,6 +33,34 @@
|
|||
|
||||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">30978 - Fixed re-serialization of tRefErr3d and tAreaErr3d</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45234 - Removed incorrect shared formula conversion in CFRuleRecord</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45001 - Improved HWPF Range.replaceText()</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Support custom image renderers in HSLF</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Correctly increment the reference count of a blip when a picture is inserted</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45110 - Fixed TextShape.resizeToFitText() to properly resize TextShape</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45091 - Fixed serialization of RefN~ tokens. Simplified Ptg class hierarchy</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45133 - Fixed OBJ Record (5Dh) to pad the sub-record data to a 4-byte boundary</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45145 - Fixed Sheet to always enforce RowRecordsAggregate before ValueRecordsAggregate</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45087 - Correctly detect date formats like [Black]YYYY as being date based</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45060 - Improved token class transformation during formula parsing</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45043 - Support for getting excel cell comments when extracting text</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45025 - improved FormulaParser parse error messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45066 - fixed sheet encoding size mismatch problems</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45001 - Partial fix for HWPF Range.insertBefore() and Range.delete() with unicode characters</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44977 - Support for AM/PM in excel date formats</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Support for specifying a policy to HSSF on missing / blank cells when fetching</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44937 - Partial support for extracting Escher images from HWPF files</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44824 - Avoid an infinite loop when reading some HWPF pictures</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44898 - Correctly handle short last blocks in POIFS</action>
|
||||
</release>
|
||||
<release version="3.1-beta2" date="2008-05-26">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* ====================================================================
|
||||
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.hslf.usermodel.examples;
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hslf.model.*;
|
||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
||||
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
||||
import org.apache.poi.hslf.record.Record;
|
||||
import org.apache.poi.hslf.usermodel.*;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* For each slide iterate over shapes and found associated sound data.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class SoundFinder {
|
||||
public static void main(String[] args) throws Exception {
|
||||
SlideShow ppt = new SlideShow(new FileInputStream(args[0]));
|
||||
SoundData[] sounds = ppt.getSoundData();
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for (int i = 0; i < slide.length; i++) {
|
||||
Shape[] shape = slide[i].getShapes();
|
||||
for (int j = 0; j < shape.length; j++) {
|
||||
int soundRef = getSoundReference(shape[j]);
|
||||
if(soundRef != -1) {
|
||||
System.out.println("Slide["+i+"], shape["+j+"], soundRef: "+soundRef);
|
||||
System.out.println(" " + sounds[soundRef].getSoundName());
|
||||
System.out.println(" " + sounds[soundRef].getSoundType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given shape is associated with a sound.
|
||||
* @return 0-based reference to a sound in the sound collection
|
||||
* or -1 if the shape is not associated with a sound
|
||||
*/
|
||||
protected static int getSoundReference(Shape shape){
|
||||
int soundRef = -1;
|
||||
//dive into the shape container and search for InteractiveInfoAtom
|
||||
EscherContainerRecord spContainer = shape.getSpContainer();
|
||||
List spchild = spContainer.getChildRecords();
|
||||
for (Iterator it = spchild.iterator(); it.hasNext();) {
|
||||
EscherRecord obj = (EscherRecord) it.next();
|
||||
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
|
||||
byte[] data = obj.serialize();
|
||||
Record[] records = Record.findChildRecords(data, 8,
|
||||
data.length - 8);
|
||||
for (int j = 0; j < records.length; j++) {
|
||||
if (records[j] instanceof InteractiveInfo) {
|
||||
InteractiveInfoAtom info = ((InteractiveInfo)records[j]).getInteractiveInfoAtom();
|
||||
if (info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
|
||||
soundRef = info.getSoundRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return soundRef;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ package org.apache.poi;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -191,6 +192,11 @@ public abstract class POIDocument {
|
|||
System.err.println("Couldn't write property set with name " + name + " as not supported by HPSF yet");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the document out to the specified output stream
|
||||
*/
|
||||
public abstract void write(OutputStream out) throws IOException;
|
||||
|
||||
/**
|
||||
* Copies nodes from one POIFS to the other minus the excepts
|
||||
|
|
|
@ -65,20 +65,27 @@ public class EscherClientAnchorRecord
|
|||
int size = 0;
|
||||
|
||||
// Always find 4 two byte entries. Sometimes find 9
|
||||
field_1_flag = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_2_col1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_3_dx1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_4_row1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
if(bytesRemaining >= 18) {
|
||||
field_5_dy1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_6_col2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_7_dx2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_8_row2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_9_dy2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
shortRecord = false;
|
||||
} else {
|
||||
shortRecord = true;
|
||||
}
|
||||
if (bytesRemaining == 4) // Word format only 4 bytes
|
||||
{
|
||||
// Not sure exactly what the format is quite yet, likely a reference to a PLC
|
||||
}
|
||||
else
|
||||
{
|
||||
field_1_flag = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_2_col1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_3_dx1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_4_row1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
if(bytesRemaining >= 18) {
|
||||
field_5_dy1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_6_col2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_7_dx2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_8_row2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_9_dy2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
shortRecord = false;
|
||||
} else {
|
||||
shortRecord = true;
|
||||
}
|
||||
}
|
||||
bytesRemaining -= size;
|
||||
remainingData = new byte[bytesRemaining];
|
||||
System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining );
|
||||
|
|
|
@ -238,6 +238,10 @@ public class EscherDggRecord
|
|||
return maxDgId;
|
||||
}
|
||||
|
||||
public void setMaxDrawingGroupId(int id){
|
||||
maxDgId = id;
|
||||
}
|
||||
|
||||
public FileIdCluster[] getFileIdClusters()
|
||||
{
|
||||
return field_5_fileIdClusters;
|
||||
|
|
|
@ -87,7 +87,8 @@ public final class BiffViewer {
|
|||
records.add(record);
|
||||
if (activeRecord != null)
|
||||
activeRecord.dump(ps);
|
||||
activeRecord = new RecordDetails(recStream.getSid(), recStream.getLength(), (int)recStream.getPos(), record);
|
||||
int startPos = (int)(recStream.getPos()-recStream.getLength() - 4);
|
||||
activeRecord = new RecordDetails(recStream.getSid(), recStream.getLength(), startPos, record);
|
||||
}
|
||||
if (dump) {
|
||||
recStream.dumpBytes(ps);
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||
|
||||
import org.apache.poi.POIOLE2TextExtractor;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFComment;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
|
@ -39,6 +40,7 @@ public class ExcelExtractor extends POIOLE2TextExtractor {
|
|||
private HSSFWorkbook wb;
|
||||
private boolean includeSheetNames = true;
|
||||
private boolean formulasNotResults = false;
|
||||
private boolean includeCellComments = false;
|
||||
|
||||
public ExcelExtractor(HSSFWorkbook wb) {
|
||||
super(wb);
|
||||
|
@ -62,6 +64,12 @@ public class ExcelExtractor extends POIOLE2TextExtractor {
|
|||
public void setFormulasNotResults(boolean formulasNotResults) {
|
||||
this.formulasNotResults = formulasNotResults;
|
||||
}
|
||||
/**
|
||||
* Should cell comments be included? Default is true
|
||||
*/
|
||||
public void setIncludeCellComments(boolean includeCellComments) {
|
||||
this.includeCellComments = includeCellComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives the text contents of the file
|
||||
|
@ -128,6 +136,15 @@ public class ExcelExtractor extends POIOLE2TextExtractor {
|
|||
break;
|
||||
}
|
||||
|
||||
// Output the comment, if requested and exists
|
||||
HSSFComment comment = cell.getCellComment();
|
||||
if(includeCellComments && comment != null) {
|
||||
// Replace any newlines with spaces, otherwise it
|
||||
// breaks the output
|
||||
String commentText = comment.getString().getString().replace('\n', ' ');
|
||||
text.append(" Comment by "+comment.getAuthor()+": "+commentText);
|
||||
}
|
||||
|
||||
// Output a tab if we're not on the last cell
|
||||
if(outputContents && k < (lastCell-1)) {
|
||||
text.append("\t");
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package org.apache.poi.hssf.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -55,23 +54,23 @@ public final class FormulaParser {
|
|||
*/
|
||||
static final class FormulaParseException extends RuntimeException {
|
||||
// This class was given package scope until it would become clear that it is useful to
|
||||
// general client code.
|
||||
// general client code.
|
||||
public FormulaParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static int FORMULA_TYPE_CELL = 0;
|
||||
public static int FORMULA_TYPE_SHARED = 1;
|
||||
public static int FORMULA_TYPE_ARRAY =2;
|
||||
public static int FORMULA_TYPE_CONDFOMRAT = 3;
|
||||
public static int FORMULA_TYPE_NAMEDRANGE = 4;
|
||||
public static final int FORMULA_TYPE_CELL = 0;
|
||||
public static final int FORMULA_TYPE_SHARED = 1;
|
||||
public static final int FORMULA_TYPE_ARRAY =2;
|
||||
public static final int FORMULA_TYPE_CONDFOMRAT = 3;
|
||||
public static final int FORMULA_TYPE_NAMEDRANGE = 4;
|
||||
|
||||
private final String formulaString;
|
||||
private final int formulaLength;
|
||||
private int pointer;
|
||||
|
||||
private final List tokens = new Stack();
|
||||
private ParseNode _rootNode;
|
||||
|
||||
/**
|
||||
* Used for spotting if we have a cell reference,
|
||||
|
@ -127,39 +126,34 @@ public final class FormulaParser {
|
|||
// Just return if so and reset 'look' to something to keep
|
||||
// SkipWhitespace from spinning
|
||||
look = (char)0;
|
||||
}
|
||||
}
|
||||
pointer++;
|
||||
//System.out.println("Got char: "+ look);
|
||||
}
|
||||
|
||||
/** Report What Was Expected */
|
||||
private RuntimeException expected(String s) {
|
||||
return new FormulaParseException(s + " Expected");
|
||||
String msg = "Parse error near char " + (pointer-1) + " '" + look + "'"
|
||||
+ " in specified formula '" + formulaString + "'. Expected "
|
||||
+ s;
|
||||
return new FormulaParseException(msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Recognize an Alpha Character */
|
||||
private boolean IsAlpha(char c) {
|
||||
return Character.isLetter(c) || c == '$' || c=='_';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Recognize a Decimal Digit */
|
||||
private boolean IsDigit(char c) {
|
||||
//System.out.println("Checking digit for"+c);
|
||||
return Character.isDigit(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Recognize an Alphanumeric */
|
||||
private boolean IsAlNum(char c) {
|
||||
return (IsAlpha(c) || IsDigit(c));
|
||||
}
|
||||
|
||||
|
||||
/** Recognize White Space */
|
||||
private boolean IsWhite( char c) {
|
||||
return (c ==' ' || c== TAB);
|
||||
|
@ -175,7 +169,7 @@ public final class FormulaParser {
|
|||
/**
|
||||
* Consumes the next input character if it is equal to the one specified otherwise throws an
|
||||
* unchecked exception. This method does <b>not</b> consume whitespace (before or after the
|
||||
* matched character).
|
||||
* matched character).
|
||||
*/
|
||||
private void Match(char x) {
|
||||
if (look != x) {
|
||||
|
@ -215,7 +209,6 @@ public final class FormulaParser {
|
|||
return Token.toString();
|
||||
}
|
||||
|
||||
|
||||
/** Get a Number */
|
||||
private String GetNum() {
|
||||
StringBuffer value = new StringBuffer();
|
||||
|
@ -227,14 +220,15 @@ public final class FormulaParser {
|
|||
return value.length() == 0 ? null : value.toString();
|
||||
}
|
||||
|
||||
/** Parse and Translate a String Identifier */
|
||||
private Ptg parseIdent() {
|
||||
String name;
|
||||
name = GetName();
|
||||
private ParseNode parseFunctionOrIdentifier() {
|
||||
String name = GetName();
|
||||
if (look == '('){
|
||||
//This is a function
|
||||
return function(name);
|
||||
}
|
||||
return new ParseNode(parseIdentifier(name));
|
||||
}
|
||||
private Ptg parseIdentifier(String name) {
|
||||
|
||||
if (look == ':' || look == '.') { // this is a AreaReference
|
||||
GetChar();
|
||||
|
@ -278,88 +272,45 @@ public final class FormulaParser {
|
|||
// This can be either a cell ref or a named range
|
||||
// Try to spot which it is
|
||||
boolean cellRef = CELL_REFERENCE_PATTERN.matcher(name).matches();
|
||||
|
||||
|
||||
if (cellRef) {
|
||||
return new ReferencePtg(name);
|
||||
return new RefPtg(name);
|
||||
}
|
||||
|
||||
for(int i = 0; i < book.getNumberOfNames(); i++) {
|
||||
// named range name matching is case insensitive
|
||||
if(book.getNameAt(i).getNameName().equalsIgnoreCase(name)) {
|
||||
if(book.getNameAt(i).getNameName().equalsIgnoreCase(name)) {
|
||||
return new NamePtg(name, book);
|
||||
}
|
||||
}
|
||||
throw new FormulaParseException("Found reference to named range \""
|
||||
throw new FormulaParseException("Found reference to named range \""
|
||||
+ name + "\", but that named range wasn't defined!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pointer to the last token to the latest function argument list.
|
||||
* @param obj
|
||||
*/
|
||||
private void addArgumentPointer(List argumentPointers) {
|
||||
argumentPointers.add(tokens.get(tokens.size()-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Note - Excel function names are 'case aware but not case sensitive'. This method may end
|
||||
* up creating a defined name record in the workbook if the specified name is not an internal
|
||||
* Excel function, and has not been encountered before.
|
||||
*
|
||||
* @param name case preserved function name (as it was entered/appeared in the formula).
|
||||
* Excel function, and has not been encountered before.
|
||||
*
|
||||
* @param name case preserved function name (as it was entered/appeared in the formula).
|
||||
*/
|
||||
private Ptg function(String name) {
|
||||
int numArgs =0 ;
|
||||
// Note regarding parameter -
|
||||
private ParseNode function(String name) {
|
||||
NamePtg nameToken = null;
|
||||
// Note regarding parameter -
|
||||
if(!AbstractFunctionPtg.isInternalFunctionName(name)) {
|
||||
// external functions get a Name token which points to a defined name record
|
||||
NamePtg nameToken = new NamePtg(name, this.book);
|
||||
|
||||
nameToken = new NamePtg(name, this.book);
|
||||
|
||||
// in the token tree, the name is more or less the first argument
|
||||
numArgs++;
|
||||
tokens.add(nameToken);
|
||||
}
|
||||
//average 2 args per function
|
||||
List argumentPointers = new ArrayList(2);
|
||||
|
||||
Match('(');
|
||||
numArgs += Arguments(argumentPointers);
|
||||
ParseNode[] args = Arguments();
|
||||
Match(')');
|
||||
|
||||
return getFunction(name, numArgs, argumentPointers);
|
||||
return getFunction(name, nameToken, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the size of all the ptgs after the provided index (inclusive).
|
||||
* <p>
|
||||
* Initially used to count a goto
|
||||
* @param index
|
||||
* @return int
|
||||
*/
|
||||
private int getPtgSize(int index) {
|
||||
int count = 0;
|
||||
|
||||
Iterator ptgIterator = tokens.listIterator(index);
|
||||
while (ptgIterator.hasNext()) {
|
||||
Ptg ptg = (Ptg)ptgIterator.next();
|
||||
count+=ptg.getSize();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private int getPtgSize(int start, int end) {
|
||||
int count = 0;
|
||||
int index = start;
|
||||
Iterator ptgIterator = tokens.listIterator(index);
|
||||
while (ptgIterator.hasNext() && index <= end) {
|
||||
Ptg ptg = (Ptg)ptgIterator.next();
|
||||
count+=ptg.getSize();
|
||||
index++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
/**
|
||||
* Generates the variable function ptg for the formula.
|
||||
* <p>
|
||||
|
@ -368,84 +319,35 @@ public final class FormulaParser {
|
|||
* @param numArgs
|
||||
* @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this function
|
||||
*/
|
||||
private AbstractFunctionPtg getFunction(String name, int numArgs, List argumentPointers) {
|
||||
private ParseNode getFunction(String name, NamePtg namePtg, ParseNode[] args) {
|
||||
|
||||
boolean isVarArgs;
|
||||
int funcIx;
|
||||
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase());
|
||||
int numArgs = args.length;
|
||||
if(fm == null) {
|
||||
if (namePtg == null) {
|
||||
throw new IllegalStateException("NamePtg must be supplied for external functions");
|
||||
}
|
||||
// must be external function
|
||||
isVarArgs = true;
|
||||
funcIx = FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL;
|
||||
} else {
|
||||
isVarArgs = !fm.hasFixedArgsLength();
|
||||
funcIx = fm.getIndex();
|
||||
validateNumArgs(numArgs, fm);
|
||||
ParseNode[] allArgs = new ParseNode[numArgs+1];
|
||||
allArgs[0] = new ParseNode(namePtg);
|
||||
System.arraycopy(args, 0, allArgs, 1, numArgs);
|
||||
return new ParseNode(new FuncVarPtg(name, (byte)(numArgs+1)), allArgs);
|
||||
}
|
||||
|
||||
if (namePtg != null) {
|
||||
throw new IllegalStateException("NamePtg no applicable to internal functions");
|
||||
}
|
||||
boolean isVarArgs = !fm.hasFixedArgsLength();
|
||||
int funcIx = fm.getIndex();
|
||||
validateNumArgs(args.length, fm);
|
||||
|
||||
AbstractFunctionPtg retval;
|
||||
if(isVarArgs) {
|
||||
retval = new FuncVarPtg(name, (byte)numArgs);
|
||||
} else {
|
||||
retval = new FuncPtg(funcIx);
|
||||
}
|
||||
if (!name.equals(AbstractFunctionPtg.FUNCTION_NAME_IF)) {
|
||||
// early return for everything else besides IF()
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
AttrPtg ifPtg = new AttrPtg();
|
||||
ifPtg.setData((short)7); //mirroring excel output
|
||||
ifPtg.setOptimizedIf(true);
|
||||
|
||||
if (argumentPointers.size() != 2 && argumentPointers.size() != 3) {
|
||||
throw new IllegalArgumentException("["+argumentPointers.size()+"] Arguments Found - An IF formula requires 2 or 3 arguments. IF(CONDITION, TRUE_VALUE, FALSE_VALUE [OPTIONAL]");
|
||||
}
|
||||
|
||||
//Biffview of an IF formula record indicates the attr ptg goes after the condition ptgs and are
|
||||
//tracked in the argument pointers
|
||||
//The beginning first argument pointer is the last ptg of the condition
|
||||
int ifIndex = tokens.indexOf(argumentPointers.get(0))+1;
|
||||
tokens.add(ifIndex, ifPtg);
|
||||
|
||||
//we now need a goto ptgAttr to skip to the end of the formula after a true condition
|
||||
//the true condition is should be inserted after the last ptg in the first argument
|
||||
|
||||
int gotoIndex = tokens.indexOf(argumentPointers.get(1))+1;
|
||||
|
||||
AttrPtg goto1Ptg = new AttrPtg();
|
||||
goto1Ptg.setGoto(true);
|
||||
|
||||
|
||||
tokens.add(gotoIndex, goto1Ptg);
|
||||
|
||||
|
||||
if (numArgs > 2) { //only add false jump if there is a false condition
|
||||
|
||||
//second goto to skip past the function ptg
|
||||
AttrPtg goto2Ptg = new AttrPtg();
|
||||
goto2Ptg.setGoto(true);
|
||||
goto2Ptg.setData((short)(retval.getSize()-1));
|
||||
//Page 472 of the Microsoft Excel Developer's kit states that:
|
||||
//The b(or w) field specifies the number byes (or words to skip, minus 1
|
||||
|
||||
tokens.add(goto2Ptg); //this goes after all the arguments are defined
|
||||
}
|
||||
|
||||
//data portion of the if ptg points to the false subexpression (Page 472 of MS Excel Developer's kit)
|
||||
//count the number of bytes after the ifPtg to the False Subexpression
|
||||
//doesn't specify -1 in the documentation
|
||||
ifPtg.setData((short)(getPtgSize(ifIndex+1, gotoIndex)));
|
||||
|
||||
//count all the additional (goto) ptgs but dont count itself
|
||||
int ptgCount = this.getPtgSize(gotoIndex)-goto1Ptg.getSize()+retval.getSize();
|
||||
if (ptgCount > Short.MAX_VALUE) {
|
||||
throw new RuntimeException("Ptg Size exceeds short when being specified for a goto ptg in an if");
|
||||
}
|
||||
|
||||
goto1Ptg.setData((short)(ptgCount-1));
|
||||
|
||||
return retval;
|
||||
return new ParseNode(retval, args);
|
||||
}
|
||||
|
||||
private void validateNumArgs(int numArgs, FunctionMetadata fm) {
|
||||
|
@ -474,99 +376,99 @@ public final class FormulaParser {
|
|||
private static boolean isArgumentDelimiter(char ch) {
|
||||
return ch == ',' || ch == ')';
|
||||
}
|
||||
|
||||
|
||||
/** get arguments to a function */
|
||||
private int Arguments(List argumentPointers) {
|
||||
private ParseNode[] Arguments() {
|
||||
//average 2 args per function
|
||||
List temp = new ArrayList(2);
|
||||
SkipWhite();
|
||||
if(look == ')') {
|
||||
return 0;
|
||||
return ParseNode.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
boolean missedPrevArg = true;
|
||||
|
||||
int numArgs = 0;
|
||||
while(true) {
|
||||
while (true) {
|
||||
SkipWhite();
|
||||
if(isArgumentDelimiter(look)) {
|
||||
if(missedPrevArg) {
|
||||
tokens.add(new MissingArgPtg());
|
||||
addArgumentPointer(argumentPointers);
|
||||
if (isArgumentDelimiter(look)) {
|
||||
if (missedPrevArg) {
|
||||
temp.add(new ParseNode(MissingArgPtg.instance));
|
||||
numArgs++;
|
||||
}
|
||||
if(look == ')') {
|
||||
if (look == ')') {
|
||||
break;
|
||||
}
|
||||
Match(',');
|
||||
missedPrevArg = true;
|
||||
continue;
|
||||
}
|
||||
comparisonExpression();
|
||||
addArgumentPointer(argumentPointers);
|
||||
temp.add(comparisonExpression());
|
||||
numArgs++;
|
||||
missedPrevArg = false;
|
||||
SkipWhite();
|
||||
if (!isArgumentDelimiter(look)) {
|
||||
throw expected("',' or ')'");
|
||||
}
|
||||
}
|
||||
return numArgs;
|
||||
ParseNode[] result = new ParseNode[temp.size()];
|
||||
temp.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Parse and Translate a Math Factor */
|
||||
private void powerFactor() {
|
||||
percentFactor();
|
||||
private ParseNode powerFactor() {
|
||||
ParseNode result = percentFactor();
|
||||
while(true) {
|
||||
SkipWhite();
|
||||
if(look != '^') {
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
Match('^');
|
||||
percentFactor();
|
||||
tokens.add(new PowerPtg());
|
||||
ParseNode other = percentFactor();
|
||||
result = new ParseNode(PowerPtg.instance, result, other);
|
||||
}
|
||||
}
|
||||
|
||||
private void percentFactor() {
|
||||
tokens.add(parseSimpleFactor());
|
||||
|
||||
private ParseNode percentFactor() {
|
||||
ParseNode result = parseSimpleFactor();
|
||||
while(true) {
|
||||
SkipWhite();
|
||||
if(look != '%') {
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
Match('%');
|
||||
tokens.add(new PercentPtg());
|
||||
result = new ParseNode(PercentPtg.instance, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* factors (without ^ or % )
|
||||
*/
|
||||
private Ptg parseSimpleFactor() {
|
||||
private ParseNode parseSimpleFactor() {
|
||||
SkipWhite();
|
||||
switch(look) {
|
||||
case '#':
|
||||
return parseErrorLiteral();
|
||||
return new ParseNode(parseErrorLiteral());
|
||||
case '-':
|
||||
Match('-');
|
||||
powerFactor();
|
||||
return new UnaryMinusPtg();
|
||||
return new ParseNode(UnaryMinusPtg.instance, powerFactor());
|
||||
case '+':
|
||||
Match('+');
|
||||
powerFactor();
|
||||
return new UnaryPlusPtg();
|
||||
return new ParseNode(UnaryPlusPtg.instance, powerFactor());
|
||||
case '(':
|
||||
Match('(');
|
||||
comparisonExpression();
|
||||
ParseNode inside = comparisonExpression();
|
||||
Match(')');
|
||||
return new ParenthesisPtg();
|
||||
return new ParseNode(ParenthesisPtg.instance, inside);
|
||||
case '"':
|
||||
return parseStringLiteral();
|
||||
case ',':
|
||||
case ')':
|
||||
return new MissingArgPtg(); // TODO - not quite the right place to recognise a missing arg
|
||||
return new ParseNode(parseStringLiteral());
|
||||
}
|
||||
if (IsAlpha(look) || look == '\''){
|
||||
return parseIdent();
|
||||
return parseFunctionOrIdentifier();
|
||||
}
|
||||
// else - assume number
|
||||
return parseNumber();
|
||||
return new ParseNode(parseNumber());
|
||||
}
|
||||
|
||||
|
||||
|
@ -704,10 +606,9 @@ public final class FormulaParser {
|
|||
}
|
||||
|
||||
|
||||
private StringPtg parseStringLiteral()
|
||||
{
|
||||
private StringPtg parseStringLiteral() {
|
||||
Match('"');
|
||||
|
||||
|
||||
StringBuffer token = new StringBuffer();
|
||||
while (true) {
|
||||
if (look == '"') {
|
||||
|
@ -723,28 +624,30 @@ public final class FormulaParser {
|
|||
}
|
||||
|
||||
/** Parse and Translate a Math Term */
|
||||
private void Term() {
|
||||
powerFactor();
|
||||
private ParseNode Term() {
|
||||
ParseNode result = powerFactor();
|
||||
while(true) {
|
||||
SkipWhite();
|
||||
Ptg operator;
|
||||
switch(look) {
|
||||
case '*':
|
||||
Match('*');
|
||||
powerFactor();
|
||||
tokens.add(new MultiplyPtg());
|
||||
continue;
|
||||
operator = MultiplyPtg.instance;
|
||||
break;
|
||||
case '/':
|
||||
Match('/');
|
||||
powerFactor();
|
||||
tokens.add(new DividePtg());
|
||||
continue;
|
||||
operator = DividePtg.instance;
|
||||
break;
|
||||
default:
|
||||
return result; // finished with Term
|
||||
}
|
||||
return; // finished with Term
|
||||
ParseNode other = powerFactor();
|
||||
result = new ParseNode(operator, result, other);
|
||||
}
|
||||
}
|
||||
|
||||
private void comparisonExpression() {
|
||||
concatExpression();
|
||||
|
||||
private ParseNode comparisonExpression() {
|
||||
ParseNode result = concatExpression();
|
||||
while (true) {
|
||||
SkipWhite();
|
||||
switch(look) {
|
||||
|
@ -752,72 +655,75 @@ public final class FormulaParser {
|
|||
case '>':
|
||||
case '<':
|
||||
Ptg comparisonToken = getComparisonToken();
|
||||
concatExpression();
|
||||
tokens.add(comparisonToken);
|
||||
ParseNode other = concatExpression();
|
||||
result = new ParseNode(comparisonToken, result, other);
|
||||
continue;
|
||||
}
|
||||
return; // finished with predicate expression
|
||||
return result; // finished with predicate expression
|
||||
}
|
||||
}
|
||||
|
||||
private Ptg getComparisonToken() {
|
||||
if(look == '=') {
|
||||
Match(look);
|
||||
return new EqualPtg();
|
||||
return EqualPtg.instance;
|
||||
}
|
||||
boolean isGreater = look == '>';
|
||||
Match(look);
|
||||
if(isGreater) {
|
||||
if(look == '=') {
|
||||
Match('=');
|
||||
return new GreaterEqualPtg();
|
||||
return GreaterEqualPtg.instance;
|
||||
}
|
||||
return new GreaterThanPtg();
|
||||
return GreaterThanPtg.instance;
|
||||
}
|
||||
switch(look) {
|
||||
case '=':
|
||||
Match('=');
|
||||
return new LessEqualPtg();
|
||||
return LessEqualPtg.instance;
|
||||
case '>':
|
||||
Match('>');
|
||||
return new NotEqualPtg();
|
||||
return NotEqualPtg.instance;
|
||||
}
|
||||
return new LessThanPtg();
|
||||
return LessThanPtg.instance;
|
||||
}
|
||||
|
||||
|
||||
private void concatExpression() {
|
||||
additiveExpression();
|
||||
|
||||
private ParseNode concatExpression() {
|
||||
ParseNode result = additiveExpression();
|
||||
while (true) {
|
||||
SkipWhite();
|
||||
if(look != '&') {
|
||||
break; // finished with concat expression
|
||||
}
|
||||
Match('&');
|
||||
additiveExpression();
|
||||
tokens.add(new ConcatPtg());
|
||||
ParseNode other = additiveExpression();
|
||||
result = new ParseNode(ConcatPtg.instance, result, other);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Parse and Translate an Expression */
|
||||
private void additiveExpression() {
|
||||
Term();
|
||||
private ParseNode additiveExpression() {
|
||||
ParseNode result = Term();
|
||||
while (true) {
|
||||
SkipWhite();
|
||||
Ptg operator;
|
||||
switch(look) {
|
||||
case '+':
|
||||
Match('+');
|
||||
Term();
|
||||
tokens.add(new AddPtg());
|
||||
continue;
|
||||
operator = AddPtg.instance;
|
||||
break;
|
||||
case '-':
|
||||
Match('-');
|
||||
Term();
|
||||
tokens.add(new SubtractPtg());
|
||||
continue;
|
||||
operator = SubtractPtg.instance;
|
||||
break;
|
||||
default:
|
||||
return result; // finished with additive expression
|
||||
}
|
||||
return; // finished with additive expression
|
||||
ParseNode other = Term();
|
||||
result = new ParseNode(operator, result, other);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,17 +741,18 @@ end;
|
|||
**/
|
||||
|
||||
|
||||
/** API call to execute the parsing of the formula
|
||||
*
|
||||
/**
|
||||
* API call to execute the parsing of the formula
|
||||
* @deprecated use Ptg[] FormulaParser.parse(String, HSSFWorkbook) directly
|
||||
*/
|
||||
public void parse() {
|
||||
pointer=0;
|
||||
GetChar();
|
||||
comparisonExpression();
|
||||
_rootNode = comparisonExpression();
|
||||
|
||||
if(pointer <= formulaLength) {
|
||||
String msg = "Unused input [" + formulaString.substring(pointer-1)
|
||||
+ "] after attempting to parse the formula [" + formulaString + "]";
|
||||
String msg = "Unused input [" + formulaString.substring(pointer-1)
|
||||
+ "] after attempting to parse the formula [" + formulaString + "]";
|
||||
throw new FormulaParseException(msg);
|
||||
}
|
||||
}
|
||||
|
@ -860,92 +767,18 @@ end;
|
|||
* a result of the parsing
|
||||
*/
|
||||
public Ptg[] getRPNPtg() {
|
||||
return getRPNPtg(FORMULA_TYPE_CELL);
|
||||
return getRPNPtg(FORMULA_TYPE_CELL);
|
||||
}
|
||||
|
||||
public Ptg[] getRPNPtg(int formulaType) {
|
||||
Node node = createTree();
|
||||
setRootLevelRVA(node, formulaType);
|
||||
setParameterRVA(node,formulaType);
|
||||
return (Ptg[]) tokens.toArray(new Ptg[0]);
|
||||
OperandClassTransformer oct = new OperandClassTransformer(formulaType);
|
||||
// RVA is for 'operand class': 'reference', 'value', 'array'
|
||||
oct.transformFormula(_rootNode);
|
||||
return ParseNode.toTokenArray(_rootNode);
|
||||
}
|
||||
|
||||
private void setRootLevelRVA(Node n, int formulaType) {
|
||||
//Pg 16, excelfileformat.pdf @ openoffice.org
|
||||
Ptg p = n.getValue();
|
||||
if (formulaType == FormulaParser.FORMULA_TYPE_NAMEDRANGE) {
|
||||
if (p.getDefaultOperandClass() == Ptg.CLASS_REF) {
|
||||
setClass(n,Ptg.CLASS_REF);
|
||||
} else {
|
||||
setClass(n,Ptg.CLASS_ARRAY);
|
||||
}
|
||||
} else {
|
||||
setClass(n,Ptg.CLASS_VALUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setParameterRVA(Node n, int formulaType) {
|
||||
Ptg p = n.getValue();
|
||||
int numOperands = n.getNumChildren();
|
||||
if (p instanceof AbstractFunctionPtg) {
|
||||
for (int i =0;i<numOperands;i++) {
|
||||
setParameterRVA(n.getChild(i),((AbstractFunctionPtg)p).getParameterClass(i),formulaType);
|
||||
// if (n.getChild(i).getValue() instanceof AbstractFunctionPtg) {
|
||||
// setParameterRVA(n.getChild(i),formulaType);
|
||||
// }
|
||||
setParameterRVA(n.getChild(i),formulaType);
|
||||
}
|
||||
} else {
|
||||
for (int i =0;i<numOperands;i++) {
|
||||
setParameterRVA(n.getChild(i),formulaType);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void setParameterRVA(Node n, int expectedClass,int formulaType) {
|
||||
Ptg p = n.getValue();
|
||||
if (expectedClass == Ptg.CLASS_REF) { //pg 15, table 1
|
||||
if (p.getDefaultOperandClass() == Ptg.CLASS_REF ) {
|
||||
setClass(n, Ptg.CLASS_REF);
|
||||
}
|
||||
if (p.getDefaultOperandClass() == Ptg.CLASS_VALUE) {
|
||||
if (formulaType==FORMULA_TYPE_CELL || formulaType == FORMULA_TYPE_SHARED) {
|
||||
setClass(n,Ptg.CLASS_VALUE);
|
||||
} else {
|
||||
setClass(n,Ptg.CLASS_ARRAY);
|
||||
}
|
||||
}
|
||||
if (p.getDefaultOperandClass() == Ptg.CLASS_ARRAY ) {
|
||||
setClass(n, Ptg.CLASS_ARRAY);
|
||||
}
|
||||
} else if (expectedClass == Ptg.CLASS_VALUE) { //pg 15, table 2
|
||||
if (formulaType == FORMULA_TYPE_NAMEDRANGE) {
|
||||
setClass(n,Ptg.CLASS_ARRAY) ;
|
||||
} else {
|
||||
setClass(n,Ptg.CLASS_VALUE);
|
||||
}
|
||||
} else { //Array class, pg 16.
|
||||
if (p.getDefaultOperandClass() == Ptg.CLASS_VALUE &&
|
||||
(formulaType==FORMULA_TYPE_CELL || formulaType == FORMULA_TYPE_SHARED)) {
|
||||
setClass(n,Ptg.CLASS_VALUE);
|
||||
} else {
|
||||
setClass(n,Ptg.CLASS_ARRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setClass(Node n, byte theClass) {
|
||||
Ptg p = n.getValue();
|
||||
if (p instanceof AbstractFunctionPtg || !(p instanceof OperationPtg)) {
|
||||
p.setClass(theClass);
|
||||
} else {
|
||||
for (int i =0;i<n.getNumChildren();i++) {
|
||||
setClass(n.getChild(i),theClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Convience method which takes in a list then passes it to the
|
||||
* Convenience method which takes in a list then passes it to the
|
||||
* other toFormulaString signature.
|
||||
* @param book workbook for 3D and named references
|
||||
* @param lptgs list of Ptg, can be null or empty
|
||||
|
@ -960,7 +793,7 @@ end;
|
|||
return retval;
|
||||
}
|
||||
/**
|
||||
* Convience method which takes in a list then passes it to the
|
||||
* Convenience method which takes in a list then passes it to the
|
||||
* other toFormulaString signature. Works on the current
|
||||
* workbook for 3D and named references
|
||||
* @param lptgs list of Ptg, can be null or empty
|
||||
|
@ -993,11 +826,11 @@ end;
|
|||
// TODO - put comment and throw exception in toFormulaString() of these classes
|
||||
continue;
|
||||
}
|
||||
if (! (ptg instanceof OperationPtg)) {
|
||||
stack.push(ptg.toFormulaString(book));
|
||||
if (ptg instanceof ParenthesisPtg) {
|
||||
String contents = (String)stack.pop();
|
||||
stack.push ("(" + contents + ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ptg instanceof AttrPtg) {
|
||||
AttrPtg attrPtg = ((AttrPtg) ptg);
|
||||
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
|
||||
|
@ -1008,34 +841,31 @@ end;
|
|||
continue;
|
||||
// but if it ever did, care must be taken:
|
||||
// tAttrSpace comes *before* the operand it applies to, which may be consistent
|
||||
// with how the formula text appears but is against the RPN ordering assumed here
|
||||
// with how the formula text appears but is against the RPN ordering assumed here
|
||||
}
|
||||
if (attrPtg.isSemiVolatile()) {
|
||||
// similar to tAttrSpace - RPN is violated
|
||||
continue;
|
||||
}
|
||||
if (!attrPtg.isSum()) {
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
if (attrPtg.isSum()) {
|
||||
String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
|
||||
stack.push(attrPtg.toFormulaString(operands));
|
||||
continue;
|
||||
}
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
}
|
||||
|
||||
final OperationPtg o = (OperationPtg) ptg;
|
||||
int nOperands = o.getNumberOfOperands();
|
||||
final String[] operands = new String[nOperands];
|
||||
|
||||
for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
|
||||
if(stack.isEmpty()) {
|
||||
String msg = "Too few arguments suppled to operation token ("
|
||||
+ o.getClass().getName() + "). Expected (" + nOperands
|
||||
+ ") operands but got (" + (nOperands - j - 1) + ")";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
operands[j] = (String) stack.pop();
|
||||
if (! (ptg instanceof OperationPtg)) {
|
||||
stack.push(ptg.toFormulaString(book));
|
||||
continue;
|
||||
}
|
||||
|
||||
OperationPtg o = (OperationPtg) ptg;
|
||||
String[] operands = getOperands(stack, o.getNumberOfOperands());
|
||||
stack.push(o.toFormulaString(operands));
|
||||
}
|
||||
if(stack.isEmpty()) {
|
||||
// inspection of the code above reveals that every stack.pop() is followed by a
|
||||
// inspection of the code above reveals that every stack.pop() is followed by a
|
||||
// stack.push(). So this is either an internal error or impossible.
|
||||
throw new IllegalStateException("Stack underflow");
|
||||
}
|
||||
|
@ -1047,6 +877,20 @@ end;
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String[] getOperands(Stack stack, int nOperands) {
|
||||
String[] operands = new String[nOperands];
|
||||
|
||||
for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
|
||||
if(stack.isEmpty()) {
|
||||
String msg = "Too few arguments supplied to operation. Expected (" + nOperands
|
||||
+ ") operands but got (" + (nOperands - j - 1) + ")";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
operands[j] = (String) stack.pop();
|
||||
}
|
||||
return operands;
|
||||
}
|
||||
/**
|
||||
* Static method to convert an array of Ptgs in RPN order
|
||||
* to a human readable string format in infix mode. Works
|
||||
|
@ -1057,59 +901,4 @@ end;
|
|||
public String toFormulaString(Ptg[] ptgs) {
|
||||
return toFormulaString(book, ptgs);
|
||||
}
|
||||
|
||||
|
||||
/** Create a tree representation of the RPN token array
|
||||
*used to run the class(RVA) change algo
|
||||
*/
|
||||
private Node createTree() {
|
||||
Stack stack = new Stack();
|
||||
int numPtgs = tokens.size();
|
||||
OperationPtg o;
|
||||
int numOperands;
|
||||
Node[] operands;
|
||||
for (int i=0;i<numPtgs;i++) {
|
||||
if (tokens.get(i) instanceof OperationPtg) {
|
||||
|
||||
o = (OperationPtg) tokens.get(i);
|
||||
numOperands = o.getNumberOfOperands();
|
||||
operands = new Node[numOperands];
|
||||
for (int j=0;j<numOperands;j++) {
|
||||
operands[numOperands-j-1] = (Node) stack.pop();
|
||||
}
|
||||
Node result = new Node(o);
|
||||
result.setChildren(operands);
|
||||
stack.push(result);
|
||||
} else {
|
||||
stack.push(new Node((Ptg)tokens.get(i)));
|
||||
}
|
||||
}
|
||||
return (Node) stack.pop();
|
||||
}
|
||||
|
||||
/** toString on the parser instance returns the RPN ordered list of tokens
|
||||
* Useful for testing
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i=0;i<tokens.size();i++) {
|
||||
buf.append( ( (Ptg)tokens.get(i)).toFormulaString(book));
|
||||
buf.append(' ');
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/** Private helper class, used to create a tree representation of the formula*/
|
||||
private static final class Node {
|
||||
private Ptg value=null;
|
||||
private Node[] children=new Node[0];
|
||||
private int numChild=0;
|
||||
public Node(Ptg val) {
|
||||
value = val;
|
||||
}
|
||||
public void setChildren(Node[] child) {children = child;numChild=child.length;}
|
||||
public int getNumChildren() {return numChild;}
|
||||
public Node getChild(int number) {return children[number];}
|
||||
public Ptg getValue() {return value;}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ import org.apache.poi.hssf.record.SupBookRecord;
|
|||
*
|
||||
* In BIFF8 the Link Table consists of
|
||||
* <ul>
|
||||
* <li>one or more EXTERNALBOOK Blocks<p/>
|
||||
* <li>zero or more EXTERNALBOOK Blocks<p/>
|
||||
* each consisting of
|
||||
* <ul>
|
||||
* <li>exactly one EXTERNALBOOK (0x01AE) record</li>
|
||||
|
@ -55,7 +55,7 @@ import org.apache.poi.hssf.record.SupBookRecord;
|
|||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>exactly one EXTERNSHEET (0x0017) record</li>
|
||||
* <li>zero or one EXTERNSHEET (0x0017) record</li>
|
||||
* <li>zero or more DEFINEDNAME (0x0018) records</li>
|
||||
* </ul>
|
||||
*
|
||||
|
@ -63,6 +63,7 @@ import org.apache.poi.hssf.record.SupBookRecord;
|
|||
* @author Josh Micich
|
||||
*/
|
||||
final class LinkTable {
|
||||
// TODO make this class into a record aggregate
|
||||
|
||||
private static final class CRNBlock {
|
||||
|
||||
|
@ -79,8 +80,8 @@ final class LinkTable {
|
|||
_crns = crns;
|
||||
}
|
||||
public CRNRecord[] getCrns() {
|
||||
return (CRNRecord[]) _crns.clone();
|
||||
}
|
||||
return (CRNRecord[]) _crns.clone();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ExternalBookBlock {
|
||||
|
@ -136,16 +137,19 @@ final class LinkTable {
|
|||
while(rs.peekNextClass() == SupBookRecord.class) {
|
||||
temp.add(new ExternalBookBlock(rs));
|
||||
}
|
||||
if(temp.size() < 1) {
|
||||
throw new RuntimeException("Need at least one EXTERNALBOOK blocks");
|
||||
}
|
||||
|
||||
_externalBookBlocks = new ExternalBookBlock[temp.size()];
|
||||
temp.toArray(_externalBookBlocks);
|
||||
temp.clear();
|
||||
|
||||
// If link table is present, there is always 1 of ExternSheetRecord
|
||||
Record next = rs.getNext();
|
||||
_externSheetRecord = (ExternSheetRecord)next;
|
||||
|
||||
if (_externalBookBlocks.length > 0) {
|
||||
// If any ExternalBookBlock present, there is always 1 of ExternSheetRecord
|
||||
Record next = rs.getNext();
|
||||
_externSheetRecord = (ExternSheetRecord) next;
|
||||
} else {
|
||||
_externSheetRecord = null;
|
||||
}
|
||||
|
||||
_definedNames = new ArrayList();
|
||||
// collect zero or more DEFINEDNAMEs id=0x18
|
||||
while(rs.peekNextClass() == NameRecord.class) {
|
||||
|
@ -222,7 +226,7 @@ final class LinkTable {
|
|||
public void addName(NameRecord name) {
|
||||
_definedNames.add(name);
|
||||
|
||||
// TODO - this is messy
|
||||
// TODO - this is messy
|
||||
// Not the most efficient way but the other way was causing too many bugs
|
||||
int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
|
||||
if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid);
|
||||
|
@ -242,8 +246,8 @@ final class LinkTable {
|
|||
|
||||
public int getSheetIndexFromExternSheetIndex(int externSheetNumber) {
|
||||
if (externSheetNumber >= _externSheetRecord.getNumOfREFStructures()) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return _externSheetRecord.getREFRecordAt(externSheetNumber).getIndexToFirstSupBook();
|
||||
}
|
||||
|
||||
|
@ -265,7 +269,7 @@ final class LinkTable {
|
|||
ExternSheetSubRecord esr = _externSheetRecord.getREFRecordAt(i);
|
||||
|
||||
if (esr.getIndexToFirstSupBook() == sheetNumber
|
||||
&& esr.getIndexToLastSupBook() == sheetNumber){
|
||||
&& esr.getIndexToLastSupBook() == sheetNumber){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/* ====================================================================
|
||||
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.model;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
||||
import org.apache.poi.hssf.record.formula.ControlPtg;
|
||||
import org.apache.poi.hssf.record.formula.ValueOperatorPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* This class performs 'operand class' transformation. Non-base tokens are classified into three
|
||||
* operand classes:
|
||||
* <ul>
|
||||
* <li>reference</li>
|
||||
* <li>value</li>
|
||||
* <li>array</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
*
|
||||
* The final operand class chosen for each token depends on the formula type and the token's place
|
||||
* in the formula. If POI gets the operand class wrong, Excel <em>may</em> interpret the formula
|
||||
* incorrectly. This condition is typically manifested as a formula cell that displays as '#VALUE!',
|
||||
* but resolves correctly when the user presses F2, enter.<p/>
|
||||
*
|
||||
* The logic implemented here was partially inspired by the description in
|
||||
* "OpenOffice.org's Documentation of the Microsoft Excel File Format". The model presented there
|
||||
* seems to be inconsistent with observed Excel behaviour (These differences have not been fully
|
||||
* investigated). The implementation in this class has been heavily modified in order to satisfy
|
||||
* concrete examples of how Excel performs the same logic (see TestRVA).<p/>
|
||||
*
|
||||
* Hopefully, as additional important test cases are identified and added to the test suite,
|
||||
* patterns might become more obvious in this code and allow for simplification.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class OperandClassTransformer {
|
||||
|
||||
private final int _formulaType;
|
||||
|
||||
public OperandClassTransformer(int formulaType) {
|
||||
_formulaType = formulaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the supplied formula parse tree, calling <tt>Ptg.setClass()</tt> for each non-base
|
||||
* token to set its operand class.
|
||||
*/
|
||||
public void transformFormula(ParseNode rootNode) {
|
||||
byte rootNodeOperandClass;
|
||||
switch (_formulaType) {
|
||||
case FormulaParser.FORMULA_TYPE_CELL:
|
||||
rootNodeOperandClass = Ptg.CLASS_VALUE;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Incomplete code - formula type ("
|
||||
+ _formulaType + ") not supported yet");
|
||||
|
||||
}
|
||||
transformNode(rootNode, rootNodeOperandClass, false);
|
||||
}
|
||||
|
||||
private void transformNode(ParseNode node, byte desiredOperandClass,
|
||||
boolean callerForceArrayFlag) {
|
||||
Ptg token = node.getToken();
|
||||
ParseNode[] children = node.getChildren();
|
||||
if (token instanceof ValueOperatorPtg || token instanceof ControlPtg) {
|
||||
// Value Operator Ptgs and Control are base tokens, so token will be unchanged
|
||||
|
||||
// but any child nodes are processed according to desiredOperandClass and callerForceArrayFlag
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
ParseNode child = children[i];
|
||||
transformNode(child, desiredOperandClass, callerForceArrayFlag);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (token instanceof AbstractFunctionPtg) {
|
||||
transformFunctionNode((AbstractFunctionPtg) token, children, desiredOperandClass,
|
||||
callerForceArrayFlag);
|
||||
return;
|
||||
}
|
||||
if (children.length > 0) {
|
||||
throw new IllegalStateException("Node should not have any children");
|
||||
}
|
||||
|
||||
if (token.isBaseToken()) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
if (callerForceArrayFlag) {
|
||||
switch (desiredOperandClass) {
|
||||
case Ptg.CLASS_VALUE:
|
||||
case Ptg.CLASS_ARRAY:
|
||||
token.setClass(Ptg.CLASS_ARRAY);
|
||||
break;
|
||||
case Ptg.CLASS_REF:
|
||||
token.setClass(Ptg.CLASS_REF);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected operand class ("
|
||||
+ desiredOperandClass + ")");
|
||||
}
|
||||
} else {
|
||||
token.setClass(desiredOperandClass);
|
||||
}
|
||||
}
|
||||
|
||||
private void transformFunctionNode(AbstractFunctionPtg afp, ParseNode[] children,
|
||||
byte desiredOperandClass, boolean callerForceArrayFlag) {
|
||||
|
||||
boolean localForceArrayFlag;
|
||||
byte defaultReturnOperandClass = afp.getDefaultOperandClass();
|
||||
|
||||
if (callerForceArrayFlag) {
|
||||
switch (defaultReturnOperandClass) {
|
||||
case Ptg.CLASS_REF:
|
||||
if (desiredOperandClass == Ptg.CLASS_REF) {
|
||||
afp.setClass(Ptg.CLASS_REF);
|
||||
} else {
|
||||
afp.setClass(Ptg.CLASS_ARRAY);
|
||||
}
|
||||
localForceArrayFlag = false;
|
||||
break;
|
||||
case Ptg.CLASS_ARRAY:
|
||||
afp.setClass(Ptg.CLASS_ARRAY);
|
||||
localForceArrayFlag = false;
|
||||
break;
|
||||
case Ptg.CLASS_VALUE:
|
||||
afp.setClass(Ptg.CLASS_ARRAY);
|
||||
localForceArrayFlag = true;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected operand class ("
|
||||
+ defaultReturnOperandClass + ")");
|
||||
}
|
||||
} else {
|
||||
if (defaultReturnOperandClass == desiredOperandClass) {
|
||||
localForceArrayFlag = false;
|
||||
// an alternative would have been to for non-base Ptgs to set their operand class
|
||||
// from their default, but this would require the call in many subclasses because
|
||||
// the default OC is not known until the end of the constructor
|
||||
afp.setClass(defaultReturnOperandClass);
|
||||
} else {
|
||||
switch (desiredOperandClass) {
|
||||
case Ptg.CLASS_VALUE:
|
||||
// always OK to set functions to return 'value'
|
||||
afp.setClass(Ptg.CLASS_VALUE);
|
||||
localForceArrayFlag = false;
|
||||
break;
|
||||
case Ptg.CLASS_ARRAY:
|
||||
switch (defaultReturnOperandClass) {
|
||||
case Ptg.CLASS_REF:
|
||||
afp.setClass(Ptg.CLASS_REF);
|
||||
break;
|
||||
case Ptg.CLASS_VALUE:
|
||||
afp.setClass(Ptg.CLASS_ARRAY);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected operand class ("
|
||||
+ defaultReturnOperandClass + ")");
|
||||
}
|
||||
localForceArrayFlag = (defaultReturnOperandClass == Ptg.CLASS_VALUE);
|
||||
break;
|
||||
case Ptg.CLASS_REF:
|
||||
switch (defaultReturnOperandClass) {
|
||||
case Ptg.CLASS_ARRAY:
|
||||
afp.setClass(Ptg.CLASS_ARRAY);
|
||||
break;
|
||||
case Ptg.CLASS_VALUE:
|
||||
afp.setClass(Ptg.CLASS_VALUE);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected operand class ("
|
||||
+ defaultReturnOperandClass + ")");
|
||||
}
|
||||
localForceArrayFlag = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected operand class ("
|
||||
+ desiredOperandClass + ")");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
ParseNode child = children[i];
|
||||
byte paramOperandClass = afp.getParameterClass(i);
|
||||
transformNode(child, paramOperandClass, localForceArrayFlag);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/* ====================================================================
|
||||
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.model;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
||||
/**
|
||||
* Represents a syntactic element from a formula by encapsulating the corresponding <tt>Ptg</tt>
|
||||
* token. Each <tt>ParseNode</tt> may have child <tt>ParseNode</tt>s in the case when the wrapped
|
||||
* <tt>Ptg</tt> is non-atomic.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ParseNode {
|
||||
|
||||
public static final ParseNode[] EMPTY_ARRAY = { };
|
||||
private final Ptg _token;
|
||||
private final ParseNode[] _children;
|
||||
private boolean _isIf;
|
||||
private final int _tokenCount;
|
||||
|
||||
public ParseNode(Ptg token, ParseNode[] children) {
|
||||
_token = token;
|
||||
_children = children;
|
||||
_isIf = isIf(token);
|
||||
int tokenCount = 1;
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
tokenCount += children[i].getTokenCount();
|
||||
}
|
||||
if (_isIf) {
|
||||
// there will be 2 or 3 extra tAttr tokens according to whether the false param is present
|
||||
tokenCount += children.length;
|
||||
}
|
||||
_tokenCount = tokenCount;
|
||||
}
|
||||
public ParseNode(Ptg token) {
|
||||
this(token, EMPTY_ARRAY);
|
||||
}
|
||||
public ParseNode(Ptg token, ParseNode child0) {
|
||||
this(token, new ParseNode[] { child0, });
|
||||
}
|
||||
public ParseNode(Ptg token, ParseNode child0, ParseNode child1) {
|
||||
this(token, new ParseNode[] { child0, child1, });
|
||||
}
|
||||
private int getTokenCount() {
|
||||
return _tokenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the array of <tt>Ptg</tt> tokens for the specified tree.
|
||||
*/
|
||||
public static Ptg[] toTokenArray(ParseNode rootNode) {
|
||||
TokenCollector temp = new TokenCollector(rootNode.getTokenCount());
|
||||
rootNode.collectPtgs(temp);
|
||||
return temp.getResult();
|
||||
}
|
||||
private void collectPtgs(TokenCollector temp) {
|
||||
if (isIf(getToken())) {
|
||||
collectIfPtgs(temp);
|
||||
return;
|
||||
}
|
||||
for (int i=0; i< getChildren().length; i++) {
|
||||
getChildren()[i].collectPtgs(temp);
|
||||
}
|
||||
temp.add(getToken());
|
||||
}
|
||||
/**
|
||||
* The IF() function gets marked up with two or three tAttr tokens.
|
||||
* Similar logic will be required for CHOOSE() when it is supported
|
||||
*
|
||||
* See excelfileformat.pdf sec 3.10.5 "tAttr (19H)
|
||||
*/
|
||||
private void collectIfPtgs(TokenCollector temp) {
|
||||
|
||||
// condition goes first
|
||||
getChildren()[0].collectPtgs(temp);
|
||||
|
||||
// placeholder for tAttrIf
|
||||
int ifAttrIndex = temp.createPlaceholder();
|
||||
|
||||
// true parameter
|
||||
getChildren()[1].collectPtgs(temp);
|
||||
|
||||
// placeholder for first skip attr
|
||||
int skipAfterTrueParamIndex = temp.createPlaceholder();
|
||||
int trueParamSize = temp.sumTokenSizes(ifAttrIndex+1, skipAfterTrueParamIndex);
|
||||
|
||||
AttrPtg attrIf = new AttrPtg();
|
||||
attrIf.setOptimizedIf(true);
|
||||
AttrPtg attrSkipAfterTrue = new AttrPtg();
|
||||
attrSkipAfterTrue.setGoto(true);
|
||||
|
||||
if (getChildren().length > 2) {
|
||||
// false param present
|
||||
|
||||
// false parameter
|
||||
getChildren()[2].collectPtgs(temp);
|
||||
|
||||
int skipAfterFalseParamIndex = temp.createPlaceholder();
|
||||
|
||||
AttrPtg attrSkipAfterFalse = new AttrPtg();
|
||||
attrSkipAfterFalse.setGoto(true);
|
||||
|
||||
int falseParamSize = temp.sumTokenSizes(skipAfterTrueParamIndex+1, skipAfterFalseParamIndex);
|
||||
|
||||
attrIf.setData((short)(trueParamSize + 4)); // distance to start of false parameter. +4 for skip after true
|
||||
attrSkipAfterTrue.setData((short)(falseParamSize + 4 + 4 - 1)); // 1 less than distance to end of if FuncVar(size=4). +4 for attr skip before
|
||||
attrSkipAfterFalse.setData((short)(4 - 1)); // 1 less than distance to end of if FuncVar(size=4).
|
||||
|
||||
temp.setPlaceholder(ifAttrIndex, attrIf);
|
||||
temp.setPlaceholder(skipAfterTrueParamIndex, attrSkipAfterTrue);
|
||||
temp.setPlaceholder(skipAfterFalseParamIndex, attrSkipAfterFalse);
|
||||
} else {
|
||||
// false parameter not present
|
||||
attrIf.setData((short)(trueParamSize + 4)); // distance to start of FuncVar. +4 for skip after true
|
||||
attrSkipAfterTrue.setData((short)(4 - 1)); // 1 less than distance to end of if FuncVar(size=4).
|
||||
|
||||
temp.setPlaceholder(ifAttrIndex, attrIf);
|
||||
temp.setPlaceholder(skipAfterTrueParamIndex, attrSkipAfterTrue);
|
||||
}
|
||||
|
||||
temp.add(getToken());
|
||||
}
|
||||
|
||||
private static boolean isIf(Ptg token) {
|
||||
if (token instanceof FuncVarPtg) {
|
||||
FuncVarPtg func = (FuncVarPtg) token;
|
||||
if (FunctionMetadataRegistry.FUNCTION_NAME_IF.equals(func.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Ptg getToken() {
|
||||
return _token;
|
||||
}
|
||||
|
||||
public ParseNode[] getChildren() {
|
||||
return _children;
|
||||
}
|
||||
|
||||
private static final class TokenCollector {
|
||||
|
||||
private final Ptg[] _ptgs;
|
||||
private int _offset;
|
||||
|
||||
public TokenCollector(int tokenCount) {
|
||||
_ptgs = new Ptg[tokenCount];
|
||||
_offset = 0;
|
||||
}
|
||||
|
||||
public int sumTokenSizes(int fromIx, int toIx) {
|
||||
int result = 0;
|
||||
for (int i=fromIx; i<toIx; i++) {
|
||||
result += _ptgs[i].getSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int createPlaceholder() {
|
||||
return _offset++;
|
||||
}
|
||||
|
||||
public void add(Ptg token) {
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("token must not be null");
|
||||
}
|
||||
_ptgs[_offset] = token;
|
||||
_offset++;
|
||||
}
|
||||
|
||||
public void setPlaceholder(int index, Ptg token) {
|
||||
if (_ptgs[index] != null) {
|
||||
throw new IllegalStateException("Invalid placeholder index (" + index + ")");
|
||||
}
|
||||
_ptgs[index] = token;
|
||||
}
|
||||
|
||||
public Ptg[] getResult() {
|
||||
return _ptgs;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@ public final class Sheet implements Model {
|
|||
protected ArrayList records = null;
|
||||
int preoffset = 0; // offset of the sheet in a new file
|
||||
int loc = 0;
|
||||
protected int dimsloc = 0;
|
||||
protected int dimsloc = -1; // TODO - is it legal for dims record to be missing?
|
||||
protected DimensionsRecord dims;
|
||||
protected DefaultColWidthRecord defaultcolwidth = null;
|
||||
protected DefaultRowHeightRecord defaultrowheight = null;
|
||||
|
@ -96,8 +96,8 @@ public final class Sheet implements Model {
|
|||
protected List condFormatting = new ArrayList();
|
||||
|
||||
/** Add an UncalcedRecord if not true indicating formulas have not been calculated */
|
||||
protected boolean uncalced = false;
|
||||
|
||||
protected boolean _isUncalced = false;
|
||||
|
||||
public static final byte PANE_LOWER_RIGHT = (byte)0;
|
||||
public static final byte PANE_UPPER_RIGHT = (byte)1;
|
||||
public static final byte PANE_LOWER_LEFT = (byte)2;
|
||||
|
@ -162,7 +162,7 @@ public final class Sheet implements Model {
|
|||
}
|
||||
}
|
||||
else if (rec.getSid() == UncalcedRecord.sid) {
|
||||
retval.uncalced = true;
|
||||
retval._isUncalced = true;
|
||||
}
|
||||
else if (rec.getSid() == DimensionsRecord.sid)
|
||||
{
|
||||
|
@ -295,6 +295,8 @@ public final class Sheet implements Model {
|
|||
}
|
||||
else if ( rec.getSid() == IndexRecord.sid )
|
||||
{
|
||||
// ignore INDEX record because it is only needed by Excel,
|
||||
// and POI always re-calculates its contents
|
||||
rec = null;
|
||||
}
|
||||
|
||||
|
@ -329,16 +331,8 @@ public final class Sheet implements Model {
|
|||
}
|
||||
}
|
||||
retval.records = records;
|
||||
// if (retval.rows == null)
|
||||
// {
|
||||
// retval.rows = new RowRecordsAggregate();
|
||||
// }
|
||||
retval.checkCells();
|
||||
retval.checkRows();
|
||||
// if (retval.cells == null)
|
||||
// {
|
||||
// retval.cells = new ValueRecordsAggregate();
|
||||
// }
|
||||
retval.checkCells();
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
|
||||
return retval;
|
||||
|
@ -494,7 +488,15 @@ public final class Sheet implements Model {
|
|||
if (cells == null)
|
||||
{
|
||||
cells = new ValueRecordsAggregate();
|
||||
records.add(getDimsLoc() + 1, cells);
|
||||
// In the worksheet stream, the row records always occur before the cell (value)
|
||||
// records. Therefore POI's aggregates (RowRecordsAggregate, ValueRecordsAggregate)
|
||||
// should follow suit. Some methods in this class tolerate either order, while
|
||||
// others have been found to fail (see bug 45145).
|
||||
int rraIndex = getDimsLoc() + 1;
|
||||
if (records.get(rraIndex).getClass() != RowRecordsAggregate.class) {
|
||||
throw new IllegalStateException("Cannot create value records before row records exist");
|
||||
}
|
||||
records.add(rraIndex+1, cells);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -816,17 +818,17 @@ public final class Sheet implements Model {
|
|||
// Once the rows have been found in the list of records, start
|
||||
// writing out the blocked row information. This includes the DBCell references
|
||||
if (record instanceof RowRecordsAggregate) {
|
||||
pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
|
||||
pos += ((RowRecordsAggregate)record).serialize(pos, data, cells);
|
||||
} else if (record instanceof ValueRecordsAggregate) {
|
||||
//Do nothing here. The records were serialized during the RowRecordAggregate block serialization
|
||||
} else {
|
||||
pos += record.serialize(pos, data ); // rec.length;
|
||||
pos += record.serialize(pos, data );
|
||||
}
|
||||
|
||||
// If the BOF record was just serialized then add the IndexRecord
|
||||
if (record.getSid() == BOFRecord.sid) {
|
||||
// Add an optional UncalcedRecord
|
||||
if (uncalced) {
|
||||
if (_isUncalced) {
|
||||
UncalcedRecord rec = new UncalcedRecord();
|
||||
pos += rec.serialize(pos, data);
|
||||
}
|
||||
|
@ -837,67 +839,68 @@ public final class Sheet implements Model {
|
|||
pos += serializeIndexRecord(k, pos, data);
|
||||
}
|
||||
}
|
||||
|
||||
//// uncomment to test record sizes ////
|
||||
// System.out.println( record.getClass().getName() );
|
||||
// byte[] data2 = new byte[record.getRecordSize()];
|
||||
// record.serialize(0, data2 ); // rec.length;
|
||||
// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
|
||||
// && record instanceof RowRecordsAggregate == false
|
||||
// && record instanceof ValueRecordsAggregate == false
|
||||
// && record instanceof EscherAggregate == false)
|
||||
// {
|
||||
// throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
|
||||
// }
|
||||
|
||||
//asd: int len = record.serialize(pos + offset, data );
|
||||
|
||||
///// DEBUG BEGIN /////
|
||||
//asd: if (len != record.getRecordSize())
|
||||
//asd: throw new IllegalStateException("Record size does not match serialized bytes. Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize() + ". Record object is " + record.getClass());
|
||||
///// DEBUG END /////
|
||||
|
||||
//asd: pos += len; // rec.length;
|
||||
|
||||
}
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
if (log.check( POILogger.DEBUG )) {
|
||||
log.log(POILogger.DEBUG, "Sheet.serialize returning ");
|
||||
}
|
||||
return pos-offset;
|
||||
}
|
||||
|
||||
private int serializeIndexRecord(final int BOFRecordIndex, final int offset, byte[] data) {
|
||||
IndexRecord index = new IndexRecord();
|
||||
index.setFirstRow(rows.getFirstRowNum());
|
||||
index.setLastRowAdd1(rows.getLastRowNum()+1);
|
||||
//Calculate the size of the records from the end of the BOF
|
||||
//and up to the RowRecordsAggregate...
|
||||
int sheetRecSize = 0;
|
||||
for (int j = BOFRecordIndex+1; j < records.size(); j++)
|
||||
{
|
||||
Record tmpRec = (( Record ) records.get(j));
|
||||
if (tmpRec instanceof RowRecordsAggregate)
|
||||
break;
|
||||
sheetRecSize+= tmpRec.getRecordSize();
|
||||
}
|
||||
//Add the references to the DBCells in the IndexRecord (one for each block)
|
||||
int blockCount = rows.getRowBlockCount();
|
||||
//Calculate the size of this IndexRecord
|
||||
int indexRecSize = IndexRecord.getRecordSizeForBlockCount(blockCount);
|
||||
/**
|
||||
* @param indexRecordOffset also happens to be the end of the BOF record
|
||||
* @return the size of the serialized INDEX record
|
||||
*/
|
||||
private int serializeIndexRecord(final int bofRecordIndex, final int indexRecordOffset,
|
||||
byte[] data) {
|
||||
IndexRecord index = new IndexRecord();
|
||||
index.setFirstRow(rows.getFirstRowNum());
|
||||
index.setLastRowAdd1(rows.getLastRowNum() + 1);
|
||||
// Calculate the size of the records from the end of the BOF
|
||||
// and up to the RowRecordsAggregate...
|
||||
|
||||
int rowBlockOffset = 0;
|
||||
int cellBlockOffset = 0;
|
||||
int dbCellOffset = 0;
|
||||
for (int block=0;block<blockCount;block++) {
|
||||
rowBlockOffset += rows.getRowBlockSize(block);
|
||||
cellBlockOffset += null == cells ? 0 : cells.getRowCellBlockSize(rows.getStartRowNumberForBlock(block),
|
||||
rows.getEndRowNumberForBlock(block));
|
||||
//Note: The offsets are relative to the Workbook BOF. Assume that this is
|
||||
//0 for now.....
|
||||
index.addDbcell(offset + indexRecSize + sheetRecSize + dbCellOffset + rowBlockOffset + cellBlockOffset);
|
||||
//Add space required to write the dbcell record(s) (whose references were just added).
|
||||
dbCellOffset += (8 + (rows.getRowCountForBlock(block) * 2));
|
||||
}
|
||||
return index.serialize(offset, data);
|
||||
// 'initial sheet records' are between INDEX and first ROW record.
|
||||
int sizeOfInitialSheetRecords = 0;
|
||||
// start just after BOF record (INDEX is not present in this list)
|
||||
for (int j = bofRecordIndex + 1; j < records.size(); j++) {
|
||||
Record tmpRec = ((Record) records.get(j));
|
||||
if (tmpRec instanceof UncalcedRecord) {
|
||||
continue;
|
||||
}
|
||||
if (tmpRec instanceof RowRecordsAggregate) {
|
||||
break;
|
||||
}
|
||||
sizeOfInitialSheetRecords += tmpRec.getRecordSize();
|
||||
}
|
||||
if (_isUncalced) {
|
||||
sizeOfInitialSheetRecords += UncalcedRecord.getStaticRecordSize();
|
||||
}
|
||||
|
||||
// Add the references to the DBCells in the IndexRecord (one for each block)
|
||||
// Note: The offsets are relative to the Workbook BOF. Assume that this is
|
||||
// 0 for now.....
|
||||
|
||||
int blockCount = rows.getRowBlockCount();
|
||||
// Calculate the size of this IndexRecord
|
||||
int indexRecSize = IndexRecord.getRecordSizeForBlockCount(blockCount);
|
||||
|
||||
int currentOffset = indexRecordOffset + indexRecSize + sizeOfInitialSheetRecords;
|
||||
|
||||
for (int block = 0; block < blockCount; block++) {
|
||||
// each row-block has a DBCELL record.
|
||||
// The offset of each DBCELL record needs to be updated in the INDEX record
|
||||
|
||||
// account for row records in this row-block
|
||||
currentOffset += rows.getRowBlockSize(block);
|
||||
// account for cell value records after those
|
||||
currentOffset += null == cells ? 0 : cells.getRowCellBlockSize(rows
|
||||
.getStartRowNumberForBlock(block), rows.getEndRowNumberForBlock(block));
|
||||
|
||||
// currentOffset is now the location of the DBCELL record for this row-block
|
||||
index.addDbcell(currentOffset);
|
||||
// Add space required to write the DBCELL record (whose reference was just added).
|
||||
currentOffset += (8 + (rows.getRowCountForBlock(block) * 2));
|
||||
}
|
||||
return index.serialize(indexRecordOffset, data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2017,31 +2020,33 @@ public final class Sheet implements Model {
|
|||
{
|
||||
int retval = 0;
|
||||
|
||||
for ( int k = 0; k < records.size(); k++ )
|
||||
{
|
||||
retval += ( (Record) records.get( k ) ).getRecordSize();
|
||||
}
|
||||
//Add space for the IndexRecord
|
||||
if (rows != null) {
|
||||
final int blocks = rows.getRowBlockCount();
|
||||
retval += IndexRecord.getRecordSizeForBlockCount(blocks);
|
||||
|
||||
//Add space for the DBCell records
|
||||
//Once DBCell per block.
|
||||
//8 bytes per DBCell (non variable section)
|
||||
//2 bytes per row reference
|
||||
retval += (8 * blocks);
|
||||
for (Iterator itr = rows.getIterator(); itr.hasNext();) {
|
||||
RowRecord row = (RowRecord)itr.next();
|
||||
if (cells != null && cells.rowHasCells(row.getRowNumber()))
|
||||
retval += 2;
|
||||
for ( int k = 0; k < records.size(); k++) {
|
||||
Record record = (Record) records.get(k);
|
||||
if (record instanceof UncalcedRecord) {
|
||||
// skip the UncalcedRecord if present, it's only encoded if the isUncalced flag is set
|
||||
continue;
|
||||
}
|
||||
retval += record.getRecordSize();
|
||||
}
|
||||
if (rows != null) {
|
||||
// Add space for the IndexRecord and DBCell records
|
||||
final int nBlocks = rows.getRowBlockCount();
|
||||
int nRows = 0;
|
||||
if (cells != null) {
|
||||
for (Iterator itr = rows.getIterator(); itr.hasNext();) {
|
||||
RowRecord row = (RowRecord)itr.next();
|
||||
if (cells.rowHasCells(row.getRowNumber())) {
|
||||
nRows++;
|
||||
}
|
||||
}
|
||||
}
|
||||
retval += IndexRecord.getRecordSizeForBlockCount(nBlocks);
|
||||
retval += DBCellRecord.calculateSizeOfRecords(nBlocks, nRows);
|
||||
}
|
||||
// Add space for UncalcedRecord
|
||||
if (uncalced) {
|
||||
if (_isUncalced) {
|
||||
retval += UncalcedRecord.getStaticRecordSize();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2518,13 +2523,13 @@ public final class Sheet implements Model {
|
|||
* @return whether an uncalced record must be inserted or not at generation
|
||||
*/
|
||||
public boolean getUncalced() {
|
||||
return uncalced;
|
||||
return _isUncalced;
|
||||
}
|
||||
/**
|
||||
* @param uncalced whether an uncalced record must be inserted or not at generation
|
||||
*/
|
||||
public void setUncalced(boolean uncalced) {
|
||||
this.uncalced = uncalced;
|
||||
this._isUncalced = uncalced;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -191,12 +191,11 @@ public class Workbook implements Model
|
|||
case ExternSheetRecord.sid :
|
||||
throw new RuntimeException("Extern sheet is part of LinkTable");
|
||||
case NameRecord.sid :
|
||||
throw new RuntimeException("DEFINEDNAME is part of LinkTable");
|
||||
case SupBookRecord.sid :
|
||||
// LinkTable can start with either of these
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(DEBUG, "found SupBook record at " + k);
|
||||
retval.linkTable = new LinkTable(recs, k, retval.records);
|
||||
// retval.records.supbookpos = k;
|
||||
k+=retval.linkTable.getRecordCount() - 1;
|
||||
continue;
|
||||
case FormatRecord.sid :
|
||||
|
@ -604,6 +603,29 @@ public class Workbook implements Model
|
|||
boundsheets.remove(sheetnum);
|
||||
fixTabIdRecord();
|
||||
}
|
||||
|
||||
// Within NameRecords, it's ok to have the formula
|
||||
// part point at deleted sheets. It's also ok to
|
||||
// have the ExternSheetNumber point at deleted
|
||||
// sheets.
|
||||
// However, the sheet index must be adjusted, or
|
||||
// excel will break. (Sheet index is either 0 for
|
||||
// global, or 1 based index to sheet)
|
||||
int sheetNum1Based = sheetnum + 1;
|
||||
for(int i=0; i<getNumNames(); i++) {
|
||||
NameRecord nr = getNameRecord(i);
|
||||
|
||||
if(nr.getIndexToSheet() == sheetNum1Based) {
|
||||
// Excel re-writes these to point to no sheet
|
||||
nr.setEqualsToIndexToSheet((short)0);
|
||||
} else if(nr.getIndexToSheet() > sheetNum1Based) {
|
||||
// Bump down by one, so still points
|
||||
// at the same sheet
|
||||
nr.setEqualsToIndexToSheet((short)(
|
||||
nr.getEqualsToIndexToSheet()-1
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,14 +14,10 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.model.FormulaParser;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.cf.BorderFormatting;
|
||||
import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
|
@ -30,7 +26,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Rule Record.
|
||||
|
@ -59,9 +54,6 @@ public final class CFRuleRecord extends Record
|
|||
|
||||
private byte field_2_comparison_operator;
|
||||
|
||||
private short field_3_formula1_len;
|
||||
private short field_4_formula2_len;
|
||||
|
||||
private int field_5_options;
|
||||
|
||||
private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
|
||||
|
@ -121,8 +113,6 @@ public final class CFRuleRecord extends Record
|
|||
{
|
||||
field_1_condition_type=conditionType;
|
||||
field_2_comparison_operator=comparisonOperation;
|
||||
field_3_formula1_len = (short)0;
|
||||
field_4_formula2_len = (short)0;
|
||||
|
||||
// Set modification flags to 1: by default options are not modified
|
||||
field_5_options = modificationBits.setValue(field_5_options, -1);
|
||||
|
@ -147,8 +137,8 @@ public final class CFRuleRecord extends Record
|
|||
this(conditionType, comparisonOperation);
|
||||
field_1_condition_type = CONDITION_TYPE_CELL_VALUE_IS;
|
||||
field_2_comparison_operator = comparisonOperation;
|
||||
setParsedExpression1(formula1);
|
||||
setParsedExpression2(formula2);
|
||||
field_17_formula1 = formula1;
|
||||
field_18_formula2 = formula2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,63 +157,38 @@ public final class CFRuleRecord extends Record
|
|||
Ptg[] formula1 = parseFormula(formulaText1, workbook);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, workbook);
|
||||
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Formula record and sets its fields appropriately.
|
||||
* Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
|
||||
* "explanation of this bug in the documentation) or an exception
|
||||
* will be throw upon validation
|
||||
*
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
|
||||
public CFRuleRecord(RecordInputStream in)
|
||||
{
|
||||
public CFRuleRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
try {
|
||||
field_1_condition_type = in.readByte();
|
||||
field_2_comparison_operator = in.readByte();
|
||||
field_3_formula1_len = in.readShort();
|
||||
field_4_formula2_len = in.readShort();
|
||||
field_5_options = in.readInt();
|
||||
field_6_not_used = in.readShort();
|
||||
field_1_condition_type = in.readByte();
|
||||
field_2_comparison_operator = in.readByte();
|
||||
int field_3_formula1_len = in.readUShort();
|
||||
int field_4_formula2_len = in.readUShort();
|
||||
field_5_options = in.readInt();
|
||||
field_6_not_used = in.readShort();
|
||||
|
||||
if (containsFontFormattingBlock()) {
|
||||
fontFormatting = new FontFormatting(in);
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
borderFormatting = new BorderFormatting(in);
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
patternFormatting = new PatternFormatting(in);
|
||||
}
|
||||
|
||||
if (field_3_formula1_len > 0) {
|
||||
Stack ptgs = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
|
||||
// Now convert any fields as required
|
||||
ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
|
||||
field_17_formula1 = toArray(ptgs);
|
||||
}
|
||||
if (field_4_formula2_len > 0) {
|
||||
Stack ptgs = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
|
||||
|
||||
// Now convert any fields as required
|
||||
ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
|
||||
field_18_formula2 = toArray(ptgs);
|
||||
}
|
||||
} catch (java.lang.UnsupportedOperationException uoe) {
|
||||
throw new RecordFormatException(uoe);
|
||||
if (containsFontFormattingBlock()) {
|
||||
fontFormatting = new FontFormatting(in);
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
borderFormatting = new BorderFormatting(in);
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
patternFormatting = new PatternFormatting(in);
|
||||
}
|
||||
|
||||
if (field_3_formula1_len > 0) {
|
||||
field_17_formula1 = Ptg.readTokens(field_3_formula1_len, in);
|
||||
}
|
||||
if (field_4_formula2_len > 0) {
|
||||
field_18_formula2 = Ptg.readTokens(field_4_formula2_len, in);
|
||||
}
|
||||
}
|
||||
|
||||
public byte getConditionType()
|
||||
|
@ -323,24 +288,6 @@ public final class CFRuleRecord extends Record
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the length (in number of tokens) of the expression 1
|
||||
* @return expression length
|
||||
*/
|
||||
private short getExpression1Length()
|
||||
{
|
||||
return field_3_formula1_len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the length (in number of tokens) of the expression 2
|
||||
* @return expression length
|
||||
*/
|
||||
private short getExpression2Length()
|
||||
{
|
||||
return field_4_formula2_len;
|
||||
}
|
||||
/**
|
||||
* get the option flags
|
||||
*
|
||||
|
@ -489,16 +436,6 @@ public final class CFRuleRecord extends Record
|
|||
return field_18_formula2;
|
||||
}
|
||||
|
||||
private void setParsedExpression1(Ptg[] ptgs) {
|
||||
short len = getTotalPtgSize(field_17_formula1 = ptgs);
|
||||
field_3_formula1_len = len;
|
||||
}
|
||||
|
||||
private void setParsedExpression2(Ptg[] ptgs) {
|
||||
short len = getTotalPtgSize(field_18_formula2 = ptgs);
|
||||
field_4_formula2_len = len;
|
||||
}
|
||||
|
||||
/**
|
||||
* called by constructor, should throw runtime exception in the event of a
|
||||
* record passed with a differing ID.
|
||||
|
@ -519,6 +456,17 @@ public final class CFRuleRecord extends Record
|
|||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ptgs may be <code>null</code>
|
||||
* @return encoded size of the formula
|
||||
*/
|
||||
private static int getFormulaSize(Ptg[] ptgs) {
|
||||
if (ptgs == null) {
|
||||
return 0;
|
||||
}
|
||||
return Ptg.getEncodedSize(ptgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* called by the class that is responsible for writing this sucker.
|
||||
* Subclasses should implement this so that their data is passed back in a
|
||||
|
@ -528,18 +476,20 @@ public final class CFRuleRecord extends Record
|
|||
* @param data byte array containing instance data
|
||||
* @return number of bytes written
|
||||
*/
|
||||
|
||||
public int serialize(int pOffset, byte [] data)
|
||||
{
|
||||
|
||||
int formula1Len=getFormulaSize(field_17_formula1);
|
||||
int formula2Len=getFormulaSize(field_18_formula2);
|
||||
|
||||
int offset = pOffset;
|
||||
int recordsize = getRecordSize();
|
||||
LittleEndian.putShort(data, 0 + offset, sid);
|
||||
LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
|
||||
data[4 + offset] = field_1_condition_type;
|
||||
data[5 + offset] = field_2_comparison_operator;
|
||||
LittleEndian.putShort(data, 6 + offset, field_3_formula1_len);
|
||||
LittleEndian.putShort(data, 8 + offset, field_4_formula2_len);
|
||||
LittleEndian.putUShort(data, 6 + offset, formula1Len);
|
||||
LittleEndian.putUShort(data, 8 + offset, formula2Len);
|
||||
LittleEndian.putInt(data, 10 + offset, field_5_options);
|
||||
LittleEndian.putShort(data,14 + offset, field_6_not_used);
|
||||
|
||||
|
@ -562,16 +512,12 @@ public final class CFRuleRecord extends Record
|
|||
offset += patternFormatting.serialize(offset, data);
|
||||
}
|
||||
|
||||
if (getExpression1Length()>0)
|
||||
{
|
||||
Ptg.serializePtgStack(convertToTokenStack(field_17_formula1), data, offset);
|
||||
offset += getExpression1Length();
|
||||
if (field_17_formula1 != null) {
|
||||
offset += Ptg.serializePtgs(field_17_formula1, data, offset);
|
||||
}
|
||||
|
||||
if (getExpression2Length()>0)
|
||||
{
|
||||
Ptg.serializePtgStack(convertToTokenStack(field_18_formula2), data, offset);
|
||||
offset += getExpression2Length();
|
||||
if (field_18_formula2 != null) {
|
||||
offset += Ptg.serializePtgs(field_18_formula2, data, offset);
|
||||
}
|
||||
if(offset - pOffset != recordsize) {
|
||||
throw new IllegalStateException("write mismatch (" + (offset - pOffset) + "!=" + recordsize + ")");
|
||||
|
@ -586,24 +532,12 @@ public final class CFRuleRecord extends Record
|
|||
(containsFontFormattingBlock()?fontFormatting.getRawRecord().length:0)+
|
||||
(containsBorderFormattingBlock()?8:0)+
|
||||
(containsPatternFormattingBlock()?4:0)+
|
||||
getExpression1Length()+
|
||||
getExpression2Length()
|
||||
getFormulaSize(field_17_formula1)+
|
||||
getFormulaSize(field_18_formula2)
|
||||
;
|
||||
return retval;
|
||||
}
|
||||
|
||||
private short getTotalPtgSize(Ptg[] ptgs)
|
||||
{
|
||||
if( ptgs == null) {
|
||||
return 0;
|
||||
}
|
||||
short retval = 0;
|
||||
for (int i = 0; i < ptgs.length; i++)
|
||||
{
|
||||
retval += ptgs[i].getSize();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
|
@ -629,8 +563,6 @@ public final class CFRuleRecord extends Record
|
|||
|
||||
public Object clone() {
|
||||
CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
|
||||
rec.field_3_formula1_len = field_3_formula1_len;
|
||||
rec.field_4_formula2_len = field_4_formula2_len;
|
||||
rec.field_5_options = field_5_options;
|
||||
rec.field_6_not_used = field_6_not_used;
|
||||
if (containsFontFormattingBlock()) {
|
||||
|
@ -642,10 +574,10 @@ public final class CFRuleRecord extends Record
|
|||
if (containsPatternFormattingBlock()) {
|
||||
rec.patternFormatting = (PatternFormatting) patternFormatting.clone();
|
||||
}
|
||||
if (field_3_formula1_len > 0) {
|
||||
if (field_17_formula1 != null) {
|
||||
rec.field_17_formula1 = (Ptg[]) field_17_formula1.clone();
|
||||
}
|
||||
if (field_4_formula2_len > 0) {
|
||||
if (field_18_formula2 != null) {
|
||||
rec.field_18_formula2 = (Ptg[]) field_18_formula2.clone();
|
||||
}
|
||||
|
||||
|
@ -653,30 +585,17 @@ public final class CFRuleRecord extends Record
|
|||
}
|
||||
|
||||
/**
|
||||
* TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
|
||||
* this call will produce the wrong results if the formula contains any cell references
|
||||
* One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
|
||||
* Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects.
|
||||
*
|
||||
* @return <code>null</code> if <tt>formula</tt> was null.
|
||||
*/
|
||||
private static Ptg[] parseFormula(String formula, HSSFWorkbook workbook)
|
||||
{
|
||||
private static Ptg[] parseFormula(String formula, HSSFWorkbook workbook) {
|
||||
if(formula == null) {
|
||||
return null;
|
||||
}
|
||||
return FormulaParser.parse(formula, workbook);
|
||||
}
|
||||
|
||||
// TODO - treat formulas as token arrays instead of Stacks throughout the rest of POI
|
||||
private static Stack convertToTokenStack(Ptg[] ptgs)
|
||||
{
|
||||
Stack parsedExpression = new Stack();
|
||||
// fill the Ptg Stack with Ptgs of new formula
|
||||
for (int k = 0; k < ptgs.length; k++)
|
||||
{
|
||||
parsedExpression.push(ptgs[ k ]);
|
||||
}
|
||||
return parsedExpression;
|
||||
}
|
||||
private static Ptg[] toArray(Stack ptgs) {
|
||||
Ptg[] result = new Ptg[ptgs.size()];
|
||||
ptgs.toArray(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,7 +14,6 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
|
@ -29,10 +27,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Jason Height
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
|
||||
public class DBCellRecord
|
||||
extends Record
|
||||
{
|
||||
public final class DBCellRecord extends Record {
|
||||
public final static int BLOCK_SIZE = 32;
|
||||
public final static short sid = 0xd7;
|
||||
private int field_1_row_offset;
|
||||
|
@ -46,7 +41,6 @@ public class DBCellRecord
|
|||
* Constructs a DBCellRecord and sets its fields appropriately
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
|
||||
public DBCellRecord(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
|
@ -78,7 +72,6 @@ public class DBCellRecord
|
|||
*
|
||||
* @param offset offset to the start of the first cell in the next DBCell block
|
||||
*/
|
||||
|
||||
public void setRowOffset(int offset)
|
||||
{
|
||||
field_1_row_offset = offset;
|
||||
|
@ -108,7 +101,6 @@ public class DBCellRecord
|
|||
*
|
||||
* @return rowoffset to the start of the first cell in the next DBCell block
|
||||
*/
|
||||
|
||||
public int getRowOffset()
|
||||
{
|
||||
return field_1_row_offset;
|
||||
|
@ -120,7 +112,6 @@ public class DBCellRecord
|
|||
* @param index of the cell offset to retrieve
|
||||
* @return celloffset from the celloffset array
|
||||
*/
|
||||
|
||||
public short getCellOffsetAt(int index)
|
||||
{
|
||||
return field_2_cell_offsets[ index ];
|
||||
|
@ -131,7 +122,6 @@ public class DBCellRecord
|
|||
*
|
||||
* @return number of cell offsets
|
||||
*/
|
||||
|
||||
public int getNumCellOffsets()
|
||||
{
|
||||
return field_2_cell_offsets.length;
|
||||
|
@ -175,9 +165,15 @@ public class DBCellRecord
|
|||
return 8 + (getNumCellOffsets() * 2);
|
||||
}
|
||||
|
||||
/** Returns the size of a DBCellRecord when it needs to reference a certain number of rows*/
|
||||
public static int getRecordSizeForRows(int rows) {
|
||||
return 8 + (rows * 2);
|
||||
/**
|
||||
* @returns the size of the group of <tt>DBCellRecord</tt>s needed to encode
|
||||
* the specified number of blocks and rows
|
||||
*/
|
||||
public static int calculateSizeOfRecords(int nBlocks, int nRows) {
|
||||
// One DBCell per block.
|
||||
// 8 bytes per DBCell (non variable section)
|
||||
// 2 bytes per row reference
|
||||
return nBlocks * 8 + nRows * 2;
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
|
|
|
@ -108,7 +108,10 @@ public class EmbeddedObjectRefSubRecord
|
|||
in.readByte(); // discard
|
||||
}
|
||||
|
||||
field_6_stream_id = in.readInt();
|
||||
// Fetch the stream ID
|
||||
field_6_stream_id = in.readInt();
|
||||
|
||||
// Store what's left
|
||||
remainingBytes = in.readRemainder();
|
||||
}
|
||||
|
||||
|
|
|
@ -557,7 +557,7 @@ public final class FormulaRecord
|
|||
if (field_8_parsed_expr != null)
|
||||
size = field_8_parsed_expr.size();
|
||||
for (int i=0; i< size; i++) {
|
||||
Ptg ptg = (Ptg)((Ptg)field_8_parsed_expr.get(i)).clone();
|
||||
Ptg ptg = ((Ptg)field_8_parsed_expr.get(i)).copy();
|
||||
rec.field_8_parsed_expr.add(i, ptg);
|
||||
}
|
||||
rec.value_data = value_data;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
|
@ -22,9 +21,8 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.model.FormulaParser;
|
||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.DeletedRef3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
||||
|
@ -44,8 +42,7 @@ import org.apache.poi.util.StringUtil;
|
|||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
* @version 1.0-pre
|
||||
*/
|
||||
|
||||
public class NameRecord extends Record {
|
||||
public final class NameRecord extends Record {
|
||||
/**
|
||||
*/
|
||||
public final static short sid = 0x18; //Docs says that it is 0x218
|
||||
|
@ -650,50 +647,9 @@ public class NameRecord extends Record {
|
|||
/** gets the reference , the area only (range)
|
||||
* @return area reference
|
||||
*/
|
||||
public String getAreaReference(HSSFWorkbook book){
|
||||
if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return "Error";
|
||||
Ptg ptg = (Ptg) field_13_name_definition.peek();
|
||||
String result = "";
|
||||
|
||||
// If it's a union, descend in and process
|
||||
if (ptg.getClass() == UnionPtg.class) {
|
||||
Iterator it =field_13_name_definition.iterator();
|
||||
while( it.hasNext() ) {
|
||||
Ptg p = (Ptg)it.next();
|
||||
|
||||
String thisRes = getAreaRefString(p, book);
|
||||
if(thisRes.length() > 0) {
|
||||
// Add a comma to the end if needed
|
||||
if(result.length() > 0 && !result.endsWith(",")) {
|
||||
result += ",";
|
||||
}
|
||||
// And add the string it corresponds to
|
||||
result += thisRes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Otherwise just get the string
|
||||
result = getAreaRefString(ptg, book);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the given ptg into a string, or
|
||||
* return an empty string if nothing is possible
|
||||
* for it.
|
||||
*/
|
||||
private String getAreaRefString(Ptg ptg,HSSFWorkbook book) {
|
||||
if (ptg.getClass() == Area3DPtg.class){
|
||||
return ptg.toFormulaString(book);
|
||||
} else if (ptg.getClass() == Ref3DPtg.class){
|
||||
return ptg.toFormulaString(book);
|
||||
} else if (ptg.getClass() == DeletedArea3DPtg.class || ptg.getClass() == DeletedRef3DPtg.class) {
|
||||
return "#REF!";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public String getAreaReference(HSSFWorkbook book){
|
||||
return FormulaParser.toFormulaString(book, field_13_name_definition);
|
||||
}
|
||||
|
||||
/** sets the reference , the area only (range)
|
||||
* @param ref area reference
|
||||
|
@ -737,7 +693,7 @@ public class NameRecord extends Record {
|
|||
}
|
||||
// And then a union if we had more than one area
|
||||
if(refs.length > 1) {
|
||||
ptg = new UnionPtg();
|
||||
ptg = UnionPtg.instance;
|
||||
field_13_name_definition.push(ptg);
|
||||
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,27 +15,21 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
|
||||
|
||||
import org.apache.poi.util.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* The obj record is used to hold various graphic objects and controls.
|
||||
*
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
public class ObjRecord
|
||||
extends Record
|
||||
{
|
||||
public final class ObjRecord extends Record {
|
||||
public final static short sid = 0x5D;
|
||||
private List subrecords;
|
||||
|
||||
|
@ -47,6 +40,7 @@ public class ObjRecord
|
|||
public ObjRecord()
|
||||
{
|
||||
subrecords = new ArrayList(2);
|
||||
// TODO - ensure 2 sub-records (ftCmo 15h, and ftEnd 00h) are always created
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,6 +74,7 @@ public class ObjRecord
|
|||
//following wont work properly
|
||||
int subSize = 0;
|
||||
byte[] subRecordData = in.readRemainder();
|
||||
|
||||
RecordInputStream subRecStream = new RecordInputStream(new ByteArrayInputStream(subRecordData));
|
||||
while(subRecStream.hasNextRecord()) {
|
||||
subRecStream.nextRecord();
|
||||
|
@ -89,28 +84,19 @@ public class ObjRecord
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the RecordInputStream skipped EndSubRecord,
|
||||
* if it did then append it explicitly.
|
||||
* See Bug 41242 for details.
|
||||
* Add the EndSubRecord explicitly.
|
||||
*
|
||||
* TODO - the reason the EndSubRecord is always skipped is because its 'sid' is zero and
|
||||
* that causes subRecStream.hasNextRecord() to return false.
|
||||
* There may be more than the size of EndSubRecord left-over, if there is any padding
|
||||
* after that record. The content of the EndSubRecord and the padding is all zeros.
|
||||
* So there's not much to look at past the last substantial record.
|
||||
*
|
||||
* See Bugs 41242/45133 for details.
|
||||
*/
|
||||
if (subRecordData.length - subSize == 4){
|
||||
if (subRecordData.length - subSize >= 4) {
|
||||
subrecords.add(new EndSubRecord());
|
||||
}
|
||||
|
||||
/* JMH the size present/not present in the code below
|
||||
needs to be considered in the RecordInputStream??
|
||||
int pos = offset;
|
||||
while (pos - offset <= size-2) // atleast one "short" must be present
|
||||
{
|
||||
short subRecordSid = LittleEndian.getShort(data, pos);
|
||||
short subRecordSize = -1; // set default to "< 0"
|
||||
if (pos-offset <= size-4) { // see if size info is present, else default to -1
|
||||
subRecordSize = LittleEndian.getShort(data, pos + 2);
|
||||
}
|
||||
Record subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4);
|
||||
subrecords.add(subRecord);
|
||||
pos += subRecord.getRecordSize();
|
||||
}*/
|
||||
}
|
||||
|
||||
public String toString()
|
||||
|
@ -140,6 +126,8 @@ public class ObjRecord
|
|||
Record record = (Record) iterator.next();
|
||||
pos += record.serialize(pos, data);
|
||||
}
|
||||
// assume padding (if present) does not need to be written.
|
||||
// it is probably zero already, and it probably doesn't matter anyway
|
||||
|
||||
return getRecordSize();
|
||||
}
|
||||
|
@ -155,7 +143,9 @@ public class ObjRecord
|
|||
Record record = (Record) iterator.next();
|
||||
size += record.getRecordSize();
|
||||
}
|
||||
return 4 + size;
|
||||
int oddBytes = size & 0x03;
|
||||
int padding = oddBytes == 0 ? 0 : 4 - oddBytes;
|
||||
return 4 + size + padding;
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
|
@ -192,9 +182,4 @@ public class ObjRecord
|
|||
|
||||
return rec;
|
||||
}
|
||||
|
||||
} // END OF CLASS
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -201,24 +201,16 @@ public final class SharedFormulaRecord extends Record {
|
|||
if (ptgs != null)
|
||||
for (int k = 0; k < ptgs.size(); k++) {
|
||||
Ptg ptg = (Ptg) ptgs.get(k);
|
||||
byte originalOperandClass = -1;
|
||||
if (!ptg.isBaseToken()) {
|
||||
originalOperandClass = ptg.getPtgClass();
|
||||
}
|
||||
if (ptg instanceof RefNPtg) {
|
||||
RefNPtg refNPtg = (RefNPtg)ptg;
|
||||
ptg = new ReferencePtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
|
||||
ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
|
||||
fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()),
|
||||
refNPtg.isRowRelative(),
|
||||
refNPtg.isColRelative());
|
||||
} else if (ptg instanceof RefNVPtg) {
|
||||
RefNVPtg refNVPtg = (RefNVPtg)ptg;
|
||||
ptg = new RefVPtg(fixupRelativeRow(formulaRow,refNVPtg.getRow(),refNVPtg.isRowRelative()),
|
||||
fixupRelativeColumn(formulaColumn,refNVPtg.getColumn(),refNVPtg.isColRelative()),
|
||||
refNVPtg.isRowRelative(),
|
||||
refNVPtg.isColRelative());
|
||||
} else if (ptg instanceof RefNAPtg) {
|
||||
RefNAPtg refNAPtg = (RefNAPtg)ptg;
|
||||
ptg = new RefAPtg( fixupRelativeRow(formulaRow,refNAPtg.getRow(),refNAPtg.isRowRelative()),
|
||||
fixupRelativeColumn(formulaColumn,refNAPtg.getColumn(),refNAPtg.isColRelative()),
|
||||
refNAPtg.isRowRelative(),
|
||||
refNAPtg.isColRelative());
|
||||
} else if (ptg instanceof AreaNPtg) {
|
||||
AreaNPtg areaNPtg = (AreaNPtg)ptg;
|
||||
ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()),
|
||||
|
@ -229,27 +221,11 @@ public final class SharedFormulaRecord extends Record {
|
|||
areaNPtg.isLastRowRelative(),
|
||||
areaNPtg.isFirstColRelative(),
|
||||
areaNPtg.isLastColRelative());
|
||||
} else if (ptg instanceof AreaNVPtg) {
|
||||
AreaNVPtg areaNVPtg = (AreaNVPtg)ptg;
|
||||
ptg = new AreaVPtg(fixupRelativeRow(formulaRow,areaNVPtg.getFirstRow(),areaNVPtg.isFirstRowRelative()),
|
||||
fixupRelativeRow(formulaRow,areaNVPtg.getLastRow(),areaNVPtg.isLastRowRelative()),
|
||||
fixupRelativeColumn(formulaColumn,areaNVPtg.getFirstColumn(),areaNVPtg.isFirstColRelative()),
|
||||
fixupRelativeColumn(formulaColumn,areaNVPtg.getLastColumn(),areaNVPtg.isLastColRelative()),
|
||||
areaNVPtg.isFirstRowRelative(),
|
||||
areaNVPtg.isLastRowRelative(),
|
||||
areaNVPtg.isFirstColRelative(),
|
||||
areaNVPtg.isLastColRelative());
|
||||
} else if (ptg instanceof AreaNAPtg) {
|
||||
AreaNAPtg areaNAPtg = (AreaNAPtg)ptg;
|
||||
ptg = new AreaAPtg(fixupRelativeRow(formulaRow,areaNAPtg.getFirstRow(),areaNAPtg.isFirstRowRelative()),
|
||||
fixupRelativeRow(formulaRow,areaNAPtg.getLastRow(),areaNAPtg.isLastRowRelative()),
|
||||
fixupRelativeColumn(formulaColumn,areaNAPtg.getFirstColumn(),areaNAPtg.isFirstColRelative()),
|
||||
fixupRelativeColumn(formulaColumn,areaNAPtg.getLastColumn(),areaNAPtg.isLastColRelative()),
|
||||
areaNAPtg.isFirstRowRelative(),
|
||||
areaNAPtg.isLastRowRelative(),
|
||||
areaNAPtg.isFirstColRelative(),
|
||||
areaNAPtg.isLastColRelative());
|
||||
}
|
||||
}
|
||||
if (!ptg.isBaseToken()) {
|
||||
ptg.setClass(originalOperandClass);
|
||||
}
|
||||
|
||||
newPtgStack.add(ptg);
|
||||
}
|
||||
return newPtgStack;
|
||||
|
|
|
@ -37,7 +37,7 @@ import java.util.List;
|
|||
public final class ValueRecordsAggregate
|
||||
extends Record
|
||||
{
|
||||
public final static short sid = -1000;
|
||||
public final static short sid = -1001; // 1000 clashes with RowRecordsAggregate
|
||||
int firstcell = -1;
|
||||
int lastcell = -1;
|
||||
CellValueRecordInterface[][] records;
|
||||
|
|
|
@ -44,6 +44,10 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||
protected byte field_1_num_args;
|
||||
protected short field_2_fnc_index;
|
||||
|
||||
public final boolean isBaseToken() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
|
@ -52,12 +56,6 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public short getFunctionIndex() {
|
||||
return field_2_fnc_index;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,69 +15,32 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* AddPtg.java
|
||||
*
|
||||
* Created on October 29, 2001, 7:48 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Addition operator PTG the "+" binomial operator. If you need more
|
||||
* explanation than that then well...We really can't help you here.
|
||||
* @author Andrew C. Oliver (acoliver@apache.org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class AddPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class AddPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x03;
|
||||
|
||||
private final static String ADD = "+";
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new AddPtg();
|
||||
|
||||
public AddPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public AddPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
private AddPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "+";
|
||||
}
|
||||
|
||||
/** implementation of method from OperationsPtg*/
|
||||
public String toFormulaString(String[] operands) {
|
||||
|
@ -89,11 +51,4 @@ public class AddPtg
|
|||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new AddPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
|
||||
|
||||
/**
|
||||
* Title: Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
|
||||
* Title: Area 3D Ptg - 3D reference (Sheet + Area)<P>
|
||||
* Description: Defined a area in Extern Sheet. <P>
|
||||
* REFERENCE: <P>
|
||||
* @author Libin Roman (Vista Portal LDT. Developer)
|
||||
|
@ -35,9 +35,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @version 1.0-pre
|
||||
*/
|
||||
|
||||
public class Area3DPtg extends Ptg implements AreaI
|
||||
{
|
||||
public final class Area3DPtg extends OperandPtg implements AreaI {
|
||||
public final static byte sid = 0x3b;
|
||||
private final static int SIZE = 11; // 10 + 1 for Ptg
|
||||
private short field_1_index_extern_sheet;
|
||||
|
@ -84,28 +82,20 @@ public class Area3DPtg extends Ptg implements AreaI
|
|||
setExternSheetIndex(externalSheetIndex);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append( "AreaPtg\n" );
|
||||
buffer.append( "Index to Extern Sheet = " + getExternSheetIndex() ).append( "\n" );
|
||||
buffer.append( "firstRow = " + getFirstRow() ).append( "\n" );
|
||||
buffer.append( "lastRow = " + getLastRow() ).append( "\n" );
|
||||
buffer.append( "firstCol = " + getFirstColumn() ).append( "\n" );
|
||||
buffer.append( "lastCol = " + getLastColumn() ).append( "\n" );
|
||||
buffer.append( "firstColRel= "
|
||||
+ isFirstRowRelative() ).append( "\n" );
|
||||
buffer.append( "lastColRowRel = "
|
||||
+ isLastRowRelative() ).append( "\n" );
|
||||
buffer.append( "firstColRel = " + isFirstColRelative() ).append( "\n" );
|
||||
buffer.append( "lastColRel = " + isLastColRelative() ).append( "\n" );
|
||||
return buffer.toString();
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append("sheetIx=").append(getExternSheetIndex());
|
||||
sb.append(" ! ");
|
||||
sb.append(AreaReference.formatAsString(this));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void writeBytes( byte[] array, int offset )
|
||||
{
|
||||
array[0 + offset] = (byte) ( sid + ptgClass );
|
||||
array[0 + offset] = (byte) ( sid + getPtgClass() );
|
||||
LittleEndian.putShort( array, 1 + offset, getExternSheetIndex() );
|
||||
LittleEndian.putShort( array, 3 + offset, (short)getFirstRow() );
|
||||
LittleEndian.putShort( array, 5 + offset, (short)getLastRow() );
|
||||
|
@ -279,35 +269,28 @@ public class Area3DPtg extends Ptg implements AreaI
|
|||
StringBuffer retval = new StringBuffer();
|
||||
String sheetName = Ref3DPtg.getSheetName(book, field_1_index_extern_sheet);
|
||||
if(sheetName != null) {
|
||||
SheetNameFormatter.appendFormat(retval, sheetName);
|
||||
if(sheetName.length() == 0) {
|
||||
// What excel does if sheet has been deleted
|
||||
sheetName = "#REF";
|
||||
retval.append(sheetName);
|
||||
} else {
|
||||
// Normal
|
||||
SheetNameFormatter.appendFormat(retval, sheetName);
|
||||
}
|
||||
retval.append( '!' );
|
||||
}
|
||||
|
||||
// Now the normal area bit
|
||||
retval.append( AreaPtg.toFormulaString(this, book) );
|
||||
retval.append(AreaReference.formatAsString(this));
|
||||
|
||||
// All done
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass()
|
||||
{
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
Area3DPtg ptg = new Area3DPtg();
|
||||
ptg.field_1_index_extern_sheet = field_1_index_extern_sheet;
|
||||
ptg.field_2_first_row = field_2_first_row;
|
||||
ptg.field_3_last_row = field_3_last_row;
|
||||
ptg.field_4_first_column = field_4_first_column;
|
||||
ptg.field_5_last_column = field_5_last_column;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
|
||||
// TODO - one junit relies on this. remove
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
if ( this == o ) return true;
|
||||
|
@ -323,17 +306,4 @@ public class Area3DPtg extends Ptg implements AreaI
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int result;
|
||||
result = (int) field_1_index_extern_sheet;
|
||||
result = 29 * result + (int) field_2_first_row;
|
||||
result = 29 * result + (int) field_3_last_row;
|
||||
result = 29 * result + (int) field_4_first_column;
|
||||
result = 29 * result + (int) field_5_last_column;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
|
||||
/* ====================================================================
|
||||
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.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* AreaPtg.java
|
||||
*
|
||||
* Created on November 17, 2001, 9:30 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public final class AreaAPtg extends AreaPtg {
|
||||
public final static short sid = 0x65;
|
||||
|
||||
protected AreaAPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public AreaAPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
|
||||
}
|
||||
|
||||
public AreaAPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getAreaPtgName() {
|
||||
return "AreaAPtg";
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AreaAPtg ptg = new AreaAPtg();
|
||||
ptg.setFirstRow(getFirstRow());
|
||||
ptg.setLastRow(getLastRow());
|
||||
ptg.setFirstColumnRaw(getFirstColumnRaw());
|
||||
ptg.setLastColumnRaw(getLastColumnRaw());
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -17,73 +17,40 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* AreaErr - handles deleted cell area references.
|
||||
*
|
||||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
public class AreaErrPtg extends AreaPtg
|
||||
{
|
||||
public final class AreaErrPtg extends OperandPtg {
|
||||
public final static byte sid = 0x2b;
|
||||
|
||||
private AreaErrPtg()
|
||||
{
|
||||
//Required for clone methods
|
||||
super();
|
||||
}
|
||||
|
||||
public AreaErrPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("AreaErrPtg\n");
|
||||
buffer.append("firstRow = " + getFirstRow()).append("\n");
|
||||
buffer.append("lastRow = " + getLastRow()).append("\n");
|
||||
buffer.append("firstCol = " + getFirstColumn()).append("\n");
|
||||
buffer.append("lastCol = " + getLastColumn()).append("\n");
|
||||
buffer.append("firstColRowRel= "
|
||||
+ isFirstRowRelative()).append("\n");
|
||||
buffer.append("lastColRowRel = "
|
||||
+ isLastRowRelative()).append("\n");
|
||||
buffer.append("firstColRel = " + isFirstColRelative()).append("\n");
|
||||
buffer.append("lastColRel = " + isLastColRelative()).append("\n");
|
||||
return buffer.toString();
|
||||
public AreaErrPtg(RecordInputStream in) {
|
||||
// 8 bytes unused:
|
||||
in.readInt();
|
||||
in.readInt();
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
super.writeBytes(array, offset);
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
array[offset] = (byte) (sid + getPtgClass());
|
||||
LittleEndian.putInt(array, offset+1, 0);
|
||||
LittleEndian.putInt(array, offset+5, 0);
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
public String toFormulaString(HSSFWorkbook book) {
|
||||
return "#REF!";
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
AreaErrPtg ptg = new AreaErrPtg();
|
||||
ptg.setFirstRow(getFirstRow());
|
||||
ptg.setFirstColumn(getFirstColumn());
|
||||
ptg.setLastRow(getLastRow());
|
||||
ptg.setLastColumn(getLastColumn());
|
||||
ptg.setFirstColRelative(isFirstColRelative());
|
||||
ptg.setLastColRelative(isLastColRelative());
|
||||
ptg.setFirstRowRelative(isFirstRowRelative());
|
||||
ptg.setLastRowRelative(isLastRowRelative());
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,49 +15,22 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* AreaPtg.java
|
||||
*
|
||||
* Created on November 17, 2001, 9:30 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class AreaNPtg extends AreaPtgBase {
|
||||
public final static short sid = 0x2D;
|
||||
|
||||
public final class AreaNPtg extends AreaPtg
|
||||
{
|
||||
public final static short sid = 0x2D;
|
||||
public AreaNPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
protected AreaNPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public AreaNPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getAreaPtgName() {
|
||||
return "AreaNPtg";
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
throw notImplemented();
|
||||
}
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,323 +17,25 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class AreaPtg extends Ptg implements AreaI {
|
||||
/**
|
||||
* TODO - (May-2008) fix subclasses of AreaPtg 'AreaN~' which are used in shared formulas.
|
||||
* see similar comment in ReferencePtg
|
||||
*/
|
||||
protected final RuntimeException notImplemented() {
|
||||
return new RuntimeException("Coding Error: This method should never be called. This ptg should be converted");
|
||||
}
|
||||
|
||||
public final class AreaPtg extends AreaPtgBase {
|
||||
public final static short sid = 0x25;
|
||||
private final static int SIZE = 9;
|
||||
/** zero based, unsigned 16 bit */
|
||||
private int field_1_first_row;
|
||||
/** zero based, unsigned 16 bit */
|
||||
private int field_2_last_row;
|
||||
/** zero based, unsigned 8 bit */
|
||||
private int field_3_first_column;
|
||||
/** zero based, unsigned 8 bit */
|
||||
private int field_4_last_column;
|
||||
|
||||
private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000);
|
||||
private final static BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
||||
private final static BitField columnMask = BitFieldFactory.getInstance(0x3FFF);
|
||||
|
||||
protected AreaPtg() {
|
||||
//Required for clone methods
|
||||
public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
|
||||
}
|
||||
public AreaPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public AreaPtg(String arearef) {
|
||||
AreaReference ar = new AreaReference(arearef);
|
||||
CellReference firstCell = ar.getFirstCell();
|
||||
CellReference lastCell = ar.getLastCell();
|
||||
setFirstRow(firstCell.getRow());
|
||||
setFirstColumn(firstCell.getCol());
|
||||
setLastRow(lastCell.getRow());
|
||||
setLastColumn(lastCell.getCol());
|
||||
setFirstColRelative(!firstCell.isColAbsolute());
|
||||
setLastColRelative(!lastCell.isColAbsolute());
|
||||
setFirstRowRelative(!firstCell.isRowAbsolute());
|
||||
setLastRowRelative(!lastCell.isRowAbsolute());
|
||||
}
|
||||
|
||||
public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn,
|
||||
boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
|
||||
checkColumnBounds(firstColumn);
|
||||
checkColumnBounds(lastColumn);
|
||||
checkRowBounds(firstRow);
|
||||
checkRowBounds(lastRow);
|
||||
setFirstRow(firstRow);
|
||||
setLastRow(lastRow);
|
||||
setFirstColumn(firstColumn);
|
||||
setLastColumn(lastColumn);
|
||||
setFirstRowRelative(firstRowRelative);
|
||||
setLastRowRelative(lastRowRelative);
|
||||
setFirstColRelative(firstColRelative);
|
||||
setLastColRelative(lastColRelative);
|
||||
}
|
||||
|
||||
private static void checkColumnBounds(int colIx) {
|
||||
if((colIx & 0x0FF) != colIx) {
|
||||
throw new IllegalArgumentException("colIx (" + colIx + ") is out of range");
|
||||
}
|
||||
}
|
||||
private static void checkRowBounds(int rowIx) {
|
||||
if((rowIx & 0x0FFFF) != rowIx) {
|
||||
throw new IllegalArgumentException("rowIx (" + rowIx + ") is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
public AreaPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_first_row = in.readUShort();
|
||||
field_2_last_row = in.readUShort();
|
||||
field_3_first_column = in.readUShort();
|
||||
field_4_last_column = in.readUShort();
|
||||
//System.out.println(toString());
|
||||
}
|
||||
|
||||
public String getAreaPtgName() {
|
||||
return "AreaPtg";
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(getAreaPtgName());
|
||||
buffer.append("\n");
|
||||
buffer.append("firstRow = " + getFirstRow()).append("\n");
|
||||
buffer.append("lastRow = " + getLastRow()).append("\n");
|
||||
buffer.append("firstCol = " + getFirstColumn()).append("\n");
|
||||
buffer.append("lastCol = " + getLastColumn()).append("\n");
|
||||
buffer.append("firstColRowRel= "
|
||||
+ isFirstRowRelative()).append("\n");
|
||||
buffer.append("lastColRowRel = "
|
||||
+ isLastRowRelative()).append("\n");
|
||||
buffer.append("firstColRel = " + isFirstColRelative()).append("\n");
|
||||
buffer.append("lastColRel = " + isLastColRelative()).append("\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
LittleEndian.putShort(array,offset+1,(short)field_1_first_row);
|
||||
LittleEndian.putShort(array,offset+3,(short)field_2_last_row);
|
||||
LittleEndian.putShort(array,offset+5,(short)field_3_first_column);
|
||||
LittleEndian.putShort(array,offset+7,(short)field_4_last_column);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first row in the area
|
||||
*/
|
||||
public int getFirstRow()
|
||||
{
|
||||
return field_1_first_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first row
|
||||
* @param rowIx number (0-based)
|
||||
*/
|
||||
public void setFirstRow(int rowIx) {
|
||||
checkRowBounds(rowIx);
|
||||
field_1_first_row = rowIx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last row in the range (x2 in x1,y1-x2,y2)
|
||||
*/
|
||||
public int getLastRow()
|
||||
{
|
||||
return field_2_last_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowIx last row number in the area
|
||||
*/
|
||||
public void setLastRow(int rowIx) {
|
||||
checkRowBounds(rowIx);
|
||||
field_2_last_row = rowIx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first column number in the area.
|
||||
*/
|
||||
public int getFirstColumn()
|
||||
{
|
||||
return columnMask.getValue(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first column number + the options bit settings unstripped
|
||||
*/
|
||||
public short getFirstColumnRaw()
|
||||
{
|
||||
return (short) field_3_first_column; // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether or not the first row is a relative reference or not.
|
||||
*/
|
||||
public boolean isFirstRowRelative()
|
||||
{
|
||||
return rowRelative.isSet(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first row to relative or not
|
||||
* @param rel is relative or not.
|
||||
*/
|
||||
public void setFirstRowRelative(boolean rel) {
|
||||
field_3_first_column=rowRelative.setBoolean(field_3_first_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return isrelative first column to relative or not
|
||||
*/
|
||||
public boolean isFirstColRelative()
|
||||
{
|
||||
return colRelative.isSet(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the first column is relative
|
||||
*/
|
||||
public void setFirstColRelative(boolean rel) {
|
||||
field_3_first_column=colRelative.setBoolean(field_3_first_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the first column in the area
|
||||
*/
|
||||
public void setFirstColumn(int colIx) {
|
||||
checkColumnBounds(colIx);
|
||||
field_3_first_column=columnMask.setValue(field_3_first_column, colIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the first column irespective of the bitmasks
|
||||
*/
|
||||
public void setFirstColumnRaw(int column)
|
||||
{
|
||||
field_3_first_column = column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lastcolumn in the area
|
||||
*/
|
||||
public int getLastColumn()
|
||||
{
|
||||
return columnMask.getValue(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last column and bitmask (the raw field)
|
||||
*/
|
||||
public short getLastColumnRaw()
|
||||
{
|
||||
return (short) field_4_last_column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last row relative or not
|
||||
*/
|
||||
public boolean isLastRowRelative()
|
||||
{
|
||||
return rowRelative.isSet(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the last row is relative or not
|
||||
* @param rel <code>true</code> if the last row relative, else
|
||||
* <code>false</code>
|
||||
*/
|
||||
public void setLastRowRelative(boolean rel) {
|
||||
field_4_last_column=rowRelative.setBoolean(field_4_last_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lastcol relative or not
|
||||
*/
|
||||
public boolean isLastColRelative()
|
||||
{
|
||||
return colRelative.isSet(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the last column should be relative or not
|
||||
*/
|
||||
public void setLastColRelative(boolean rel) {
|
||||
field_4_last_column=colRelative.setBoolean(field_4_last_column,rel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set the last column in the area
|
||||
*/
|
||||
public void setLastColumn(int colIx) {
|
||||
checkColumnBounds(colIx);
|
||||
field_4_last_column=columnMask.setValue(field_4_last_column, colIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the last column irrespective of the bitmasks
|
||||
*/
|
||||
public void setLastColumnRaw(short column)
|
||||
{
|
||||
field_4_last_column = column;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return toFormulaString(this, book);
|
||||
}
|
||||
protected static String toFormulaString(AreaI area, HSSFWorkbook book) {
|
||||
CellReference topLeft = new CellReference(area.getFirstRow(),area.getFirstColumn(),!area.isFirstRowRelative(),!area.isFirstColRelative());
|
||||
CellReference botRight = new CellReference(area.getLastRow(),area.getLastColumn(),!area.isLastRowRelative(),!area.isLastColRelative());
|
||||
|
||||
if(AreaReference.isWholeColumnReference(topLeft, botRight)) {
|
||||
return (new AreaReference(topLeft, botRight)).formatAsString();
|
||||
} else {
|
||||
return topLeft.formatAsString() + ":" + botRight.formatAsString();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AreaPtg ptg = new AreaPtg();
|
||||
ptg.field_1_first_row = field_1_first_row;
|
||||
ptg.field_2_last_row = field_2_last_row;
|
||||
ptg.field_3_first_column = field_3_first_column;
|
||||
ptg.field_4_last_column = field_4_last_column;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
super(arearef);
|
||||
}
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public abstract class AreaPtgBase extends OperandPtg implements AreaI {
|
||||
/**
|
||||
* TODO - (May-2008) fix subclasses of AreaPtg 'AreaN~' which are used in shared formulas.
|
||||
* see similar comment in ReferencePtg
|
||||
*/
|
||||
protected final RuntimeException notImplemented() {
|
||||
return new RuntimeException("Coding Error: This method should never be called. This ptg should be converted");
|
||||
}
|
||||
|
||||
public final static short sid = 0x25;
|
||||
private final static int SIZE = 9;
|
||||
/** zero based, unsigned 16 bit */
|
||||
private int field_1_first_row;
|
||||
/** zero based, unsigned 16 bit */
|
||||
private int field_2_last_row;
|
||||
/** zero based, unsigned 8 bit */
|
||||
private int field_3_first_column;
|
||||
/** zero based, unsigned 8 bit */
|
||||
private int field_4_last_column;
|
||||
|
||||
private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000);
|
||||
private final static BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
||||
private final static BitField columnMask = BitFieldFactory.getInstance(0x3FFF);
|
||||
|
||||
protected AreaPtgBase(String arearef) {
|
||||
AreaReference ar = new AreaReference(arearef);
|
||||
CellReference firstCell = ar.getFirstCell();
|
||||
CellReference lastCell = ar.getLastCell();
|
||||
setFirstRow(firstCell.getRow());
|
||||
setFirstColumn(firstCell.getCol());
|
||||
setLastRow(lastCell.getRow());
|
||||
setLastColumn(lastCell.getCol());
|
||||
setFirstColRelative(!firstCell.isColAbsolute());
|
||||
setLastColRelative(!lastCell.isColAbsolute());
|
||||
setFirstRowRelative(!firstCell.isRowAbsolute());
|
||||
setLastRowRelative(!lastCell.isRowAbsolute());
|
||||
}
|
||||
|
||||
protected AreaPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn,
|
||||
boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
|
||||
checkColumnBounds(firstColumn);
|
||||
checkColumnBounds(lastColumn);
|
||||
checkRowBounds(firstRow);
|
||||
checkRowBounds(lastRow);
|
||||
setFirstRow(firstRow);
|
||||
setLastRow(lastRow);
|
||||
setFirstColumn(firstColumn);
|
||||
setLastColumn(lastColumn);
|
||||
setFirstRowRelative(firstRowRelative);
|
||||
setLastRowRelative(lastRowRelative);
|
||||
setFirstColRelative(firstColRelative);
|
||||
setLastColRelative(lastColRelative);
|
||||
}
|
||||
|
||||
private static void checkColumnBounds(int colIx) {
|
||||
if((colIx & 0x0FF) != colIx) {
|
||||
throw new IllegalArgumentException("colIx (" + colIx + ") is out of range");
|
||||
}
|
||||
}
|
||||
private static void checkRowBounds(int rowIx) {
|
||||
if((rowIx & 0x0FFFF) != rowIx) {
|
||||
throw new IllegalArgumentException("rowIx (" + rowIx + ") is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
protected AreaPtgBase(RecordInputStream in)
|
||||
{
|
||||
field_1_first_row = in.readUShort();
|
||||
field_2_last_row = in.readUShort();
|
||||
field_3_first_column = in.readUShort();
|
||||
field_4_last_column = in.readUShort();
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append(AreaReference.formatAsString(this));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
protected abstract byte getSid();
|
||||
|
||||
public final void writeBytes(byte [] array, int offset) {
|
||||
array[offset] = (byte) (getSid() + getPtgClass());
|
||||
LittleEndian.putShort(array,offset+1,(short)field_1_first_row);
|
||||
LittleEndian.putShort(array,offset+3,(short)field_2_last_row);
|
||||
LittleEndian.putShort(array,offset+5,(short)field_3_first_column);
|
||||
LittleEndian.putShort(array,offset+7,(short)field_4_last_column);
|
||||
}
|
||||
|
||||
|
||||
public final int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first row in the area
|
||||
*/
|
||||
public final int getFirstRow() {
|
||||
return field_1_first_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first row
|
||||
* @param rowIx number (0-based)
|
||||
*/
|
||||
public final void setFirstRow(int rowIx) {
|
||||
checkRowBounds(rowIx);
|
||||
field_1_first_row = rowIx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last row in the range (x2 in x1,y1-x2,y2)
|
||||
*/
|
||||
public final int getLastRow() {
|
||||
return field_2_last_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowIx last row number in the area
|
||||
*/
|
||||
public final void setLastRow(int rowIx) {
|
||||
checkRowBounds(rowIx);
|
||||
field_2_last_row = rowIx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first column number in the area.
|
||||
*/
|
||||
public final int getFirstColumn() {
|
||||
return columnMask.getValue(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first column number + the options bit settings unstripped
|
||||
*/
|
||||
public final short getFirstColumnRaw() {
|
||||
return (short) field_3_first_column; // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether or not the first row is a relative reference or not.
|
||||
*/
|
||||
public final boolean isFirstRowRelative() {
|
||||
return rowRelative.isSet(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first row to relative or not
|
||||
* @param rel is relative or not.
|
||||
*/
|
||||
public final void setFirstRowRelative(boolean rel) {
|
||||
field_3_first_column=rowRelative.setBoolean(field_3_first_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return isrelative first column to relative or not
|
||||
*/
|
||||
public final boolean isFirstColRelative() {
|
||||
return colRelative.isSet(field_3_first_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the first column is relative
|
||||
*/
|
||||
public final void setFirstColRelative(boolean rel) {
|
||||
field_3_first_column=colRelative.setBoolean(field_3_first_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the first column in the area
|
||||
*/
|
||||
public final void setFirstColumn(int colIx) {
|
||||
checkColumnBounds(colIx);
|
||||
field_3_first_column=columnMask.setValue(field_3_first_column, colIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the first column irrespective of the bitmasks
|
||||
*/
|
||||
public final void setFirstColumnRaw(int column) {
|
||||
field_3_first_column = column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lastcolumn in the area
|
||||
*/
|
||||
public final int getLastColumn() {
|
||||
return columnMask.getValue(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last column and bitmask (the raw field)
|
||||
*/
|
||||
public final short getLastColumnRaw() {
|
||||
return (short) field_4_last_column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return last row relative or not
|
||||
*/
|
||||
public final boolean isLastRowRelative() {
|
||||
return rowRelative.isSet(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the last row is relative or not
|
||||
* @param rel <code>true</code> if the last row relative, else
|
||||
* <code>false</code>
|
||||
*/
|
||||
public final void setLastRowRelative(boolean rel) {
|
||||
field_4_last_column=rowRelative.setBoolean(field_4_last_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lastcol relative or not
|
||||
*/
|
||||
public final boolean isLastColRelative() {
|
||||
return colRelative.isSet(field_4_last_column);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether the last column should be relative or not
|
||||
*/
|
||||
public final void setLastColRelative(boolean rel) {
|
||||
field_4_last_column=colRelative.setBoolean(field_4_last_column,rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the last column in the area
|
||||
*/
|
||||
public final void setLastColumn(int colIx) {
|
||||
checkColumnBounds(colIx);
|
||||
field_4_last_column=columnMask.setValue(field_4_last_column, colIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the last column irrespective of the bitmasks
|
||||
*/
|
||||
public final void setLastColumnRaw(short column) {
|
||||
field_4_last_column = column;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book) {
|
||||
return AreaReference.formatAsString(this);
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
|
||||
/* ====================================================================
|
||||
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.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* AreaPtg.java
|
||||
*
|
||||
* Created on November 17, 2001, 9:30 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public final class AreaVPtg
|
||||
extends AreaPtg
|
||||
{
|
||||
public final static short sid = 0x45;
|
||||
|
||||
protected AreaVPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public AreaVPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
|
||||
}
|
||||
|
||||
|
||||
public AreaVPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getAreaPtgName() {
|
||||
return "AreaVPtg";
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AreaVPtg ptg = new AreaVPtg();
|
||||
ptg.setFirstRow(getFirstRow());
|
||||
ptg.setLastRow(getLastRow());
|
||||
ptg.setFirstColumnRaw(getFirstColumnRaw());
|
||||
ptg.setLastColumnRaw(getLastColumnRaw());
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -35,29 +35,32 @@ import org.apache.poi.util.LittleEndian;
|
|||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class ArrayPtg extends Ptg {
|
||||
public final class ArrayPtg extends Ptg {
|
||||
public static final byte sid = 0x20;
|
||||
|
||||
private static final int RESERVED_FIELD_LEN = 7;
|
||||
// TODO - fix up field visibility and subclasses
|
||||
protected byte[] field_1_reserved;
|
||||
private byte[] field_1_reserved;
|
||||
|
||||
// data from these fields comes after the Ptg data of all tokens in current formula
|
||||
protected short token_1_columns;
|
||||
protected short token_2_rows;
|
||||
protected Object[] token_3_arrayValues;
|
||||
private short token_1_columns;
|
||||
private short token_2_rows;
|
||||
private Object[] token_3_arrayValues;
|
||||
|
||||
protected ArrayPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtg(RecordInputStream in)
|
||||
{
|
||||
public ArrayPtg(RecordInputStream in) {
|
||||
field_1_reserved = new byte[RESERVED_FIELD_LEN];
|
||||
// TODO - add readFully method to RecordInputStream
|
||||
for(int i=0; i< RESERVED_FIELD_LEN; i++) {
|
||||
field_1_reserved[i] = in.readByte();
|
||||
}
|
||||
}
|
||||
public Object[] getTokenArrayValues() {
|
||||
return (Object[]) token_3_arrayValues.clone();
|
||||
}
|
||||
|
||||
public boolean isBaseToken() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the actual token (array) values. This occurs
|
||||
|
@ -95,6 +98,10 @@ public class ArrayPtg extends Ptg {
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note - (2D) array elements are stored column by column
|
||||
* @return the index into the internal 1D array for the specified column and row
|
||||
*/
|
||||
/* package */ int getValueIndex(int colIx, int rowIx) {
|
||||
if(colIx < 0 || colIx >= token_1_columns) {
|
||||
throw new IllegalArgumentException("Specified colIx (" + colIx
|
||||
|
@ -104,12 +111,12 @@ public class ArrayPtg extends Ptg {
|
|||
throw new IllegalArgumentException("Specified rowIx (" + rowIx
|
||||
+ ") is outside the allowed range (0.." + (token_2_rows-1) + ")");
|
||||
}
|
||||
return rowIx * token_1_columns + colIx;
|
||||
return rowIx + token_2_rows * colIx;
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] data, int offset) {
|
||||
|
||||
LittleEndian.putByte(data, offset + 0, sid + ptgClass);
|
||||
LittleEndian.putByte(data, offset + 0, sid + getPtgClass());
|
||||
System.arraycopy(field_1_reserved, 0, data, offset+1, RESERVED_FIELD_LEN);
|
||||
}
|
||||
|
||||
|
@ -182,13 +189,9 @@ public class ArrayPtg extends Ptg {
|
|||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtg ptg = new ArrayPtg();
|
||||
ArrayPtg ptg = (ArrayPtg) super.clone();
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* ArrayPtgA - handles arrays
|
||||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class ArrayPtgA extends ArrayPtg {
|
||||
public final static byte sid = 0x60;
|
||||
|
||||
private ArrayPtgA() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtgA(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtgA ptg = new ArrayPtgA();
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* ArrayPtg - handles arrays
|
||||
*
|
||||
* The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
|
||||
* includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
|
||||
* It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
|
||||
* held after this. So Ptg.createParsedExpression keeps track of the number of
|
||||
* ArrayPtg elements and need to parse the data upto the FORMULA record size.
|
||||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class ArrayPtgV extends ArrayPtg {
|
||||
public final static byte sid = 0x40;
|
||||
|
||||
private ArrayPtgV() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtgV(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtgV ptg = new ArrayPtgV();
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
@ -32,8 +31,7 @@ import org.apache.poi.util.BitFieldFactory;
|
|||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public final class AttrPtg extends OperationPtg {
|
||||
public final class AttrPtg extends ControlPtg {
|
||||
public final static byte sid = 0x19;
|
||||
private final static int SIZE = 4;
|
||||
private byte field_1_options;
|
||||
|
@ -289,12 +287,6 @@ public final class AttrPtg extends OperationPtg {
|
|||
}
|
||||
return "UNKNOWN ATTRIBUTE";
|
||||
}
|
||||
|
||||
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
int[] jt;
|
||||
|
|
|
@ -27,17 +27,10 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class BoolPtg
|
||||
extends Ptg
|
||||
{
|
||||
public final class BoolPtg extends ScalarConstantPtg {
|
||||
public final static int SIZE = 2;
|
||||
public final static byte sid = 0x1d;
|
||||
private boolean field_1_value;
|
||||
|
||||
private BoolPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
private final boolean field_1_value;
|
||||
|
||||
public BoolPtg(RecordInputStream in)
|
||||
{
|
||||
|
@ -49,11 +42,6 @@ public class BoolPtg
|
|||
field_1_value = (formulaToken.equals("TRUE"));
|
||||
}
|
||||
|
||||
public void setValue(boolean value)
|
||||
{
|
||||
field_1_value = value;
|
||||
}
|
||||
|
||||
public boolean getValue()
|
||||
{
|
||||
return field_1_value;
|
||||
|
@ -74,12 +62,4 @@ public class BoolPtg
|
|||
{
|
||||
return field_1_value ? "TRUE" : "FALSE";
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
BoolPtg ptg = new BoolPtg();
|
||||
ptg.field_1_value = field_1_value;
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,60 +15,31 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class ConcatPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class ConcatPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x08;
|
||||
|
||||
private final static String CONCAT = "&";
|
||||
|
||||
public ConcatPtg(RecordInputStream in)
|
||||
{
|
||||
// No contents
|
||||
public static final ValueOperatorPtg instance = new ConcatPtg();
|
||||
|
||||
private ConcatPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public ConcatPtg() {
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return CONCAT;
|
||||
}
|
||||
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -78,9 +49,4 @@ public class ConcatPtg
|
|||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new ConcatPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,11 +15,24 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
public abstract class ControlPtg
|
||||
extends Ptg
|
||||
{
|
||||
/**
|
||||
* Common superclass for
|
||||
* tExp
|
||||
* tTbl
|
||||
* tParen
|
||||
* tNlr
|
||||
* tAttr
|
||||
* tSheet
|
||||
* tEndSheet
|
||||
*/
|
||||
public abstract class ControlPtg extends Ptg {
|
||||
|
||||
public boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
public final byte getDefaultOperandClass() {
|
||||
throw new IllegalStateException("Control tokens are not classified");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Title: Deleted Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
|
||||
|
@ -26,19 +29,30 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Patrick Luby
|
||||
* @version 1.0-pre
|
||||
*/
|
||||
|
||||
public class DeletedArea3DPtg extends Area3DPtg
|
||||
{
|
||||
public final class DeletedArea3DPtg extends OperandPtg {
|
||||
public final static byte sid = 0x3d;
|
||||
private final int field_1_index_extern_sheet;
|
||||
private final int unused1;
|
||||
private final int unused2;
|
||||
|
||||
/** Creates new DeletedArea3DPtg */
|
||||
public DeletedArea3DPtg( String arearef, short externIdx )
|
||||
{
|
||||
super(arearef, externIdx);
|
||||
}
|
||||
|
||||
public DeletedArea3DPtg( RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
public DeletedArea3DPtg( RecordInputStream in) {
|
||||
field_1_index_extern_sheet = in.readUShort();
|
||||
unused1 = in.readInt();
|
||||
unused2 = in.readInt();
|
||||
}
|
||||
public String toFormulaString(HSSFWorkbook book) {
|
||||
return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
public int getSize() {
|
||||
return 11;
|
||||
}
|
||||
public void writeBytes(byte[] data, int offset) {
|
||||
LittleEndian.putByte(data, 0 + offset, sid + getPtgClass());
|
||||
LittleEndian.putUShort(data, 1 + offset, field_1_index_extern_sheet);
|
||||
LittleEndian.putInt(data, 3 + offset, unused1);
|
||||
LittleEndian.putInt(data, 7 + offset, unused2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Title: Deleted Reference 3D Ptg <P>
|
||||
|
@ -28,16 +30,29 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Patrick Luby
|
||||
* @version 1.0-pre
|
||||
*/
|
||||
public final class DeletedRef3DPtg extends OperandPtg {
|
||||
public final static byte sid = 0x3c;
|
||||
private final int field_1_index_extern_sheet;
|
||||
private final int unused1;
|
||||
|
||||
public class DeletedRef3DPtg extends Ref3DPtg {
|
||||
public final static byte sid = 0x3c;
|
||||
/** Creates new DeletedRef3DPtg */
|
||||
public DeletedRef3DPtg(RecordInputStream in) {
|
||||
field_1_index_extern_sheet = in.readUShort();
|
||||
unused1 = in.readInt();
|
||||
}
|
||||
|
||||
/** Creates new DeletedRef3DPtg */
|
||||
public DeletedRef3DPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public DeletedRef3DPtg(String cellref, short externIdx ) {
|
||||
super(cellref, externIdx);
|
||||
}
|
||||
public String toFormulaString(HSSFWorkbook book) {
|
||||
return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
public int getSize() {
|
||||
return 7;
|
||||
}
|
||||
public void writeBytes(byte[] data, int offset) {
|
||||
LittleEndian.putByte(data, 0 + offset, sid + getPtgClass());
|
||||
LittleEndian.putUShort(data, 1 + offset, field_1_index_extern_sheet);
|
||||
LittleEndian.putInt(data, 3 + offset, unused1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,72 +15,36 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* This PTG implements the standard binomial divide "/"
|
||||
* @author Andrew C. Oliver acoliver at apache dot org
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class DividePtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class DividePtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x06;
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new DividePtg();
|
||||
|
||||
public DividePtg()
|
||||
{
|
||||
private DividePtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public DividePtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append("/");
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
DividePtg ptg = new DividePtg();
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,70 +17,34 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author andy
|
||||
*/
|
||||
|
||||
public class EqualPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class EqualPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x0b;
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new EqualPtg();
|
||||
|
||||
public EqualPtg()
|
||||
{
|
||||
private EqualPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public EqualPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "=";
|
||||
}
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append("=");
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new EqualPtg();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,7 +15,6 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
@ -26,7 +24,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
|||
/**
|
||||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
public final class ErrPtg extends Ptg {
|
||||
public final class ErrPtg extends ScalarConstantPtg {
|
||||
|
||||
// convenient access to namespace
|
||||
private static final HSSFErrorConstants EC = null;
|
||||
|
@ -49,7 +47,7 @@ public final class ErrPtg extends Ptg {
|
|||
|
||||
public static final short sid = 0x1c;
|
||||
private static final int SIZE = 2;
|
||||
private int field_1_error_code;
|
||||
private final int field_1_error_code;
|
||||
|
||||
/** Creates new ErrPtg */
|
||||
|
||||
|
@ -66,7 +64,7 @@ public final class ErrPtg extends Ptg {
|
|||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
array[offset] = (byte) (sid + getPtgClass());
|
||||
array[offset + 1] = (byte)field_1_error_code;
|
||||
}
|
||||
|
||||
|
@ -78,14 +76,6 @@ public final class ErrPtg extends Ptg {
|
|||
return SIZE;
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new ErrPtg(field_1_error_code);
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return field_1_error_code;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -30,29 +29,18 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @author dmui (save existing implementation)
|
||||
*/
|
||||
|
||||
public class ExpPtg
|
||||
extends Ptg
|
||||
{
|
||||
public final class ExpPtg extends ControlPtg {
|
||||
private final static int SIZE = 5;
|
||||
public final static short sid = 0x1;
|
||||
private short field_1_first_row;
|
||||
private short field_2_first_col;
|
||||
|
||||
/** Creates new ExpPtg */
|
||||
|
||||
public ExpPtg()
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates new ExpPtg */
|
||||
private final short field_1_first_row;
|
||||
private final short field_2_first_col;
|
||||
|
||||
public ExpPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_first_row = in.readShort();
|
||||
field_2_first_col = in.readShort();
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset+0]= (byte) (sid);
|
||||
|
@ -85,14 +73,4 @@ public class ExpPtg
|
|||
buffer.append("col = ").append(getColumn()).append("\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
ExpPtg result = new ExpPtg();
|
||||
result.field_1_first_row = field_1_first_row;
|
||||
result.field_2_first_col = field_2_first_col;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
|
||||
}
|
||||
numParams = fm.getMinParams();
|
||||
returnClass = fm.getReturnClassCode();
|
||||
paramClass = fm.getParameterClassCodes();
|
||||
}
|
||||
public FuncPtg(int functionIndex) {
|
||||
field_2_fnc_index = (short) functionIndex;
|
||||
|
@ -54,7 +56,7 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||
}
|
||||
|
||||
public void writeBytes(byte[] array, int offset) {
|
||||
array[offset+0]= (byte) (sid + ptgClass);
|
||||
array[offset+0]= (byte) (sid + getPtgClass());
|
||||
LittleEndian.putShort(array,offset+1,field_2_fnc_index);
|
||||
}
|
||||
|
||||
|
@ -62,12 +64,6 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||
return numParams;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
FuncPtg ptg = new FuncPtg(field_2_fnc_index);
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
|
|
@ -30,16 +30,21 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
|
|||
public final static byte sid = 0x22;
|
||||
private final static int SIZE = 4;
|
||||
|
||||
private FuncVarPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/**Creates new function pointer from a byte array
|
||||
/**Creates new function pointer from a byte array
|
||||
* usually called while reading an excel file.
|
||||
*/
|
||||
public FuncVarPtg(RecordInputStream in) {
|
||||
field_1_num_args = in.readByte();
|
||||
field_2_fnc_index = in.readShort();
|
||||
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 = fm.getReturnClassCode();
|
||||
paramClass = fm.getParameterClassCodes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +65,7 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
|
|||
}
|
||||
|
||||
public void writeBytes(byte[] array, int offset) {
|
||||
array[offset+0]=(byte) (sid + ptgClass);
|
||||
array[offset+0]=(byte) (sid + getPtgClass());
|
||||
array[offset+1]=field_1_num_args;
|
||||
LittleEndian.putShort(array,offset+2,field_2_fnc_index);
|
||||
}
|
||||
|
@ -69,14 +74,6 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
|
|||
return field_1_num_args;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
FuncVarPtg ptg = new FuncVarPtg();
|
||||
ptg.field_1_num_args = field_1_num_args;
|
||||
ptg.field_2_fnc_index = field_2_fnc_index;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,75 +15,40 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
|
||||
/**
|
||||
* PTG class to implement greater or equal to
|
||||
*
|
||||
* @author fred at stsci dot edu
|
||||
*/
|
||||
|
||||
public class GreaterEqualPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final class GreaterEqualPtg extends ValueOperatorPtg {
|
||||
public final static int SIZE = 1;
|
||||
public final static byte sid = 0x0c;
|
||||
|
||||
/** Creates new GreaterEqualPtg */
|
||||
public static final ValueOperatorPtg instance = new GreaterEqualPtg();
|
||||
|
||||
public GreaterEqualPtg()
|
||||
{
|
||||
private GreaterEqualPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public GreaterEqualPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return ">=";
|
||||
}
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
|
||||
buffer.append(toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append(">=");
|
||||
buffer.append(operands[ 1 ]);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new GreaterEqualPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,93 +15,35 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* GreaterThanPtg.java
|
||||
*
|
||||
* Created on January 23, 2003, 9:47 AM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Greater than operator PTG ">"
|
||||
* @author Cameron Riley (criley at ekmail.com)
|
||||
*/
|
||||
public class GreaterThanPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class GreaterThanPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x0D;
|
||||
private final static String GREATERTHAN = ">";
|
||||
|
||||
/**
|
||||
* Constructor. Creates new GreaterThanPtg
|
||||
*/
|
||||
public GreaterThanPtg()
|
||||
{
|
||||
//deliberately empty
|
||||
}
|
||||
public static final ValueOperatorPtg instance = new GreaterThanPtg();
|
||||
|
||||
/**
|
||||
* Constructor. Create a new GreaterThanPtg.
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
public GreaterThanPtg(RecordInputStream in)
|
||||
{
|
||||
//deliberately empty
|
||||
private GreaterThanPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the sid to an array
|
||||
* @param array the array of bytes to write the sid to
|
||||
* @param offset the offset to add the sid to
|
||||
*/
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the sid
|
||||
* @return int the size of the sid in terms of byte additions to an array
|
||||
*/
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of PTG for Greater Than
|
||||
* @return int the identifier for the type
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of operands for the Less than operator
|
||||
* @return int the number of operands
|
||||
*/
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of method from Ptg
|
||||
* @param book the Sheet References
|
||||
*/
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return this.GREATERTHAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of method from OperationsPtg
|
||||
* @param operands a String array of operands
|
||||
|
@ -112,26 +54,8 @@ public class GreaterThanPtg
|
|||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(this.GREATERTHAN);
|
||||
buffer.append(GREATERTHAN);
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default operands class value
|
||||
* @return byte the Ptg Class Value as a byte from the Ptg Parent object
|
||||
*/
|
||||
public byte getDefaultOperandClass()
|
||||
{
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of clone method from Object
|
||||
* @return Object a clone of this class as an Object
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new GreaterThanPtg();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class IntPtg extends Ptg {
|
||||
public final class IntPtg extends ScalarConstantPtg {
|
||||
// 16 bit unsigned integer
|
||||
private static final int MIN_VALUE = 0x0000;
|
||||
private static final int MAX_VALUE = 0xFFFF;
|
||||
|
@ -43,13 +43,12 @@ public final class IntPtg extends Ptg {
|
|||
|
||||
public final static int SIZE = 3;
|
||||
public final static byte sid = 0x1e;
|
||||
private int field_1_value;
|
||||
private final int field_1_value;
|
||||
|
||||
public IntPtg(RecordInputStream in) {
|
||||
this(in.readUShort());
|
||||
}
|
||||
|
||||
|
||||
public IntPtg(int value) {
|
||||
if(!isInRange(value)) {
|
||||
throw new IllegalArgumentException("value is out of range: " + value);
|
||||
|
@ -61,7 +60,6 @@ public final class IntPtg extends Ptg {
|
|||
return field_1_value;
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
|
@ -75,13 +73,7 @@ public final class IntPtg extends Ptg {
|
|||
public String toFormulaString(HSSFWorkbook book) {
|
||||
return String.valueOf(getValue());
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new IntPtg(field_1_value);
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
|
|
|
@ -18,26 +18,23 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
public class IntersectionPtg extends OperationPtg
|
||||
{
|
||||
public final class IntersectionPtg extends OperationPtg {
|
||||
public final static byte sid = 0x0f;
|
||||
|
||||
public static final OperationPtg instance = new IntersectionPtg();
|
||||
|
||||
public IntersectionPtg()
|
||||
{
|
||||
private IntersectionPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public IntersectionPtg(RecordInputStream in)
|
||||
{
|
||||
// doesn't need anything
|
||||
public final boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return 1;
|
||||
|
@ -48,16 +45,6 @@ public class IntersectionPtg extends OperationPtg
|
|||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new IntersectionPtg();
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
|
|
|
@ -16,12 +16,9 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -29,61 +26,28 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
*
|
||||
* @author fred at stsci dot edu
|
||||
*/
|
||||
public class LessEqualPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class LessEqualPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x0a;
|
||||
|
||||
/**
|
||||
* Creates new LessEqualPtg
|
||||
*/
|
||||
public LessEqualPtg()
|
||||
{
|
||||
public static final ValueOperatorPtg instance = new LessEqualPtg();
|
||||
|
||||
private LessEqualPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public LessEqualPtg( RecordInputStream in )
|
||||
{
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes( byte[] array, int offset )
|
||||
{
|
||||
array[offset + 0] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString( HSSFWorkbook book )
|
||||
{
|
||||
return "<=";
|
||||
}
|
||||
|
||||
public String toFormulaString( String[] operands )
|
||||
{
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( operands[0] );
|
||||
buffer.append( toFormulaString( (HSSFWorkbook) null ) );
|
||||
buffer.append("<=");
|
||||
buffer.append( operands[1] );
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new LessEqualPtg();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,103 +15,40 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* LessThanPtg.java
|
||||
*
|
||||
* Created on January 23, 2003, 9:47 AM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
//JDK
|
||||
import java.util.List;
|
||||
|
||||
//POI
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Less than operator PTG "<". The SID is taken from the
|
||||
* Openoffice.orgs Documentation of the Excel File Format,
|
||||
* Table 3.5.7
|
||||
* @author Cameron Riley (criley at ekmail.com)
|
||||
*/
|
||||
public class LessThanPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
/** the size of the Ptg */
|
||||
public final static int SIZE = 1;
|
||||
|
||||
public final class LessThanPtg extends ValueOperatorPtg {
|
||||
/** the sid for the less than operator as hex */
|
||||
public final static byte sid = 0x09;
|
||||
|
||||
/** identifier for LESS THAN char */
|
||||
private final static String LESSTHAN = "<";
|
||||
|
||||
/**
|
||||
* Constructor. Creates new LessThanPtg
|
||||
*/
|
||||
public LessThanPtg()
|
||||
{
|
||||
//deliberately empty
|
||||
}
|
||||
public static final ValueOperatorPtg instance = new LessThanPtg();
|
||||
|
||||
/**
|
||||
* Constructor. Create a new LessThanPtg.
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
public LessThanPtg(RecordInputStream in)
|
||||
{
|
||||
//deliberately empty
|
||||
private LessThanPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the sid to an array
|
||||
* @param array the array of bytes to write the sid to
|
||||
* @param offset the offset to add the sid to
|
||||
*/
|
||||
public void writeBytes(byte[] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the sid
|
||||
* @return int the size of the sid in terms of byte additions to an array
|
||||
*/
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of PTG for Less Than
|
||||
* @return int the identifier for the type
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of operands for the Less than operator
|
||||
* @return int the number of operands
|
||||
*/
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of method from Ptg
|
||||
* @param book the Sheet References
|
||||
*/
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return this.LESSTHAN;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Implementation of method from OperationsPtg
|
||||
* @param operands a String array of operands
|
||||
* @return String the Formula as a String
|
||||
|
@ -120,27 +57,8 @@ public class LessThanPtg
|
|||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(this.LESSTHAN);
|
||||
buffer.append(LESSTHAN);
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default operands class value
|
||||
* @return byte the Ptg Class Value as a byte from the Ptg Parent object
|
||||
*/
|
||||
public byte getDefaultOperandClass()
|
||||
{
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of clone method from Object
|
||||
* @return Object a clone of this class as an Object
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new LessThanPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,12 +15,6 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* MemAreaPtg.java
|
||||
*
|
||||
* Created on November 21, 2001, 8:46 AM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
@ -31,9 +24,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
/**
|
||||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
public class MemAreaPtg
|
||||
extends Ptg
|
||||
{
|
||||
public class MemAreaPtg extends OperandPtg {
|
||||
public final static short sid = 0x26;
|
||||
private final static int SIZE = 7;
|
||||
private int field_1_reserved;
|
||||
|
@ -73,7 +64,7 @@ public class MemAreaPtg
|
|||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
array[offset] = (byte) (sid + getPtgClass());
|
||||
LittleEndian.putInt(array, offset + 1, field_1_reserved);
|
||||
LittleEndian.putShort(array, offset + 5, field_2_subex_len);
|
||||
}
|
||||
|
@ -88,12 +79,7 @@ public class MemAreaPtg
|
|||
return ""; // TODO: Not sure how to format this. -- DN
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
MemAreaPtg ptg = new MemAreaPtg();
|
||||
ptg.field_1_reserved = field_1_reserved;
|
||||
ptg.field_2_subex_len = field_2_subex_len;
|
||||
return ptg;
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,17 +15,10 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* MemErrPtg.java
|
||||
*
|
||||
* Created on November 21, 2001, 8:46 AM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -35,9 +27,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
|
||||
public class MemErrPtg
|
||||
extends MemAreaPtg
|
||||
{
|
||||
public final class MemErrPtg extends MemAreaPtg {
|
||||
public final static short sid = 0x27;
|
||||
|
||||
/** Creates new MemErrPtg */
|
||||
|
@ -46,26 +36,17 @@ public class MemErrPtg
|
|||
{
|
||||
}
|
||||
|
||||
public MemErrPtg(RecordInputStream in)
|
||||
{
|
||||
public MemErrPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
super.writeBytes(array, offset);
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
array[offset] = (byte) (sid + getPtgClass());
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "ERR#";
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MemErrPtg ptg = new MemErrPtg();
|
||||
ptg.setReserved(getReserved());
|
||||
ptg.setSubexpressionLength(getSubexpressionLength());
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* Ptg.java
|
||||
*
|
||||
* Created on October 28, 2001, 6:30 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
@ -30,26 +24,23 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
/**
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
public class MemFuncPtg extends ControlPtg
|
||||
{
|
||||
public final class MemFuncPtg extends OperandPtg {
|
||||
|
||||
public final static byte sid = 0x29;
|
||||
private short field_1_len_ref_subexpression = 0;
|
||||
|
||||
public MemFuncPtg()
|
||||
{
|
||||
//Required for clone methods
|
||||
}
|
||||
private final int field_1_len_ref_subexpression;
|
||||
|
||||
/**Creates new function pointer from a byte array
|
||||
* usually called while reading an excel file.
|
||||
*/
|
||||
public MemFuncPtg( RecordInputStream in )
|
||||
{
|
||||
field_1_len_ref_subexpression = in.readShort();
|
||||
public MemFuncPtg(RecordInputStream in) {
|
||||
this(in.readUShort());
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
public MemFuncPtg(int subExprLen) {
|
||||
field_1_len_ref_subexpression = subExprLen;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
@ -57,7 +48,7 @@ public class MemFuncPtg extends ControlPtg
|
|||
public void writeBytes( byte[] array, int offset )
|
||||
{
|
||||
array[offset + 0] = sid ;
|
||||
LittleEndian.putShort( array, offset + 1, (short)field_1_len_ref_subexpression );
|
||||
LittleEndian.putUShort( array, offset + 1, field_1_len_ref_subexpression );
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
|
@ -67,7 +58,7 @@ public class MemFuncPtg extends ControlPtg
|
|||
|
||||
public byte getDefaultOperandClass()
|
||||
{
|
||||
return 0;
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
|
@ -75,21 +66,8 @@ public class MemFuncPtg extends ControlPtg
|
|||
return field_1_len_ref_subexpression;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
MemFuncPtg ptg = new MemFuncPtg();
|
||||
ptg.field_1_len_ref_subexpression = this.field_1_len_ref_subexpression;
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public int getLenRefSubexpression()
|
||||
{
|
||||
return field_1_len_ref_subexpression;
|
||||
}
|
||||
|
||||
public void setLenRefSubexpression(int len)
|
||||
{
|
||||
field_1_len_ref_subexpression = (short)len;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Missing Function Arguments
|
||||
|
@ -26,23 +25,15 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* Avik Sengupta <avik at apache.org>
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class MissingArgPtg
|
||||
extends Ptg
|
||||
{
|
||||
public final class MissingArgPtg extends ScalarConstantPtg {
|
||||
|
||||
private final static int SIZE = 1;
|
||||
public final static byte sid = 0x16;
|
||||
|
||||
public MissingArgPtg()
|
||||
public static final Ptg instance = new MissingArgPtg();
|
||||
private MissingArgPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public MissingArgPtg(RecordInputStream in)
|
||||
{
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
|
@ -53,17 +44,9 @@ public class MissingArgPtg
|
|||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return " ";
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new MissingArgPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,85 +14,37 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
/**
|
||||
* Implements the standard mathmatical multiplication - *
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class MultiplyPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class MultiplyPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x05;
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new MultiplyPtg();
|
||||
|
||||
public MultiplyPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public MultiplyPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
private MultiplyPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int getStringLength() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "*";
|
||||
}
|
||||
|
||||
public String toFormulaString(Ptg [] operands)
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(operands[ 0 ].toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append("*");
|
||||
buffer.append(operands[ 1 ].toFormulaString((HSSFWorkbook)null));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append("*");
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new MultiplyPtg();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,32 +17,22 @@
|
|||
|
||||
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.usermodel.HSSFName;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class NamePtg
|
||||
extends Ptg
|
||||
{
|
||||
public final class NamePtg extends OperandPtg {
|
||||
public final static short sid = 0x23;
|
||||
private final static int SIZE = 5;
|
||||
/** one-based index to defined name record */
|
||||
private short field_1_label_index;
|
||||
private short field_2_zero; // reserved must be 0
|
||||
boolean xtra=false;
|
||||
|
||||
|
||||
private NamePtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new NamePtg and sets its name index to that of the corresponding defined name record
|
||||
|
@ -72,12 +62,9 @@ public class NamePtg
|
|||
|
||||
/** Creates new NamePtg */
|
||||
|
||||
public NamePtg(RecordInputStream in)
|
||||
{
|
||||
//field_1_ixti = LittleEndian.getShort(data, offset);
|
||||
public NamePtg(RecordInputStream in) {
|
||||
field_1_label_index = in.readShort();
|
||||
field_2_zero = in.readShort();
|
||||
//if (data[offset+6]==0) xtra=true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,15 +74,13 @@ public class NamePtg
|
|||
return field_1_label_index-1; // convert to zero based
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset+0]= (byte) (sid + ptgClass);
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
array[offset+0]= (byte) (sid + getPtgClass());
|
||||
LittleEndian.putShort(array,offset+1,field_1_label_index);
|
||||
LittleEndian.putShort(array,offset+3, field_2_zero);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
|
@ -104,12 +89,7 @@ public class NamePtg
|
|||
return book.getNameName(field_1_label_index - 1);
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_REF;}
|
||||
|
||||
public Object clone() {
|
||||
NamePtg ptg = new NamePtg();
|
||||
ptg.field_1_label_index = field_1_label_index;
|
||||
ptg.field_2_zero = field_2_zero;
|
||||
return ptg;
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
*
|
||||
* @author aviks
|
||||
*/
|
||||
public final class NameXPtg extends Ptg {
|
||||
public final class NameXPtg extends OperandPtg {
|
||||
public final static short sid = 0x39;
|
||||
private final static int SIZE = 7;
|
||||
private short field_1_ixals; // index to REF entry in externsheet record
|
||||
|
@ -33,31 +33,20 @@ public final class NameXPtg extends Ptg {
|
|||
private short field_3_reserved; // reserved must be 0
|
||||
|
||||
|
||||
private NameXPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/** Creates new NamePtg */
|
||||
|
||||
public NameXPtg(RecordInputStream in)
|
||||
{
|
||||
public NameXPtg(RecordInputStream in) {
|
||||
field_1_ixals = in.readShort();
|
||||
field_2_ilbl = in.readShort();
|
||||
field_3_reserved = in.readShort();
|
||||
|
||||
//field_2_reserved = LittleEndian.getByteArray(data, offset + 12,12);
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = (byte)(sid + ptgClass);
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
array[ offset + 0 ] = (byte)(sid + getPtgClass());
|
||||
LittleEndian.putShort(array, offset + 1, field_1_ixals);
|
||||
LittleEndian.putShort(array,offset+3, field_2_ilbl);
|
||||
LittleEndian.putShort(array, offset + 5, field_3_reserved);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
|
@ -67,14 +56,7 @@ public final class NameXPtg extends Ptg {
|
|||
return book.resolveNameXText(field_1_ixals, field_2_ilbl-1);
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
NameXPtg ptg = new NameXPtg();
|
||||
ptg.field_1_ixals = field_1_ixals;
|
||||
ptg.field_3_reserved = field_3_reserved;
|
||||
ptg.field_2_ilbl = field_2_ilbl;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,72 +17,36 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Ptg class to implement not equal
|
||||
*
|
||||
* @author fred at stsci dot edu
|
||||
*/
|
||||
public class NotEqualPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class NotEqualPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x0e;
|
||||
|
||||
/**
|
||||
* Creates new NotEqualPtg
|
||||
*/
|
||||
public NotEqualPtg()
|
||||
{
|
||||
public static final ValueOperatorPtg instance = new NotEqualPtg();
|
||||
|
||||
private NotEqualPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public NotEqualPtg( RecordInputStream in )
|
||||
{
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes( byte[] array, int offset )
|
||||
{
|
||||
array[offset + 0] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString( HSSFWorkbook book )
|
||||
{
|
||||
return "<>";
|
||||
}
|
||||
|
||||
public String toFormulaString( String[] operands )
|
||||
{
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append( operands[0] );
|
||||
|
||||
buffer.append( toFormulaString( (HSSFWorkbook) null ) );
|
||||
buffer.append("<>");
|
||||
buffer.append( operands[1] );
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new NotEqualPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,22 +28,15 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Avik Sengupta
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class NumberPtg
|
||||
extends Ptg
|
||||
{
|
||||
public final class NumberPtg extends ScalarConstantPtg {
|
||||
public final static int SIZE = 9;
|
||||
public final static byte sid = 0x1f;
|
||||
private double field_1_value;
|
||||
|
||||
private NumberPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
private final double field_1_value;
|
||||
|
||||
/** Create a NumberPtg from a byte array read from disk */
|
||||
public NumberPtg(RecordInputStream in)
|
||||
{
|
||||
setValue(in.readDouble());
|
||||
field_1_value = in.readDouble();
|
||||
}
|
||||
|
||||
/** Create a NumberPtg from a string representation of the number
|
||||
|
@ -52,13 +45,7 @@ public class NumberPtg
|
|||
* @param value : String representation of a floating point number
|
||||
*/
|
||||
public NumberPtg(String value) {
|
||||
setValue(Double.parseDouble(value));
|
||||
}
|
||||
|
||||
|
||||
public void setValue(double value)
|
||||
{
|
||||
field_1_value = value;
|
||||
field_1_value = Double.parseDouble(value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,11 +69,4 @@ public class NumberPtg
|
|||
{
|
||||
return "" + getValue();
|
||||
}
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
NumberPtg ptg = new NumberPtg();
|
||||
ptg.field_1_value = field_1_value;
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,38 +17,15 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* RefNVPtg
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class OperandPtg extends Ptg {
|
||||
|
||||
public final class RefNVPtg extends ReferencePtg {
|
||||
public final static byte sid = 0x4C;
|
||||
|
||||
protected RefNVPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/** Creates new ValueReferencePtg */
|
||||
|
||||
public RefNVPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "RefNVPtg";
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
throw notImplemented();
|
||||
}
|
||||
/**
|
||||
* All Operand <tt>Ptg</tt>s are classifed ('relative', 'value', 'array')
|
||||
*/
|
||||
public final boolean isBaseToken() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -17,21 +17,15 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* defines a Ptg that is an operation instead of an operand
|
||||
* @author andy
|
||||
*/
|
||||
|
||||
public abstract class OperationPtg extends Ptg
|
||||
{
|
||||
public abstract class OperationPtg extends Ptg {
|
||||
public final static int TYPE_UNARY = 0;
|
||||
public final static int TYPE_BINARY = 1;
|
||||
public final static int TYPE_FUNCTION = 2;
|
||||
|
||||
public abstract int getType();
|
||||
|
||||
/**
|
||||
* returns a string representation of the operations
|
||||
* the length of the input array should equal the number returned by
|
||||
|
@ -45,6 +39,12 @@ public abstract class OperationPtg extends Ptg
|
|||
*/
|
||||
public abstract int getNumberOfOperands();
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
public final int getType() {
|
||||
// TODO remove "int getType();" from Eval hierarchy
|
||||
throw new RuntimeException("remove this method");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,24 +32,15 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class ParenthesisPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final class ParenthesisPtg extends ControlPtg {
|
||||
|
||||
private final static int SIZE = 1;
|
||||
public final static byte sid = 0x15;
|
||||
|
||||
public ParenthesisPtg()
|
||||
{
|
||||
public static final ControlPtg instance = new ParenthesisPtg();
|
||||
private ParenthesisPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public ParenthesisPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
|
@ -61,16 +52,6 @@ public class ParenthesisPtg
|
|||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "()";
|
||||
|
@ -80,11 +61,4 @@ public class ParenthesisPtg
|
|||
public String toFormulaString(String[] operands) {
|
||||
return "("+operands[0]+")";
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new ParenthesisPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -16,70 +15,33 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* PercentPtg.java
|
||||
*
|
||||
* Created on March 29, 2006, 9:23 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Percent PTG.
|
||||
*
|
||||
* @author Daniel Noll (daniel at nuix.com.au)
|
||||
*/
|
||||
|
||||
public class PercentPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final class PercentPtg extends ValueOperatorPtg {
|
||||
public final static int SIZE = 1;
|
||||
public final static byte sid = 0x14;
|
||||
|
||||
private final static String PERCENT = "%";
|
||||
|
||||
/** Creates new PercentPtg */
|
||||
public static final ValueOperatorPtg instance = new PercentPtg();
|
||||
|
||||
public PercentPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public PercentPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
private PercentPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_UNARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "%";
|
||||
}
|
||||
|
||||
/** implementation of method from OperationsPtg*/
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
|
@ -87,11 +49,4 @@ public class PercentPtg
|
|||
buffer.append(PERCENT);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new PercentPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,58 +17,26 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class PowerPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class PowerPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x07;
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new PowerPtg();
|
||||
|
||||
public PowerPtg()
|
||||
{
|
||||
private PowerPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public PowerPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "^";
|
||||
public int getNumberOfOperands() {
|
||||
return 2; // TODO - 2 seems wrong (Jun 2008). Maybe this method is not relevant
|
||||
}
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
|
@ -76,13 +44,8 @@ public class PowerPtg
|
|||
|
||||
|
||||
buffer.append(operands[ 0 ]);
|
||||
buffer.append(toFormulaString((HSSFWorkbook)null));
|
||||
buffer.append("^");
|
||||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new PowerPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,456 +17,371 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* <tt>Ptg</tt> represents a syntactic token in a formula. 'PTG' is an acronym for
|
||||
* '<b>p</b>arse <b>t</b>hin<b>g</b>'. Originally, the name referred to the single
|
||||
* byte identifier at the start of the token, but in POI, <tt>Ptg</tt> encapsulates
|
||||
* the whole formula token (initial byte + value data).
|
||||
* <p/>
|
||||
*
|
||||
* <tt>Ptg</tt>s are logically arranged in a tree representing the structure of the
|
||||
* parsed formula. However, in BIFF files <tt>Ptg</tt>s are written/read in
|
||||
* <em>Reverse-Polish Notation</em> order. The RPN ordering also simplifies formula
|
||||
* evaluation logic, so POI mostly accesses <tt>Ptg</tt>s in the same way.
|
||||
*
|
||||
* @author andy
|
||||
* @author avik
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public abstract class Ptg
|
||||
{
|
||||
|
||||
|
||||
/* convert infix order ptg list to rpn order ptg list
|
||||
* @return List ptgs in RPN order
|
||||
* @param infixPtgs List of ptgs in infix order
|
||||
*/
|
||||
|
||||
/* DO NOT REMOVE
|
||||
*we keep this method in case we wish to change the way we parse
|
||||
*It needs a getPrecedence in OperationsPtg
|
||||
|
||||
public static List ptgsToRpn(List infixPtgs) {
|
||||
java.util.Stack operands = new java.util.Stack();
|
||||
java.util.List retval = new java.util.Stack();
|
||||
|
||||
java.util.ListIterator i = infixPtgs.listIterator();
|
||||
Object p;
|
||||
OperationPtg o ;
|
||||
boolean weHaveABracket = false;
|
||||
while (i.hasNext()) {
|
||||
p=i.next();
|
||||
if (p instanceof OperationPtg) {
|
||||
if (p instanceof ParenthesisPtg) {
|
||||
if (!weHaveABracket) {
|
||||
operands.push(p);
|
||||
weHaveABracket = true;
|
||||
} else {
|
||||
o = (OperationPtg) operands.pop();
|
||||
while (!(o instanceof ParenthesisPtg)) {
|
||||
retval.add(o);
|
||||
}
|
||||
weHaveABracket = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
operands.push(p);
|
||||
}
|
||||
} else {
|
||||
retval.add(p);
|
||||
}
|
||||
}
|
||||
while (!operands.isEmpty()) {
|
||||
if (operands.peek() instanceof ParenthesisPtg ){
|
||||
//throw some error
|
||||
} else {
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads <tt>size</tt> bytes of the input stream, to create an array of <tt>Ptg</tt>s.
|
||||
* Extra data (beyond <tt>size</tt>) may be read if and <tt>ArrayPtg</tt>s are present.
|
||||
*/
|
||||
public static Stack createParsedExpressionTokens(short size, RecordInputStream in )
|
||||
{
|
||||
Stack stack = new Stack();
|
||||
int pos = 0;
|
||||
List arrayPtgs = null;
|
||||
while ( pos < size )
|
||||
{
|
||||
Ptg ptg = Ptg.createPtg( in );
|
||||
if (ptg instanceof ArrayPtg) {
|
||||
if (arrayPtgs == null)
|
||||
arrayPtgs = new ArrayList(5);
|
||||
arrayPtgs.add(ptg);
|
||||
pos += 8;
|
||||
} else pos += ptg.getSize();
|
||||
stack.push( ptg );
|
||||
}
|
||||
if(pos != size) {
|
||||
throw new RuntimeException("Ptg array size mismatch");
|
||||
}
|
||||
if (arrayPtgs != null) {
|
||||
for (int i=0;i<arrayPtgs.size();i++) {
|
||||
ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
|
||||
p.readTokenValues(in);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static Ptg createPtg(RecordInputStream in)
|
||||
{
|
||||
byte id = in.readByte();
|
||||
Ptg retval = null;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case ExpPtg.sid : // 0x01
|
||||
retval = new ExpPtg(in);
|
||||
break;
|
||||
|
||||
case AddPtg.sid : // 0x03
|
||||
retval = new AddPtg(in);
|
||||
break;
|
||||
|
||||
case SubtractPtg.sid : // 0x04
|
||||
retval = new SubtractPtg(in);
|
||||
break;
|
||||
|
||||
case MultiplyPtg.sid : // 0x05
|
||||
retval = new MultiplyPtg(in);
|
||||
break;
|
||||
|
||||
case DividePtg.sid : // 0x06
|
||||
retval = new DividePtg(in);
|
||||
break;
|
||||
|
||||
case PowerPtg.sid : // 0x07
|
||||
retval = new PowerPtg(in);
|
||||
break;
|
||||
|
||||
case ConcatPtg.sid : // 0x08
|
||||
retval = new ConcatPtg(in);
|
||||
break;
|
||||
|
||||
case LessThanPtg.sid: // 0x09
|
||||
retval = new LessThanPtg(in);
|
||||
break;
|
||||
|
||||
case LessEqualPtg.sid : // 0x0a
|
||||
retval = new LessEqualPtg(in);
|
||||
break;
|
||||
|
||||
case EqualPtg.sid : // 0x0b
|
||||
retval = new EqualPtg(in);
|
||||
break;
|
||||
|
||||
case GreaterEqualPtg.sid : // 0x0c
|
||||
retval = new GreaterEqualPtg(in);
|
||||
break;
|
||||
|
||||
case GreaterThanPtg.sid : // 0x0d
|
||||
retval = new GreaterThanPtg(in);
|
||||
break;
|
||||
|
||||
case NotEqualPtg.sid : // 0x0e
|
||||
retval = new NotEqualPtg(in);
|
||||
break;
|
||||
|
||||
case IntersectionPtg.sid : // 0x0f
|
||||
retval = new IntersectionPtg(in);
|
||||
break;
|
||||
case UnionPtg.sid : // 0x10
|
||||
retval = new UnionPtg(in);
|
||||
break;
|
||||
|
||||
case RangePtg.sid : // 0x11
|
||||
retval = new RangePtg(in);
|
||||
break;
|
||||
|
||||
case UnaryPlusPtg.sid : // 0x12
|
||||
retval = new UnaryPlusPtg(in);
|
||||
break;
|
||||
|
||||
case UnaryMinusPtg.sid : // 0x13
|
||||
retval = new UnaryMinusPtg(in);
|
||||
break;
|
||||
|
||||
case PercentPtg.sid : // 0x14
|
||||
retval = new PercentPtg(in);
|
||||
break;
|
||||
|
||||
case ParenthesisPtg.sid : // 0x15
|
||||
retval = new ParenthesisPtg(in);
|
||||
break;
|
||||
|
||||
case MissingArgPtg.sid : // 0x16
|
||||
retval = new MissingArgPtg(in);
|
||||
break;
|
||||
|
||||
case StringPtg.sid : // 0x17
|
||||
retval = new StringPtg(in);
|
||||
break;
|
||||
|
||||
case AttrPtg.sid : // 0x19
|
||||
case 0x1a :
|
||||
retval = new AttrPtg(in);
|
||||
break;
|
||||
|
||||
case ErrPtg.sid : // 0x1c
|
||||
retval = new ErrPtg(in);
|
||||
break;
|
||||
|
||||
case BoolPtg.sid : // 0x1d
|
||||
retval = new BoolPtg(in);
|
||||
break;
|
||||
|
||||
case IntPtg.sid : // 0x1e
|
||||
retval = new IntPtg(in);
|
||||
break;
|
||||
|
||||
case NumberPtg.sid : // 0x1f
|
||||
retval = new NumberPtg(in);
|
||||
break;
|
||||
|
||||
case ArrayPtg.sid : // 0x20
|
||||
retval = new ArrayPtg(in);
|
||||
break;
|
||||
case ArrayPtgV.sid : // 0x40
|
||||
retval = new ArrayPtgV(in);
|
||||
break;
|
||||
case ArrayPtgA.sid : // 0x60
|
||||
retval = new ArrayPtgA(in);
|
||||
break;
|
||||
|
||||
case FuncPtg.sid : // 0x21
|
||||
case FuncPtg.sid + 0x20 : // 0x41
|
||||
case FuncPtg.sid + 0x40 : // 0x61
|
||||
retval = new FuncPtg(in);
|
||||
break;
|
||||
|
||||
case FuncVarPtg.sid : // 0x22
|
||||
case FuncVarPtg.sid + 0x20 : // 0x42
|
||||
case FuncVarPtg.sid + 0x40 : // 0x62
|
||||
retval = new FuncVarPtg(in);
|
||||
break;
|
||||
|
||||
case ReferencePtg.sid : // 0x24
|
||||
retval = new ReferencePtg(in);
|
||||
break;
|
||||
case RefAPtg.sid : // 0x64
|
||||
retval = new RefAPtg(in);
|
||||
break;
|
||||
case RefVPtg.sid : // 0x44
|
||||
retval = new RefVPtg(in);
|
||||
break;
|
||||
case RefNAPtg.sid : // 0x6C
|
||||
retval = new RefNAPtg(in);
|
||||
break;
|
||||
case RefNPtg.sid : // 0x2C
|
||||
retval = new RefNPtg(in);
|
||||
break;
|
||||
case RefNVPtg.sid : // 0x4C
|
||||
retval = new RefNVPtg(in);
|
||||
break;
|
||||
|
||||
case AreaPtg.sid : // 0x25
|
||||
retval = new AreaPtg(in);
|
||||
break;
|
||||
case AreaVPtg.sid: // 0x45
|
||||
retval = new AreaVPtg(in);
|
||||
break;
|
||||
case AreaAPtg.sid: // 0x65
|
||||
retval = new AreaAPtg(in);
|
||||
break;
|
||||
case AreaNAPtg.sid : // 0x6D
|
||||
retval = new AreaNAPtg(in);
|
||||
break;
|
||||
case AreaNPtg.sid : // 0x2D
|
||||
retval = new AreaNPtg(in);
|
||||
break;
|
||||
case AreaNVPtg.sid : // 0x4D
|
||||
retval = new AreaNVPtg(in);
|
||||
break;
|
||||
|
||||
case MemAreaPtg.sid : // 0x26
|
||||
case MemAreaPtg.sid + 0x40 : // 0x46
|
||||
case MemAreaPtg.sid + 0x20 : // 0x66
|
||||
retval = new MemAreaPtg(in);
|
||||
break;
|
||||
|
||||
case MemErrPtg.sid : // 0x27
|
||||
case MemErrPtg.sid + 0x20 : // 0x47
|
||||
case MemErrPtg.sid + 0x40 : // 0x67
|
||||
retval = new MemErrPtg(in);
|
||||
break;
|
||||
|
||||
case MemFuncPtg.sid : // 0x29
|
||||
retval = new MemFuncPtg(in);
|
||||
break;
|
||||
|
||||
case RefErrorPtg.sid : // 0x2a
|
||||
case RefErrorPtg.sid + 0x20 : // 0x4a
|
||||
case RefErrorPtg.sid + 0x40 : // 0x6a
|
||||
retval = new RefErrorPtg(in);
|
||||
break;
|
||||
|
||||
case AreaErrPtg.sid : // 0x2b
|
||||
case AreaErrPtg.sid + 0x20 : // 0x4b
|
||||
case AreaErrPtg.sid + 0x40 : // 0x6b
|
||||
retval = new AreaErrPtg(in);
|
||||
break;
|
||||
|
||||
case NamePtg.sid : // 0x23
|
||||
case NamePtg.sid + 0x20 : // 0x43
|
||||
case NamePtg.sid + 0x40 : // 0x63
|
||||
retval = new NamePtg(in);
|
||||
break;
|
||||
|
||||
case NameXPtg.sid : // 0x39
|
||||
case NameXPtg.sid + 0x20 : // 0x45
|
||||
case NameXPtg.sid + 0x40 : // 0x79
|
||||
retval = new NameXPtg(in);
|
||||
break;
|
||||
|
||||
case Area3DPtg.sid : // 0x3b
|
||||
case Area3DPtg.sid + 0x20 : // 0x5b
|
||||
case Area3DPtg.sid + 0x40 : // 0x7b
|
||||
retval = new Area3DPtg(in);
|
||||
break;
|
||||
|
||||
case Ref3DPtg.sid : // 0x3a
|
||||
case Ref3DPtg.sid + 0x20: // 0x5a
|
||||
case Ref3DPtg.sid + 0x40: // 0x7a
|
||||
retval = new Ref3DPtg(in);
|
||||
break;
|
||||
|
||||
case DeletedRef3DPtg.sid: // 0x3c
|
||||
case DeletedRef3DPtg.sid + 0x20: // 0x5c
|
||||
case DeletedRef3DPtg.sid + 0x40: // 0x7c
|
||||
retval = new DeletedRef3DPtg(in);
|
||||
break;
|
||||
|
||||
case DeletedArea3DPtg.sid : // 0x3d
|
||||
case DeletedArea3DPtg.sid + 0x20 : // 0x5d
|
||||
case DeletedArea3DPtg.sid + 0x40 : // 0x7d
|
||||
retval = new DeletedArea3DPtg(in);
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
retval = new UnknownPtg();
|
||||
break;
|
||||
|
||||
default :
|
||||
//retval = new UnknownPtg();
|
||||
throw new java.lang.UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+
|
||||
Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
|
||||
}
|
||||
|
||||
if (id > 0x60) {
|
||||
retval.setClass(CLASS_ARRAY);
|
||||
} else if (id > 0x40) {
|
||||
retval.setClass(CLASS_VALUE);
|
||||
} else {
|
||||
retval.setClass(CLASS_REF);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
public static int serializePtgStack(Stack expression, byte[] array, int offset) {
|
||||
int pos = 0;
|
||||
int size = 0;
|
||||
if (expression != null)
|
||||
size = expression.size();
|
||||
|
||||
List arrayPtgs = null;
|
||||
|
||||
for (int k = 0; k < size; k++) {
|
||||
Ptg ptg = ( Ptg ) expression.get(k);
|
||||
|
||||
ptg.writeBytes(array, pos + offset);
|
||||
if (ptg instanceof ArrayPtg) {
|
||||
if (arrayPtgs == null)
|
||||
arrayPtgs = new ArrayList(5);
|
||||
arrayPtgs.add(ptg);
|
||||
pos += 8;
|
||||
} else pos += ptg.getSize();
|
||||
}
|
||||
if (arrayPtgs != null) {
|
||||
for (int i=0;i<arrayPtgs.size();i++) {
|
||||
ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
|
||||
pos += p.writeTokenValueBytes(array, pos + offset);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public abstract int getSize();
|
||||
|
||||
public final byte [] getBytes()
|
||||
{
|
||||
int size = getSize();
|
||||
byte[] bytes = new byte[ size ];
|
||||
|
||||
writeBytes(bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
/** write this Ptg to a byte array*/
|
||||
public abstract void writeBytes(byte [] array, int offset);
|
||||
|
||||
/**
|
||||
* return a string representation of this token alone
|
||||
*/
|
||||
public abstract String toFormulaString(HSSFWorkbook book);
|
||||
/**
|
||||
* dump a debug representation (hexdump) to a string
|
||||
*/
|
||||
public String toDebugString() {
|
||||
byte[] ba = new byte[getSize()];
|
||||
String retval=null;
|
||||
writeBytes(ba,0);
|
||||
try {
|
||||
retval = org.apache.poi.util.HexDump.dump(ba,0,0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Overridden toString method to ensure object hash is not printed.
|
||||
* This helps get rid of gratuitous diffs when comparing two dumps
|
||||
* Subclasses may output more relevant information by overriding this method
|
||||
**/
|
||||
public String toString(){
|
||||
return this.getClass().toString();
|
||||
}
|
||||
|
||||
public static final byte CLASS_REF = 0x00;
|
||||
public static final byte CLASS_VALUE = 0x20;
|
||||
public static final byte CLASS_ARRAY = 0x40;
|
||||
|
||||
protected byte ptgClass = CLASS_REF; //base ptg
|
||||
|
||||
public void setClass(byte thePtgClass) {
|
||||
ptgClass = thePtgClass;
|
||||
}
|
||||
|
||||
/** returns the class (REF/VALUE/ARRAY) for this Ptg */
|
||||
public byte getPtgClass() {
|
||||
return ptgClass;
|
||||
}
|
||||
|
||||
public abstract byte getDefaultOperandClass();
|
||||
|
||||
public abstract Object clone();
|
||||
|
||||
|
||||
|
||||
public abstract class Ptg implements Cloneable {
|
||||
|
||||
/* convert infix order ptg list to rpn order ptg list
|
||||
* @return List ptgs in RPN order
|
||||
* @param infixPtgs List of ptgs in infix order
|
||||
*/
|
||||
|
||||
/* DO NOT REMOVE
|
||||
*we keep this method in case we wish to change the way we parse
|
||||
*It needs a getPrecedence in OperationsPtg
|
||||
|
||||
public static List ptgsToRpn(List infixPtgs) {
|
||||
java.util.Stack operands = new java.util.Stack();
|
||||
java.util.List retval = new java.util.Stack();
|
||||
|
||||
java.util.ListIterator i = infixPtgs.listIterator();
|
||||
Object p;
|
||||
OperationPtg o ;
|
||||
boolean weHaveABracket = false;
|
||||
while (i.hasNext()) {
|
||||
p=i.next();
|
||||
if (p instanceof OperationPtg) {
|
||||
if (p instanceof ParenthesisPtg) {
|
||||
if (!weHaveABracket) {
|
||||
operands.push(p);
|
||||
weHaveABracket = true;
|
||||
} else {
|
||||
o = (OperationPtg) operands.pop();
|
||||
while (!(o instanceof ParenthesisPtg)) {
|
||||
retval.add(o);
|
||||
}
|
||||
weHaveABracket = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
operands.push(p);
|
||||
}
|
||||
} else {
|
||||
retval.add(p);
|
||||
}
|
||||
}
|
||||
while (!operands.isEmpty()) {
|
||||
if (operands.peek() instanceof ParenthesisPtg ){
|
||||
//throw some error
|
||||
} else {
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads <tt>size</tt> bytes of the input stream, to create an array of <tt>Ptg</tt>s.
|
||||
* Extra data (beyond <tt>size</tt>) may be read if and <tt>ArrayPtg</tt>s are present.
|
||||
*/
|
||||
public static Ptg[] readTokens(int size, RecordInputStream in) {
|
||||
Stack temp = createParsedExpressionTokens((short)size, in);
|
||||
return toPtgArray(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - use readTokens()
|
||||
*/
|
||||
public static Stack createParsedExpressionTokens(short size, RecordInputStream in)
|
||||
{
|
||||
Stack stack = new Stack();
|
||||
int pos = 0;
|
||||
List arrayPtgs = null;
|
||||
while ( pos < size )
|
||||
{
|
||||
Ptg ptg = Ptg.createPtg( in );
|
||||
if (ptg instanceof ArrayPtg) {
|
||||
if (arrayPtgs == null)
|
||||
arrayPtgs = new ArrayList(5);
|
||||
arrayPtgs.add(ptg);
|
||||
pos += 8;
|
||||
} else pos += ptg.getSize();
|
||||
stack.push( ptg );
|
||||
}
|
||||
if(pos != size) {
|
||||
throw new RuntimeException("Ptg array size mismatch");
|
||||
}
|
||||
if (arrayPtgs != null) {
|
||||
for (int i=0;i<arrayPtgs.size();i++) {
|
||||
ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
|
||||
p.readTokenValues(in);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static Ptg createPtg(RecordInputStream in) {
|
||||
byte id = in.readByte();
|
||||
|
||||
if (id < 0x20) {
|
||||
return createBasePtg(id, in);
|
||||
}
|
||||
|
||||
Ptg retval = createClassifiedPtg(id, in);
|
||||
|
||||
if (id > 0x60) {
|
||||
retval.setClass(CLASS_ARRAY);
|
||||
} else if (id > 0x40) {
|
||||
retval.setClass(CLASS_VALUE);
|
||||
} else {
|
||||
retval.setClass(CLASS_REF);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private static Ptg createClassifiedPtg(byte id, RecordInputStream in) {
|
||||
|
||||
int baseId = id & 0x1F | 0x20;
|
||||
|
||||
switch (baseId) {
|
||||
case ArrayPtg.sid: return new ArrayPtg(in); // 0x20, 0x40, 0x60
|
||||
case FuncPtg.sid: return new FuncPtg(in); // 0x21, 0x41, 0x61
|
||||
case FuncVarPtg.sid: return new FuncVarPtg(in); // 0x22, 0x42, 0x62
|
||||
case NamePtg.sid: return new NamePtg(in); // 0x23, 0x43, 0x63
|
||||
case RefPtg.sid: return new RefPtg(in); // 0x24, 0x44, 0x64
|
||||
case AreaPtg.sid: return new AreaPtg(in); // 0x25, 0x45, 0x65
|
||||
case MemAreaPtg.sid: return new MemAreaPtg(in); // 0x26, 0x46, 0x66
|
||||
case MemErrPtg.sid: return new MemErrPtg(in); // 0x27, 0x47, 0x67
|
||||
case MemFuncPtg.sid: return new MemFuncPtg(in); // 0x29, 0x49, 0x69
|
||||
case RefErrorPtg.sid: return new RefErrorPtg(in);// 0x2a, 0x4a, 0x6a
|
||||
case AreaErrPtg.sid: return new AreaErrPtg(in); // 0x2b, 0x4b, 0x6b
|
||||
case RefNPtg.sid: return new RefNPtg(in); // 0x2c, 0x4c, 0x6c
|
||||
case AreaNPtg.sid: return new AreaNPtg(in); // 0x2d, 0x4d, 0x6d
|
||||
|
||||
case NameXPtg.sid: return new NameXPtg(in); // 0x39, 0x49, 0x79
|
||||
case Ref3DPtg.sid: return new Ref3DPtg(in); // 0x3a, 0x5a, 0x7a
|
||||
case Area3DPtg.sid: return new Area3DPtg(in); // 0x3b, 0x5b, 0x7b
|
||||
case DeletedRef3DPtg.sid: return new DeletedRef3DPtg(in); // 0x3c, 0x5c, 0x7c
|
||||
case DeletedArea3DPtg.sid: return new DeletedArea3DPtg(in); // 0x3d, 0x5d, 0x7d
|
||||
}
|
||||
throw new UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+
|
||||
Integer.toHexString(id) + " (" + ( int ) id + ")");
|
||||
}
|
||||
|
||||
private static Ptg createBasePtg(byte id, RecordInputStream in) {
|
||||
switch(id) {
|
||||
case 0x00: return new UnknownPtg(); // TODO - not a real Ptg
|
||||
case ExpPtg.sid: return new ExpPtg(in); // 0x01
|
||||
case AddPtg.sid: return AddPtg.instance; // 0x03
|
||||
case SubtractPtg.sid: return SubtractPtg.instance; // 0x04
|
||||
case MultiplyPtg.sid: return MultiplyPtg.instance; // 0x05
|
||||
case DividePtg.sid: return DividePtg.instance; // 0x06
|
||||
case PowerPtg.sid: return PowerPtg.instance; // 0x07
|
||||
case ConcatPtg.sid: return ConcatPtg.instance; // 0x08
|
||||
case LessThanPtg.sid: return LessThanPtg.instance; // 0x09
|
||||
case LessEqualPtg.sid: return LessEqualPtg.instance; // 0x0a
|
||||
case EqualPtg.sid: return EqualPtg.instance; // 0x0b
|
||||
case GreaterEqualPtg.sid: return GreaterEqualPtg.instance;// 0x0c
|
||||
case GreaterThanPtg.sid: return GreaterThanPtg.instance; // 0x0d
|
||||
case NotEqualPtg.sid: return NotEqualPtg.instance; // 0x0e
|
||||
case IntersectionPtg.sid: return IntersectionPtg.instance;// 0x0f
|
||||
case UnionPtg.sid: return UnionPtg.instance; // 0x10
|
||||
case RangePtg.sid: return RangePtg.instance; // 0x11
|
||||
case UnaryPlusPtg.sid: return UnaryPlusPtg.instance; // 0x12
|
||||
case UnaryMinusPtg.sid: return UnaryMinusPtg.instance; // 0x13
|
||||
case PercentPtg.sid: return PercentPtg.instance; // 0x14
|
||||
case ParenthesisPtg.sid: return ParenthesisPtg.instance; // 0x15
|
||||
case MissingArgPtg.sid: return MissingArgPtg.instance; // 0x16
|
||||
|
||||
case StringPtg.sid: return new StringPtg(in); // 0x17
|
||||
case AttrPtg.sid:
|
||||
case 0x1a: return new AttrPtg(in); // 0x19
|
||||
case ErrPtg.sid: return new ErrPtg(in); // 0x1c
|
||||
case BoolPtg.sid: return new BoolPtg(in); // 0x1d
|
||||
case IntPtg.sid: return new IntPtg(in); // 0x1e
|
||||
case NumberPtg.sid: return new NumberPtg(in); // 0x1f
|
||||
}
|
||||
throw new RuntimeException("Unexpected base token id (" + id + ")");
|
||||
}
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static int getEncodedSize(Stack ptgs) {
|
||||
return getEncodedSize(toPtgArray(ptgs));
|
||||
}
|
||||
/**
|
||||
* @return a distinct copy of this <tt>Ptg</tt> if the class is mutable, or the same instance
|
||||
* if the class is immutable.
|
||||
*/
|
||||
public final Ptg copy() {
|
||||
// TODO - all base tokens are logically immutable, but AttrPtg needs some clean-up
|
||||
if (this instanceof ValueOperatorPtg) {
|
||||
return this;
|
||||
}
|
||||
if (this instanceof ScalarConstantPtg) {
|
||||
return this;
|
||||
}
|
||||
return (Ptg) clone();
|
||||
}
|
||||
|
||||
protected Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
private static Ptg[] toPtgArray(List l) {
|
||||
Ptg[] result = new Ptg[l.size()];
|
||||
l.toArray(result);
|
||||
return result;
|
||||
}
|
||||
private static Stack createStack(Ptg[] formulaTokens) {
|
||||
Stack result = new Stack();
|
||||
for (int i = 0; i < formulaTokens.length; i++) {
|
||||
result.add(formulaTokens[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// TODO - several duplicates of this code should be refactored here
|
||||
public static int getEncodedSize(Ptg[] ptgs) {
|
||||
int result = 0;
|
||||
for (int i = 0; i < ptgs.length; i++) {
|
||||
result += ptgs[i].getSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Writes the ptgs to the data buffer, starting at the specified offset.
|
||||
*
|
||||
* <br/>
|
||||
* The 2 byte encode length field is <b>not</b> written by this method.
|
||||
* @return number of bytes written
|
||||
*/
|
||||
public static int serializePtgs(Ptg[] ptgs, byte[] data, int offset) {
|
||||
return serializePtgStack(createStack(ptgs), data, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use serializePtgs()
|
||||
*/
|
||||
public static int serializePtgStack(Stack expression, byte[] array, int offset) {
|
||||
int pos = 0;
|
||||
int size = 0;
|
||||
if (expression != null)
|
||||
size = expression.size();
|
||||
|
||||
List arrayPtgs = null;
|
||||
|
||||
for (int k = 0; k < size; k++) {
|
||||
Ptg ptg = ( Ptg ) expression.get(k);
|
||||
|
||||
ptg.writeBytes(array, pos + offset);
|
||||
if (ptg instanceof ArrayPtg) {
|
||||
if (arrayPtgs == null)
|
||||
arrayPtgs = new ArrayList(5);
|
||||
arrayPtgs.add(ptg);
|
||||
pos += 8;
|
||||
} else pos += ptg.getSize();
|
||||
}
|
||||
if (arrayPtgs != null) {
|
||||
for (int i=0;i<arrayPtgs.size();i++) {
|
||||
ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
|
||||
pos += p.writeTokenValueBytes(array, pos + offset);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the encoded length of this Ptg, including the initial Ptg type identifier byte.
|
||||
*/
|
||||
public abstract int getSize();
|
||||
|
||||
/**
|
||||
* @return the encoded length of this Ptg, not including the initial Ptg type identifier byte.
|
||||
*/
|
||||
// public abstract int getDataSize();
|
||||
|
||||
public final byte [] getBytes()
|
||||
{
|
||||
int size = getSize();
|
||||
byte[] bytes = new byte[ size ];
|
||||
|
||||
writeBytes(bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
/** write this Ptg to a byte array*/
|
||||
public abstract void writeBytes(byte [] array, int offset);
|
||||
|
||||
/**
|
||||
* return a string representation of this token alone
|
||||
*/
|
||||
public abstract String toFormulaString(HSSFWorkbook book);
|
||||
/**
|
||||
* dump a debug representation (hexdump) to a string
|
||||
*/
|
||||
public final String toDebugString() {
|
||||
byte[] ba = new byte[getSize()];
|
||||
String retval=null;
|
||||
writeBytes(ba,0);
|
||||
try {
|
||||
retval = org.apache.poi.util.HexDump.dump(ba,0,0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Overridden toString method to ensure object hash is not printed.
|
||||
* This helps get rid of gratuitous diffs when comparing two dumps
|
||||
* Subclasses may output more relevant information by overriding this method
|
||||
**/
|
||||
public String toString(){
|
||||
return this.getClass().toString();
|
||||
}
|
||||
|
||||
public static final byte CLASS_REF = 0x00;
|
||||
public static final byte CLASS_VALUE = 0x20;
|
||||
public static final byte CLASS_ARRAY = 0x40;
|
||||
|
||||
private byte ptgClass = CLASS_REF; //base ptg
|
||||
|
||||
public final void setClass(byte thePtgClass) {
|
||||
if (isBaseToken()) {
|
||||
throw new RuntimeException("setClass should not be called on a base token");
|
||||
}
|
||||
ptgClass = thePtgClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the 'operand class' (REF/VALUE/ARRAY) for this Ptg
|
||||
*/
|
||||
public final byte getPtgClass() {
|
||||
return ptgClass;
|
||||
}
|
||||
|
||||
public abstract byte getDefaultOperandClass();
|
||||
|
||||
/**
|
||||
* @return <code>false</code> if this token is classified as 'reference', 'value', or 'array'
|
||||
*/
|
||||
public abstract boolean isBaseToken();
|
||||
}
|
||||
|
|
|
@ -18,26 +18,24 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* @author Daniel Noll (daniel at nuix dot com dot au)
|
||||
*/
|
||||
public class RangePtg extends OperationPtg
|
||||
{
|
||||
public final class RangePtg extends OperationPtg {
|
||||
public final static int SIZE = 1;
|
||||
public final static byte sid = 0x11;
|
||||
|
||||
public RangePtg()
|
||||
{
|
||||
public static final OperationPtg instance = new RangePtg();
|
||||
|
||||
private RangePtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public RangePtg(RecordInputStream in)
|
||||
{
|
||||
// No contents
|
||||
public final boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
|
@ -48,17 +46,6 @@ public class RangePtg extends OperationPtg
|
|||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new RangePtg();
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return ":";
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.util.RangeAddress;
|
||||
import org.apache.poi.hssf.util.SheetReferences;
|
||||
|
@ -35,8 +34,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @version 1.0-pre
|
||||
*/
|
||||
|
||||
public class Ref3DPtg extends Ptg {
|
||||
public final class Ref3DPtg extends OperandPtg {
|
||||
public final static byte sid = 0x3a;
|
||||
private final static int SIZE = 7; // 6 + 1 for Ptg
|
||||
private short field_1_index_extern_sheet;
|
||||
|
@ -70,20 +68,19 @@ public class Ref3DPtg extends Ptg {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("Ref3dPtg\n");
|
||||
buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n");
|
||||
buffer.append("Row = " + getRow()).append("\n");
|
||||
buffer.append("Col = " + getColumn()).append("\n");
|
||||
buffer.append("ColRowRel= "
|
||||
+ isRowRelative()).append("\n");
|
||||
buffer.append("ColRel = " + isColRelative()).append("\n");
|
||||
return buffer.toString();
|
||||
CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append("sheetIx=").append(getExternSheetIndex());
|
||||
sb.append(" ! ");
|
||||
sb.append(cr.formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
array[ 0 + offset ] = (byte) (sid + ptgClass);
|
||||
array[ 0 + offset ] = (byte) (sid + getPtgClass());
|
||||
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
|
||||
LittleEndian.putShort(array, 3 + offset , (short)getRow());
|
||||
LittleEndian.putShort(array, 5 + offset , (short)getColumnRaw());
|
||||
|
@ -191,14 +188,7 @@ public class Ref3DPtg extends Ptg {
|
|||
return retval.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_REF;}
|
||||
|
||||
public Object clone() {
|
||||
Ref3DPtg ptg = new Ref3DPtg();
|
||||
ptg.field_1_index_extern_sheet = field_1_index_extern_sheet;
|
||||
ptg.field_2_row = field_2_row;
|
||||
ptg.field_3_column = field_3_column;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,28 +17,20 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* RefError - handles deleted cell reference
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefErrorPtg extends OperandPtg {
|
||||
|
||||
public class RefErrorPtg extends Ptg
|
||||
{
|
||||
private final static int SIZE = 5;
|
||||
public final static byte sid = 0x2a;
|
||||
private int field_1_reserved;
|
||||
|
||||
private RefErrorPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public RefErrorPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_reserved = in.readInt();
|
||||
|
@ -55,7 +47,7 @@ public class RefErrorPtg extends Ptg
|
|||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
array[offset] = (byte) (sid + getPtgClass());
|
||||
LittleEndian.putInt(array,offset+1,field_1_reserved);
|
||||
}
|
||||
|
||||
|
@ -83,11 +75,4 @@ public class RefErrorPtg extends Ptg
|
|||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
RefErrorPtg ptg = new RefErrorPtg();
|
||||
ptg.field_1_reserved = field_1_reserved;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,37 +18,21 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* RefNPtg
|
||||
* @author Jason Height (jheight at apache dot com)
|
||||
*/
|
||||
public final class RefNPtg extends ReferencePtg
|
||||
{
|
||||
public final class RefNPtg extends RefPtgBase {
|
||||
public final static byte sid = 0x2C;
|
||||
|
||||
protected RefNPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/** Creates new ValueReferencePtg */
|
||||
|
||||
public RefNPtg(RecordInputStream in)
|
||||
{
|
||||
public RefNPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "RefNPtg";
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
throw notImplemented();
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +1,53 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* RefNAPtg
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public final class RefAPtg extends ReferencePtg {
|
||||
public final static byte sid = 0x64;
|
||||
|
||||
protected RefAPtg() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RefAPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
super(row, column, isRowRelative, isColumnRelative);
|
||||
}
|
||||
|
||||
public RefAPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "RefAPtg";
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
RefAPtg ptg = new RefAPtg();
|
||||
ptg.setRow(getRow());
|
||||
ptg.setColumnRaw(getColumnRaw());
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* ReferencePtg - handles references (such as A1, A2, IA4)
|
||||
* @author Andrew C. Oliver (acoliver@apache.org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefPtg extends RefPtgBase {
|
||||
public final static byte sid = 0x24;
|
||||
|
||||
/**
|
||||
* Takes in a String representation of a cell reference and fills out the
|
||||
* numeric fields.
|
||||
*/
|
||||
public RefPtg(String cellref) {
|
||||
super(cellref);
|
||||
}
|
||||
|
||||
public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
setRow(row);
|
||||
setColumn(column);
|
||||
setRowRelative(isRowRelative);
|
||||
setColRelative(isColumnRelative);
|
||||
}
|
||||
|
||||
public RefPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
}
|
|
@ -26,98 +26,75 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* ReferencePtg - handles references (such as A1, A2, IA4)
|
||||
* ReferencePtgBase - handles references (such as A1, A2, IA4)
|
||||
* @author Andrew C. Oliver (acoliver@apache.org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class ReferencePtg extends Ptg {
|
||||
/**
|
||||
* TODO - (May-2008) fix subclasses of ReferencePtg 'RefN~' which are used in shared formulas.
|
||||
* (See bugzilla 44921)
|
||||
* The 'RefN~' instances do not work properly, and are expected to be converted by
|
||||
* SharedFormulaRecord.convertSharedFormulas().
|
||||
* This conversion currently does not take place for formulas of named ranges, conditional
|
||||
* format rules and data validation rules.
|
||||
* Furthermore, conversion is probably not appropriate in those instances.
|
||||
*/
|
||||
protected final RuntimeException notImplemented() {
|
||||
return new RuntimeException("Coding Error: This method should never be called. This ptg should be converted");
|
||||
}
|
||||
public abstract class RefPtgBase extends OperandPtg {
|
||||
|
||||
private final static int SIZE = 5;
|
||||
public final static byte sid = 0x24;
|
||||
private final static int MAX_ROW_NUMBER = 65536;
|
||||
private final static int MAX_ROW_NUMBER = 65536;
|
||||
|
||||
/** The row index - zero based unsigned 16 bit value */
|
||||
private int field_1_row;
|
||||
/** Field 2
|
||||
* - lower 8 bits is the zero based unsigned byte column index
|
||||
/** Field 2
|
||||
* - lower 8 bits is the zero based unsigned byte column index
|
||||
* - bit 16 - isRowRelative
|
||||
* - bit 15 - isColumnRelative
|
||||
* - bit 15 - isColumnRelative
|
||||
*/
|
||||
private int field_2_col;
|
||||
private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000);
|
||||
private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
||||
private static final BitField column = BitFieldFactory.getInstance(0x00FF);
|
||||
|
||||
protected ReferencePtg() {
|
||||
protected RefPtgBase() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Takes in a String represnetation of a cell reference and fills out the
|
||||
* Takes in a String representation of a cell reference and fills out the
|
||||
* numeric fields.
|
||||
*/
|
||||
public ReferencePtg(String cellref) {
|
||||
protected RefPtgBase(String cellref) {
|
||||
CellReference c= new CellReference(cellref);
|
||||
setRow(c.getRow());
|
||||
setColumn(c.getCol());
|
||||
setColRelative(!c.isColAbsolute());
|
||||
setRowRelative(!c.isRowAbsolute());
|
||||
}
|
||||
|
||||
public ReferencePtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
|
||||
protected RefPtgBase(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
setRow(row);
|
||||
setColumn(column);
|
||||
setRowRelative(isRowRelative);
|
||||
setColRelative(isColumnRelative);
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates new ValueReferencePtg */
|
||||
|
||||
public ReferencePtg(RecordInputStream in)
|
||||
{
|
||||
protected RefPtgBase(RecordInputStream in) {
|
||||
field_1_row = in.readUShort();
|
||||
field_2_col = in.readUShort();
|
||||
}
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "ReferencePtg";
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer("[");
|
||||
buffer.append(getRefPtgName());
|
||||
buffer.append("]\n");
|
||||
|
||||
buffer.append("row = ").append(getRow()).append("\n");
|
||||
buffer.append("col = ").append(getColumn()).append("\n");
|
||||
buffer.append("rowrelative = ").append(isRowRelative()).append("\n");
|
||||
buffer.append("colrelative = ").append(isColRelative()).append("\n");
|
||||
return buffer.toString();
|
||||
public final String toString() {
|
||||
CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append(cr.formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset] = (byte) (sid + ptgClass);
|
||||
public final void writeBytes(byte [] array, int offset) {
|
||||
array[offset] = (byte) (getSid() + getPtgClass());
|
||||
|
||||
LittleEndian.putShort(array, offset+1, (short)field_1_row);
|
||||
LittleEndian.putShort(array, offset+3, (short)field_2_col);
|
||||
}
|
||||
|
||||
protected abstract byte getSid();
|
||||
|
||||
public void setRow(int row)
|
||||
{
|
||||
public final void setRow(int row) {
|
||||
if(row < 0 || row >= MAX_ROW_NUMBER) {
|
||||
throw new IllegalArgumentException("The row number, when specified as an integer, must be between 0 and " + MAX_ROW_NUMBER);
|
||||
}
|
||||
|
@ -128,81 +105,61 @@ public class ReferencePtg extends Ptg {
|
|||
* Returns the row number as a short, which will be
|
||||
* wrapped (negative) for values between 32769 and 65535
|
||||
*/
|
||||
public int getRow()
|
||||
{
|
||||
public final int getRow(){
|
||||
return field_1_row;
|
||||
}
|
||||
/**
|
||||
* Returns the row number as an int, between 0 and 65535
|
||||
*/
|
||||
public int getRowAsInt()
|
||||
{
|
||||
if(field_1_row < 0) {
|
||||
return field_1_row + MAX_ROW_NUMBER;
|
||||
}
|
||||
public final int getRowAsInt() {
|
||||
return field_1_row;
|
||||
}
|
||||
|
||||
public boolean isRowRelative()
|
||||
{
|
||||
public final boolean isRowRelative() {
|
||||
return rowRelative.isSet(field_2_col);
|
||||
}
|
||||
|
||||
public void setRowRelative(boolean rel) {
|
||||
|
||||
public final void setRowRelative(boolean rel) {
|
||||
field_2_col=rowRelative.setBoolean(field_2_col,rel);
|
||||
}
|
||||
|
||||
public boolean isColRelative()
|
||||
{
|
||||
|
||||
public final boolean isColRelative() {
|
||||
return colRelative.isSet(field_2_col);
|
||||
}
|
||||
|
||||
public void setColRelative(boolean rel) {
|
||||
|
||||
public final void setColRelative(boolean rel) {
|
||||
field_2_col=colRelative.setBoolean(field_2_col,rel);
|
||||
}
|
||||
|
||||
public void setColumnRaw(int col)
|
||||
{
|
||||
public final void setColumnRawX(int col) { // TODO
|
||||
field_2_col = col;
|
||||
}
|
||||
|
||||
public int getColumnRaw()
|
||||
{
|
||||
public int getColumnRawX() { // TODO
|
||||
return field_2_col;
|
||||
}
|
||||
|
||||
public void setColumn(int col)
|
||||
{
|
||||
if(col < 0 || col > 0x100) {
|
||||
public final void setColumn(int col) {
|
||||
if(col < 0 || col >= 0x100) {
|
||||
throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range");
|
||||
}
|
||||
field_2_col = column.setValue(field_2_col, col);
|
||||
}
|
||||
|
||||
public int getColumn() {
|
||||
public final int getColumn() {
|
||||
return column.getValue(field_2_col);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
public final int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
public final String toFormulaString(HSSFWorkbook book) {
|
||||
//TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
|
||||
return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
|
||||
public final byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_REF;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ReferencePtg ptg = new ReferencePtg();
|
||||
ptg.field_1_row = field_1_row;
|
||||
ptg.field_2_col = field_2_col;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* RefVPtg
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefVPtg extends ReferencePtg {
|
||||
public final static byte sid = 0x44;
|
||||
|
||||
protected RefVPtg() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RefVPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
super(row, column, isRowRelative, isColumnRelative);
|
||||
setClass(CLASS_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/** Creates new ValueReferencePtg */
|
||||
|
||||
public RefVPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "RefVPtg";
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
RefVPtg ptg = new RefVPtg();
|
||||
ptg.setRow(getRow());
|
||||
ptg.setColumnRaw(getColumnRaw());
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
|
@ -1,52 +1,30 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* RefNAPtg
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefNAPtg extends ReferencePtg
|
||||
{
|
||||
public final static byte sid = 0x6C;
|
||||
|
||||
protected RefNAPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public RefNAPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public String getRefPtgName() {
|
||||
return "RefNAPtg";
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
throw notImplemented();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class ScalarConstantPtg extends Ptg {
|
||||
public boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
public final byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @author Bernard Chesnoy
|
||||
*/
|
||||
public final class StringPtg extends Ptg {
|
||||
public final class StringPtg extends ScalarConstantPtg {
|
||||
public final static int SIZE = 9;
|
||||
public final static byte sid = 0x17;
|
||||
private static final BitField fHighByte = BitFieldFactory.getInstance(0x01);
|
||||
|
@ -42,15 +42,11 @@ public final class StringPtg extends Ptg {
|
|||
* NOTE: OO doc says 16bit length, but BiffViewer says 8 Book says something
|
||||
* totally different, so don't look there!
|
||||
*/
|
||||
private int field_1_length;
|
||||
private byte field_2_options;
|
||||
private String field_3_string;
|
||||
private final int field_1_length;
|
||||
private final byte field_2_options;
|
||||
private final String field_3_string;
|
||||
|
||||
private StringPtg() {
|
||||
// Required for clone methods
|
||||
}
|
||||
|
||||
/** Create a StringPtg from a byte array read from disk */
|
||||
/** Create a StringPtg from a stream */
|
||||
public StringPtg(RecordInputStream in) {
|
||||
field_1_length = in.readUByte();
|
||||
field_2_options = in.readByte();
|
||||
|
@ -76,9 +72,7 @@ public final class StringPtg extends Ptg {
|
|||
throw new IllegalArgumentException(
|
||||
"String literals in formulas can't be bigger than 255 characters ASCII");
|
||||
}
|
||||
field_2_options = 0;
|
||||
field_2_options = (byte) fHighByte.setBoolean(field_2_options, StringUtil
|
||||
.hasMultibyte(value));
|
||||
field_2_options = (byte) fHighByte.setBoolean(0, StringUtil.hasMultibyte(value));
|
||||
field_3_string = value;
|
||||
field_1_length = value.length(); // for the moment, we support only ASCII strings in formulas we create
|
||||
}
|
||||
|
@ -124,18 +118,6 @@ public final class StringPtg extends Ptg {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
StringPtg ptg = new StringPtg();
|
||||
ptg.field_1_length = field_1_length;
|
||||
ptg.field_2_options = field_2_options;
|
||||
ptg.field_3_string = field_3_string;
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
|
|
|
@ -17,57 +17,27 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class SubtractPtg
|
||||
extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class SubtractPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x04;
|
||||
|
||||
public SubtractPtg()
|
||||
{
|
||||
public static final ValueOperatorPtg instance = new SubtractPtg();
|
||||
|
||||
private SubtractPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public SubtractPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -77,8 +47,4 @@ public class SubtractPtg
|
|||
buffer.append(operands[ 1 ]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new SubtractPtg();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,63 +17,30 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Unary Plus operator
|
||||
* does not have any effect on the operand
|
||||
* @author Avik Sengupta
|
||||
*/
|
||||
|
||||
public class UnaryMinusPtg extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class UnaryMinusPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x13;
|
||||
|
||||
private final static String MINUS = "-";
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new UnaryMinusPtg();
|
||||
|
||||
public UnaryMinusPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public UnaryMinusPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
private UnaryMinusPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return this.TYPE_UNARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "+";
|
||||
}
|
||||
|
||||
/** implementation of method from OperationsPtg*/
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -81,11 +48,4 @@ public class UnaryMinusPtg extends OperationPtg
|
|||
buffer.append(operands[ 0]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new UnaryPlusPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,63 +17,30 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Unary Plus operator
|
||||
* does not have any effect on the operand
|
||||
* @author Avik Sengupta
|
||||
*/
|
||||
|
||||
public class UnaryPlusPtg extends OperationPtg
|
||||
{
|
||||
public final static int SIZE = 1;
|
||||
public final class UnaryPlusPtg extends ValueOperatorPtg {
|
||||
public final static byte sid = 0x12;
|
||||
|
||||
private final static String ADD = "+";
|
||||
|
||||
/** Creates new AddPtg */
|
||||
public static final ValueOperatorPtg instance = new UnaryPlusPtg();
|
||||
|
||||
public UnaryPlusPtg()
|
||||
{
|
||||
}
|
||||
|
||||
public UnaryPlusPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
// doesn't need anything
|
||||
private UnaryPlusPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return this.TYPE_UNARY;
|
||||
}
|
||||
|
||||
public int getNumberOfOperands()
|
||||
{
|
||||
public int getNumberOfOperands() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "+";
|
||||
}
|
||||
|
||||
/** implementation of method from OperationsPtg*/
|
||||
public String toFormulaString(String[] operands) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -81,11 +48,4 @@ public class UnaryPlusPtg extends OperationPtg
|
|||
buffer.append(operands[ 0]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
|
||||
public Object clone() {
|
||||
return new UnaryPlusPtg();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,26 +18,23 @@
|
|||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
public class UnionPtg extends OperationPtg
|
||||
{
|
||||
public final class UnionPtg extends OperationPtg {
|
||||
public final static byte sid = 0x10;
|
||||
|
||||
public static final OperationPtg instance = new UnionPtg();
|
||||
|
||||
public UnionPtg()
|
||||
{
|
||||
private UnionPtg() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public UnionPtg(RecordInputStream in)
|
||||
{
|
||||
// doesn't need anything
|
||||
public final boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return 1;
|
||||
|
@ -48,17 +45,6 @@ public class UnionPtg extends OperationPtg
|
|||
array[ offset + 0 ] = sid;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new UnionPtg();
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_BINARY;
|
||||
}
|
||||
|
||||
/** Implementation of method from Ptg */
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return ",";
|
||||
|
|
|
@ -24,10 +24,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
|
|||
* @author andy
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class UnknownPtg
|
||||
extends Ptg
|
||||
{
|
||||
public class UnknownPtg extends Ptg {
|
||||
private short size = 1;
|
||||
|
||||
/** Creates new UnknownPtg */
|
||||
|
@ -36,12 +33,13 @@ public class UnknownPtg
|
|||
{
|
||||
}
|
||||
|
||||
public UnknownPtg(RecordInputStream in)
|
||||
{
|
||||
|
||||
public UnknownPtg(RecordInputStream in) {
|
||||
// doesn't need anything
|
||||
}
|
||||
|
||||
public boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -17,37 +17,38 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Specifies a rectangular area of cells A1:A4 for instance.
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* Common superclass of all value operators.
|
||||
* Subclasses include all unary and binary operators except for the reference operators (IntersectionPtg, RangePtg, UnionPtg)
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class ValueOperatorPtg extends OperationPtg {
|
||||
|
||||
public final class AreaNAPtg extends AreaPtg
|
||||
{
|
||||
public final static short sid = 0x6D;
|
||||
/**
|
||||
* All Operator <tt>Ptg</tt>s are base tokens (i.e. are not RVA classified)
|
||||
*/
|
||||
public final boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected AreaNAPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
public final byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public AreaNAPtg(RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
public final void writeBytes(byte[] array, int offset) {
|
||||
array[offset + 0] = getSid();
|
||||
}
|
||||
|
||||
public String getAreaPtgName() {
|
||||
return "AreaNAPtg";
|
||||
}
|
||||
protected abstract byte getSid();
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
throw notImplemented();
|
||||
}
|
||||
public final int getSize() {
|
||||
return 1;
|
||||
}
|
||||
public final String toFormulaString(HSSFWorkbook book) {
|
||||
// TODO - prune this method out of the hierarchy
|
||||
throw new RuntimeException("toFormulaString(String[] operands) should be used for subclasses of OperationPtgs");
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
|
||||
/**
|
||||
* @author adeshmukh
|
||||
|
@ -26,9 +26,9 @@ import org.apache.poi.hssf.record.formula.ReferencePtg;
|
|||
public final class Ref2DEval implements RefEval {
|
||||
|
||||
private final ValueEval value;
|
||||
private final ReferencePtg delegate;
|
||||
private final RefPtg delegate;
|
||||
|
||||
public Ref2DEval(ReferencePtg ptg, ValueEval ve) {
|
||||
public Ref2DEval(RefPtg ptg, ValueEval ve) {
|
||||
if(ve == null) {
|
||||
throw new IllegalArgumentException("ve must not be null");
|
||||
}
|
||||
|
|
|
@ -220,13 +220,18 @@ public class HSSFDateUtil
|
|||
// switching stuff, which we can ignore
|
||||
fs = fs.replaceAll(";@", "");
|
||||
|
||||
// If it starts with [$-...], then it is a date, but
|
||||
// If it starts with [$-...], then could be a date, but
|
||||
// who knows what that starting bit is all about
|
||||
fs = fs.replaceAll("\\[\\$\\-.*?\\]", "");
|
||||
fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
|
||||
|
||||
// If it starts with something like [Black] or [Yellow],
|
||||
// then it could be a date
|
||||
fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
|
||||
|
||||
// Otherwise, check it's only made up, in any case, of:
|
||||
// y m d h s - / , . :
|
||||
if(fs.matches("^[yYmMdDhHsS\\-/,. :]+$")) {
|
||||
// optionally followed by AM/PM
|
||||
if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP]*$")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.apache.poi.hssf.record.formula.OperationPtg;
|
|||
import org.apache.poi.hssf.record.formula.ParenthesisPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.StringPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnknownPtg;
|
||||
|
@ -342,28 +342,28 @@ public class HSSFFormulaEvaluator {
|
|||
}
|
||||
private static ValueEval evaluateCell(HSSFWorkbook workbook, HSSFSheet sheet,
|
||||
int srcRowNum, short srcColNum, String cellFormulaText) {
|
||||
FormulaParser parser = new FormulaParser(cellFormulaText, workbook);
|
||||
parser.parse();
|
||||
Ptg[] ptgs = parser.getRPNPtg();
|
||||
// -- parsing over --
|
||||
|
||||
|
||||
Ptg[] ptgs = FormulaParser.parse(cellFormulaText, workbook);
|
||||
|
||||
Stack stack = new Stack();
|
||||
for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
|
||||
|
||||
// since we don't know how to handle these yet :(
|
||||
Ptg ptg = ptgs[i];
|
||||
if (ptg instanceof ControlPtg) { continue; }
|
||||
if (ptg instanceof ControlPtg) {
|
||||
// skip Parentheses, Attr, etc
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof MemErrPtg) { continue; }
|
||||
if (ptg instanceof MissingArgPtg) { continue; }
|
||||
if (ptg instanceof NamePtg) {
|
||||
// named ranges, macro functions
|
||||
// named ranges, macro functions
|
||||
NamePtg namePtg = (NamePtg) ptg;
|
||||
stack.push(new NameEval(namePtg.getIndex()));
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof NameXPtg) {
|
||||
// TODO - external functions
|
||||
// TODO - external functions
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof UnknownPtg) { continue; }
|
||||
|
@ -371,9 +371,6 @@ public class HSSFFormulaEvaluator {
|
|||
if (ptg instanceof OperationPtg) {
|
||||
OperationPtg optg = (OperationPtg) ptg;
|
||||
|
||||
// parens can be ignored since we have RPN tokens
|
||||
if (optg instanceof ParenthesisPtg) { continue; }
|
||||
if (optg instanceof AttrPtg) { continue; }
|
||||
if (optg instanceof UnionPtg) { continue; }
|
||||
|
||||
OperationEval operation = OperationEvaluatorFactory.create(optg);
|
||||
|
@ -389,8 +386,8 @@ public class HSSFFormulaEvaluator {
|
|||
Eval opresult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet);
|
||||
stack.push(opresult);
|
||||
}
|
||||
else if (ptg instanceof ReferencePtg) {
|
||||
ReferencePtg refPtg = (ReferencePtg) ptg;
|
||||
else if (ptg instanceof RefPtg) {
|
||||
RefPtg refPtg = (RefPtg) ptg;
|
||||
int colIx = refPtg.getColumn();
|
||||
int rowIx = refPtg.getRow();
|
||||
HSSFRow row = sheet.getRow(rowIx);
|
||||
|
@ -552,7 +549,7 @@ public class HSSFFormulaEvaluator {
|
|||
Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
else if (ptg instanceof ReferencePtg) {
|
||||
else if (ptg instanceof RefPtg) {
|
||||
Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
|
@ -610,7 +607,7 @@ public class HSSFFormulaEvaluator {
|
|||
* Creates a Ref2DEval for ReferencePtg.
|
||||
* Non existent cells are treated as RefEvals containing BlankEval.
|
||||
*/
|
||||
private static Ref2DEval createRef2DEval(ReferencePtg ptg, HSSFCell cell,
|
||||
private static Ref2DEval createRef2DEval(RefPtg ptg, HSSFCell cell,
|
||||
HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
if (cell == null) {
|
||||
return new Ref2DEval(ptg, BlankEval.INSTANCE);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.BoundSheetRecord;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.util.RangeAddress;
|
||||
|
||||
|
|
|
@ -55,36 +55,72 @@ public class HSSFObjectData
|
|||
this.record = record;
|
||||
this.poifs = poifs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the OLE2 Class Name of the object
|
||||
*/
|
||||
public String getOLE2ClassName() {
|
||||
EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
|
||||
return subRecord.field_5_ole_classname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object data.
|
||||
* Gets the object data. Only call for ones that have
|
||||
* data though. See {@link #hasDirectoryEntry()}
|
||||
*
|
||||
* @return the object data as an OLE2 directory.
|
||||
* @throws IOException if there was an error reading the data.
|
||||
*/
|
||||
public DirectoryEntry getDirectory() throws IOException
|
||||
{
|
||||
Iterator subRecordIter = record.getSubRecords().iterator();
|
||||
while (subRecordIter.hasNext())
|
||||
{
|
||||
Object subRecord = subRecordIter.next();
|
||||
if (subRecord instanceof EmbeddedObjectRefSubRecord)
|
||||
{
|
||||
int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
|
||||
String streamName = "MBD" + HexDump.toHex(streamId);
|
||||
public DirectoryEntry getDirectory() throws IOException {
|
||||
EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
|
||||
|
||||
Entry entry = poifs.getRoot().getEntry(streamName);
|
||||
if (entry instanceof DirectoryEntry)
|
||||
{
|
||||
return (DirectoryEntry) entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Stream " + streamName + " was not an OLE2 directory");
|
||||
}
|
||||
int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
|
||||
String streamName = "MBD" + HexDump.toHex(streamId);
|
||||
|
||||
Entry entry = poifs.getRoot().getEntry(streamName);
|
||||
if (entry instanceof DirectoryEntry) {
|
||||
return (DirectoryEntry) entry;
|
||||
} else {
|
||||
throw new IOException("Stream " + streamName + " was not an OLE2 directory");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data portion, for an ObjectData
|
||||
* that doesn't have an associated POIFS Directory
|
||||
* Entry
|
||||
*/
|
||||
public byte[] getObjectData() {
|
||||
EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
|
||||
return subRecord.remainingBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this ObjectData have an associated POIFS
|
||||
* Directory Entry?
|
||||
* (Not all do, those that don't have a data portion)
|
||||
*/
|
||||
public boolean hasDirectoryEntry() {
|
||||
EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
|
||||
|
||||
// Field 6 tells you
|
||||
return (subRecord.field_6_stream_id != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the EmbeddedObjectRefSubRecord, or throws an
|
||||
* Exception if there wasn't one
|
||||
*/
|
||||
protected EmbeddedObjectRefSubRecord findObjectRecord() {
|
||||
Iterator subRecordIter = record.getSubRecords().iterator();
|
||||
|
||||
while (subRecordIter.hasNext()) {
|
||||
Object subRecord = subRecordIter.next();
|
||||
if (subRecord instanceof EmbeddedObjectRefSubRecord) {
|
||||
return (EmbeddedObjectRefSubRecord)subRecord;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import javax.imageio.ImageIO;
|
|||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
@ -46,6 +47,20 @@ public class HSSFPicture
|
|||
public static final int PICTURE_TYPE_PNG = HSSFWorkbook.PICTURE_TYPE_PNG; // PNG
|
||||
public static final int PICTURE_TYPE_DIB = HSSFWorkbook.PICTURE_TYPE_DIB; // Windows DIB
|
||||
|
||||
/**
|
||||
* width of 1px in columns with default width in units of 1/256 of a character width
|
||||
*/
|
||||
private static final float PX_DEFAULT = 32.00f;
|
||||
/**
|
||||
* width of 1px in columns with overridden width in units of 1/256 of a character width
|
||||
*/
|
||||
private static final float PX_MODIFIED = 36.56f;
|
||||
|
||||
/**
|
||||
* Height of 1px of a row
|
||||
*/
|
||||
private static final int PX_ROW = 15;
|
||||
|
||||
int pictureIndex;
|
||||
HSSFPatriarch patriarch;
|
||||
|
||||
|
@ -100,59 +115,77 @@ public class HSSFPicture
|
|||
* @since POI 3.0.2
|
||||
*/
|
||||
public HSSFClientAnchor getPreferredSize(){
|
||||
HSSFClientAnchor anchor = new HSSFClientAnchor();
|
||||
HSSFClientAnchor anchor = (HSSFClientAnchor)getAnchor();
|
||||
|
||||
EscherBSERecord bse = (EscherBSERecord)patriarch.sheet.book.getBSERecord(pictureIndex);
|
||||
byte[] data = bse.getBlipRecord().getPicturedata();
|
||||
int type = bse.getBlipTypeWin32();
|
||||
switch (type){
|
||||
//we can calculate the preferred size only for JPEG and PNG
|
||||
//other formats like WMF, EMF and PICT are not supported in Java
|
||||
case HSSFWorkbook.PICTURE_TYPE_JPEG:
|
||||
case HSSFWorkbook.PICTURE_TYPE_PNG:
|
||||
BufferedImage img = null;
|
||||
ImageReader r = null;
|
||||
try {
|
||||
//read the image using javax.imageio.*
|
||||
ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) );
|
||||
Iterator i = ImageIO.getImageReaders( iis );
|
||||
r = (ImageReader) i.next();
|
||||
r.setInput( iis );
|
||||
img = r.read(0);
|
||||
Dimension size = getImageDimension();
|
||||
|
||||
int[] dpi = getResolution(r);
|
||||
int imgWidth = img.getWidth()*96/dpi[0];
|
||||
int imgHeight = img.getHeight()*96/dpi[1];
|
||||
float w = 0;
|
||||
|
||||
//Excel measures cells in units of 1/256th of a character width.
|
||||
//The cell width calculated based on this info is always "off".
|
||||
//A better approach seems to be to use empirically obtained cell width and row height
|
||||
int cellwidth = 64;
|
||||
int rowheight = 17;
|
||||
//space in the leftmost cell
|
||||
w += getColumnWidthInPixels(anchor.col1)*(1 - anchor.dx1/1024);
|
||||
short col2 = (short)(anchor.col1 + 1);
|
||||
int dx2 = 0;
|
||||
|
||||
int col2 = imgWidth/cellwidth;
|
||||
int row2 = imgHeight/rowheight;
|
||||
|
||||
int dx2 = (int)((float)(imgWidth % cellwidth)/cellwidth * 1024);
|
||||
int dy2 = (int)((float)(imgHeight % rowheight)/rowheight * 256);
|
||||
|
||||
anchor.setCol2((short)col2);
|
||||
anchor.setDx2(dx2);
|
||||
|
||||
anchor.setRow2(row2);
|
||||
anchor.setDy2(dy2);
|
||||
|
||||
} catch (IOException e){
|
||||
//silently return if ImageIO failed to read the image
|
||||
log.log(POILogger.WARN, e);
|
||||
img = null;
|
||||
}
|
||||
|
||||
break;
|
||||
while(w < size.width){
|
||||
w += getColumnWidthInPixels(col2++);
|
||||
}
|
||||
|
||||
if(w > size.width) {
|
||||
//calculate dx2, offset in the rightmost cell
|
||||
col2--;
|
||||
float cw = getColumnWidthInPixels(col2);
|
||||
float delta = w - size.width;
|
||||
dx2 = (int)((cw-delta)/cw*1024);
|
||||
}
|
||||
anchor.col2 = col2;
|
||||
anchor.dx2 = dx2;
|
||||
|
||||
float h = 0;
|
||||
h += (1 - anchor.dy1/256)* getRowHeightInPixels(anchor.row1);
|
||||
int row2 = anchor.row1 + 1;
|
||||
int dy2 = 0;
|
||||
|
||||
while(h < size.height){
|
||||
h += getRowHeightInPixels(row2++);
|
||||
}
|
||||
if(h > size.height) {
|
||||
row2--;
|
||||
float ch = getRowHeightInPixels(row2);
|
||||
float delta = h - size.height;
|
||||
dy2 = (int)((ch-delta)/ch*256);
|
||||
}
|
||||
anchor.row2 = row2;
|
||||
anchor.dy2 = dy2;
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
private float getColumnWidthInPixels(short column){
|
||||
|
||||
short cw = patriarch.sheet.getColumnWidth(column);
|
||||
float px = getPixelWidth(column);
|
||||
|
||||
return cw/px;
|
||||
}
|
||||
|
||||
private float getRowHeightInPixels(int i){
|
||||
|
||||
HSSFRow row = patriarch.sheet.getRow(i);
|
||||
float height;
|
||||
if(row != null) height = row.getHeight();
|
||||
else height = patriarch.sheet.getDefaultRowHeight();
|
||||
|
||||
return height/PX_ROW;
|
||||
}
|
||||
|
||||
private float getPixelWidth(short column){
|
||||
|
||||
int def = patriarch.sheet.getDefaultColumnWidth()*256;
|
||||
short cw = patriarch.sheet.getColumnWidth(column);
|
||||
|
||||
return cw == def ? PX_DEFAULT : PX_MODIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
|
||||
* Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
|
||||
|
@ -176,4 +209,42 @@ public class HSSFPicture
|
|||
return new int[]{hdpi, vdpi};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dimension of this image
|
||||
*
|
||||
* @return image dimension
|
||||
*/
|
||||
public Dimension getImageDimension(){
|
||||
EscherBSERecord bse = patriarch.sheet.book.getBSERecord(pictureIndex);
|
||||
byte[] data = bse.getBlipRecord().getPicturedata();
|
||||
int type = bse.getBlipTypeWin32();
|
||||
Dimension size = new Dimension();
|
||||
|
||||
switch (type){
|
||||
//we can calculate the preferred size only for JPEG and PNG
|
||||
//other formats like WMF, EMF and PICT are not supported in Java
|
||||
case HSSFWorkbook.PICTURE_TYPE_JPEG:
|
||||
case HSSFWorkbook.PICTURE_TYPE_PNG:
|
||||
case HSSFWorkbook.PICTURE_TYPE_DIB:
|
||||
try {
|
||||
//read the image using javax.imageio.*
|
||||
ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) );
|
||||
Iterator i = ImageIO.getImageReaders( iis );
|
||||
ImageReader r = (ImageReader) i.next();
|
||||
r.setInput( iis );
|
||||
BufferedImage img = r.read(0);
|
||||
|
||||
int[] dpi = getResolution(r);
|
||||
size.width = img.getWidth()*96/dpi[0];
|
||||
size.height = img.getHeight()*96/dpi[1];
|
||||
|
||||
} catch (IOException e){
|
||||
//silently return if ImageIO failed to read the image
|
||||
log.log(POILogger.WARN, e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,8 +276,23 @@ public final class HSSFRow implements Comparable {
|
|||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined....
|
||||
* 0-based. If you ask for a cell that is not defined, then
|
||||
* you get a null.
|
||||
* This is the basic call, with no policies applied
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @return HSSFCell representing that column or null if undefined.
|
||||
*/
|
||||
private HSSFCell retrieveCell(int cellnum) {
|
||||
if(cellnum<0||cellnum>=cells.length) return null;
|
||||
return cells[cellnum];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined then
|
||||
* you get a null, unless you have set a different
|
||||
* {@link MissingCellPolicy} on the base workbook.
|
||||
* Short method signature provided to retain binary
|
||||
* compatibility.
|
||||
*
|
||||
|
@ -288,24 +303,54 @@ public final class HSSFRow implements Comparable {
|
|||
int ushortCellNum = cellnum & 0x0000FFFF; // avoid sign extension
|
||||
return getCell(ushortCellNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined....
|
||||
* you get a null.
|
||||
* 0-based. If you ask for a cell that is not defined then
|
||||
* you get a null, unless you have set a different
|
||||
* {@link MissingCellPolicy} on the base workbook.
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @return HSSFCell representing that column or null if undefined.
|
||||
*/
|
||||
public HSSFCell getCell(int cellnum) {
|
||||
if(cellnum<0||cellnum>=cells.length) return null;
|
||||
return cells[cellnum];
|
||||
return getCell(cellnum, book.getMissingCellPolicy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined, then
|
||||
* your supplied policy says what to do
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @param policy Policy on blank / missing cells
|
||||
* @return representing that column or null if undefined + policy allows.
|
||||
*/
|
||||
public HSSFCell getCell(int cellnum, MissingCellPolicy policy) {
|
||||
HSSFCell cell = retrieveCell(cellnum);
|
||||
if(policy == RETURN_NULL_AND_BLANK) {
|
||||
return cell;
|
||||
}
|
||||
if(policy == RETURN_BLANK_AS_NULL) {
|
||||
if(cell == null) return cell;
|
||||
if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
|
||||
return null;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
if(policy == CREATE_NULL_AS_BLANK) {
|
||||
if(cell == null) {
|
||||
return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* get the number of the first cell contained in this row.
|
||||
* @return short representing the first logical cell in the row, or -1 if the row does not contain any cells.
|
||||
*/
|
||||
|
||||
public short getFirstCellNum()
|
||||
{
|
||||
if (getPhysicalNumberOfCells() == 0)
|
||||
|
@ -466,6 +511,26 @@ public final class HSSFRow implements Comparable {
|
|||
return cellnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to specify the different possible policies
|
||||
* if for the case of null and blank cells
|
||||
*/
|
||||
public static class MissingCellPolicy {
|
||||
private static int NEXT_ID = 1;
|
||||
private final int id;
|
||||
private MissingCellPolicy() {
|
||||
this.id = NEXT_ID++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Missing cells are returned as null, Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy();
|
||||
/** Missing cells are returned as null, as are blank cells */
|
||||
public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy();
|
||||
/** A new, blank cell is created for missing cells. Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy();
|
||||
|
||||
|
||||
/**
|
||||
* @return cell iterator of the physically defined cells.
|
||||
* Note that the 4th element might well not be cell 4, as the iterator
|
||||
|
@ -484,6 +549,9 @@ public final class HSSFRow implements Comparable {
|
|||
return cellIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* An iterator over the (physical) cells in the row.
|
||||
*/
|
||||
private class CellIterator implements Iterator
|
||||
{
|
||||
int thisId=-1;
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.apache.poi.hssf.model.Sheet;
|
|||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
|
||||
import org.apache.poi.hssf.util.HSSFDataValidation;
|
||||
import org.apache.poi.hssf.util.PaneInformation;
|
||||
|
@ -1304,8 +1304,8 @@ public final class HSSFSheet {
|
|||
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(ptgs[i] instanceof RefPtg) {
|
||||
RefPtg rptg = (RefPtg)ptgs[i];
|
||||
if(startRow <= rptg.getRowAsInt() &&
|
||||
rptg.getRowAsInt() <= endRow) {
|
||||
// References a row that moved
|
||||
|
|
|
@ -39,7 +39,8 @@ public final class HSSFSheetConditionalFormatting {
|
|||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule
|
||||
* with a cell comparison operator
|
||||
* with a cell comparison operator<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
*
|
||||
* @param comparisonOperation - a constant value from
|
||||
* <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
|
||||
|
@ -72,8 +73,8 @@ public final class HSSFSheetConditionalFormatting {
|
|||
/**
|
||||
* A factory method allowing to create a conditional formatting rule with a formula.<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.<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* HSSFWorkbook.java
|
||||
*
|
||||
* Created on September 30, 2001, 3:37 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.POIDocument;
|
||||
|
@ -35,6 +29,7 @@ import org.apache.poi.hssf.record.*;
|
|||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.util.SheetReferences;
|
||||
import org.apache.poi.poifs.filesystem.*;
|
||||
|
@ -64,7 +59,6 @@ import java.util.Stack;
|
|||
* @author Shawn Laubach (slaubach at apache dot org)
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
|
||||
public class HSSFWorkbook extends POIDocument
|
||||
{
|
||||
private static final int DEBUG = POILogger.DEBUG;
|
||||
|
@ -88,7 +82,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
* this holds the HSSFSheet objects attached to this workbook
|
||||
*/
|
||||
|
||||
protected ArrayList sheets;
|
||||
protected List _sheets;
|
||||
|
||||
/**
|
||||
* this holds the HSSFName objects attached to this workbook
|
||||
|
@ -109,6 +103,13 @@ public class HSSFWorkbook extends POIDocument
|
|||
* someplace else.
|
||||
*/
|
||||
private HSSFDataFormat formatter;
|
||||
|
||||
/**
|
||||
* The policy to apply in the event of missing or
|
||||
* blank cells when fetching from a row.
|
||||
* See {@link MissingCellPolicy}
|
||||
*/
|
||||
private MissingCellPolicy missingCellPolicy = HSSFRow.RETURN_NULL_AND_BLANK;
|
||||
|
||||
|
||||
/** Extended windows meta file */
|
||||
|
@ -142,7 +143,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
{
|
||||
super(null, null);
|
||||
workbook = book;
|
||||
sheets = new ArrayList( INITIAL_CAPACITY );
|
||||
_sheets = new ArrayList( INITIAL_CAPACITY );
|
||||
names = new ArrayList( INITIAL_CAPACITY );
|
||||
}
|
||||
|
||||
|
@ -233,7 +234,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
this.directory = null;
|
||||
}
|
||||
|
||||
sheets = new ArrayList(INITIAL_CAPACITY);
|
||||
_sheets = new ArrayList(INITIAL_CAPACITY);
|
||||
names = new ArrayList(INITIAL_CAPACITY);
|
||||
|
||||
// Grab the data from the workbook stream, however
|
||||
|
@ -263,7 +264,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
HSSFSheet hsheet = new HSSFSheet(this, sheet);
|
||||
|
||||
sheets.add(hsheet);
|
||||
_sheets.add(hsheet);
|
||||
|
||||
// workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size());
|
||||
}
|
||||
|
@ -352,8 +353,28 @@ public class HSSFWorkbook extends POIDocument
|
|||
log.log(POILogger.DEBUG, "convertLabelRecords exit");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current policy on what to do when
|
||||
* getting missing or blank cells from a row.
|
||||
* The default is to return blank and null cells.
|
||||
* {@link MissingCellPolicy}
|
||||
*/
|
||||
public MissingCellPolicy getMissingCellPolicy() {
|
||||
return missingCellPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the policy on what to do when
|
||||
* getting missing or blank cells from a row.
|
||||
* This will then apply to all calls to
|
||||
* {@link HSSFRow.getCell()}. See
|
||||
* {@link MissingCellPolicy}
|
||||
*/
|
||||
public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) {
|
||||
this.missingCellPolicy = missingCellPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the order of appearance for a given sheet.
|
||||
*
|
||||
* @param sheetname the name of the sheet to reorder
|
||||
|
@ -361,12 +382,12 @@ public class HSSFWorkbook extends POIDocument
|
|||
*/
|
||||
|
||||
public void setSheetOrder(String sheetname, int pos ) {
|
||||
sheets.add(pos,sheets.remove(getSheetIndex(sheetname)));
|
||||
_sheets.add(pos,_sheets.remove(getSheetIndex(sheetname)));
|
||||
workbook.setSheetOrder(sheetname, pos);
|
||||
}
|
||||
|
||||
private void validateSheetIndex(int index) {
|
||||
int lastSheetIx = sheets.size() - 1;
|
||||
int lastSheetIx = _sheets.size() - 1;
|
||||
if (index < 0 || index > lastSheetIx) {
|
||||
throw new IllegalArgumentException("Sheet index ("
|
||||
+ index +") is out of range (0.." + lastSheetIx + ")");
|
||||
|
@ -380,7 +401,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
public void setSelectedTab(int index) {
|
||||
|
||||
validateSheetIndex(index);
|
||||
int nSheets = sheets.size();
|
||||
int nSheets = _sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
getSheetAt(i).setSelected(i == index);
|
||||
}
|
||||
|
@ -398,7 +419,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
for (int i = 0; i < indexes.length; i++) {
|
||||
validateSheetIndex(indexes[i]);
|
||||
}
|
||||
int nSheets = sheets.size();
|
||||
int nSheets = _sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
boolean bSelect = false;
|
||||
for (int j = 0; j < indexes.length; j++) {
|
||||
|
@ -420,7 +441,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
public void setActiveSheet(int index) {
|
||||
|
||||
validateSheetIndex(index);
|
||||
int nSheets = sheets.size();
|
||||
int nSheets = _sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
getSheetAt(i).setActive(i == index);
|
||||
}
|
||||
|
@ -492,19 +513,15 @@ public class HSSFWorkbook extends POIDocument
|
|||
* set the sheet name.
|
||||
* Will throw IllegalArgumentException if the name is greater than 31 chars
|
||||
* or contains /\?*[]
|
||||
* @param sheet number (0 based)
|
||||
* @param sheetIx number (0 based)
|
||||
*/
|
||||
public void setSheetName(int sheet, String name)
|
||||
public void setSheetName(int sheetIx, String name)
|
||||
{
|
||||
if (workbook.doesContainsSheetName( name, sheet ))
|
||||
if (workbook.doesContainsSheetName( name, sheetIx )) {
|
||||
throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
|
||||
|
||||
if (sheet > (sheets.size() - 1))
|
||||
{
|
||||
throw new RuntimeException("Sheet out of bounds");
|
||||
}
|
||||
|
||||
workbook.setSheetName( sheet, name);
|
||||
validateSheetIndex(sheetIx);
|
||||
workbook.setSheetName(sheetIx, name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -516,15 +533,12 @@ public class HSSFWorkbook extends POIDocument
|
|||
* or contains /\?*[]
|
||||
* @param sheet number (0 based)
|
||||
*/
|
||||
public void setSheetName( int sheet, String name, short encoding )
|
||||
public void setSheetName(int sheetIx, String name, short encoding)
|
||||
{
|
||||
if (workbook.doesContainsSheetName( name, sheet ))
|
||||
if (workbook.doesContainsSheetName( name, sheetIx )) {
|
||||
throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
|
||||
|
||||
if (sheet > (sheets.size() - 1))
|
||||
{
|
||||
throw new RuntimeException("Sheet out of bounds");
|
||||
}
|
||||
validateSheetIndex(sheetIx);
|
||||
|
||||
switch ( encoding ) {
|
||||
case ENCODING_COMPRESSED_UNICODE:
|
||||
|
@ -536,51 +550,39 @@ public class HSSFWorkbook extends POIDocument
|
|||
throw new RuntimeException( "Unsupported encoding" );
|
||||
}
|
||||
|
||||
workbook.setSheetName( sheet, name, encoding );
|
||||
workbook.setSheetName( sheetIx, name, encoding );
|
||||
}
|
||||
|
||||
/**
|
||||
* get the sheet name
|
||||
* @param sheet Number
|
||||
* @param sheetIx Number
|
||||
* @return Sheet name
|
||||
*/
|
||||
|
||||
public String getSheetName(int sheet)
|
||||
public String getSheetName(int sheetIx)
|
||||
{
|
||||
if (sheet > (sheets.size() - 1))
|
||||
{
|
||||
throw new RuntimeException("Sheet out of bounds");
|
||||
}
|
||||
return workbook.getSheetName(sheet);
|
||||
validateSheetIndex(sheetIx);
|
||||
return workbook.getSheetName(sheetIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether a sheet is hidden
|
||||
* @param sheet Number
|
||||
* @param sheetIx Number
|
||||
* @return True if sheet is hidden
|
||||
*/
|
||||
|
||||
public boolean isSheetHidden(int sheet) {
|
||||
if (sheet > (sheets.size() - 1))
|
||||
{
|
||||
throw new RuntimeException("Sheet out of bounds");
|
||||
}
|
||||
return workbook.isSheetHidden(sheet);
|
||||
public boolean isSheetHidden(int sheetIx) {
|
||||
validateSheetIndex(sheetIx);
|
||||
return workbook.isSheetHidden(sheetIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide or unhide a sheet
|
||||
*
|
||||
* @param sheetnum The sheet number
|
||||
* @param sheetIx The sheet index
|
||||
* @param hidden True to mark the sheet as hidden, false otherwise
|
||||
*/
|
||||
|
||||
public void setSheetHidden(int sheet, boolean hidden) {
|
||||
if (sheet > (sheets.size() - 1))
|
||||
{
|
||||
throw new RuntimeException("Sheet out of bounds");
|
||||
}
|
||||
workbook.setSheetHidden(sheet,hidden);
|
||||
public void setSheetHidden(int sheetIx, boolean hidden) {
|
||||
validateSheetIndex(sheetIx);
|
||||
workbook.setSheetHidden(sheetIx, hidden);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -602,12 +604,12 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
/** Returns the index of the given sheet
|
||||
* @param sheet the sheet to look up
|
||||
* @return index of the sheet (0 based)
|
||||
* @return index of the sheet (0 based). <tt>-1</tt> if not found
|
||||
*/
|
||||
public int getSheetIndex(HSSFSheet sheet)
|
||||
{
|
||||
for(int i=0; i<sheets.size(); i++) {
|
||||
if(sheets.get(i) == sheet) {
|
||||
for(int i=0; i<_sheets.size(); i++) {
|
||||
if(_sheets.get(i) == sheet) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -636,9 +638,9 @@ public class HSSFWorkbook extends POIDocument
|
|||
{
|
||||
HSSFSheet sheet = new HSSFSheet(this);
|
||||
|
||||
sheets.add(sheet);
|
||||
workbook.setSheetName(sheets.size() - 1, "Sheet" + (sheets.size() - 1));
|
||||
boolean isOnlySheet = sheets.size() == 1;
|
||||
_sheets.add(sheet);
|
||||
workbook.setSheetName(_sheets.size() - 1, "Sheet" + (_sheets.size() - 1));
|
||||
boolean isOnlySheet = _sheets.size() == 1;
|
||||
sheet.setSelected(isOnlySheet);
|
||||
sheet.setActive(isOnlySheet);
|
||||
return sheet;
|
||||
|
@ -652,13 +654,13 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public HSSFSheet cloneSheet(int sheetNum) {
|
||||
validateSheetIndex(sheetNum);
|
||||
HSSFSheet srcSheet = (HSSFSheet) sheets.get(sheetNum);
|
||||
HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetNum);
|
||||
String srcName = workbook.getSheetName(sheetNum);
|
||||
HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
|
||||
clonedSheet.setSelected(false);
|
||||
clonedSheet.setActive(false);
|
||||
|
||||
sheets.add(clonedSheet);
|
||||
_sheets.add(clonedSheet);
|
||||
int i = 1;
|
||||
while (true) {
|
||||
// Try and find the next sheet name that is unique
|
||||
|
@ -672,7 +674,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
//If the sheet name is unique, then set it otherwise move on to the next number.
|
||||
if (workbook.getSheetIndex(name) == -1) {
|
||||
workbook.setSheetName(sheets.size()-1, name);
|
||||
workbook.setSheetName(_sheets.size()-1, name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -693,14 +695,14 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public HSSFSheet createSheet(String sheetname)
|
||||
{
|
||||
if (workbook.doesContainsSheetName( sheetname, sheets.size() ))
|
||||
if (workbook.doesContainsSheetName( sheetname, _sheets.size() ))
|
||||
throw new IllegalArgumentException( "The workbook already contains a sheet of this name" );
|
||||
|
||||
HSSFSheet sheet = new HSSFSheet(this);
|
||||
|
||||
sheets.add(sheet);
|
||||
workbook.setSheetName(sheets.size() - 1, sheetname);
|
||||
boolean isOnlySheet = sheets.size() == 1;
|
||||
_sheets.add(sheet);
|
||||
workbook.setSheetName(_sheets.size() - 1, sheetname);
|
||||
boolean isOnlySheet = _sheets.size() == 1;
|
||||
sheet.setSelected(isOnlySheet);
|
||||
sheet.setActive(isOnlySheet);
|
||||
return sheet;
|
||||
|
@ -713,9 +715,14 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public int getNumberOfSheets()
|
||||
{
|
||||
return sheets.size();
|
||||
return _sheets.size();
|
||||
}
|
||||
|
||||
private HSSFSheet[] getSheets() {
|
||||
HSSFSheet[] result = new HSSFSheet[_sheets.size()];
|
||||
_sheets.toArray(result);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get the HSSFSheet object at the given index.
|
||||
* @param index of the sheet number (0-based physical & logical)
|
||||
|
@ -724,7 +731,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public HSSFSheet getSheetAt(int index)
|
||||
{
|
||||
return (HSSFSheet) sheets.get(index);
|
||||
return (HSSFSheet) _sheets.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -737,13 +744,13 @@ public class HSSFWorkbook extends POIDocument
|
|||
{
|
||||
HSSFSheet retval = null;
|
||||
|
||||
for (int k = 0; k < sheets.size(); k++)
|
||||
for (int k = 0; k < _sheets.size(); k++)
|
||||
{
|
||||
String sheetname = workbook.getSheetName(k);
|
||||
|
||||
if (sheetname.equalsIgnoreCase(name))
|
||||
{
|
||||
retval = (HSSFSheet) sheets.get(k);
|
||||
retval = (HSSFSheet) _sheets.get(k);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
@ -772,11 +779,11 @@ public class HSSFWorkbook extends POIDocument
|
|||
boolean wasActive = getSheetAt(index).isActive();
|
||||
boolean wasSelected = getSheetAt(index).isSelected();
|
||||
|
||||
sheets.remove(index);
|
||||
_sheets.remove(index);
|
||||
workbook.removeSheet(index);
|
||||
|
||||
// set the remaining active/selected sheet
|
||||
int nSheets = sheets.size();
|
||||
int nSheets = _sheets.size();
|
||||
if (nSheets < 1) {
|
||||
// nothing more to do if there are no sheets left
|
||||
return;
|
||||
|
@ -902,9 +909,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
if (settingRowAndColumn)
|
||||
{
|
||||
MemFuncPtg memFuncPtg = new MemFuncPtg();
|
||||
memFuncPtg.setLenRefSubexpression(23);
|
||||
ptgs.add(memFuncPtg);
|
||||
ptgs.add(new MemFuncPtg(23)); // TODO - where did constant '23' come from?
|
||||
}
|
||||
if (startColumn >= 0)
|
||||
{
|
||||
|
@ -928,8 +933,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
}
|
||||
if (settingRowAndColumn)
|
||||
{
|
||||
UnionPtg unionPtg = new UnionPtg();
|
||||
ptgs.add(unionPtg);
|
||||
ptgs.add(UnionPtg.instance);
|
||||
}
|
||||
nameRecord.setNameDefinition(ptgs);
|
||||
|
||||
|
@ -1152,48 +1156,47 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public byte[] getBytes()
|
||||
{
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
if (log.check( POILogger.DEBUG )) {
|
||||
log.log(DEBUG, "HSSFWorkbook.getBytes()");
|
||||
}
|
||||
|
||||
HSSFSheet[] sheets = getSheets();
|
||||
int nSheets = sheets.length;
|
||||
|
||||
// before getting the workbook size we must tell the sheets that
|
||||
// serialization is about to occur.
|
||||
for (int k = 0; k < sheets.size(); k++)
|
||||
((HSSFSheet) sheets.get(k)).getSheet().preSerialize();
|
||||
for (int i = 0; i < nSheets; i++) {
|
||||
sheets[i].getSheet().preSerialize();
|
||||
}
|
||||
|
||||
int wbsize = workbook.getSize();
|
||||
int totalsize = workbook.getSize();
|
||||
|
||||
// log.debug("REMOVEME: old sizing method "+workbook.serialize().length);
|
||||
// ArrayList sheetbytes = new ArrayList(sheets.size());
|
||||
int totalsize = wbsize;
|
||||
|
||||
for (int k = 0; k < sheets.size(); k++)
|
||||
{
|
||||
// pre-calculate all the sheet sizes and set BOF indexes
|
||||
int[] estimatedSheetSizes = new int[nSheets];
|
||||
for (int k = 0; k < nSheets; k++) {
|
||||
workbook.setSheetBof(k, totalsize);
|
||||
totalsize += ((HSSFSheet) sheets.get(k)).getSheet().getSize();
|
||||
int sheetSize = sheets[k].getSheet().getSize();
|
||||
estimatedSheetSizes[k] = sheetSize;
|
||||
totalsize += sheetSize;
|
||||
}
|
||||
|
||||
|
||||
/* if (totalsize < 4096)
|
||||
{
|
||||
totalsize = 4096;
|
||||
}*/
|
||||
byte[] retval = new byte[totalsize];
|
||||
int pos = workbook.serialize(0, retval);
|
||||
|
||||
// System.arraycopy(wb, 0, retval, 0, wb.length);
|
||||
for (int k = 0; k < sheets.size(); k++)
|
||||
{
|
||||
|
||||
// byte[] sb = (byte[])sheetbytes.get(k);
|
||||
// System.arraycopy(sb, 0, retval, pos, sb.length);
|
||||
int len = ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
|
||||
retval);
|
||||
pos += len; // sb.length;
|
||||
for (int k = 0; k < nSheets; k++) {
|
||||
int serializedSize = sheets[k].getSheet().serialize(pos, retval);
|
||||
if (serializedSize != estimatedSheetSizes[k]) {
|
||||
// Wrong offset values have been passed in the call to setSheetBof() above.
|
||||
// For books with more than one sheet, this discrepancy would cause excel
|
||||
// to report errors and loose data while reading the workbook
|
||||
throw new IllegalStateException("Actual serialized sheet size (" + serializedSize
|
||||
+ ") differs from pre-calculated size (" + estimatedSheetSizes[k]
|
||||
+ ") for sheet (" + k + ")");
|
||||
// TODO - add similar sanity check to ensure that Sheet.serializeIndexRecord() does not write mis-aligned offsets either
|
||||
}
|
||||
pos += serializedSize;
|
||||
}
|
||||
/* for (int k = pos; k < totalsize; k++)
|
||||
{
|
||||
retval[k] = 0;
|
||||
}*/
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
|
||||
public final class AreaReference {
|
||||
|
||||
/** The character (!) that separates sheet names from cell references */
|
||||
|
@ -50,13 +51,13 @@ public final class AreaReference {
|
|||
|
||||
// Special handling for whole-column references
|
||||
if(parts.length == 2 && parts[0].length() == 1 &&
|
||||
parts[1].length() == 1 &&
|
||||
parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
|
||||
parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
|
||||
// Represented internally as x$1 to x$65536
|
||||
// which is the maximum range of rows
|
||||
parts[0] = parts[0] + "$1";
|
||||
parts[1] = parts[1] + "$65536";
|
||||
parts[1].length() == 1 &&
|
||||
parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
|
||||
parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
|
||||
// Represented internally as x$1 to x$65536
|
||||
// which is the maximum range of rows
|
||||
parts[0] = parts[0] + "$1";
|
||||
parts[1] = parts[1] + "$65536";
|
||||
}
|
||||
|
||||
_firstCell = new CellReference(parts[0]);
|
||||
|
@ -74,9 +75,9 @@ public final class AreaReference {
|
|||
* Creates an area ref from a pair of Cell References.
|
||||
*/
|
||||
public AreaReference(CellReference topLeft, CellReference botRight) {
|
||||
_firstCell = topLeft;
|
||||
_lastCell = botRight;
|
||||
_isSingleCell = false;
|
||||
_firstCell = topLeft;
|
||||
_lastCell = botRight;
|
||||
_isSingleCell = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,17 +99,17 @@ public final class AreaReference {
|
|||
* such as C:C or D:G ?
|
||||
*/
|
||||
public static boolean isWholeColumnReference(CellReference topLeft, CellReference botRight) {
|
||||
// These are represented as something like
|
||||
// C$1:C$65535 or D$1:F$0
|
||||
// i.e. absolute from 1st row to 0th one
|
||||
if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
|
||||
botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// These are represented as something like
|
||||
// C$1:C$65535 or D$1:F$0
|
||||
// i.e. absolute from 1st row to 0th one
|
||||
if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
|
||||
botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isWholeColumnReference() {
|
||||
return isWholeColumnReference(_firstCell, _lastCell);
|
||||
return isWholeColumnReference(_firstCell, _lastCell);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,26 +156,26 @@ public final class AreaReference {
|
|||
* Returns a reference to every cell covered by this area
|
||||
*/
|
||||
public CellReference[] getAllReferencedCells() {
|
||||
// Special case for single cell reference
|
||||
if(_isSingleCell) {
|
||||
return new CellReference[] { _firstCell, };
|
||||
}
|
||||
// Special case for single cell reference
|
||||
if(_isSingleCell) {
|
||||
return new CellReference[] { _firstCell, };
|
||||
}
|
||||
|
||||
// Interpolate between the two
|
||||
// Interpolate between the two
|
||||
int minRow = Math.min(_firstCell.getRow(), _lastCell.getRow());
|
||||
int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
|
||||
int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
|
||||
int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
|
||||
int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
|
||||
int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
|
||||
int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
|
||||
String sheetName = _firstCell.getSheetName();
|
||||
|
||||
ArrayList refs = new ArrayList();
|
||||
for(int row=minRow; row<=maxRow; row++) {
|
||||
for(int col=minCol; col<=maxCol; col++) {
|
||||
CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
|
||||
refs.add(ref);
|
||||
}
|
||||
}
|
||||
return (CellReference[])refs.toArray(new CellReference[refs.size()]);
|
||||
|
||||
ArrayList refs = new ArrayList();
|
||||
for(int row=minRow; row<=maxRow; row++) {
|
||||
for(int col=minCol; col<=maxCol; col++) {
|
||||
CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
|
||||
refs.add(ref);
|
||||
}
|
||||
}
|
||||
return (CellReference[])refs.toArray(new CellReference[refs.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,14 +190,14 @@ public final class AreaReference {
|
|||
* @return the text representation of this area reference as it would appear in a formula.
|
||||
*/
|
||||
public String formatAsString() {
|
||||
// Special handling for whole-column references
|
||||
if(isWholeColumnReference()) {
|
||||
return
|
||||
CellReference.convertNumToColString(_firstCell.getCol())
|
||||
+ ":" +
|
||||
CellReference.convertNumToColString(_lastCell.getCol());
|
||||
}
|
||||
|
||||
// Special handling for whole-column references
|
||||
if(isWholeColumnReference()) {
|
||||
return
|
||||
CellReference.convertNumToColString(_firstCell.getCol())
|
||||
+ ":" +
|
||||
CellReference.convertNumToColString(_lastCell.getCol());
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
sb.append(_firstCell.formatAsString());
|
||||
if(!_isSingleCell) {
|
||||
|
@ -210,6 +211,18 @@ public final class AreaReference {
|
|||
}
|
||||
return sb.toString();
|
||||
}
|
||||
/**
|
||||
* Formats a 2-D area as it would appear in a formula. See formatAsString() (no-arg)
|
||||
*/
|
||||
public static String formatAsString(AreaI area) {
|
||||
CellReference topLeft = new CellReference(area.getFirstRow(),area.getFirstColumn(),!area.isFirstRowRelative(),!area.isFirstColRelative());
|
||||
CellReference botRight = new CellReference(area.getLastRow(),area.getLastColumn(),!area.isLastRowRelative(),!area.isLastColRelative());
|
||||
|
||||
if(isWholeColumnReference(topLeft, botRight)) {
|
||||
return (new AreaReference(topLeft, botRight)).formatAsString();
|
||||
}
|
||||
return topLeft.formatAsString() + ":" + botRight.formatAsString();
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.util;
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* Intends to provide support for the very evil index to triplet issue and
|
||||
* will likely replace the color contants interface for HSSF 2.0.
|
||||
* will likely replace the color constants interface for HSSF 2.0.
|
||||
* This class contains static inner class members for representing colors.
|
||||
* Each color has an index (for the standard palette in Excel (tm) ),
|
||||
* native (RGB) triplet and string triplet. The string triplet is as the
|
||||
|
@ -33,14 +33,9 @@ import java.util.*;
|
|||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Brian Sanders (bsanders at risklabs dot com) - full default color palette
|
||||
*/
|
||||
|
||||
public class HSSFColor
|
||||
{
|
||||
private final static int PALETTE_SIZE = 56;
|
||||
private final static int DISTINCT_COLOR_COUNT = 46;
|
||||
|
||||
public class HSSFColor {
|
||||
// TODO make subclass instances immutable
|
||||
/** Creates a new instance of HSSFColor */
|
||||
|
||||
public HSSFColor()
|
||||
{
|
||||
}
|
||||
|
@ -52,87 +47,86 @@ public class HSSFColor
|
|||
* it takes to create it once per request but you will not hold onto it
|
||||
* if you have none of those requests.
|
||||
*
|
||||
* @return a hashtable containing all colors mapped to their excel-style
|
||||
* pallette index
|
||||
* @return a hashtable containing all colors keyed by <tt>Integer</tt> excel-style palette indexes
|
||||
*/
|
||||
public final static Hashtable getIndexHash() {
|
||||
|
||||
Hashtable hash = new Hashtable(PALETTE_SIZE);
|
||||
return createColorsByIndexMap();
|
||||
}
|
||||
|
||||
hash.put(new Integer(HSSFColor.BLACK.index), new HSSFColor.BLACK());
|
||||
hash.put(new Integer(HSSFColor.BROWN.index), new HSSFColor.BROWN());
|
||||
hash.put(new Integer(HSSFColor.OLIVE_GREEN.index),
|
||||
new HSSFColor.OLIVE_GREEN());
|
||||
hash.put(new Integer(HSSFColor.DARK_GREEN.index), new HSSFColor.DARK_GREEN());
|
||||
hash.put(new Integer(HSSFColor.DARK_TEAL.index), new HSSFColor.DARK_TEAL());
|
||||
hash.put(new Integer(HSSFColor.DARK_BLUE.index), new HSSFColor.DARK_BLUE());
|
||||
hash.put(new Integer(HSSFColor.DARK_BLUE.index2), new HSSFColor.DARK_BLUE());
|
||||
hash.put(new Integer(HSSFColor.INDIGO.index), new HSSFColor.INDIGO());
|
||||
hash.put(new Integer(HSSFColor.GREY_80_PERCENT.index),
|
||||
new HSSFColor.GREY_80_PERCENT());
|
||||
hash.put(new Integer(HSSFColor.ORANGE.index), new HSSFColor.ORANGE());
|
||||
hash.put(new Integer(HSSFColor.DARK_YELLOW.index),
|
||||
new HSSFColor.DARK_YELLOW());
|
||||
hash.put(new Integer(HSSFColor.GREEN.index), new HSSFColor.GREEN());
|
||||
hash.put(new Integer(HSSFColor.TEAL.index), new HSSFColor.TEAL());
|
||||
hash.put(new Integer(HSSFColor.TEAL.index2), new HSSFColor.TEAL());
|
||||
hash.put(new Integer(HSSFColor.BLUE.index), new HSSFColor.BLUE());
|
||||
hash.put(new Integer(HSSFColor.BLUE.index2), new HSSFColor.BLUE());
|
||||
hash.put(new Integer(HSSFColor.BLUE_GREY.index), new HSSFColor.BLUE_GREY());
|
||||
hash.put(new Integer(HSSFColor.GREY_50_PERCENT.index),
|
||||
new HSSFColor.GREY_50_PERCENT());
|
||||
hash.put(new Integer(HSSFColor.RED.index), new HSSFColor.RED());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_ORANGE.index),
|
||||
new HSSFColor.LIGHT_ORANGE());
|
||||
hash.put(new Integer(HSSFColor.LIME.index), new HSSFColor.LIME());
|
||||
hash.put(new Integer(HSSFColor.SEA_GREEN.index), new HSSFColor.SEA_GREEN());
|
||||
hash.put(new Integer(HSSFColor.AQUA.index), new HSSFColor.AQUA());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_BLUE.index), new HSSFColor.LIGHT_BLUE());
|
||||
hash.put(new Integer(HSSFColor.VIOLET.index), new HSSFColor.VIOLET());
|
||||
hash.put(new Integer(HSSFColor.VIOLET.index2), new HSSFColor.VIOLET());
|
||||
hash.put(new Integer(HSSFColor.GREY_40_PERCENT.index),
|
||||
new HSSFColor.GREY_40_PERCENT());
|
||||
hash.put(new Integer(HSSFColor.PINK.index), new HSSFColor.PINK());
|
||||
hash.put(new Integer(HSSFColor.PINK.index2), new HSSFColor.PINK());
|
||||
hash.put(new Integer(HSSFColor.GOLD.index), new HSSFColor.GOLD());
|
||||
hash.put(new Integer(HSSFColor.YELLOW.index), new HSSFColor.YELLOW());
|
||||
hash.put(new Integer(HSSFColor.YELLOW.index2), new HSSFColor.YELLOW());
|
||||
hash.put(new Integer(HSSFColor.BRIGHT_GREEN.index),
|
||||
new HSSFColor.BRIGHT_GREEN());
|
||||
hash.put(new Integer(HSSFColor.BRIGHT_GREEN.index2),
|
||||
new HSSFColor.BRIGHT_GREEN());
|
||||
hash.put(new Integer(HSSFColor.TURQUOISE.index), new HSSFColor.TURQUOISE());
|
||||
hash.put(new Integer(HSSFColor.TURQUOISE.index2), new HSSFColor.TURQUOISE());
|
||||
hash.put(new Integer(HSSFColor.DARK_RED.index), new HSSFColor.DARK_RED());
|
||||
hash.put(new Integer(HSSFColor.DARK_RED.index2), new HSSFColor.DARK_RED());
|
||||
hash.put(new Integer(HSSFColor.SKY_BLUE.index), new HSSFColor.SKY_BLUE());
|
||||
hash.put(new Integer(HSSFColor.PLUM.index), new HSSFColor.PLUM());
|
||||
hash.put(new Integer(HSSFColor.PLUM.index2), new HSSFColor.PLUM());
|
||||
hash.put(new Integer(HSSFColor.GREY_25_PERCENT.index),
|
||||
new HSSFColor.GREY_25_PERCENT());
|
||||
hash.put(new Integer(HSSFColor.ROSE.index), new HSSFColor.ROSE());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_YELLOW.index),
|
||||
new HSSFColor.LIGHT_YELLOW());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_GREEN.index),
|
||||
new HSSFColor.LIGHT_GREEN());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_TURQUOISE.index),
|
||||
new HSSFColor.LIGHT_TURQUOISE());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_TURQUOISE.index2),
|
||||
new HSSFColor.LIGHT_TURQUOISE());
|
||||
hash.put(new Integer(HSSFColor.PALE_BLUE.index), new HSSFColor.PALE_BLUE());
|
||||
hash.put(new Integer(HSSFColor.LAVENDER.index), new HSSFColor.LAVENDER());
|
||||
hash.put(new Integer(HSSFColor.WHITE.index), new HSSFColor.WHITE());
|
||||
hash.put(new Integer(HSSFColor.CORNFLOWER_BLUE.index),
|
||||
new HSSFColor.CORNFLOWER_BLUE());
|
||||
hash.put(new Integer(HSSFColor.LEMON_CHIFFON.index),
|
||||
new HSSFColor.LEMON_CHIFFON());
|
||||
hash.put(new Integer(HSSFColor.MAROON.index), new HSSFColor.MAROON());
|
||||
hash.put(new Integer(HSSFColor.ORCHID.index), new HSSFColor.ORCHID());
|
||||
hash.put(new Integer(HSSFColor.CORAL.index), new HSSFColor.CORAL());
|
||||
hash.put(new Integer(HSSFColor.ROYAL_BLUE.index), new HSSFColor.ROYAL_BLUE());
|
||||
hash.put(new Integer(HSSFColor.LIGHT_CORNFLOWER_BLUE.index),
|
||||
new HSSFColor.LIGHT_CORNFLOWER_BLUE());
|
||||
return hash;
|
||||
private static Hashtable createColorsByIndexMap() {
|
||||
HSSFColor[] colors = getAllColors();
|
||||
Hashtable result = new Hashtable(colors.length * 3 / 2);
|
||||
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
HSSFColor color = colors[i];
|
||||
|
||||
Integer index1 = new Integer(color.getIndex());
|
||||
if (result.containsKey(index1)) {
|
||||
HSSFColor prevColor = (HSSFColor)result.get(index1);
|
||||
throw new RuntimeException("Dup color index (" + index1
|
||||
+ ") for colors (" + prevColor.getClass().getName()
|
||||
+ "),(" + color.getClass().getName() + ")");
|
||||
}
|
||||
result.put(index1, color);
|
||||
}
|
||||
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
HSSFColor color = colors[i];
|
||||
Integer index2 = getIndex2(color);
|
||||
if (index2 == null) {
|
||||
// most colors don't have a second index
|
||||
continue;
|
||||
}
|
||||
if (result.containsKey(index2)) {
|
||||
if (false) { // Many of the second indexes clash
|
||||
HSSFColor prevColor = (HSSFColor)result.get(index2);
|
||||
throw new RuntimeException("Dup color index (" + index2
|
||||
+ ") for colors (" + prevColor.getClass().getName()
|
||||
+ "),(" + color.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
result.put(index2, color);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Integer getIndex2(HSSFColor color) {
|
||||
|
||||
Field f;
|
||||
try {
|
||||
f = color.getClass().getDeclaredField("index2");
|
||||
} catch (NoSuchFieldException e) {
|
||||
// can happen because not all colors have a second index
|
||||
return null;
|
||||
}
|
||||
|
||||
Short s;
|
||||
try {
|
||||
s = (Short) f.get(color);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new Integer(s.intValue());
|
||||
}
|
||||
|
||||
private static HSSFColor[] getAllColors() {
|
||||
|
||||
return new HSSFColor[] {
|
||||
new BLACK(), new BROWN(), new OLIVE_GREEN(), new DARK_GREEN(),
|
||||
new DARK_TEAL(), new DARK_BLUE(), new INDIGO(), new GREY_80_PERCENT(),
|
||||
new ORANGE(), new DARK_YELLOW(), new GREEN(), new TEAL(), new BLUE(),
|
||||
new BLUE_GREY(), new GREY_50_PERCENT(), new RED(), new LIGHT_ORANGE(), new LIME(),
|
||||
new SEA_GREEN(), new AQUA(), new LIGHT_BLUE(), new VIOLET(), new GREY_40_PERCENT(),
|
||||
new PINK(), new GOLD(), new YELLOW(), new BRIGHT_GREEN(), new TURQUOISE(),
|
||||
new DARK_RED(), new SKY_BLUE(), new PLUM(), new GREY_25_PERCENT(), new ROSE(),
|
||||
new LIGHT_YELLOW(), new LIGHT_GREEN(), new LIGHT_TURQUOISE(), new PALE_BLUE(),
|
||||
new LAVENDER(), new WHITE(), new CORNFLOWER_BLUE(), new LEMON_CHIFFON(),
|
||||
new MAROON(), new ORCHID(), new CORAL(), new ROYAL_BLUE(),
|
||||
new LIGHT_CORNFLOWER_BLUE(), new TAN(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,73 +136,28 @@ public class HSSFColor
|
|||
* it takes to create it once per request but you will not hold onto it
|
||||
* if you have none of those requests.
|
||||
*
|
||||
* @return a hashtable containing all colors mapped to their gnumeric-like
|
||||
* triplet string
|
||||
* @return a hashtable containing all colors keyed by String gnumeric-like triplets
|
||||
*/
|
||||
|
||||
public final static Hashtable getTripletHash()
|
||||
{
|
||||
Hashtable hash = new Hashtable(DISTINCT_COLOR_COUNT);
|
||||
return createColorsByHexStringMap();
|
||||
}
|
||||
|
||||
hash.put(HSSFColor.BLACK.hexString, new HSSFColor.BLACK());
|
||||
hash.put(HSSFColor.BROWN.hexString, new HSSFColor.BROWN());
|
||||
hash.put(HSSFColor.OLIVE_GREEN.hexString,
|
||||
new HSSFColor.OLIVE_GREEN());
|
||||
hash.put(HSSFColor.DARK_GREEN.hexString, new HSSFColor.DARK_GREEN());
|
||||
hash.put(HSSFColor.DARK_TEAL.hexString, new HSSFColor.DARK_TEAL());
|
||||
hash.put(HSSFColor.DARK_BLUE.hexString, new HSSFColor.DARK_BLUE());
|
||||
hash.put(HSSFColor.INDIGO.hexString, new HSSFColor.INDIGO());
|
||||
hash.put(HSSFColor.GREY_80_PERCENT.hexString,
|
||||
new HSSFColor.GREY_80_PERCENT());
|
||||
hash.put(HSSFColor.ORANGE.hexString, new HSSFColor.ORANGE());
|
||||
hash.put(HSSFColor.DARK_YELLOW.hexString,
|
||||
new HSSFColor.DARK_YELLOW());
|
||||
hash.put(HSSFColor.GREEN.hexString, new HSSFColor.GREEN());
|
||||
hash.put(HSSFColor.TEAL.hexString, new HSSFColor.TEAL());
|
||||
hash.put(HSSFColor.BLUE.hexString, new HSSFColor.BLUE());
|
||||
hash.put(HSSFColor.BLUE_GREY.hexString, new HSSFColor.BLUE_GREY());
|
||||
hash.put(HSSFColor.GREY_50_PERCENT.hexString,
|
||||
new HSSFColor.GREY_50_PERCENT());
|
||||
hash.put(HSSFColor.RED.hexString, new HSSFColor.RED());
|
||||
hash.put(HSSFColor.LIGHT_ORANGE.hexString,
|
||||
new HSSFColor.LIGHT_ORANGE());
|
||||
hash.put(HSSFColor.LIME.hexString, new HSSFColor.LIME());
|
||||
hash.put(HSSFColor.SEA_GREEN.hexString, new HSSFColor.SEA_GREEN());
|
||||
hash.put(HSSFColor.AQUA.hexString, new HSSFColor.AQUA());
|
||||
hash.put(HSSFColor.LIGHT_BLUE.hexString, new HSSFColor.LIGHT_BLUE());
|
||||
hash.put(HSSFColor.VIOLET.hexString, new HSSFColor.VIOLET());
|
||||
hash.put(HSSFColor.GREY_40_PERCENT.hexString,
|
||||
new HSSFColor.GREY_40_PERCENT());
|
||||
hash.put(HSSFColor.PINK.hexString, new HSSFColor.PINK());
|
||||
hash.put(HSSFColor.GOLD.hexString, new HSSFColor.GOLD());
|
||||
hash.put(HSSFColor.YELLOW.hexString, new HSSFColor.YELLOW());
|
||||
hash.put(HSSFColor.BRIGHT_GREEN.hexString,
|
||||
new HSSFColor.BRIGHT_GREEN());
|
||||
hash.put(HSSFColor.TURQUOISE.hexString, new HSSFColor.TURQUOISE());
|
||||
hash.put(HSSFColor.DARK_RED.hexString, new HSSFColor.DARK_RED());
|
||||
hash.put(HSSFColor.SKY_BLUE.hexString, new HSSFColor.SKY_BLUE());
|
||||
hash.put(HSSFColor.PLUM.hexString, new HSSFColor.PLUM());
|
||||
hash.put(HSSFColor.GREY_25_PERCENT.hexString,
|
||||
new HSSFColor.GREY_25_PERCENT());
|
||||
hash.put(HSSFColor.ROSE.hexString, new HSSFColor.ROSE());
|
||||
hash.put(HSSFColor.LIGHT_YELLOW.hexString,
|
||||
new HSSFColor.LIGHT_YELLOW());
|
||||
hash.put(HSSFColor.LIGHT_GREEN.hexString,
|
||||
new HSSFColor.LIGHT_GREEN());
|
||||
hash.put(HSSFColor.LIGHT_TURQUOISE.hexString,
|
||||
new HSSFColor.LIGHT_TURQUOISE());
|
||||
hash.put(HSSFColor.PALE_BLUE.hexString, new HSSFColor.PALE_BLUE());
|
||||
hash.put(HSSFColor.LAVENDER.hexString, new HSSFColor.LAVENDER());
|
||||
hash.put(HSSFColor.WHITE.hexString, new HSSFColor.WHITE());
|
||||
hash.put(HSSFColor.CORNFLOWER_BLUE.hexString, new HSSFColor.CORNFLOWER_BLUE());
|
||||
hash.put(HSSFColor.LEMON_CHIFFON.hexString, new HSSFColor.LEMON_CHIFFON());
|
||||
hash.put(HSSFColor.MAROON.hexString, new HSSFColor.MAROON());
|
||||
hash.put(HSSFColor.ORCHID.hexString, new HSSFColor.ORCHID());
|
||||
hash.put(HSSFColor.CORAL.hexString, new HSSFColor.CORAL());
|
||||
hash.put(HSSFColor.ROYAL_BLUE.hexString, new HSSFColor.ROYAL_BLUE());
|
||||
hash.put(HSSFColor.LIGHT_CORNFLOWER_BLUE.hexString,
|
||||
new HSSFColor.LIGHT_CORNFLOWER_BLUE());
|
||||
return hash;
|
||||
private static Hashtable createColorsByHexStringMap() {
|
||||
HSSFColor[] colors = getAllColors();
|
||||
Hashtable result = new Hashtable(colors.length * 3 / 2);
|
||||
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
HSSFColor color = colors[i];
|
||||
|
||||
String hexString = color.getHexString();
|
||||
if (result.containsKey(hexString)) {
|
||||
throw new RuntimeException("Dup color hexString (" + hexString
|
||||
+ ") for color (" + color.getClass().getName() + ")");
|
||||
}
|
||||
result.put(hexString, color);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1490,7 +1439,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class CORNFLOWER_BLUE
|
||||
*/
|
||||
|
@ -1519,8 +1468,8 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class LEMON_CHIFFON
|
||||
*/
|
||||
|
@ -1549,7 +1498,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class MAROON
|
||||
*/
|
||||
|
@ -1578,7 +1527,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class ORCHID
|
||||
*/
|
||||
|
@ -1607,7 +1556,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class CORAL
|
||||
*/
|
||||
|
@ -1636,7 +1585,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class ROYAL_BLUE
|
||||
*/
|
||||
|
@ -1665,7 +1614,7 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class LIGHT_CORNFLOWER_BLUE
|
||||
*/
|
||||
|
@ -1694,19 +1643,19 @@ public class HSSFColor
|
|||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special Default/Normal/Automatic color.
|
||||
* <p><i>Note:</i> This class is NOT in the default HashTables returned by HSSFColor.
|
||||
* The index is a special case which is interpreted in the various setXXXColor calls.
|
||||
*
|
||||
*
|
||||
* @author Jason
|
||||
*
|
||||
*/
|
||||
public final static class AUTOMATIC extends HSSFColor
|
||||
{
|
||||
private static HSSFColor instance = new AUTOMATIC();
|
||||
|
||||
private static HSSFColor instance = new AUTOMATIC();
|
||||
|
||||
public final static short index = 0x40;
|
||||
|
||||
public short getIndex()
|
||||
|
@ -1723,7 +1672,7 @@ public class HSSFColor
|
|||
{
|
||||
return BLACK.hexString;
|
||||
}
|
||||
|
||||
|
||||
public static HSSFColor getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ public class RawDataBlock
|
|||
{
|
||||
private byte[] _data;
|
||||
private boolean _eof;
|
||||
private boolean _hasData;
|
||||
private static POILogger log = POILogFactory.getLogger(RawDataBlock.class);
|
||||
|
||||
/**
|
||||
|
@ -66,6 +67,7 @@ public class RawDataBlock
|
|||
throws IOException {
|
||||
_data = new byte[ blockSize ];
|
||||
int count = IOUtils.readFully(stream, _data);
|
||||
_hasData = (count > 0);
|
||||
|
||||
if (count == -1) {
|
||||
_eof = true;
|
||||
|
@ -94,16 +96,21 @@ public class RawDataBlock
|
|||
/**
|
||||
* When we read the data, did we hit end of file?
|
||||
*
|
||||
* @return true if no data was read because we were at the end of
|
||||
* the file, else false
|
||||
*
|
||||
* @exception IOException
|
||||
* @return true if the EoF was hit during this block, or
|
||||
* false if not. If you have a dodgy short last block, then
|
||||
* it's possible to both have data, and also hit EoF...
|
||||
*/
|
||||
public boolean eof()
|
||||
throws IOException
|
||||
{
|
||||
public boolean eof() {
|
||||
return _eof;
|
||||
}
|
||||
/**
|
||||
* Did we actually find any data to read? It's possible,
|
||||
* in the event of a short last block, to both have hit
|
||||
* the EoF, but also to have data
|
||||
*/
|
||||
public boolean hasData() {
|
||||
return _hasData;
|
||||
}
|
||||
|
||||
/* ********** START implementation of ListManagedBlock ********** */
|
||||
|
||||
|
@ -117,7 +124,7 @@ public class RawDataBlock
|
|||
public byte [] getData()
|
||||
throws IOException
|
||||
{
|
||||
if (eof())
|
||||
if (! hasData())
|
||||
{
|
||||
throw new IOException("Cannot return empty data");
|
||||
}
|
||||
|
|
|
@ -51,12 +51,16 @@ public class RawDataBlockList
|
|||
while (true)
|
||||
{
|
||||
RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
|
||||
|
||||
// If there was data, add the block to the list
|
||||
if(block.hasData()) {
|
||||
blocks.add(block);
|
||||
}
|
||||
|
||||
if (block.eof())
|
||||
{
|
||||
// If the stream is now at the End Of File, we're done
|
||||
if (block.eof()) {
|
||||
break;
|
||||
}
|
||||
blocks.add(block);
|
||||
}
|
||||
setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ]));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
# Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
|
||||
# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
|
||||
# from source file 'excelfileformat.odt' (size=356107, md5=0x8f789cb6e75594caf068f8e193004ef4)
|
||||
#
|
||||
#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
|||
15 SIN 1 1 V V
|
||||
16 COS 1 1 V V
|
||||
17 TAN 1 1 V V
|
||||
18 ARCTAN 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
|
||||
|
@ -141,8 +141,8 @@
|
|||
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
|
||||
189 DPRODUCT 3 3 V R R R
|
||||
190 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
|
||||
|
@ -184,6 +184,8 @@
|
|||
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 2 V 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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue