Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657165,657168-657179,657181-657354,657356-657357,657359-657701,657703-657874,657876-658032,658034-658284,658286,658288-658301,658303-658307,658309-659484 via svnmerge from
https://svn.apache.org:443/repos/asf/poi/trunk ........ r658322 | nick | 2008-05-20 17:37:15 +0100 (Tue, 20 May 2008) | 1 line Fix bug #44977 - Support for AM/PM in excel date formats ........ r658336 | nick | 2008-05-20 17:51:49 +0100 (Tue, 20 May 2008) | 1 line Test which seems to show that bug #44996 is invalid, but not completely sure ........ r658349 | nick | 2008-05-20 17:57:20 +0100 (Tue, 20 May 2008) | 1 line Patch from bug #45001 - Partial fix for HWPF Range.insertBefore() and Range.delete() with unicode characters ........ r658350 | nick | 2008-05-20 18:12:08 +0100 (Tue, 20 May 2008) | 1 line Put abstract write(OutputStream) method on POIDocument ........ r658352 | nick | 2008-05-20 18:17:16 +0100 (Tue, 20 May 2008) | 1 line Patch from bug #45003 - Support embeded HDGF visio documents ........ r658833 | josh | 2008-05-21 20:57:40 +0100 (Wed, 21 May 2008) | 1 line improved toString and refactored toFormulaString on Area(3D)Ptg ........ r658984 | josh | 2008-05-22 04:00:29 +0100 (Thu, 22 May 2008) | 1 line Fixed compiler errors. Other improvements for type safety and immutability. ........ r658986 | josh | 2008-05-22 04:26:25 +0100 (Thu, 22 May 2008) | 1 line Follow on from bug 44675 - regenerated functionMetadata.txt from new ooo excelfileformat.odt ........ r659067 | nick | 2008-05-22 10:51:44 +0100 (Thu, 22 May 2008) | 1 line Example for finding hslf sounds from Yegor ........ r659403 | josh | 2008-05-23 04:56:31 +0100 (Fri, 23 May 2008) | 1 line Fix for 45066 - sheet encoding size mismatch problems ........ r659429 | josh | 2008-05-23 06:28:54 +0100 (Fri, 23 May 2008) | 1 line Fix for bug 45046 - allowed DEFINEDNAME records without EXTERNALBOOK records ........ r659452 | josh | 2008-05-23 07:43:51 +0100 (Fri, 23 May 2008) | 1 line Bug 45041 - improved FormulaParser parse error messages ........ r659455 | josh | 2008-05-23 07:54:46 +0100 (Fri, 23 May 2008) | 1 line Bug 45025 - improved FormulaParser parse error messages (r659452 had wrong bug number) ........ r659462 | josh | 2008-05-23 08:42:14 +0100 (Fri, 23 May 2008) | 1 line Marked out test failure which was fixed by patch for bug 39903 ........ r659478 | josh | 2008-05-23 09:55:48 +0100 (Fri, 23 May 2008) | 1 line Fix for bug 35925 - Missing HSSFColor.TAN from HashTables returned by getIndexHash() and getTripletHash() ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@659485 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
81550a63a9
commit
e34bbfc887
@ -245,6 +245,7 @@ under the License.
|
||||
<path id="examples.classpath">
|
||||
<path refid="main.classpath"/>
|
||||
<pathelement location="${main.output.dir}"/>
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
</path>
|
||||
|
||||
|
||||
|
@ -44,6 +44,12 @@
|
||||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
||||
</release>
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">45025 - improved FormulaParser parse error messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">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>
|
||||
|
@ -41,6 +41,12 @@
|
||||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
||||
</release>
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">45025 - improved FormulaParser parse error messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">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>
|
||||
|
@ -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
|
||||
|
@ -55,7 +55,7 @@ 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);
|
||||
}
|
||||
@ -127,42 +127,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) {
|
||||
String msg = "Parse error near char " + (pointer-1) + "'" + look + "'"
|
||||
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);
|
||||
@ -178,7 +170,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) {
|
||||
@ -218,7 +210,6 @@ public final class FormulaParser {
|
||||
return Token.toString();
|
||||
}
|
||||
|
||||
|
||||
/** Get a Number */
|
||||
private String GetNum() {
|
||||
StringBuffer value = new StringBuffer();
|
||||
@ -281,18 +272,18 @@ 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);
|
||||
}
|
||||
|
||||
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!");
|
||||
}
|
||||
|
||||
@ -307,19 +298,19 @@ public final class FormulaParser {
|
||||
/**
|
||||
* 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 -
|
||||
// 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);
|
||||
|
||||
|
||||
// in the token tree, the name is more or less the first argument
|
||||
numArgs++;
|
||||
numArgs++;
|
||||
tokens.add(nameToken);
|
||||
}
|
||||
//average 2 args per function
|
||||
@ -477,26 +468,25 @@ public final class FormulaParser {
|
||||
private static boolean isArgumentDelimiter(char ch) {
|
||||
return ch == ',' || ch == ')';
|
||||
}
|
||||
|
||||
|
||||
/** get arguments to a function */
|
||||
private int Arguments(List argumentPointers) {
|
||||
SkipWhite();
|
||||
if(look == ')') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
boolean missedPrevArg = true;
|
||||
|
||||
int numArgs = 0;
|
||||
while(true) {
|
||||
while (true) {
|
||||
SkipWhite();
|
||||
if(isArgumentDelimiter(look)) {
|
||||
if(missedPrevArg) {
|
||||
if (isArgumentDelimiter(look)) {
|
||||
if (missedPrevArg) {
|
||||
tokens.add(new MissingArgPtg());
|
||||
addArgumentPointer(argumentPointers);
|
||||
numArgs++;
|
||||
}
|
||||
if(look == ')') {
|
||||
if (look == ')') {
|
||||
break;
|
||||
}
|
||||
Match(',');
|
||||
@ -507,6 +497,10 @@ public final class FormulaParser {
|
||||
addArgumentPointer(argumentPointers);
|
||||
numArgs++;
|
||||
missedPrevArg = false;
|
||||
SkipWhite();
|
||||
if (!isArgumentDelimiter(look)) {
|
||||
throw expected("',' or ')'");
|
||||
}
|
||||
}
|
||||
return numArgs;
|
||||
}
|
||||
@ -524,7 +518,7 @@ public final class FormulaParser {
|
||||
tokens.add(new PowerPtg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void percentFactor() {
|
||||
tokens.add(parseSimpleFactor());
|
||||
while(true) {
|
||||
@ -536,8 +530,8 @@ public final class FormulaParser {
|
||||
tokens.add(new PercentPtg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* factors (without ^ or % )
|
||||
*/
|
||||
@ -561,9 +555,6 @@ public final class FormulaParser {
|
||||
return new ParenthesisPtg();
|
||||
case '"':
|
||||
return parseStringLiteral();
|
||||
case ',':
|
||||
case ')':
|
||||
return new MissingArgPtg(); // TODO - not quite the right place to recognise a missing arg
|
||||
}
|
||||
if (IsAlpha(look) || look == '\''){
|
||||
return parseIdent();
|
||||
@ -707,10 +698,9 @@ public final class FormulaParser {
|
||||
}
|
||||
|
||||
|
||||
private StringPtg parseStringLiteral()
|
||||
{
|
||||
private StringPtg parseStringLiteral() {
|
||||
Match('"');
|
||||
|
||||
|
||||
StringBuffer token = new StringBuffer();
|
||||
while (true) {
|
||||
if (look == '"') {
|
||||
@ -745,7 +735,7 @@ public final class FormulaParser {
|
||||
return; // finished with Term
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void comparisonExpression() {
|
||||
concatExpression();
|
||||
while (true) {
|
||||
@ -787,7 +777,7 @@ public final class FormulaParser {
|
||||
}
|
||||
return new LessThanPtg();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void concatExpression() {
|
||||
additiveExpression();
|
||||
@ -801,7 +791,7 @@ public final class FormulaParser {
|
||||
tokens.add(new ConcatPtg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Parse and Translate an Expression */
|
||||
private void additiveExpression() {
|
||||
@ -838,8 +828,9 @@ 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;
|
||||
@ -847,8 +838,8 @@ end;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -863,11 +854,12 @@ 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();
|
||||
// RVA is for 'operand class': 'reference', 'value', 'array'
|
||||
setRootLevelRVA(node, formulaType);
|
||||
setParameterRVA(node,formulaType);
|
||||
return (Ptg[]) tokens.toArray(new Ptg[0]);
|
||||
@ -948,7 +940,7 @@ end;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
@ -963,7 +955,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
|
||||
@ -1011,7 +1003,7 @@ 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
|
||||
@ -1038,7 +1030,7 @@ end;
|
||||
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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
@ -329,16 +329,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();
|
||||
// }
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
|
||||
return retval;
|
||||
@ -816,17 +808,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,31 +829,10 @@ 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;
|
||||
}
|
||||
|
||||
@ -875,10 +846,17 @@ public final class Sheet implements Model {
|
||||
for (int j = BOFRecordIndex+1; j < records.size(); j++)
|
||||
{
|
||||
Record tmpRec = (( Record ) records.get(j));
|
||||
if (tmpRec instanceof RowRecordsAggregate)
|
||||
break;
|
||||
if (tmpRec instanceof UncalcedRecord) {
|
||||
continue;
|
||||
}
|
||||
if (tmpRec instanceof RowRecordsAggregate) {
|
||||
break;
|
||||
}
|
||||
sheetRecSize+= tmpRec.getRecordSize();
|
||||
}
|
||||
if (_isUncalced) {
|
||||
sheetRecSize += UncalcedRecord.getStaticRecordSize();
|
||||
}
|
||||
//Add the references to the DBCells in the IndexRecord (one for each block)
|
||||
int blockCount = rows.getRowBlockCount();
|
||||
//Calculate the size of this IndexRecord
|
||||
@ -2017,31 +1995,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 +2498,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 :
|
||||
|
@ -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()
|
||||
|
@ -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,7 +35,6 @@ 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 static byte sid = 0x3b;
|
||||
@ -84,23 +83,15 @@ 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 )
|
||||
@ -284,7 +275,7 @@ public class Area3DPtg extends Ptg implements AreaI
|
||||
}
|
||||
|
||||
// Now the normal area bit
|
||||
retval.append( AreaPtg.toFormulaString(this, book) );
|
||||
retval.append(AreaReference.formatAsString(this));
|
||||
|
||||
// All done
|
||||
return retval.toString();
|
||||
@ -326,6 +317,7 @@ public class Area3DPtg extends Ptg implements AreaI
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
// TODO - hashCode seems to be unused
|
||||
int result;
|
||||
result = (int) field_1_index_extern_sheet;
|
||||
result = 29 * result + (int) field_2_first_row;
|
||||
|
@ -114,23 +114,13 @@ public class AreaPtg extends Ptg implements AreaI {
|
||||
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 String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append(AreaReference.formatAsString(this));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset) {
|
||||
@ -307,19 +297,8 @@ public class AreaPtg extends Ptg implements AreaI {
|
||||
field_4_last_column = column;
|
||||
}
|
||||
|
||||
public String toFormulaString(Workbook book)
|
||||
{
|
||||
return toFormulaString(this, book);
|
||||
}
|
||||
protected static String toFormulaString(AreaI area, Workbook 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 String toFormulaString(Workbook book) {
|
||||
return AreaReference.formatAsString(this);
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
|
@ -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 java.io.ByteArrayInputStream;
|
||||
@ -81,7 +75,6 @@ import org.apache.poi.util.POILogger;
|
||||
* @author Shawn Laubach (slaubach at apache dot org)
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
|
||||
public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook
|
||||
{
|
||||
private static final int DEBUG = POILogger.DEBUG;
|
||||
@ -105,7 +98,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
* this holds the HSSFSheet objects attached to this workbook
|
||||
*/
|
||||
|
||||
protected ArrayList sheets;
|
||||
protected List _sheets;
|
||||
|
||||
/**
|
||||
* this holds the HSSFName objects attached to this workbook
|
||||
@ -159,7 +152,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
{
|
||||
super(null, null);
|
||||
workbook = book;
|
||||
sheets = new ArrayList( INITIAL_CAPACITY );
|
||||
_sheets = new ArrayList( INITIAL_CAPACITY );
|
||||
names = new ArrayList( INITIAL_CAPACITY );
|
||||
}
|
||||
|
||||
@ -250,7 +243,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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
|
||||
@ -280,7 +273,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
HSSFSheet hsheet = new HSSFSheet(this, sheet);
|
||||
|
||||
sheets.add(hsheet);
|
||||
_sheets.add(hsheet);
|
||||
|
||||
// workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size());
|
||||
}
|
||||
@ -378,12 +371,12 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
*/
|
||||
|
||||
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 + ")");
|
||||
@ -397,7 +390,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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);
|
||||
}
|
||||
@ -415,7 +408,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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++) {
|
||||
@ -437,7 +430,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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);
|
||||
}
|
||||
@ -509,19 +502,15 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@ -533,15 +522,12 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
* 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:
|
||||
@ -553,51 +539,39 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -619,12 +593,12 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
/** 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(org.apache.poi.ss.usermodel.Sheet 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;
|
||||
}
|
||||
}
|
||||
@ -653,9 +627,9 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
{
|
||||
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;
|
||||
@ -669,13 +643,13 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
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
|
||||
@ -689,7 +663,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
//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;
|
||||
}
|
||||
}
|
||||
@ -710,14 +684,14 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
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;
|
||||
@ -730,13 +704,19 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
public int getNumberOfSheets()
|
||||
{
|
||||
return sheets.size();
|
||||
return _sheets.size();
|
||||
}
|
||||
|
||||
public int getSheetIndexFromExternSheetIndex(int externSheetNumber) {
|
||||
return workbook.getSheetIndexFromExternSheetIndex(externSheetNumber);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -745,7 +725,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
public HSSFSheet getSheetAt(int index)
|
||||
{
|
||||
return (HSSFSheet) sheets.get(index);
|
||||
return (HSSFSheet) _sheets.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -758,13 +738,13 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
{
|
||||
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;
|
||||
@ -793,11 +773,11 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
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;
|
||||
@ -1173,48 +1153,47 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
|
||||
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,16 +15,16 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Color;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -35,14 +35,10 @@ import org.apache.poi.ss.usermodel.Color;
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Brian Sanders (bsanders at risklabs dot com) - full default color palette
|
||||
*/
|
||||
|
||||
public class HSSFColor implements Color
|
||||
{
|
||||
private final static int PALETTE_SIZE = 56;
|
||||
private final static int DISTINCT_COLOR_COUNT = 46;
|
||||
public class HSSFColor implements Color {
|
||||
// TODO make subclass instances immutable
|
||||
|
||||
/** Creates a new instance of HSSFColor */
|
||||
|
||||
public HSSFColor()
|
||||
{
|
||||
}
|
||||
@ -54,87 +50,86 @@ public class HSSFColor implements Color
|
||||
* 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(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,73 +139,28 @@ public class HSSFColor implements Color
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1492,7 +1442,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class CORNFLOWER_BLUE
|
||||
*/
|
||||
@ -1521,8 +1471,8 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class LEMON_CHIFFON
|
||||
*/
|
||||
@ -1551,7 +1501,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class MAROON
|
||||
*/
|
||||
@ -1580,7 +1530,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class ORCHID
|
||||
*/
|
||||
@ -1609,7 +1559,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class CORAL
|
||||
*/
|
||||
@ -1638,7 +1588,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class ROYAL_BLUE
|
||||
*/
|
||||
@ -1667,7 +1617,7 @@ public class HSSFColor implements Color
|
||||
return hexString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class LIGHT_CORNFLOWER_BLUE
|
||||
*/
|
||||
@ -1696,19 +1646,19 @@ public class HSSFColor implements Color
|
||||
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()
|
||||
@ -1725,7 +1675,7 @@ public class HSSFColor implements Color
|
||||
{
|
||||
return BLACK.hexString;
|
||||
}
|
||||
|
||||
|
||||
public static HSSFColor getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
@ -226,7 +226,9 @@ public class DateUtil
|
||||
|
||||
// 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
|
||||
// optionally followed by AM/PM
|
||||
if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP]*$")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -14,11 +14,9 @@
|
||||
# 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 )
|
||||
#
|
||||
# + some manual edits !
|
||||
|
||||
# Built-In Sheet Functions in BIFF2
|
||||
0 COUNT 0 30 V R
|
||||
@ -186,7 +184,7 @@
|
||||
244 INFO 1 1 V V
|
||||
# New Built-In Sheet Functions in BIFF4
|
||||
14 FIXED 2 3 V V V V x
|
||||
204 USDOLLAR 1 1 V V x
|
||||
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
|
||||
|
@ -18,6 +18,7 @@ package org.apache.poi.hdgf;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.hdgf.chunks.ChunkFactory;
|
||||
@ -27,6 +28,7 @@ import org.apache.poi.hdgf.streams.PointerContainingStream;
|
||||
import org.apache.poi.hdgf.streams.Stream;
|
||||
import org.apache.poi.hdgf.streams.StringsStream;
|
||||
import org.apache.poi.hdgf.streams.TrailerStream;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
@ -53,14 +55,17 @@ public class HDGFDiagram extends POIDocument {
|
||||
private PointerFactory ptrFactory;
|
||||
|
||||
public HDGFDiagram(POIFSFileSystem fs) throws IOException {
|
||||
super(fs);
|
||||
this(fs.getRoot(), fs);
|
||||
}
|
||||
public HDGFDiagram(DirectoryNode dir, POIFSFileSystem fs) throws IOException {
|
||||
super(dir, fs);
|
||||
|
||||
DocumentEntry docProps =
|
||||
(DocumentEntry)filesystem.getRoot().getEntry("VisioDocument");
|
||||
(DocumentEntry)dir.getEntry("VisioDocument");
|
||||
|
||||
// Grab the document stream
|
||||
_docstream = new byte[docProps.getSize()];
|
||||
filesystem.createDocumentInputStream("VisioDocument").read(_docstream);
|
||||
dir.createDocumentInputStream("VisioDocument").read(_docstream);
|
||||
|
||||
// Read in the common POI streams
|
||||
readProperties();
|
||||
@ -149,6 +154,10 @@ public class HDGFDiagram extends POIDocument {
|
||||
}
|
||||
}
|
||||
|
||||
public void write(OutputStream out) {
|
||||
throw new IllegalStateException("Writing is not yet implemented, see http://poi.apache.org/hdgf/");
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing only
|
||||
*/
|
||||
|
@ -21,17 +21,18 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class holds all the FSPA (File Shape Address) structures.
|
||||
*
|
||||
* @author Squeeself
|
||||
*/
|
||||
public class FSPATable
|
||||
public final class FSPATable
|
||||
{
|
||||
protected ArrayList shapes = new ArrayList();
|
||||
protected HashMap cps = new HashMap();
|
||||
protected List _text;
|
||||
private final List _shapes = new ArrayList();
|
||||
private final Map _shapeIndexesByPropertyStart = new HashMap();
|
||||
private final List _text;
|
||||
|
||||
public FSPATable(byte[] tableStream, int fcPlcspa, int lcbPlcspa, List tpt)
|
||||
{
|
||||
@ -46,32 +47,35 @@ public class FSPATable
|
||||
GenericPropertyNode property = plex.getProperty(i);
|
||||
FSPA fspa = new FSPA(property.getBytes(), 0);
|
||||
|
||||
shapes.add(fspa);
|
||||
cps.put(Integer.valueOf(property.getStart()), Integer.valueOf(i));
|
||||
_shapes.add(fspa);
|
||||
_shapeIndexesByPropertyStart.put(new Integer(property.getStart()), new Integer(i));
|
||||
}
|
||||
}
|
||||
|
||||
public FSPA getFspaFromCp(int cp)
|
||||
{
|
||||
Integer idx = (Integer)cps.get(Integer.valueOf(cp));
|
||||
if (idx == null)
|
||||
Integer idx = (Integer)_shapeIndexesByPropertyStart.get(new Integer(cp));
|
||||
if (idx == null) {
|
||||
return null;
|
||||
return (FSPA)shapes.get(idx.intValue());
|
||||
}
|
||||
return (FSPA)_shapes.get(idx.intValue());
|
||||
}
|
||||
|
||||
public List getShapes()
|
||||
public FSPA[] getShapes()
|
||||
{
|
||||
return shapes;
|
||||
FSPA[] result = new FSPA[_shapes.size()];
|
||||
_shapes.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("[FPSA PLC size=").append(shapes.size()).append("]\n");
|
||||
for (Iterator it = cps.keySet().iterator(); it.hasNext(); )
|
||||
buf.append("[FPSA PLC size=").append(_shapes.size()).append("]\n");
|
||||
for (Iterator it = _shapeIndexesByPropertyStart.keySet().iterator(); it.hasNext(); )
|
||||
{
|
||||
Integer i = (Integer) it.next();
|
||||
FSPA fspa = (FSPA) shapes.get(((Integer)cps.get(i)).intValue());
|
||||
FSPA fspa = (FSPA) _shapes.get(((Integer)_shapeIndexesByPropertyStart.get(i)).intValue());
|
||||
buf.append(" [FC: ").append(i.toString()).append("] ");
|
||||
buf.append(fspa.toString());
|
||||
buf.append("\n");
|
||||
|
@ -294,6 +294,16 @@ public class FileInformationBlock extends FIBAbstractType
|
||||
_longHandler.setLong(FIBLongHandler.CBMAC, cbMac);
|
||||
}
|
||||
|
||||
public int getCcpText()
|
||||
{
|
||||
return _longHandler.getLong(FIBLongHandler.CCPTEXT);
|
||||
}
|
||||
|
||||
public void setCcpText(int ccpText)
|
||||
{
|
||||
_longHandler.setLong(FIBLongHandler.CCPTEXT, ccpText);
|
||||
}
|
||||
|
||||
public void clearOffsetsSizes()
|
||||
{
|
||||
_fieldHandler.clearFields();
|
||||
|
@ -90,12 +90,20 @@ public class TextPiece extends PropertyNode implements Comparable
|
||||
|
||||
public void adjustForDelete(int start, int length)
|
||||
{
|
||||
|
||||
if (usesUnicode()) {
|
||||
|
||||
start /= 2;
|
||||
length /= 2;
|
||||
}
|
||||
|
||||
int myStart = getStart();
|
||||
int myEnd = getEnd();
|
||||
int end = start + length;
|
||||
|
||||
/* do we have to delete from this text piece? */
|
||||
if (start <= myEnd && end >= myStart) {
|
||||
|
||||
/* find where the deleted area overlaps with this text piece */
|
||||
int overlapStart = Math.max(myStart, start);
|
||||
int overlapEnd = Math.min(myEnd, end);
|
||||
|
@ -226,6 +226,25 @@ public class Range
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does any <code>TextPiece</code> in this Range use unicode?
|
||||
*
|
||||
* @return true if it does and false if it doesn't
|
||||
*/
|
||||
public boolean usesUnicode() {
|
||||
|
||||
initText();
|
||||
|
||||
for (int i = _textStart; i < _textEnd; i++)
|
||||
{
|
||||
TextPiece piece = (TextPiece)_text.get(i);
|
||||
if (piece.usesUnicode())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text that this Range contains.
|
||||
*
|
||||
@ -306,13 +325,19 @@ public class Range
|
||||
// Since this is the first item in our list, it is safe to assume that
|
||||
// _start >= tp.getStart()
|
||||
int insertIndex = _start - tp.getStart();
|
||||
if (tp.usesUnicode())
|
||||
insertIndex /= 2;
|
||||
sb.insert(insertIndex, text);
|
||||
|
||||
int adjustedLength = _doc.getTextTable().adjustForInsert(_textStart, text.length());
|
||||
_doc.getCharacterTable().adjustForInsert(_charStart, adjustedLength);
|
||||
_doc.getParagraphTable().adjustForInsert(_parStart, adjustedLength);
|
||||
_doc.getSectionTable().adjustForInsert(_sectionStart, adjustedLength);
|
||||
adjustForInsert(text.length());
|
||||
|
||||
// update the FIB.CCPText field
|
||||
adjustFIB(text.length());
|
||||
|
||||
return getCharacterRun(0);
|
||||
}
|
||||
|
||||
@ -489,6 +514,7 @@ public class Range
|
||||
|
||||
public void delete()
|
||||
{
|
||||
|
||||
initAll();
|
||||
|
||||
int numSections = _sections.size();
|
||||
@ -519,6 +545,12 @@ public class Range
|
||||
TextPiece piece = (TextPiece)_text.get(x);
|
||||
piece.adjustForDelete(_start, _end - _start);
|
||||
}
|
||||
|
||||
// update the FIB.CCPText field
|
||||
if (usesUnicode())
|
||||
adjustFIB(-((_end - _start) / 2));
|
||||
else
|
||||
adjustFIB(-(_end - _start));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -827,6 +859,19 @@ public class Range
|
||||
_sectionRangeFound = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the value of <code>FIB.CCPText</code> after an insert or a delete...
|
||||
*
|
||||
* @param adjustment The (signed) value that should be added to <code>FIB.CCPText</code>
|
||||
*/
|
||||
protected void adjustFIB(int adjustment) {
|
||||
|
||||
// update the FIB.CCPText field (this should happen once per adjustment, so we don't want it in
|
||||
// adjustForInsert() or it would get updated multiple times if the range has a parent)
|
||||
// without this, OpenOffice.org (v. 2.2.x) does not see all the text in the document
|
||||
_doc.getFileInformationBlock().setCcpText(_doc.getFileInformationBlock().getCcpText() + adjustment);
|
||||
}
|
||||
|
||||
/**
|
||||
* adjust this range after an insert happens.
|
||||
* @param length the length to adjust for
|
||||
@ -834,6 +879,7 @@ public class Range
|
||||
private void adjustForInsert(int length)
|
||||
{
|
||||
_end += length;
|
||||
|
||||
reset();
|
||||
Range parent = (Range)_parent.get();
|
||||
if (parent != null)
|
||||
@ -842,4 +888,14 @@ public class Range
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getStartOffset() {
|
||||
|
||||
return _start;
|
||||
}
|
||||
|
||||
public int getEndOffset() {
|
||||
|
||||
return _end;
|
||||
}
|
||||
}
|
||||
|
BIN
src/testcases/org/apache/poi/hssf/data/ex45046-21984.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/ex45046-21984.xls
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.poi.hssf.model;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||
@ -351,5 +352,25 @@ public final class TestSheet extends TestCase {
|
||||
xfindex = sheet.getXFIndexForColAt((short) 10);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prior to bug 45066, POI would get the estimated sheet size wrong
|
||||
* when an <tt>UncalcedRecord</tt> was present.<p/>
|
||||
*/
|
||||
public void testUncalcSize_bug45066() {
|
||||
|
||||
List records = new ArrayList();
|
||||
records.add(new BOFRecord());
|
||||
records.add(new UncalcedRecord());
|
||||
records.add(new EOFRecord());
|
||||
Sheet sheet = Sheet.createSheet( records, 0, 0 );
|
||||
|
||||
int estimatedSize = sheet.getSize();
|
||||
int serializedSize = sheet.serialize(0, new byte[estimatedSize]);
|
||||
if (serializedSize != estimatedSize) {
|
||||
throw new AssertionFailedError("Identified bug 45066 b");
|
||||
}
|
||||
assertEquals(50, serializedSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,12 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -37,7 +40,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@ -149,7 +151,6 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
|
||||
private static final class FunctionDataCollector {
|
||||
|
||||
|
||||
private final Map _allFunctionsByIndex;
|
||||
private final Map _allFunctionsByName;
|
||||
private final Set _groupFunctionIndexes;
|
||||
@ -184,25 +185,29 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
_allFunctionsByName.put(funcName, fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some extra validation here.
|
||||
* Any function which changes definition will have a footnote in the source document
|
||||
*/
|
||||
private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) {
|
||||
FunctionData fdPrev;
|
||||
// check by index
|
||||
fdPrev = (FunctionData) _allFunctionsByIndex.get(funcIxKey);
|
||||
if(fdPrev != null) {
|
||||
if(fdPrev.hasFootnote() && hasNote) {
|
||||
// func def can change if both have a foot-note
|
||||
_allFunctionsByName.remove(fdPrev.getName());
|
||||
} else {
|
||||
throw new RuntimeException("changing function definition without foot-note");
|
||||
if(!fdPrev.hasFootnote() || !hasNote) {
|
||||
throw new RuntimeException("changing function ["
|
||||
+ funcIxKey + "] definition without foot-note");
|
||||
}
|
||||
_allFunctionsByName.remove(fdPrev.getName());
|
||||
}
|
||||
// check by name
|
||||
fdPrev = (FunctionData) _allFunctionsByName.get(funcName);
|
||||
if(fdPrev != null) {
|
||||
if(fdPrev.hasFootnote() && hasNote) {
|
||||
// func def can change if both have a foot-note
|
||||
_allFunctionsByIndex.remove(new Integer(fdPrev.getIndex()));
|
||||
} else {
|
||||
throw new RuntimeException("changing function definition without foot-note");
|
||||
if(!fdPrev.hasFootnote() || !hasNote) {
|
||||
throw new RuntimeException("changing function '"
|
||||
+ funcName + "' definition without foot-note");
|
||||
}
|
||||
_allFunctionsByIndex.remove(new Integer(fdPrev.getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,9 +242,13 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
private static final String[] TABLE_CELL_RELPATH_NAMES = {
|
||||
"table:table-row", "table:table-cell", "text:p",
|
||||
};
|
||||
private static final String[] NOTE_REF_RELPATH_NAMES = {
|
||||
// after May 2008 there was one more style applied to the footnotes
|
||||
private static final String[] NOTE_REF_RELPATH_NAMES_OLD = {
|
||||
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
|
||||
};
|
||||
private static final String[] NOTE_REF_RELPATH_NAMES = {
|
||||
"table:table-row", "table:table-cell", "text:p", "text:span", "text:span", "text:note-ref",
|
||||
};
|
||||
|
||||
|
||||
private final Stack _elemNameStack;
|
||||
@ -368,6 +377,8 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
} else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
|
||||
_textNodeBuffer.setLength(0);
|
||||
_cellHasNote = false;
|
||||
} else if(matchesRelPath(NOTE_REF_RELPATH_NAMES_OLD)) {
|
||||
_cellHasNote = true;
|
||||
} else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) {
|
||||
_cellHasNote = true;
|
||||
}
|
||||
@ -456,6 +467,9 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
}
|
||||
|
||||
private static void processFile(File effDocFile, File outFile) {
|
||||
if(!effDocFile.exists()) {
|
||||
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
|
||||
}
|
||||
OutputStream os;
|
||||
try {
|
||||
os = new FileOutputStream(outFile);
|
||||
@ -475,7 +489,7 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
ps.println("# Created by (" + genClass.getName() + ")");
|
||||
// identify the source file
|
||||
ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'");
|
||||
ps.println(" (size=" + effDocFile.length() + ", crc=" + getFileCRC(effDocFile) + ")");
|
||||
ps.println(" (size=" + effDocFile.length() + ", md5=" + getFileMD5(effDocFile) + ")");
|
||||
ps.println("#");
|
||||
ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )");
|
||||
ps.println("");
|
||||
@ -490,6 +504,14 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ps.close();
|
||||
|
||||
String canonicalOutputFileName;
|
||||
try {
|
||||
canonicalOutputFileName = outFile.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("Successfully output to '" + canonicalOutputFileName + "'");
|
||||
}
|
||||
|
||||
private static void outputLicenseHeader(PrintStream ps) {
|
||||
@ -519,8 +541,14 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
/**
|
||||
* Helps identify the source file
|
||||
*/
|
||||
private static String getFileCRC(File f) {
|
||||
CRC32 crc = new CRC32();
|
||||
private static String getFileMD5(File f) {
|
||||
MessageDigest m;
|
||||
try {
|
||||
m = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
byte[]buf = new byte[2048];
|
||||
try {
|
||||
InputStream is = new FileInputStream(f);
|
||||
@ -529,21 +557,17 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
if(bytesRead<1) {
|
||||
break;
|
||||
}
|
||||
crc.update(buf, 0, bytesRead);
|
||||
m.update(buf, 0, bytesRead);
|
||||
}
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
|
||||
|
||||
return "0x" + new BigInteger(1, m.digest()).toString(16);
|
||||
}
|
||||
|
||||
private static File getSourceFile() {
|
||||
if (false) {
|
||||
File dir = new File("c:/temp");
|
||||
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
|
||||
return effDocFile;
|
||||
}
|
||||
private static File downloadSourceFile() {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME);
|
||||
@ -557,7 +581,7 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
URLConnection conn = url.openConnection();
|
||||
InputStream is = conn.getInputStream();
|
||||
System.out.println("downloading " + url.toExternalForm());
|
||||
result = File.createTempFile("excelfileformat", "odt");
|
||||
result = File.createTempFile("excelfileformat", ".odt");
|
||||
OutputStream os = new FileOutputStream(result);
|
||||
while(true) {
|
||||
int bytesRead = is.read(buf);
|
||||
@ -577,12 +601,17 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File effDocFile = getSourceFile();
|
||||
if(!effDocFile.exists()) {
|
||||
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
|
||||
}
|
||||
|
||||
File outFile = new File("functionMetadata-asGenerated.txt");
|
||||
processFile(effDocFile, outFile);
|
||||
|
||||
if (false) { // set true to use local file
|
||||
File dir = new File("c:/temp");
|
||||
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
|
||||
processFile(effDocFile, outFile);
|
||||
return;
|
||||
}
|
||||
|
||||
File tempEFFDocFile = downloadSourceFile();
|
||||
processFile(tempEFFDocFile, outFile);
|
||||
tempEFFDocFile.delete();
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.model.FormulaParser;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
@ -29,7 +28,7 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
/**
|
||||
* Tests parsing of some built-in functions that were not properly
|
||||
* registered in POI as bug #44675, #44733 (March/April 2008).
|
||||
* registered in POI as of bug #44675, #44733 (March/April 2008).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
@ -76,7 +75,7 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
|
||||
}
|
||||
|
||||
public void testUsdollar() {
|
||||
confirmFunc("USDOLLAR(1)", 2, false, 204);
|
||||
confirmFunc("USDOLLAR(1)", 2, true, 204);
|
||||
}
|
||||
|
||||
public void testDBCS() {
|
||||
|
@ -17,22 +17,18 @@
|
||||
|
||||
package org.apache.poi.hssf.record.formula.function;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
/**
|
||||
* Tests reading from a sample spreadsheet some built-in functions that were not properly
|
||||
* registered in POI as bug #44675, #44733 (March/April 2008).
|
||||
* registered in POI as of bug #44675, #44733 (March/April 2008).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
|
@ -28,7 +28,7 @@ import junit.framework.TestSuite;
|
||||
public class AllUserModelTests {
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.usermodel");
|
||||
TestSuite result = new TestSuite(AllUserModelTests.class.getName());
|
||||
|
||||
result.addTestSuite(TestBugs.class);
|
||||
result.addTestSuite(TestCellStyle.class);
|
||||
@ -58,6 +58,7 @@ public class AllUserModelTests {
|
||||
result.addTestSuite(TestHSSFSheetSetOrder.class);
|
||||
result.addTestSuite(TestHSSFTextbox.class);
|
||||
result.addTestSuite(TestHSSFWorkbook.class);
|
||||
result.addTestSuite(TestLinkTable.class);
|
||||
result.addTestSuite(TestNamedRange.class);
|
||||
result.addTestSuite(TestOLE2Embeding.class);
|
||||
result.addTestSuite(TestPOIFSProperties.class);
|
||||
|
@ -58,6 +58,30 @@ public final class TestHSSFCell extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetValues() throws Exception {
|
||||
HSSFWorkbook book = new HSSFWorkbook();
|
||||
HSSFSheet sheet = book.createSheet("test");
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
|
||||
HSSFCell cell = row.createCell((short)0);
|
||||
|
||||
cell.setCellValue(1.2);
|
||||
assertEquals(1.2, cell.getNumericCellValue(), 0.0001);
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cell.getCellType());
|
||||
|
||||
cell.setCellValue(false);
|
||||
assertEquals(false, cell.getBooleanCellValue());
|
||||
assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, cell.getCellType());
|
||||
|
||||
cell.setCellValue(new HSSFRichTextString("Foo"));
|
||||
assertEquals("Foo", cell.getRichStringCellValue().getString());
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, cell.getCellType());
|
||||
|
||||
cell.setCellValue(new HSSFRichTextString("345"));
|
||||
assertEquals("345", cell.getRichStringCellValue().getString());
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, cell.getCellType());
|
||||
}
|
||||
|
||||
/**
|
||||
* test that Boolean and Error types (BoolErrRecord) are supported properly.
|
||||
*/
|
||||
|
@ -266,6 +266,8 @@ public class TestHSSFDateUtil extends TestCase {
|
||||
formats = new String[] {
|
||||
"yyyy-mm-dd hh:mm:ss", "yyyy/mm/dd HH:MM:SS",
|
||||
"mm/dd HH:MM", "yy/mmm/dd SS",
|
||||
"mm/dd HH:MM AM", "mm/dd HH:MM am",
|
||||
"mm/dd HH:MM PM", "mm/dd HH:MM pm"
|
||||
};
|
||||
for(int i=0; i<formats.length; i++) {
|
||||
assertTrue( HSSFDateUtil.isADateFormat(formatId, formats[i]) );
|
||||
|
@ -36,7 +36,6 @@ import org.apache.poi.hssf.record.VCenterRecord;
|
||||
import org.apache.poi.hssf.record.WSBoolRecord;
|
||||
import org.apache.poi.hssf.record.WindowTwoRecord;
|
||||
import org.apache.poi.ss.util.Region;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
/**
|
||||
* Tests HSSFSheet. This test case is very incomplete at the moment.
|
||||
@ -54,10 +53,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
/**
|
||||
* Test the gridset field gets set as expected.
|
||||
*/
|
||||
|
||||
public void testBackupRecord()
|
||||
throws Exception
|
||||
{
|
||||
public void testBackupRecord() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
Sheet sheet = s.getSheet();
|
||||
@ -70,10 +66,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
/**
|
||||
* Test vertically centered output.
|
||||
*/
|
||||
|
||||
public void testVerticallyCenter()
|
||||
throws Exception
|
||||
{
|
||||
public void testVerticallyCenter() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
Sheet sheet = s.getSheet();
|
||||
@ -90,10 +83,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
/**
|
||||
* Test horizontally centered output.
|
||||
*/
|
||||
|
||||
public void testHorizontallyCenter()
|
||||
throws Exception
|
||||
{
|
||||
public void testHorizontallyCenter() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
Sheet sheet = s.getSheet();
|
||||
@ -103,16 +93,13 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(false, record.getHCenter());
|
||||
s.setHorizontallyCenter(true);
|
||||
assertEquals(true, record.getHCenter());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test WSBboolRecord fields get set in the user model.
|
||||
*/
|
||||
|
||||
public void testWSBool()
|
||||
{
|
||||
public void testWSBool() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
Sheet sheet = s.getSheet();
|
||||
@ -158,9 +145,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(true, s.getRowSumsRight());
|
||||
}
|
||||
|
||||
public void testReadBooleans()
|
||||
throws Exception
|
||||
{
|
||||
public void testReadBooleans() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet("Test boolean");
|
||||
HSSFRow row = sheet.createRow((short) 2);
|
||||
@ -168,23 +153,16 @@ public final class TestHSSFSheet extends TestCase {
|
||||
cell.setCellValue(true);
|
||||
cell = row.createCell((short) 11);
|
||||
cell.setCellValue(true);
|
||||
File tempFile = TempFile.createTempFile("bool", "test.xls");
|
||||
FileOutputStream stream = new FileOutputStream(tempFile);
|
||||
workbook.write(stream);
|
||||
stream.close();
|
||||
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
FileInputStream readStream = new FileInputStream(tempFile);
|
||||
workbook = new HSSFWorkbook(readStream);
|
||||
sheet = workbook.getSheetAt(0);
|
||||
row = sheet.getRow(2);
|
||||
stream.close();
|
||||
tempFile.delete();
|
||||
assertNotNull(row);
|
||||
assertEquals(2, row.getPhysicalNumberOfCells());
|
||||
}
|
||||
|
||||
public void testRemoveRow()
|
||||
{
|
||||
public void testRemoveRow() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet("Test boolean");
|
||||
HSSFRow row = sheet.createRow((short) 2);
|
||||
@ -197,8 +175,8 @@ public final class TestHSSFSheet extends TestCase {
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell((short) 0);
|
||||
HSSFCell cell2 = row.createCell((short) 1);
|
||||
cell.setCellValue(new HSSFRichTextString("clone_test"));
|
||||
cell2.setCellFormula("sin(1)");
|
||||
cell.setCellValue(new HSSFRichTextString("clone_test"));
|
||||
cell2.setCellFormula("sin(1)");
|
||||
|
||||
HSSFSheet clonedSheet = workbook.cloneSheet(0);
|
||||
HSSFRow clonedRow = clonedSheet.getRow(0);
|
||||
@ -234,7 +212,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
|
||||
assertNotNull(workbook.getSheet("Test Clone"));
|
||||
assertNotNull(workbook.getSheet("Test Clone(1)"));
|
||||
assertNotNull(workbook.getSheet("Test Clone(2)"));
|
||||
assertNotNull(workbook.getSheet("Test Clone(2)"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,7 +253,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
/**
|
||||
* Setting landscape and portrait stuff on existing sheets
|
||||
*/
|
||||
public void testPrintSetupLandscapeExisting() throws Exception {
|
||||
public void testPrintSetupLandscapeExisting() {
|
||||
HSSFWorkbook workbook = openSample("SimpleWithPageBreaks.xls");
|
||||
|
||||
assertEquals(3, workbook.getNumberOfSheets());
|
||||
@ -306,9 +284,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(1, sheetLS.getPrintSetup().getCopies());
|
||||
|
||||
// Save and re-load, and check still there
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
workbook.write(baos);
|
||||
workbook = new HSSFWorkbook(new ByteArrayInputStream(baos.toByteArray()));
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
assertTrue(sheetL.getPrintSetup().getLandscape());
|
||||
assertFalse(sheetPM.getPrintSetup().getLandscape());
|
||||
@ -318,7 +294,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(1, sheetLS.getPrintSetup().getCopies());
|
||||
}
|
||||
|
||||
public void testGroupRows() throws Exception {
|
||||
public void testGroupRows() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet s = workbook.createSheet();
|
||||
HSSFRow r1 = s.createRow(0);
|
||||
@ -342,11 +318,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(0, r5.getOutlineLevel());
|
||||
|
||||
// Save and re-open
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
workbook.write(baos);
|
||||
workbook = new HSSFWorkbook(
|
||||
new ByteArrayInputStream(baos.toByteArray())
|
||||
);
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
s = workbook.getSheetAt(0);
|
||||
r1 = s.getRow(0);
|
||||
@ -362,7 +334,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(0, r5.getOutlineLevel());
|
||||
}
|
||||
|
||||
public void testGroupRowsExisting() throws Exception {
|
||||
public void testGroupRowsExisting() {
|
||||
HSSFWorkbook workbook = openSample("NoGutsRecords.xls");
|
||||
|
||||
HSSFSheet s = workbook.getSheetAt(0);
|
||||
@ -391,11 +363,11 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(0, r6.getOutlineLevel());
|
||||
|
||||
// Save and re-open
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
workbook.write(baos);
|
||||
workbook = new HSSFWorkbook(
|
||||
new ByteArrayInputStream(baos.toByteArray())
|
||||
);
|
||||
try {
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new AssertionFailedError("Identified bug 39903");
|
||||
}
|
||||
|
||||
s = workbook.getSheetAt(0);
|
||||
r1 = s.getRow(0);
|
||||
@ -413,7 +385,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals(0, r6.getOutlineLevel());
|
||||
}
|
||||
|
||||
public void testGetDrawings() throws Exception {
|
||||
public void testGetDrawings() {
|
||||
HSSFWorkbook wb1c = openSample("WithChart.xls");
|
||||
HSSFWorkbook wb2c = openSample("WithTwoCharts.xls");
|
||||
|
||||
@ -440,7 +412,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
HSSFSheet hssfSheet = workbook.createSheet();
|
||||
Sheet sheet = hssfSheet.getSheet();
|
||||
ProtectRecord protect = sheet.getProtect();
|
||||
|
||||
|
||||
assertFalse(protect.getProtect());
|
||||
|
||||
// This will tell us that cloneSheet, and by extension,
|
||||
@ -454,12 +426,12 @@ public final class TestHSSFSheet extends TestCase {
|
||||
|
||||
public void testProtectSheet() {
|
||||
short expected = (short)0xfef1;
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
s.protectSheet("abcdefghij");
|
||||
Sheet sheet = s.getSheet();
|
||||
ProtectRecord protect = sheet.getProtect();
|
||||
PasswordRecord pass = sheet.getPassword();
|
||||
ProtectRecord protect = sheet.getProtect();
|
||||
PasswordRecord pass = sheet.getPassword();
|
||||
assertTrue("protection should be on",protect.getProtect());
|
||||
assertTrue("object protection should be on",sheet.isProtected()[1]);
|
||||
assertTrue("scenario protection should be on",sheet.isProtected()[2]);
|
||||
@ -467,9 +439,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
}
|
||||
|
||||
|
||||
public void testZoom()
|
||||
throws Exception
|
||||
{
|
||||
public void testZoom() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sheet = wb.createSheet();
|
||||
assertEquals(-1, sheet.getSheet().findFirstRecordLocBySid(SCLRecord.sid));
|
||||
@ -482,7 +452,6 @@ public final class TestHSSFSheet extends TestCase {
|
||||
int sclLoc = sheet.getSheet().findFirstRecordLocBySid(SCLRecord.sid);
|
||||
int window2Loc = sheet.getSheet().findFirstRecordLocBySid(WindowTwoRecord.sid);
|
||||
assertTrue(sclLoc == window2Loc + 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -493,7 +462,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
public void testRemoveMerged() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sheet = wb.createSheet();
|
||||
Region region = new Region(0, (short)0, 1, (short)1);
|
||||
Region region = new Region(0, (short)0, 1, (short)1);
|
||||
sheet.addMergedRegion(region);
|
||||
region = new Region(1, (short)0, 2, (short)1);
|
||||
sheet.addMergedRegion(region);
|
||||
@ -522,7 +491,6 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertTrue("there isn't more than one merged region in there", 1 <= sheet.getNumMergedRegions());
|
||||
region = sheet.getMergedRegionAt(0);
|
||||
assertEquals("the merged row to doesnt match the one we put in ", 4, region.getRowTo());
|
||||
|
||||
}
|
||||
|
||||
public void testShiftMerged() {
|
||||
@ -536,33 +504,25 @@ public final class TestHSSFSheet extends TestCase {
|
||||
cell = row.createCell((short)1);
|
||||
cell.setCellValue(new HSSFRichTextString("second row, second cell"));
|
||||
|
||||
Region region = new Region(1, (short)0, 1, (short)1);
|
||||
Region region = new Region(1, (short)0, 1, (short)1);
|
||||
sheet.addMergedRegion(region);
|
||||
|
||||
sheet.shiftRows(1, 1, 1);
|
||||
|
||||
region = sheet.getMergedRegionAt(0);
|
||||
assertEquals("Merged region not moved over to row 2", 2, region.getRowFrom());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the display of gridlines, formulas, and rowcolheadings.
|
||||
* @author Shawn Laubach (slaubach at apache dot org)
|
||||
*/
|
||||
public void testDisplayOptions() throws Exception {
|
||||
public void testDisplayOptions() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sheet = wb.createSheet();
|
||||
|
||||
File tempFile = TempFile.createTempFile("display", "test.xls");
|
||||
FileOutputStream stream = new FileOutputStream(tempFile);
|
||||
wb.write(stream);
|
||||
stream.close();
|
||||
|
||||
FileInputStream readStream = new FileInputStream(tempFile);
|
||||
wb = new HSSFWorkbook(readStream);
|
||||
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
sheet = wb.getSheetAt(0);
|
||||
readStream.close();
|
||||
|
||||
assertEquals(sheet.isDisplayGridlines(), true);
|
||||
assertEquals(sheet.isDisplayRowColHeadings(), true);
|
||||
@ -572,16 +532,8 @@ public final class TestHSSFSheet extends TestCase {
|
||||
sheet.setDisplayRowColHeadings(false);
|
||||
sheet.setDisplayFormulas(true);
|
||||
|
||||
tempFile = TempFile.createTempFile("display", "test.xls");
|
||||
stream = new FileOutputStream(tempFile);
|
||||
wb.write(stream);
|
||||
stream.close();
|
||||
|
||||
readStream = new FileInputStream(tempFile);
|
||||
wb = new HSSFWorkbook(readStream);
|
||||
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
sheet = wb.getSheetAt(0);
|
||||
readStream.close();
|
||||
|
||||
|
||||
assertEquals(sheet.isDisplayGridlines(), false);
|
||||
assertEquals(sheet.isDisplayRowColHeadings(), false);
|
||||
@ -593,7 +545,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
* Make sure the excel file loads work
|
||||
*
|
||||
*/
|
||||
public void testPageBreakFiles() throws Exception{
|
||||
public void testPageBreakFiles() {
|
||||
HSSFWorkbook wb = openSample("SimpleWithPageBreaks.xls");
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
@ -611,27 +563,19 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertEquals("row breaks number", 2, sheet.getRowBreaks().length);
|
||||
assertEquals("column breaks number", 2, sheet.getColumnBreaks().length);
|
||||
|
||||
File tempFile = TempFile.createTempFile("display", "testPagebreaks.xls");
|
||||
FileOutputStream stream = new FileOutputStream(tempFile);
|
||||
wb.write(stream);
|
||||
stream.close();
|
||||
|
||||
wb = new HSSFWorkbook(new FileInputStream(tempFile));
|
||||
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
sheet = wb.getSheetAt(0);
|
||||
|
||||
assertTrue("No row page break", sheet.isRowBroken(22));
|
||||
assertTrue("No column page break", sheet.isColumnBroken((short)4));
|
||||
|
||||
|
||||
assertEquals("row breaks number", 2, sheet.getRowBreaks().length);
|
||||
assertEquals("column breaks number", 2, sheet.getColumnBreaks().length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testDBCSName () throws Exception {
|
||||
public void testDBCSName () {
|
||||
HSSFWorkbook wb = openSample("DBCSSheetName.xls");
|
||||
HSSFSheet s= wb.getSheetAt(1);
|
||||
wb.getSheetAt(1);
|
||||
assertEquals ("DBCS Sheet Name 2", wb.getSheetName(1),"\u090f\u0915" );
|
||||
assertEquals("DBCS Sheet Name 1", wb.getSheetName(0),"\u091c\u093e");
|
||||
}
|
||||
@ -684,17 +628,15 @@ public final class TestHSSFSheet extends TestCase {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void testAddEmptyRow() throws Exception {
|
||||
public void testAddEmptyRow() {
|
||||
//try to add 5 empty rows to a new sheet
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
for (int i = 0; i < 5; i++) sheet.createRow(i);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sheet.createRow(i);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
workbook.write(out);
|
||||
out.close();
|
||||
|
||||
workbook = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
//try adding empty rows in an existing worksheet
|
||||
workbook = openSample("Simple.xls");
|
||||
@ -702,14 +644,10 @@ public final class TestHSSFSheet extends TestCase {
|
||||
sheet = workbook.getSheetAt(0);
|
||||
for (int i = 3; i < 10; i++) sheet.createRow(i);
|
||||
|
||||
out = new ByteArrayOutputStream();
|
||||
workbook.write(out);
|
||||
out.close();
|
||||
|
||||
workbook = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
}
|
||||
|
||||
public void testAutoSizeColumn() throws Exception {
|
||||
public void testAutoSizeColumn() {
|
||||
HSSFWorkbook wb = openSample("43902.xls");
|
||||
String sheetName = "my sheet";
|
||||
HSSFSheet sheet = wb.getSheet(sheetName);
|
||||
@ -719,7 +657,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
// machines based on the fonts available.
|
||||
// So, we use ranges, which are pretty large, but
|
||||
// thankfully don't overlap!
|
||||
int minWithRow1And2 = 6400;
|
||||
int minWithRow1And2 = 6400;
|
||||
int maxWithRow1And2 = 7800;
|
||||
int minWithRow1Only = 2750;
|
||||
int maxWithRow1Only = 3300;
|
||||
@ -733,13 +671,10 @@ public final class TestHSSFSheet extends TestCase {
|
||||
//create a region over the 2nd row and auto size the first column
|
||||
sheet.addMergedRegion(new Region(1,(short)0,1,(short)1));
|
||||
sheet.autoSizeColumn((short)0);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
wb.write(out);
|
||||
out.close();
|
||||
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
|
||||
// check that the autoSized column width has ignored the 2nd row
|
||||
// check that the autoSized column width has ignored the 2nd row
|
||||
// because it is included in a merged region (Excel like behavior)
|
||||
HSSFWorkbook wb2 = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
|
||||
HSSFSheet sheet2 = wb2.getSheet(sheetName);
|
||||
assertTrue(sheet2.getColumnWidth((short)0) >= minWithRow1Only);
|
||||
assertTrue(sheet2.getColumnWidth((short)0) <= maxWithRow1Only);
|
||||
@ -747,10 +682,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
// remove the 2nd row merged region and check that the 2nd row value is used to the autoSizeColumn width
|
||||
sheet2.removeMergedRegion(1);
|
||||
sheet2.autoSizeColumn((short)0);
|
||||
out = new ByteArrayOutputStream();
|
||||
wb2.write(out);
|
||||
out.close();
|
||||
HSSFWorkbook wb3 = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
|
||||
HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2);
|
||||
HSSFSheet sheet3 = wb3.getSheet(sheetName);
|
||||
assertTrue(sheet3.getColumnWidth((short)0) >= minWithRow1And2);
|
||||
assertTrue(sheet3.getColumnWidth((short)0) <= maxWithRow1And2);
|
||||
@ -827,7 +759,7 @@ public final class TestHSSFSheet extends TestCase {
|
||||
assertTrue(wb3.getSheetAt(3).getForceFormulaRecalculation());
|
||||
}
|
||||
|
||||
public void testColumnWidth() throws Exception {
|
||||
public void testColumnWidth() {
|
||||
//check we can correctly read column widths from a reference workbook
|
||||
HSSFWorkbook wb = openSample("colwidth.xls");
|
||||
|
||||
@ -867,11 +799,8 @@ public final class TestHSSFSheet extends TestCase {
|
||||
}
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
wb.write(out);
|
||||
out.close();
|
||||
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
|
||||
wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
|
||||
sh = wb.getSheetAt(0);
|
||||
assertEquals(10, sh.getDefaultColumnWidth());
|
||||
//columns A-C have default width
|
||||
|
@ -20,12 +20,16 @@ package org.apache.poi.hssf.usermodel;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.model.Sheet;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.util.TempFile;
|
||||
/**
|
||||
*
|
||||
@ -376,4 +380,49 @@ public final class TestHSSFWorkbook extends TestCase {
|
||||
assertEquals("active", expectedActive, sheet.isActive());
|
||||
assertEquals("selected", expectedSelected, sheet.isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If Sheet.getSize() returns a different result to Sheet.serialize(), this will cause the BOF
|
||||
* records to be written with invalid offset indexes. Excel does not like this, and such
|
||||
* errors are particularly hard to track down. This test ensures that HSSFWorkbook throws
|
||||
* a specific exception as soon as the situation is detected. See bugzilla 45066
|
||||
*/
|
||||
public void testSheetSerializeSizeMismatch_bug45066() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
Sheet sheet = wb.createSheet("Sheet1").getSheet();
|
||||
List sheetRecords = sheet.getRecords();
|
||||
// one way (of many) to cause the discrepancy is with a badly behaved record:
|
||||
sheetRecords.add(new BadlyBehavedRecord());
|
||||
// There is also much logic inside Sheet that (if buggy) might also cause the discrepancy
|
||||
try {
|
||||
wb.getBytes();
|
||||
throw new AssertionFailedError("Identified bug 45066 a");
|
||||
} catch (IllegalStateException e) {
|
||||
// Expected badly behaved sheet record to cause exception
|
||||
assertTrue(e.getMessage().startsWith("Actual serialized sheet size"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* result returned by getRecordSize() differs from result returned by serialize()
|
||||
*/
|
||||
private static final class BadlyBehavedRecord extends Record {
|
||||
public BadlyBehavedRecord() {
|
||||
//
|
||||
}
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
throw new RuntimeException("Should not be called");
|
||||
}
|
||||
public short getSid() {
|
||||
return 0x777;
|
||||
}
|
||||
public int serialize(int offset, byte[] data) {
|
||||
return 4;
|
||||
}
|
||||
protected void validateSid(short id) {
|
||||
throw new RuntimeException("Should not be called");
|
||||
}
|
||||
public int getRecordSize() {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
/**
|
||||
* Tests for LinkTable
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class TestLinkTable extends TestCase {
|
||||
|
||||
/**
|
||||
* The example file attached to bugzilla 45046 is a clear example of Name records being present
|
||||
* without an External Book (SupBook) record. Excel has no trouble reading this file.<br/>
|
||||
* TODO get OOO documentation updated to reflect this (that EXTERNALBOOK is optional).
|
||||
*
|
||||
* It's not clear what exact steps need to be taken in Excel to create such a workbook
|
||||
*/
|
||||
public void testLinkTableWithoutExternalBookRecord_bug45046() {
|
||||
HSSFWorkbook wb;
|
||||
|
||||
try {
|
||||
wb = HSSFTestDataSamples.openSampleWorkbook("ex45046-21984.xls");
|
||||
} catch (RuntimeException e) {
|
||||
if ("DEFINEDNAME is part of LinkTable".equals(e.getMessage())) {
|
||||
throw new AssertionFailedError("Identified bug 45046 b");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
// some other sanity checks
|
||||
assertEquals(3, wb.getNumberOfSheets());
|
||||
String formula = wb.getSheetAt(0).getRow(4).getCell(13).getCellFormula();
|
||||
|
||||
if ("ipcSummenproduktIntern($P5,N$6,$A$9,N$5)".equals(formula)) {
|
||||
// The reported symptom of this bugzilla is an earlier bug (already fixed)
|
||||
throw new AssertionFailedError("Identified bug 41726");
|
||||
// This is observable in version 3.0
|
||||
}
|
||||
|
||||
assertEquals("ipcSummenproduktIntern($C5,N$2,$A$9,N$1)", formula);
|
||||
}
|
||||
}
|
@ -45,8 +45,8 @@ public final class TestSheetHiding extends TestCase {
|
||||
*/
|
||||
public void testTextSheets() throws Exception {
|
||||
// Both should have two sheets
|
||||
assertEquals(2, wbH.sheets.size());
|
||||
assertEquals(2, wbU.sheets.size());
|
||||
assertEquals(2, wbH.getNumberOfSheets());
|
||||
assertEquals(2, wbU.getNumberOfSheets());
|
||||
|
||||
// All sheets should have one row
|
||||
assertEquals(0, wbH.getSheetAt(0).getLastRowNum());
|
||||
|
Loading…
Reference in New Issue
Block a user