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:
Nick Burch 2008-05-23 09:48:23 +00:00
parent 81550a63a9
commit e34bbfc887
36 changed files with 1592 additions and 1486 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
@ -192,6 +193,11 @@ public abstract class POIDocument {
}
}
/**
* 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
* @param source is the source POIFS to copy from

View File

@ -140,29 +140,21 @@ public final class FormulaParser {
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);
@ -218,7 +210,6 @@ public final class FormulaParser {
return Token.toString();
}
/** Get a Number */
private String GetNum() {
StringBuffer value = new StringBuffer();
@ -486,7 +477,6 @@ public final class FormulaParser {
}
boolean missedPrevArg = true;
int numArgs = 0;
while (true) {
SkipWhite();
@ -507,6 +497,10 @@ public final class FormulaParser {
addArgumentPointer(argumentPointers);
numArgs++;
missedPrevArg = false;
SkipWhite();
if (!isArgumentDelimiter(look)) {
throw expected("',' or ')'");
}
}
return numArgs;
}
@ -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,8 +698,7 @@ public final class FormulaParser {
}
private StringPtg parseStringLiteral()
{
private StringPtg parseStringLiteral() {
Match('"');
StringBuffer token = new StringBuffer();
@ -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;
@ -868,6 +859,7 @@ end;
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

View File

@ -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 {
@ -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
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) {

View File

@ -96,7 +96,7 @@ 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;
@ -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)
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();
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();
}
//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);
// 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 != null && cells.rowHasCells(row.getRowNumber()))
retval += 2;
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;
}
/**

View File

@ -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 :

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
@ -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()

View File

@ -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;

View File

@ -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() {

View File

@ -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;
}

View File

@ -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 */
@ -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(" [");

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
*/

View File

@ -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");

View File

@ -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();

View File

@ -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);

View File

@ -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;
}
}

View File

@ -56,8 +56,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Test the low level formula parser functionality. High level tests are to
* be done via usermodel/HSSFCell.setFormulaValue().
* Some tests are also done in scratchpad, if they need
* HSSFFormulaEvaluator, which is there
*/
public final class TestFormulaParser extends TestCase {
@ -65,7 +63,6 @@ public final class TestFormulaParser extends TestCase {
* @return parsed token array already confirmed not <code>null</code>
*/
private static Ptg[] parseFormula(String s) {
// TODO - replace multiple copies of this code with calls to this method
FormulaParser fp = new FormulaParser(s, null);
fp.parse();
Ptg[] result = fp.getRPNPtg();
@ -74,69 +71,49 @@ public final class TestFormulaParser extends TestCase {
}
public void testSimpleFormula() {
FormulaParser fp = new FormulaParser("2+2",null);
fp.parse();
Ptg[] ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
Ptg[] ptgs = parseFormula("2+2");
assertEquals(3, ptgs.length);
}
public void testFormulaWithSpace1() {
FormulaParser fp = new FormulaParser(" 2 + 2 ",null);
fp.parse();
Ptg[] ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
Ptg[] ptgs = parseFormula(" 2 + 2 ");
assertEquals(3, ptgs.length);
assertTrue("",(ptgs[0] instanceof IntPtg));
assertTrue("",(ptgs[1] instanceof IntPtg));
assertTrue("",(ptgs[2] instanceof AddPtg));
}
public void testFormulaWithSpace2() {
Ptg[] ptgs;
FormulaParser fp;
fp = new FormulaParser("2+ sum( 3 , 4) ",null);
fp.parse();
ptgs = fp.getRPNPtg();
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
Ptg[] ptgs = parseFormula("2+ sum( 3 , 4) ");
assertEquals(5, ptgs.length);
}
public void testFormulaWithSpaceNRef() {
Ptg[] ptgs;
FormulaParser fp;
fp = new FormulaParser("sum( A2:A3 )",null);
fp.parse();
ptgs = fp.getRPNPtg();
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
Ptg[] ptgs = parseFormula("sum( A2:A3 )");
assertEquals(2, ptgs.length);
}
public void testFormulaWithString() {
Ptg[] ptgs;
FormulaParser fp;
fp = new FormulaParser("\"hello\" & \"world\" ",null);
fp.parse();
ptgs = fp.getRPNPtg();
assertTrue("three token expected, got " + ptgs.length, ptgs.length == 3);
Ptg[] ptgs = parseFormula("\"hello\" & \"world\" ");
assertEquals(3, ptgs.length);
}
public void testTRUE() throws Exception {
FormulaParser fp = new FormulaParser("TRUE", null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals(1, asts.length);
BoolPtg flag = (BoolPtg) asts[0];
public void testTRUE() {
Ptg[] ptgs = parseFormula("TRUE");
assertEquals(1, ptgs.length);
BoolPtg flag = (BoolPtg) ptgs[0];
assertEquals(true, flag.getValue());
}
public void testYN() throws Exception {
final String yn = "IF(TRUE,\"Y\",\"N\")";
FormulaParser fp = new FormulaParser(yn, null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals(7, asts.length);
public void testYN() {
Ptg[] ptgs = parseFormula("IF(TRUE,\"Y\",\"N\")");
assertEquals(7, ptgs.length);
BoolPtg flag = (BoolPtg) asts[0];
AttrPtg funif = (AttrPtg) asts[1];
StringPtg y = (StringPtg) asts[2];
AttrPtg goto1 = (AttrPtg) asts[3];
StringPtg n = (StringPtg) asts[4];
BoolPtg flag = (BoolPtg) ptgs[0];
AttrPtg funif = (AttrPtg) ptgs[1];
StringPtg y = (StringPtg) ptgs[2];
AttrPtg goto1 = (AttrPtg) ptgs[3];
StringPtg n = (StringPtg) ptgs[4];
assertEquals(true, flag.getValue());
@ -146,29 +123,31 @@ public final class TestFormulaParser extends TestCase {
assertTrue("Goto ptg exists", goto1.isGoto());
}
public void testSimpleIf() throws Exception {
final String simpleif = "IF(1=1,0,1)";
FormulaParser fp = new FormulaParser(simpleif, null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals(9, asts.length);
public void testSimpleIf() {
String formula = "IF(1=1,0,1)";
IntPtg op1 = (IntPtg) asts[0];
IntPtg op2 = (IntPtg) asts[1];
EqualPtg eq = (EqualPtg) asts[2];
AttrPtg ifPtg = (AttrPtg) asts[3];
IntPtg res1 = (IntPtg) asts[4];
Class[] expectedClasses = {
IntPtg.class,
IntPtg.class,
EqualPtg.class,
AttrPtg.class,
IntPtg.class,
AttrPtg.class,
IntPtg.class,
AttrPtg.class,
FuncVarPtg.class,
};
confirmTokenClasses(formula, expectedClasses);
AttrPtg ptgGoto= (AttrPtg) asts[5];
assertEquals("Goto 1 Length", (short)10, ptgGoto.getData());
Ptg[] ptgs = parseFormula(formula);
IntPtg res2 = (IntPtg) asts[6];
AttrPtg ptgGoto2 = (AttrPtg) asts[7];
assertEquals("Goto 2 Length", (short)3, ptgGoto2.getData());
AttrPtg ifPtg = (AttrPtg) ptgs[3];
AttrPtg ptgGoto= (AttrPtg) ptgs[5];
assertEquals("Goto 1 Length", 10, ptgGoto.getData());
assertEquals("If FALSE offset", (short)7, ifPtg.getData());
FuncVarPtg funcPtg = (FuncVarPtg)asts[8];
AttrPtg ptgGoto2 = (AttrPtg) ptgs[7];
assertEquals("Goto 2 Length", 3, ptgGoto2.getData());
assertEquals("If FALSE offset", 7, ifPtg.getData());
}
/**
@ -176,47 +155,36 @@ public final class TestFormulaParser extends TestCase {
*
*/
public void testNestedFunctionIf() {
String function = "IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))";
Ptg[] ptgs = parseFormula("IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))");
assertEquals(11, ptgs.length);
FormulaParser fp = new FormulaParser(function, null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals("11 Ptgs expected", 11, asts.length);
assertTrue("IF Attr set correctly", (asts[3] instanceof AttrPtg));
AttrPtg ifFunc = (AttrPtg)asts[3];
assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
AttrPtg ifFunc = (AttrPtg)ptgs[3];
assertTrue("It is not an if", ifFunc.isOptimizedIf());
assertTrue("Average Function set correctly", (asts[5] instanceof FuncVarPtg));
assertTrue("Average Function set correctly", (ptgs[5] instanceof FuncVarPtg));
}
public void testIfSingleCondition(){
String function = "IF(1=1,10)";
Ptg[] ptgs = parseFormula("IF(1=1,10)");
assertEquals(7, ptgs.length);
FormulaParser fp = new FormulaParser(function, null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals("7 Ptgs expected", 7, asts.length);
assertTrue("IF Attr set correctly", (asts[3] instanceof AttrPtg));
AttrPtg ifFunc = (AttrPtg)asts[3];
assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
AttrPtg ifFunc = (AttrPtg)ptgs[3];
assertTrue("It is not an if", ifFunc.isOptimizedIf());
assertTrue("Single Value is not an IntPtg", (asts[4] instanceof IntPtg));
IntPtg intPtg = (IntPtg)asts[4];
assertTrue("Single Value is not an IntPtg", (ptgs[4] instanceof IntPtg));
IntPtg intPtg = (IntPtg)ptgs[4];
assertEquals("Result", (short)10, intPtg.getValue());
assertTrue("Ptg is not a Variable Function", (asts[6] instanceof FuncVarPtg));
FuncVarPtg funcPtg = (FuncVarPtg)asts[6];
assertTrue("Ptg is not a Variable Function", (ptgs[6] instanceof FuncVarPtg));
FuncVarPtg funcPtg = (FuncVarPtg)ptgs[6];
assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
}
public void testSumIf() {
String function ="SUMIF(A1:A5,\">4000\",B1:B5)";
FormulaParser fp = new FormulaParser(function, null);
fp.parse();
Ptg[] asts = fp.getRPNPtg();
assertEquals("4 Ptgs expected", 4, asts.length);
Ptg[] ptgs = parseFormula("SUMIF(A1:A5,\">4000\",B1:B5)");
assertEquals(4, ptgs.length);
}
/**
@ -226,12 +194,10 @@ public final class TestFormulaParser extends TestCase {
*/
public void testNonAlphaFormula() {
String currencyCell = "F3";
String function="\"TOTAL[\"&"+currencyCell+"&\"]\"";
Ptg[] asts = parseFormula(function);
assertEquals("5 ptgs expected", 5, asts.length);
assertTrue ("Ptg[0] is a string", (asts[0] instanceof StringPtg));
StringPtg firstString = (StringPtg)asts[0];
Ptg[] ptgs = parseFormula("\"TOTAL[\"&"+currencyCell+"&\"]\"");
assertEquals(5, ptgs.length);
assertTrue ("Ptg[0] is a string", (ptgs[0] instanceof StringPtg));
StringPtg firstString = (StringPtg)ptgs[0];
assertEquals("TOTAL[", firstString.getValue());
//the PTG order isn't 100% correct but it still works - dmui
@ -239,20 +205,20 @@ public final class TestFormulaParser extends TestCase {
public void testSimpleLogical() {
Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
assertEquals("Ptg array length", 9, ptgs.length);
assertEquals(9, ptgs.length);
assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
}
public void testParenIf() {
Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
assertEquals("Ptg array length", 12, ptgs.length);
assertEquals(12, ptgs.length);
assertEquals("6th Ptg is less than equal",LessEqualPtg.class,ptgs[5].getClass());
assertEquals("11th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[10].getClass());
}
public void testEmbeddedIf() {
Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
assertEquals("Ptg array length", 17, ptgs.length);
assertEquals(17, ptgs.length);
assertEquals("6th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[5].getClass());
assertEquals("9th Ptg is not a not equal ptg",NotEqualPtg.class,ptgs[8].getClass());
@ -274,23 +240,18 @@ public final class TestFormulaParser extends TestCase {
}
public void testEmbeddedSlash() {
FormulaParser fp = new FormulaParser("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")",null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
Ptg[] ptgs = parseFormula("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")");
assertTrue("first ptg is string", ptgs[0] instanceof StringPtg);
assertTrue("second ptg is string", ptgs[1] instanceof StringPtg);
}
public void testConcatenate() {
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
assertTrue("first ptg is string", ptg[0] instanceof StringPtg);
assertTrue("second ptg is string", ptg[1] instanceof StringPtg);
Ptg[] ptgs = parseFormula("CONCATENATE(\"first\",\"second\")");
assertTrue("first ptg is string", ptgs[0] instanceof StringPtg);
assertTrue("second ptg is string", ptgs[1] instanceof StringPtg);
}
public void testWorksheetReferences()
{
public void testWorksheetReferences() {
HSSFWorkbook wb = new HSSFWorkbook();
wb.createSheet("NoQuotesNeeded");
@ -307,74 +268,54 @@ public final class TestFormulaParser extends TestCase {
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
}
public void testUnaryMinus()
{
FormulaParser fp = new FormulaParser("-A1", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
assertTrue("got 2 ptgs", ptg.length == 2);
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
assertTrue("second ptg is Minus",ptg[1] instanceof UnaryMinusPtg);
public void testUnaryMinus() {
Ptg[] ptgs = parseFormula("-A1");
assertEquals(2, ptgs.length);
assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg);
assertTrue("second ptg is Minus",ptgs[1] instanceof UnaryMinusPtg);
}
public void testUnaryPlus()
{
FormulaParser fp = new FormulaParser("+A1", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
assertTrue("got 2 ptgs", ptg.length == 2);
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
assertTrue("second ptg is Plus",ptg[1] instanceof UnaryPlusPtg);
public void testUnaryPlus() {
Ptg[] ptgs = parseFormula("+A1");
assertEquals(2, ptgs.length);
assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg);
assertTrue("second ptg is Plus",ptgs[1] instanceof UnaryPlusPtg);
}
public void testLeadingSpaceInString()
{
public void testLeadingSpaceInString() {
String value = " hi ";
FormulaParser fp = new FormulaParser("\"" + value + "\"", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
Ptg[] ptgs = parseFormula("\"" + value + "\"");
assertTrue("got 1 ptg", ptg.length == 1);
assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
assertEquals(1, ptgs.length);
assertTrue("ptg0 is a StringPtg", ptgs[0] instanceof StringPtg);
assertTrue("ptg0 contains exact value", ((StringPtg)ptgs[0]).getValue().equals(value));
}
public void testLookupAndMatchFunctionArgs()
{
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
public void testLookupAndMatchFunctionArgs() {
Ptg[] ptgs = parseFormula("lookup(A1, A3:A52, B3:B52)");
assertTrue("got 4 ptg", ptg.length == 4);
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
assertEquals(4, ptgs.length);
assertTrue("ptg0 has Value class", ptgs[0].getPtgClass() == Ptg.CLASS_VALUE);
fp = new FormulaParser("match(A1, A3:A52)", null);
fp.parse();
ptg = fp.getRPNPtg();
ptgs = parseFormula("match(A1, A3:A52)");
assertTrue("got 3 ptg", ptg.length == 3);
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
assertEquals(3, ptgs.length);
assertTrue("ptg0 has Value class", ptgs[0].getPtgClass() == Ptg.CLASS_VALUE);
}
/** bug 33160*/
public void testLargeInt() {
FormulaParser fp = new FormulaParser("40", null);
fp.parse();
Ptg[] ptg=fp.getRPNPtg();
assertTrue("ptg is Int, is "+ptg[0].getClass(),ptg[0] instanceof IntPtg);
Ptg[] ptgs = parseFormula("40");
assertTrue("ptg is Int, is "+ptgs[0].getClass(),ptgs[0] instanceof IntPtg);
fp = new FormulaParser("40000", null);
fp.parse();
ptg=fp.getRPNPtg();
assertTrue("ptg should be IntPtg, is "+ptg[0].getClass(), ptg[0] instanceof IntPtg);
ptgs = parseFormula("40000");
assertTrue("ptg should be IntPtg, is "+ptgs[0].getClass(), ptgs[0] instanceof IntPtg);
}
/** bug 33160, testcase by Amol Deshmukh*/
public void testSimpleLongFormula() {
FormulaParser fp = new FormulaParser("40000/2", null);
fp.parse();
Ptg[] ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
Ptg[] ptgs = parseFormula("40000/2");
assertEquals(3, ptgs.length);
assertTrue("IntPtg", (ptgs[0] instanceof IntPtg));
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
@ -392,37 +333,31 @@ public final class TestFormulaParser extends TestCase {
cell = row.createCell((short)0);
cell.setCellFormula("Cash_Flow!A1");
}
// bug 38396 : Formula with exponential numbers not parsed correctly.
public void testExponentialParsing() {
FormulaParser fp = new FormulaParser("1.3E21/2", null);
fp.parse();
Ptg[] ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
Ptg[] ptgs;
ptgs = parseFormula("1.3E21/2");
assertEquals(3, ptgs.length);
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
fp = new FormulaParser("1322E21/2", null);
fp.parse();
ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
ptgs = parseFormula("1322E21/2");
assertEquals(3, ptgs.length);
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
fp = new FormulaParser("1.3E1/2", null);
fp.parse();
ptgs = fp.getRPNPtg();
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
ptgs = parseFormula("1.3E1/2");
assertEquals(3, ptgs.length);
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
}
public void testExponentialInSheet() throws Exception {
public void testExponentialInSheet() {
HSSFWorkbook wb = new HSSFWorkbook();
wb.createSheet("Cash_Flow");
@ -493,11 +428,6 @@ public final class TestFormulaParser extends TestCase {
assertEquals("Exponential formula string", "-1.0/310.0*4000.0/30000.0", formula);
}
public static void main(String [] args) {
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
junit.textui.TestRunner.run(TestFormulaParser.class);
}
public void testNumbers() {
HSSFWorkbook wb = new HSSFWorkbook();
@ -896,15 +826,15 @@ public final class TestFormulaParser extends TestCase {
* (e.g. COUNTIF) Excel fails to evaluate the formula, giving '#VALUE!' instead.
*/
public void testFuncPtgSelection() {
HSSFWorkbook book = new HSSFWorkbook();
Ptg[] ptgs;
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
ptgs = parseFormula("countif(A1:A2, 1)");
assertEquals(3, ptgs.length);
if(FuncVarPtg.class == ptgs[2].getClass()) {
throw new AssertionFailedError("Identified bug 44675");
}
assertEquals(FuncPtg.class, ptgs[2].getClass());
ptgs = FormulaParser.parse("sin(1)", book);
ptgs = parseFormula("sin(1)");
assertEquals(2, ptgs.length);
assertEquals(FuncPtg.class, ptgs[1].getClass());
}
@ -925,4 +855,14 @@ public final class TestFormulaParser extends TestCase {
assertEquals(expectedMessage, e.getMessage());
}
}
public void testParseErrorExpecteMsg() {
try {
parseFormula("round(3.14;2)");
throw new AssertionFailedError("Didn't get parse exception as expected");
} catch (FormulaParseException e) {
assertEquals("Parse error near char 10 ';' in specified formula 'round(3.14;2)'. Expected ',' or ')'", e.getMessage());
}
}
}

View File

@ -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);
}
}

View File

@ -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
if(!fdPrev.hasFootnote() || !hasNote) {
throw new RuntimeException("changing function ["
+ funcIxKey + "] definition without foot-note");
}
_allFunctionsByName.remove(fdPrev.getName());
} else {
throw new RuntimeException("changing function definition without foot-note");
}
}
// 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");
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 outFile = new File("functionMetadata-asGenerated.txt");
processFile(effDocFile, outFile);
File tempEFFDocFile = downloadSourceFile();
processFile(tempEFFDocFile, outFile);
tempEFFDocFile.delete();
}
}

View File

@ -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() {

View File

@ -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
*/

View File

@ -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);

View File

@ -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.
*/

View File

@ -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]) );

View File

@ -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();
FileInputStream readStream = new FileInputStream(tempFile);
workbook = new HSSFWorkbook(readStream);
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
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);
@ -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");
@ -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);
}
@ -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() {
@ -543,26 +511,18 @@ public final class TestHSSFSheet extends TestCase {
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);
@ -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
// 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

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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());