mirror of https://github.com/apache/poi.git
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-658312 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r657702 | josh | 2008-05-19 02:06:54 +0100 (Mon, 19 May 2008) | 1 line Bug 44306 - fixed reading/writing of AttrPtg and rendering of CHOOSE formulas ........ r657875 | yegor | 2008-05-19 18:29:55 +0100 (Mon, 19 May 2008) | 1 line updated release date and started a new section for 3.1-final ........ r658033 | josh | 2008-05-20 00:07:27 +0100 (Tue, 20 May 2008) | 1 line Minor patch to improve FormulaParser error messages like those from bug 45041 ........ r658285 | nick | 2008-05-20 16:42:16 +0100 (Tue, 20 May 2008) | 1 line Fix bug 44898 - Correctly handle short last blocks in POIFS ........ r658287 | nick | 2008-05-20 16:46:54 +0100 (Tue, 20 May 2008) | 1 line Fix #44824 - Avoid an infinite loop when reading some HWPF pictures ........ r658302 | nick | 2008-05-20 17:01:53 +0100 (Tue, 20 May 2008) | 1 line Patch from bug #44937 from Squeeself- Partial support for extracting Escher images from HWPF files ........ r658308 | nick | 2008-05-20 17:30:19 +0100 (Tue, 20 May 2008) | 1 line Support for specifying a policy to HSSF on missing / blank cells when fetching ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@658333 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d0fec10d56
commit
d643dc1cf1
|
@ -43,7 +43,14 @@
|
|||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
|
||||
<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-beta2" date="2008-05-??">
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">Support for specifying a policy to HSSF on missing / blank cells when fetching</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44937 - Partial support for extracting Escher images from HWPF files</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44824 - Avoid an infinite loop when reading some HWPF pictures</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44898 - Correctly handle short last blocks in POIFS</action>
|
||||
</release>
|
||||
<release version="3.1-beta2" date="2008-05-26">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">40414 - fixed selected/active sheet after removing sheet from workbook</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44523 - fixed workbook sheet selection and focus</action>
|
||||
|
|
|
@ -40,7 +40,14 @@
|
|||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
|
||||
<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-beta2" date="2008-05-??">
|
||||
<release version="3.1-final" date="2008-06-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">Support for specifying a policy to HSSF on missing / blank cells when fetching</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44937 - Partial support for extracting Escher images from HWPF files</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44824 - Avoid an infinite loop when reading some HWPF pictures</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44898 - Correctly handle short last blocks in POIFS</action>
|
||||
</release>
|
||||
<release version="3.1-beta2" date="2008-05-26">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">40414 - fixed selected/active sheet after removing sheet from workbook</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44523 - fixed workbook sheet selection and focus</action>
|
||||
|
|
|
@ -65,20 +65,27 @@ public class EscherClientAnchorRecord
|
|||
int size = 0;
|
||||
|
||||
// Always find 4 two byte entries. Sometimes find 9
|
||||
field_1_flag = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_2_col1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_3_dx1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_4_row1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
if(bytesRemaining >= 18) {
|
||||
field_5_dy1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_6_col2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_7_dx2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_8_row2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_9_dy2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
shortRecord = false;
|
||||
} else {
|
||||
shortRecord = true;
|
||||
}
|
||||
if (bytesRemaining == 4) // Word format only 4 bytes
|
||||
{
|
||||
// Not sure exactly what the format is quite yet, likely a reference to a PLC
|
||||
}
|
||||
else
|
||||
{
|
||||
field_1_flag = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_2_col1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_3_dx1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_4_row1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
if(bytesRemaining >= 18) {
|
||||
field_5_dy1 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_6_col2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_7_dx2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_8_row2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
field_9_dy2 = LittleEndian.getShort( data, pos + size ); size += 2;
|
||||
shortRecord = false;
|
||||
} else {
|
||||
shortRecord = true;
|
||||
}
|
||||
}
|
||||
bytesRemaining -= size;
|
||||
remainingData = new byte[bytesRemaining];
|
||||
System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining );
|
||||
|
|
|
@ -134,7 +134,10 @@ public final class FormulaParser {
|
|||
|
||||
/** Report What Was Expected */
|
||||
private RuntimeException expected(String s) {
|
||||
return new FormulaParseException(s + " Expected");
|
||||
String msg = "Parse error near char " + (pointer-1) + "'" + look + "'"
|
||||
+ " in specified formula '" + formulaString + "'. Expected "
|
||||
+ s;
|
||||
return new FormulaParseException(msg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1000,7 +1003,7 @@ end;
|
|||
|
||||
if (ptg instanceof AttrPtg) {
|
||||
AttrPtg attrPtg = ((AttrPtg) ptg);
|
||||
if (attrPtg.isOptimizedIf()) {
|
||||
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSpace()) {
|
||||
|
@ -1014,6 +1017,9 @@ end;
|
|||
// similar to tAttrSpace - RPN is violated
|
||||
continue;
|
||||
}
|
||||
if (!attrPtg.isSum()) {
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
}
|
||||
}
|
||||
|
||||
final OperationPtg o = (OperationPtg) ptg;
|
||||
|
|
|
@ -39,6 +39,11 @@ public final class AttrPtg extends OperationPtg {
|
|||
private byte field_1_options;
|
||||
private short field_2_data;
|
||||
|
||||
/** only used for tAttrChoose: table of offsets to starts of args */
|
||||
private final int[] _jumpTable;
|
||||
/** only used for tAttrChoose: offset to the tFuncVar for CHOOSE() */
|
||||
private final int _chooseFuncOffset;
|
||||
|
||||
// flags 'volatile' and 'space', can be combined.
|
||||
// OOO spec says other combinations are theoretically possible but not likely to occur.
|
||||
private static final BitField semiVolatile = BitFieldFactory.getInstance(0x01);
|
||||
|
@ -63,7 +68,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
/** 03H = Carriage returns before opening parenthesis (only allowed before tParen token) */
|
||||
public static final int CR_BEFORE_OPEN_PAREN = 0x03;
|
||||
/** 04H = Spaces before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
|
||||
public static final int SPACE_BEFORE_CLOSE_PAERN = 0x04;
|
||||
public static final int SPACE_BEFORE_CLOSE_PAREN = 0x04;
|
||||
/** 05H = Carriage returns before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
|
||||
public static final int CR_BEFORE_CLOSE_PAREN = 0x05;
|
||||
/** 06H = Spaces following the equality sign (only in macro sheets) */
|
||||
|
@ -71,16 +76,33 @@ public final class AttrPtg extends OperationPtg {
|
|||
}
|
||||
|
||||
public AttrPtg() {
|
||||
_jumpTable = null;
|
||||
_chooseFuncOffset = -1;
|
||||
}
|
||||
|
||||
public AttrPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_options = in.readByte();
|
||||
field_2_data = in.readShort();
|
||||
if (isOptimizedChoose()) {
|
||||
int nCases = field_2_data;
|
||||
int[] jumpTable = new int[nCases];
|
||||
for (int i = 0; i < jumpTable.length; i++) {
|
||||
jumpTable[i] = in.readUShort();
|
||||
}
|
||||
_jumpTable = jumpTable;
|
||||
_chooseFuncOffset = in.readUShort();
|
||||
} else {
|
||||
_jumpTable = null;
|
||||
_chooseFuncOffset = -1;
|
||||
}
|
||||
|
||||
}
|
||||
private AttrPtg(int options, int data) {
|
||||
private AttrPtg(int options, int data, int[] jt, int chooseFuncOffset) {
|
||||
field_1_options = (byte) options;
|
||||
field_2_data = (short) data;
|
||||
_jumpTable = jt;
|
||||
_chooseFuncOffset = chooseFuncOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,7 +111,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
*/
|
||||
public static AttrPtg createSpace(int type, int count) {
|
||||
int data = type & 0x00FF | (count << 8) & 0x00FFFF;
|
||||
return new AttrPtg(space.set(0), data);
|
||||
return new AttrPtg(space.set(0), data, null, -1);
|
||||
}
|
||||
|
||||
public void setOptions(byte options)
|
||||
|
@ -136,13 +158,13 @@ public final class AttrPtg extends OperationPtg {
|
|||
field_1_options=optiIf.setByteBoolean(field_1_options,bif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags this ptg as a goto/jump
|
||||
* @param isGoto
|
||||
*/
|
||||
public void setGoto(boolean isGoto) {
|
||||
field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
|
||||
}
|
||||
/**
|
||||
* Flags this ptg as a goto/jump
|
||||
* @param isGoto
|
||||
*/
|
||||
public void setGoto(boolean isGoto) {
|
||||
field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
|
||||
}
|
||||
|
||||
// lets hope no one uses this anymore
|
||||
public boolean isBaxcel()
|
||||
|
@ -181,7 +203,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
if(isOptimizedIf()) {
|
||||
sb.append("if dist=").append(getData());
|
||||
} else if(isOptimizedChoose()) {
|
||||
sb.append("choose dist=").append(getData());
|
||||
sb.append("choose nCases=").append(getData());
|
||||
} else if(isGoto()) {
|
||||
sb.append("skip dist=").append(getData());
|
||||
} else if(isSum()) {
|
||||
|
@ -195,13 +217,28 @@ public final class AttrPtg extends OperationPtg {
|
|||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset]=sid;
|
||||
array[offset+1]=field_1_options;
|
||||
LittleEndian.putShort(array,offset+2,field_2_data);
|
||||
LittleEndian.putByte(array, offset+0, sid);
|
||||
LittleEndian.putByte(array, offset+1, field_1_options);
|
||||
LittleEndian.putShort(array,offset+2, field_2_data);
|
||||
int[] jt = _jumpTable;
|
||||
if (jt != null) {
|
||||
int joff = offset+4;
|
||||
LittleEndian.putUShort(array, joff, _chooseFuncOffset);
|
||||
joff+=2;
|
||||
for (int i = 0; i < jt.length; i++) {
|
||||
LittleEndian.putUShort(array, joff, jt[i]);
|
||||
joff+=2;
|
||||
}
|
||||
LittleEndian.putUShort(array, joff, _chooseFuncOffset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
if (_jumpTable != null) {
|
||||
return SIZE + (_jumpTable.length + 1) * LittleEndian.SHORT_SIZE;
|
||||
}
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
|
@ -255,12 +292,17 @@ public final class AttrPtg extends OperationPtg {
|
|||
|
||||
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AttrPtg ptg = new AttrPtg();
|
||||
ptg.field_1_options = field_1_options;
|
||||
ptg.field_2_data = field_2_data;
|
||||
return ptg;
|
||||
int[] jt;
|
||||
if (_jumpTable == null) {
|
||||
jt = null;
|
||||
} else {
|
||||
jt = (int[]) _jumpTable.clone();
|
||||
}
|
||||
return new AttrPtg(field_1_options, field_2_data, jt, _chooseFuncOffset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,6 +320,36 @@ public final class HSSFRow implements Comparable, Row {
|
|||
return cells[cellnum];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined, then
|
||||
* your supplied policy says what to do
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @param policy Policy on blank / missing cells
|
||||
* @return representing that column or null if undefined + policy allows.
|
||||
*/
|
||||
public HSSFCell getCell(int cellnum, MissingCellPolicy policy) {
|
||||
HSSFCell cell = getCell(cellnum);
|
||||
if(policy == RETURN_NULL_AND_BLANK) {
|
||||
return cell;
|
||||
}
|
||||
if(policy == RETURN_BLANK_AS_NULL) {
|
||||
if(cell == null) return cell;
|
||||
if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
|
||||
return null;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
if(policy == CREATE_NULL_AS_BLANK) {
|
||||
if(cell == null) {
|
||||
return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* get the number of the first cell contained in this row.
|
||||
* @return short representing the first logical cell in the row, or -1 if the row does not contain any cells.
|
||||
|
@ -485,6 +515,7 @@ public final class HSSFRow implements Comparable, Row {
|
|||
return cellnum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return cell iterator of the physically defined cells.
|
||||
* Note that the 4th element might well not be cell 4, as the iterator
|
||||
|
@ -503,6 +534,9 @@ public final class HSSFRow implements Comparable, Row {
|
|||
return cellIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* An iterator over the (physical) cells in the row.
|
||||
*/
|
||||
private class CellIterator implements Iterator
|
||||
{
|
||||
int thisId=-1;
|
||||
|
|
|
@ -37,6 +37,7 @@ public class RawDataBlock
|
|||
{
|
||||
private byte[] _data;
|
||||
private boolean _eof;
|
||||
private boolean _hasData;
|
||||
private static POILogger log = POILogFactory.getLogger(RawDataBlock.class);
|
||||
|
||||
/**
|
||||
|
@ -66,6 +67,7 @@ public class RawDataBlock
|
|||
throws IOException {
|
||||
_data = new byte[ blockSize ];
|
||||
int count = IOUtils.readFully(stream, _data);
|
||||
_hasData = (count > 0);
|
||||
|
||||
if (count == -1) {
|
||||
_eof = true;
|
||||
|
@ -94,16 +96,21 @@ public class RawDataBlock
|
|||
/**
|
||||
* When we read the data, did we hit end of file?
|
||||
*
|
||||
* @return true if no data was read because we were at the end of
|
||||
* the file, else false
|
||||
*
|
||||
* @exception IOException
|
||||
* @return true if the EoF was hit during this block, or
|
||||
* false if not. If you have a dodgy short last block, then
|
||||
* it's possible to both have data, and also hit EoF...
|
||||
*/
|
||||
public boolean eof()
|
||||
throws IOException
|
||||
{
|
||||
public boolean eof() {
|
||||
return _eof;
|
||||
}
|
||||
/**
|
||||
* Did we actually find any data to read? It's possible,
|
||||
* in the event of a short last block, to both have hit
|
||||
* the EoF, but also to have data
|
||||
*/
|
||||
public boolean hasData() {
|
||||
return _hasData;
|
||||
}
|
||||
|
||||
/* ********** START implementation of ListManagedBlock ********** */
|
||||
|
||||
|
@ -117,7 +124,7 @@ public class RawDataBlock
|
|||
public byte [] getData()
|
||||
throws IOException
|
||||
{
|
||||
if (eof())
|
||||
if (! hasData())
|
||||
{
|
||||
throw new IOException("Cannot return empty data");
|
||||
}
|
||||
|
|
|
@ -52,11 +52,15 @@ public class RawDataBlockList
|
|||
{
|
||||
RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
|
||||
|
||||
if (block.eof())
|
||||
{
|
||||
// If there was data, add the block to the list
|
||||
if(block.hasData()) {
|
||||
blocks.add(block);
|
||||
}
|
||||
|
||||
// If the stream is now at the End Of File, we're done
|
||||
if (block.eof()) {
|
||||
break;
|
||||
}
|
||||
blocks.add(block);
|
||||
}
|
||||
setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ]));
|
||||
}
|
||||
|
|
|
@ -33,4 +33,22 @@ public interface Row {
|
|||
HSSFCell getCell(int cellnum);
|
||||
|
||||
Iterator cellIterator();
|
||||
|
||||
/**
|
||||
* Used to specify the different possible policies
|
||||
* if for the case of null and blank cells
|
||||
*/
|
||||
public static class MissingCellPolicy {
|
||||
private static int NEXT_ID = 1;
|
||||
public final int id;
|
||||
private MissingCellPolicy() {
|
||||
this.id = NEXT_ID++;
|
||||
}
|
||||
}
|
||||
/** Missing cells are returned as null, Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy();
|
||||
/** Missing cells are returned as null, as are blank cells */
|
||||
public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy();
|
||||
/** A new, blank cell is created for missing cells. Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy();
|
||||
}
|
||||
|
|
|
@ -88,10 +88,21 @@ public interface Row extends Iterable<Cell> {
|
|||
* ask for a cell that is not defined....you get a null.
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @return HSSFCell representing that column or null if undefined.
|
||||
* @return Cell representing that column or null if undefined.
|
||||
*/
|
||||
Cell getCell(int cellnum);
|
||||
|
||||
/**
|
||||
* Get the hssfcell representing a given column (logical cell)
|
||||
* 0-based. If you ask for a cell that is not defined, then
|
||||
* your supplied policy says what to do
|
||||
*
|
||||
* @param cellnum 0 based column number
|
||||
* @param policy Policy on blank / missing cells
|
||||
* @return representing that column or null if undefined + policy allows.
|
||||
*/
|
||||
public Cell getCell(int cellnum, MissingCellPolicy policy);
|
||||
|
||||
/**
|
||||
* get the number of the first cell contained in this row.
|
||||
* @return short representing the first logical cell in the row, or -1 if the row does not contain any cells.
|
||||
|
@ -170,4 +181,22 @@ public interface Row extends Iterable<Cell> {
|
|||
|
||||
boolean equals(Object obj);
|
||||
|
||||
|
||||
/**
|
||||
* Used to specify the different possible policies
|
||||
* if for the case of null and blank cells
|
||||
*/
|
||||
public static class MissingCellPolicy {
|
||||
private static int NEXT_ID = 1;
|
||||
public final int id;
|
||||
private MissingCellPolicy() {
|
||||
this.id = NEXT_ID++;
|
||||
}
|
||||
}
|
||||
/** Missing cells are returned as null, Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy();
|
||||
/** Missing cells are returned as null, as are blank cells */
|
||||
public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy();
|
||||
/** A new, blank cell is created for missing cells. Blank cells are returned as normal */
|
||||
public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Iterator;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
||||
|
@ -139,6 +140,27 @@ public class XSSFRow implements Row {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Cell getCell(int cellnum, MissingCellPolicy policy) {
|
||||
Cell cell = getCell(cellnum);
|
||||
if(policy == RETURN_NULL_AND_BLANK) {
|
||||
return cell;
|
||||
}
|
||||
if(policy == RETURN_BLANK_AS_NULL) {
|
||||
if(cell == null) return cell;
|
||||
if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
|
||||
return null;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
if(policy == CREATE_NULL_AS_BLANK) {
|
||||
if(cell == null) {
|
||||
return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
|
||||
}
|
||||
|
||||
public short getFirstCellNum() {
|
||||
for (Iterator<Cell> it = cellIterator() ; it.hasNext() ; ) {
|
||||
Cell cell = it.next();
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Iterator;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.xssf.usermodel.TestXSSFCell.DummySharedStringSource;
|
||||
|
||||
/**
|
||||
|
@ -167,6 +168,64 @@ public final class TestXSSFRow extends TestCase {
|
|||
assertTrue(row.getZeroHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for the missing/blank cell policy stuff
|
||||
*/
|
||||
public void testGetCellPolicy() throws Exception {
|
||||
XSSFRow row = new XSSFRow(createParentObjects());
|
||||
|
||||
// 0 -> string
|
||||
// 1 -> num
|
||||
// 2 missing
|
||||
// 3 missing
|
||||
// 4 -> blank
|
||||
// 5 -> num
|
||||
row.createCell((short)0).setCellValue(new XSSFRichTextString("test"));
|
||||
row.createCell((short)1).setCellValue(3.2);
|
||||
row.createCell((short)4, Cell.CELL_TYPE_BLANK);
|
||||
row.createCell((short)5).setCellValue(4);
|
||||
|
||||
// First up, no policy
|
||||
assertEquals(Cell.CELL_TYPE_STRING, row.getCell(0).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType());
|
||||
assertEquals(null, row.getCell(2));
|
||||
assertEquals(null, row.getCell(3));
|
||||
assertEquals(Cell.CELL_TYPE_BLANK, row.getCell(4).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(5).getCellType());
|
||||
|
||||
// RETURN_NULL_AND_BLANK - same as default
|
||||
assertEquals(Cell.CELL_TYPE_STRING, row.getCell(0, Row.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1, Row.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(null, row.getCell(2, Row.RETURN_NULL_AND_BLANK));
|
||||
assertEquals(null, row.getCell(3, Row.RETURN_NULL_AND_BLANK));
|
||||
assertEquals(Cell.CELL_TYPE_BLANK, row.getCell(4, Row.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(5, Row.RETURN_NULL_AND_BLANK).getCellType());
|
||||
|
||||
// RETURN_BLANK_AS_NULL - nearly the same
|
||||
assertEquals(Cell.CELL_TYPE_STRING, row.getCell(0, XSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1, XSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
assertEquals(null, row.getCell(2, XSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(null, row.getCell(3, XSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(null, row.getCell(4, XSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(5, XSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
|
||||
// CREATE_NULL_AS_BLANK - creates as needed
|
||||
assertEquals(Cell.CELL_TYPE_STRING, row.getCell(0, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_BLANK, row.getCell(2, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_BLANK, row.getCell(3, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_BLANK, row.getCell(4, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(5, XSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
|
||||
// Check created ones get the right column
|
||||
assertEquals((short)0, row.getCell(0, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)1, row.getCell(1, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)2, row.getCell(2, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)3, row.getCell(3, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)4, row.getCell(4, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)5, row.getCell(5, XSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that returns a row with some sample cells
|
||||
* @return row
|
||||
|
|
|
@ -53,10 +53,10 @@ public class HWPFDocument extends POIDocument
|
|||
protected FileInformationBlock _fib;
|
||||
|
||||
/** main document stream buffer*/
|
||||
private byte[] _mainStream;
|
||||
protected byte[] _mainStream;
|
||||
|
||||
/** table stream buffer*/
|
||||
private byte[] _tableStream;
|
||||
protected byte[] _tableStream;
|
||||
|
||||
/** data stream buffer*/
|
||||
protected byte[] _dataStream;
|
||||
|
@ -94,6 +94,12 @@ public class HWPFDocument extends POIDocument
|
|||
/** Holds pictures table */
|
||||
protected PicturesTable _pictures;
|
||||
|
||||
/** Holds FSBA (shape) information */
|
||||
protected FSPATable _fspa;
|
||||
|
||||
/** Escher Drawing Group information */
|
||||
protected EscherRecordHolder _dgg;
|
||||
|
||||
protected HWPFDocument()
|
||||
{
|
||||
super(null, null);
|
||||
|
@ -205,9 +211,6 @@ public class HWPFDocument extends POIDocument
|
|||
_dataStream = new byte[0];
|
||||
}
|
||||
|
||||
// read in the pictures stream
|
||||
_pictures = new PicturesTable(this, _dataStream);
|
||||
|
||||
// get the start of text in the main stream
|
||||
int fcMin = _fib.getFcMin();
|
||||
|
||||
|
@ -227,6 +230,20 @@ public class HWPFDocument extends POIDocument
|
|||
_pbt.adjustForDelete(0, 0, cpMin);
|
||||
}
|
||||
|
||||
// Read FSPA and Escher information
|
||||
_fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(), _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
|
||||
|
||||
if (_fib.getFcDggInfo() != 0)
|
||||
{
|
||||
_dgg = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
|
||||
} else
|
||||
{
|
||||
_dgg = new EscherRecordHolder();
|
||||
}
|
||||
|
||||
// read in the pictures stream
|
||||
_pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg);
|
||||
|
||||
_st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, getTextTable().getTextPieces());
|
||||
_ss = new StyleSheet(_tableStream, _fib.getFcStshf());
|
||||
_ft = new FontTable(_tableStream, _fib.getFcSttbfffn(), _fib.getLcbSttbfffn());
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hwpf.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.apache.poi.ddf.DefaultEscherRecordFactory;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherRecordFactory;
|
||||
|
||||
/**
|
||||
* Based on AbstractEscherRecordHolder fomr HSSF.
|
||||
*
|
||||
* @author Squeeself
|
||||
*/
|
||||
public class EscherRecordHolder
|
||||
{
|
||||
protected ArrayList escherRecords = new ArrayList();
|
||||
|
||||
public EscherRecordHolder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EscherRecordHolder(byte[] data, int offset, int size)
|
||||
{
|
||||
fillEscherRecords(data, offset, size);
|
||||
}
|
||||
|
||||
private void fillEscherRecords(byte[] data, int offset, int size)
|
||||
{
|
||||
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
|
||||
int pos = offset;
|
||||
while ( pos < offset + size)
|
||||
{
|
||||
EscherRecord r = recordFactory.createRecord(data, pos);
|
||||
escherRecords.add(r);
|
||||
int bytesRead = r.fillFields(data, pos, recordFactory);
|
||||
pos += bytesRead + 1; // There is an empty byte between each top-level record in a Word doc
|
||||
}
|
||||
}
|
||||
|
||||
public List getEscherRecords()
|
||||
{
|
||||
return escherRecords;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
final String nl = System.getProperty("line.separator");
|
||||
if (escherRecords.size() == 0)
|
||||
buffer.append("No Escher Records Decoded" + nl);
|
||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord r = (EscherRecord) iterator.next();
|
||||
buffer.append(r.toString());
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have a EscherContainerRecord as one of our
|
||||
* children (and most top level escher holders do),
|
||||
* then return that.
|
||||
*/
|
||||
public EscherContainerRecord getEscherContainer() {
|
||||
for(Iterator it = escherRecords.iterator(); it.hasNext();) {
|
||||
Object er = it.next();
|
||||
if(er instanceof EscherContainerRecord) {
|
||||
return (EscherContainerRecord)er;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Descends into all our children, returning the
|
||||
* first EscherRecord with the given id, or null
|
||||
* if none found
|
||||
*/
|
||||
public EscherRecord findFirstWithId(short id) {
|
||||
return findFirstWithId(id, getEscherRecords());
|
||||
}
|
||||
private EscherRecord findFirstWithId(short id, List records) {
|
||||
// Check at our level
|
||||
for(Iterator it = records.iterator(); it.hasNext();) {
|
||||
EscherRecord r = (EscherRecord)it.next();
|
||||
if(r.getRecordId() == id) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
// Then check our children in turn
|
||||
for(Iterator it = records.iterator(); it.hasNext();) {
|
||||
EscherRecord r = (EscherRecord)it.next();
|
||||
if(r.isContainerRecord()) {
|
||||
EscherRecord found =
|
||||
findFirstWithId(id, r.getChildRecords());
|
||||
if(found != null) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found in this lot
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/* ====================================================================
|
||||
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.hwpf.model;
|
||||
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* File Shape Address structure
|
||||
*
|
||||
* @author Squeeself
|
||||
*/
|
||||
public class FSPA
|
||||
{
|
||||
public static final int FSPA_SIZE = 26;
|
||||
private int spid; // Shape identifier. Used to get data position
|
||||
private int xaLeft; // Enclosing rectangle
|
||||
private int yaTop; // Enclosing rectangle
|
||||
private int xaRight; // Enclosing rectangle
|
||||
private int yaBottom; // Enclosing rectangle
|
||||
private short options;
|
||||
private static BitField fHdr = BitFieldFactory.getInstance(0x0001); // 1 in undo when in header
|
||||
private static BitField bx = BitFieldFactory.getInstance(0x0006); // x pos relative to anchor CP: 0 - page margin, 1 - top of page, 2 - text, 3 - reserved
|
||||
private static BitField by = BitFieldFactory.getInstance(0x0018); // y pos relative to anchor CP: ditto
|
||||
private static BitField wr = BitFieldFactory.getInstance(0x01E0); // Text wrapping mode: 0 - like 2 w/o absolute, 1 - no text next to shape, 2 - wrap around absolute object, 3 - wrap as if no object, 4 - wrap tightly around object, 5 - wrap tightly, allow holes, 6-15 - reserved
|
||||
private static BitField wrk = BitFieldFactory.getInstance(0x1E00); // Text wrapping mode type (for modes 2&4): 0 - wrap both sides, 1 - wrap only left, 2 - wrap only right, 3 - wrap largest side
|
||||
private static BitField fRcaSimple = BitFieldFactory.getInstance(0x2000); // Overwrites bx if set, forcing rectangle to be page relative
|
||||
private static BitField fBelowText = BitFieldFactory.getInstance(0x4000); // if true, shape is below text, otherwise above
|
||||
private static BitField fAnchorLock = BitFieldFactory.getInstance(0x8000); // if true, anchor is locked
|
||||
private int cTxbx; // Count of textboxes in shape (undo doc only)
|
||||
|
||||
public FSPA()
|
||||
{
|
||||
}
|
||||
|
||||
public FSPA(byte[] bytes, int offset)
|
||||
{
|
||||
spid = LittleEndian.getInt(bytes, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
xaLeft = LittleEndian.getInt(bytes, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
yaTop = LittleEndian.getInt(bytes, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
xaRight = LittleEndian.getInt(bytes, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
yaBottom = LittleEndian.getInt(bytes, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
options = LittleEndian.getShort(bytes, offset);
|
||||
offset += LittleEndian.SHORT_SIZE;
|
||||
cTxbx = LittleEndian.getInt(bytes, offset);
|
||||
}
|
||||
|
||||
public int getSpid()
|
||||
{
|
||||
return spid;
|
||||
}
|
||||
|
||||
public int getXaLeft()
|
||||
{
|
||||
return xaLeft;
|
||||
}
|
||||
|
||||
public int getYaTop()
|
||||
{
|
||||
return yaTop;
|
||||
}
|
||||
|
||||
public int getXaRight()
|
||||
{
|
||||
return xaRight;
|
||||
}
|
||||
|
||||
public int getYaBottom()
|
||||
{
|
||||
return yaBottom;
|
||||
}
|
||||
|
||||
public boolean isFHdr()
|
||||
{
|
||||
return fHdr.isSet(options);
|
||||
}
|
||||
|
||||
public short getBx()
|
||||
{
|
||||
return bx.getShortValue(options);
|
||||
}
|
||||
|
||||
public short getBy()
|
||||
{
|
||||
return by.getShortValue(options);
|
||||
}
|
||||
|
||||
public short getWr()
|
||||
{
|
||||
return wr.getShortValue(options);
|
||||
}
|
||||
|
||||
public short getWrk()
|
||||
{
|
||||
return wrk.getShortValue(options);
|
||||
}
|
||||
|
||||
public boolean isFRcaSimple()
|
||||
{
|
||||
return fRcaSimple.isSet(options);
|
||||
}
|
||||
|
||||
public boolean isFBelowText()
|
||||
{
|
||||
return fBelowText.isSet(options);
|
||||
}
|
||||
|
||||
public boolean isFAnchorLock()
|
||||
{
|
||||
return fAnchorLock.isSet(options);
|
||||
}
|
||||
|
||||
public int getCTxbx()
|
||||
{
|
||||
return cTxbx;
|
||||
}
|
||||
|
||||
public byte[] toByteArray()
|
||||
{
|
||||
int offset = 0;
|
||||
byte[] buf = new byte[FSPA_SIZE];
|
||||
|
||||
LittleEndian.putInt(buf, offset, spid);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
LittleEndian.putInt(buf, offset, xaLeft);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
LittleEndian.putInt(buf, offset, yaTop);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
LittleEndian.putInt(buf, offset, xaRight);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
LittleEndian.putInt(buf, offset, yaBottom);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
LittleEndian.putShort(buf, offset, options);
|
||||
offset += LittleEndian.SHORT_SIZE;
|
||||
LittleEndian.putInt(buf, offset, cTxbx);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("spid: ").append(spid);
|
||||
buf.append(", xaLeft: ").append(xaLeft);
|
||||
buf.append(", yaTop: ").append(yaTop);
|
||||
buf.append(", xaRight: ").append(xaRight);
|
||||
buf.append(", yaBottom: ").append(yaBottom);
|
||||
buf.append(", options: ").append(options);
|
||||
buf.append(" (fHdr: ").append(isFHdr());
|
||||
buf.append(", bx: ").append(getBx());
|
||||
buf.append(", by: ").append(getBy());
|
||||
buf.append(", wr: ").append(getWr());
|
||||
buf.append(", wrk: ").append(getWrk());
|
||||
buf.append(", fRcaSimple: ").append(isFRcaSimple());
|
||||
buf.append(", fBelowText: ").append(isFBelowText());
|
||||
buf.append(", fAnchorLock: ").append(isFAnchorLock());
|
||||
buf.append("), cTxbx: ").append(cTxbx);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hwpf.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class holds all the FSPA (File Shape Address) structures.
|
||||
*
|
||||
* @author Squeeself
|
||||
*/
|
||||
public class FSPATable
|
||||
{
|
||||
protected ArrayList shapes = new ArrayList();
|
||||
protected HashMap cps = new HashMap();
|
||||
protected List _text;
|
||||
|
||||
public FSPATable(byte[] tableStream, int fcPlcspa, int lcbPlcspa, List tpt)
|
||||
{
|
||||
_text = tpt;
|
||||
// Will be 0 if no drawing objects in document
|
||||
if (fcPlcspa == 0)
|
||||
return;
|
||||
|
||||
PlexOfCps plex = new PlexOfCps(tableStream, fcPlcspa, lcbPlcspa, FSPA.FSPA_SIZE);
|
||||
for (int i=0; i < plex.length(); i++)
|
||||
{
|
||||
GenericPropertyNode property = plex.getProperty(i);
|
||||
FSPA fspa = new FSPA(property.getBytes(), 0);
|
||||
|
||||
shapes.add(fspa);
|
||||
cps.put(Integer.valueOf(property.getStart()), Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
public FSPA getFspaFromCp(int cp)
|
||||
{
|
||||
Integer idx = (Integer)cps.get(Integer.valueOf(cp));
|
||||
if (idx == null)
|
||||
return null;
|
||||
return (FSPA)shapes.get(idx.intValue());
|
||||
}
|
||||
|
||||
public List getShapes()
|
||||
{
|
||||
return shapes;
|
||||
}
|
||||
|
||||
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(); )
|
||||
{
|
||||
Integer i = (Integer) it.next();
|
||||
FSPA fspa = (FSPA) shapes.get(((Integer)cps.get(i)).intValue());
|
||||
buf.append(" [FC: ").append(i.toString()).append("] ");
|
||||
buf.append(fspa.toString());
|
||||
buf.append("\n");
|
||||
}
|
||||
buf.append("[/FSPA PLC]");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
|
@ -309,6 +309,26 @@ public class FileInformationBlock extends FIBAbstractType
|
|||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
|
||||
}
|
||||
|
||||
public int getFcPlcspaMom()
|
||||
{
|
||||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
|
||||
}
|
||||
|
||||
public int getLcbPlcspaMom()
|
||||
{
|
||||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
|
||||
}
|
||||
|
||||
public int getFcDggInfo()
|
||||
{
|
||||
return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
|
||||
}
|
||||
|
||||
public int getLcbDggInfo()
|
||||
{
|
||||
return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
|
||||
}
|
||||
|
||||
public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
|
||||
throws IOException
|
||||
{
|
||||
|
|
|
@ -26,7 +26,12 @@ import org.apache.poi.hwpf.usermodel.Range;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.Iterator;
|
||||
import org.apache.poi.ddf.DefaultEscherRecordFactory;
|
||||
import org.apache.poi.ddf.EscherBSERecord;
|
||||
import org.apache.poi.ddf.EscherBlipRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherRecordFactory;
|
||||
|
||||
/**
|
||||
* Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
|
||||
|
@ -57,6 +62,9 @@ public class PicturesTable
|
|||
|
||||
private HWPFDocument _document;
|
||||
private byte[] _dataStream;
|
||||
private byte[] _mainStream;
|
||||
private FSPATable _fspa;
|
||||
private EscherRecordHolder _dgg;
|
||||
|
||||
/** @link dependency
|
||||
* @stereotype instantiate*/
|
||||
|
@ -67,10 +75,13 @@ public class PicturesTable
|
|||
* @param document
|
||||
* @param _dataStream
|
||||
*/
|
||||
public PicturesTable(HWPFDocument _document, byte[] _dataStream)
|
||||
public PicturesTable(HWPFDocument _document, byte[] _dataStream, byte[] _mainStream, FSPATable fspa, EscherRecordHolder dgg)
|
||||
{
|
||||
this._document = _document;
|
||||
this._document = _document;
|
||||
this._dataStream = _dataStream;
|
||||
this._mainStream = _mainStream;
|
||||
this._fspa = fspa;
|
||||
this._dgg = dgg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,6 +95,13 @@ public class PicturesTable
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean hasEscherPicture(CharacterRun run) {
|
||||
if (run.isSpecialCharacter() && !run.isObj() && !run.isOle2() && !run.isData() && run.text().startsWith("\u0008")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* determines whether specified CharacterRun contains reference to a picture
|
||||
* @param run
|
||||
|
@ -123,6 +141,46 @@ public class PicturesTable
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a recursive search for pictures in the given list of escher records.
|
||||
*
|
||||
* @param escherRecords the escher records.
|
||||
* @param pictures the list to populate with the pictures.
|
||||
*/
|
||||
private void searchForPictures(List escherRecords, List pictures)
|
||||
{
|
||||
Iterator recordIter = escherRecords.iterator();
|
||||
while (recordIter.hasNext())
|
||||
{
|
||||
Object obj = recordIter.next();
|
||||
if (obj instanceof EscherRecord)
|
||||
{
|
||||
EscherRecord escherRecord = (EscherRecord) obj;
|
||||
|
||||
if (escherRecord instanceof EscherBSERecord)
|
||||
{
|
||||
EscherBSERecord bse = (EscherBSERecord) escherRecord;
|
||||
EscherBlipRecord blip = bse.getBlipRecord();
|
||||
if (blip != null)
|
||||
{
|
||||
pictures.add(new Picture(blip.getPicturedata()));
|
||||
}
|
||||
else if (bse.getOffset() > 0)
|
||||
{
|
||||
// Blip stored in delay stream, which in a word doc, is the main stream
|
||||
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
|
||||
blip = (EscherBlipRecord) recordFactory.createRecord(_mainStream, bse.getOffset());
|
||||
blip.fillFields(_mainStream, bse.getOffset(), recordFactory);
|
||||
pictures.add(new Picture(blip.getPicturedata()));
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive call.
|
||||
searchForPictures(escherRecord.getChildRecords(), pictures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not all documents have all the images concatenated in the data stream
|
||||
* although MS claims so. The best approach is to scan all character runs.
|
||||
|
@ -136,13 +194,14 @@ public class PicturesTable
|
|||
for (int i = 0; i < range.numCharacterRuns(); i++) {
|
||||
CharacterRun run = range.getCharacterRun(i);
|
||||
String text = run.text();
|
||||
int j = text.charAt(0);
|
||||
Picture picture = extractPicture(run, false);
|
||||
if (picture != null) {
|
||||
pictures.add(picture);
|
||||
}
|
||||
}
|
||||
|
||||
searchForPictures(_dgg.getEscherRecords(), pictures);
|
||||
|
||||
return pictures;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,15 @@ public class Picture
|
|||
}
|
||||
}
|
||||
|
||||
public Picture(byte[] _dataStream)
|
||||
{
|
||||
this._dataStream = _dataStream;
|
||||
this.dataBlockStartOfsset = 0;
|
||||
this.dataBlockSize = _dataStream.length;
|
||||
this.pictureBytesStartOffset = 0;
|
||||
this.size = _dataStream.length;
|
||||
}
|
||||
|
||||
private void fillWidthHeight()
|
||||
{
|
||||
String ext = suggestFileExtension();
|
||||
|
@ -363,6 +372,7 @@ public class Picture
|
|||
do {
|
||||
firstByte = _dataStream[pointer];
|
||||
secondByte = _dataStream[pointer+1];
|
||||
pointer += 2;
|
||||
} while (!(firstByte==(byte)0xFF) && pointer<endOfPicture-1);
|
||||
|
||||
if (firstByte==((byte)0xFF) && pointer<endOfPicture-1) {
|
||||
|
|
|
@ -35,10 +35,12 @@ public class TestHWPFPictures extends TestCase {
|
|||
private String docAFile;
|
||||
private String docBFile;
|
||||
private String docCFile;
|
||||
private String docDFile;
|
||||
|
||||
private String imgAFile;
|
||||
private String imgBFile;
|
||||
private String imgCFile;
|
||||
private String imgDFile;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
String dirname = System.getProperty("HWPF.testdata.path");
|
||||
|
@ -46,10 +48,12 @@ public class TestHWPFPictures extends TestCase {
|
|||
docAFile = dirname + "/testPictures.doc";
|
||||
docBFile = dirname + "/two_images.doc";
|
||||
docCFile = dirname + "/vector_image.doc";
|
||||
docDFile = dirname + "/GaiaTest.doc";
|
||||
|
||||
imgAFile = dirname + "/simple_image.jpg";
|
||||
imgBFile = dirname + "/simple_image.png";
|
||||
imgCFile = dirname + "/vector_image.emf";
|
||||
imgDFile = dirname + "/GaiaTestImg.png";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +131,25 @@ public class TestHWPFPictures extends TestCase {
|
|||
assertBytesSame(picBytes, pic.getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Pending the missing files being uploaded to
|
||||
* bug #44937
|
||||
*/
|
||||
public void BROKENtestEscherDrawing() throws Exception
|
||||
{
|
||||
HWPFDocument docD = new HWPFDocument(new FileInputStream(docDFile));
|
||||
List allPictures = docD.getPicturesTable().getAllPictures();
|
||||
|
||||
assertEquals(1, allPictures.size());
|
||||
|
||||
Picture pic = (Picture) allPictures.get(0);
|
||||
assertNotNull(pic);
|
||||
byte[] picD = readFile(imgDFile);
|
||||
|
||||
assertEquals(picD.length, pic.getContent().length);
|
||||
|
||||
assertBytesSame(picD, pic.getContent());
|
||||
}
|
||||
|
||||
private void assertBytesSame(byte[] a, byte[] b) {
|
||||
assertEquals(a.length, b.length);
|
||||
|
|
|
@ -38,6 +38,8 @@ public final class TestExternalNameRecord extends TestCase {
|
|||
// data taken from bugzilla 44774 att 21790
|
||||
private static final byte[] dataPlainName = {
|
||||
0, 0, 0, 0, 0, 0, 9, 0, 82, 97, 116, 101, 95, 68, 97, 116, 101, 9, 0, 58, 0, 0, 0, 0, 4, 0, 8, 0
|
||||
// TODO - the last 2 bytes of formula data (8,0) seem weird. They encode to ConcatPtg, UnknownPtg
|
||||
// UnknownPtg is otherwise not created by any other test cases
|
||||
};
|
||||
|
||||
private static ExternalNameRecord createSimpleENR(byte[] data) {
|
||||
|
|
|
@ -19,17 +19,15 @@ package org.apache.poi.hssf.record;
|
|||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.ConcatPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||
import org.apache.poi.hssf.record.formula.RangePtg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
import org.apache.poi.hssf.record.formula.UnknownPtg;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
|
||||
/**
|
||||
* Tests the serialization and deserialization of the FormulaRecord
|
||||
* class works correctly.
|
||||
|
@ -57,7 +55,7 @@ public final class TestFormulaRecord extends TestCase {
|
|||
*/
|
||||
public void testCheckNanPreserve() {
|
||||
byte[] formulaByte = new byte[29];
|
||||
for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0;
|
||||
|
||||
formulaByte[4] = (byte)0x0F;
|
||||
formulaByte[6] = (byte)0x02;
|
||||
formulaByte[8] = (byte)0x07;
|
||||
|
@ -91,8 +89,6 @@ public final class TestFormulaRecord extends TestCase {
|
|||
public void testExpFormula() {
|
||||
byte[] formulaByte = new byte[27];
|
||||
|
||||
for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0;
|
||||
|
||||
formulaByte[4] =(byte)0x0F;
|
||||
formulaByte[14]=(byte)0x08;
|
||||
formulaByte[18]=(byte)0xE0;
|
||||
|
@ -109,15 +105,14 @@ public final class TestFormulaRecord extends TestCase {
|
|||
|
||||
public void testWithConcat() throws Exception {
|
||||
// =CHOOSE(2,A2,A3,A4)
|
||||
byte[] data = new byte[] {
|
||||
byte[] data = {
|
||||
6, 0, 68, 0,
|
||||
1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 57,
|
||||
64, 0, 0, 12, 0, 12, -4, 46, 0,
|
||||
30, 2, 0, // Int - 2
|
||||
25, 4, 3, 0, // Attr
|
||||
8, 0, // Concat
|
||||
17, 0, // Range
|
||||
26, 0, 35, 0, // Bit like an attr
|
||||
8, 0, 17, 0, 26, 0, // jumpTable
|
||||
35, 0, // chooseOffset
|
||||
36, 1, 0, 0, -64, // Ref - A2
|
||||
25, 8, 21, 0, // Attr
|
||||
36, 2, 0, 0, -64, // Ref - A3
|
||||
|
@ -126,30 +121,24 @@ public final class TestFormulaRecord extends TestCase {
|
|||
25, 8, 3, 0, // Attr
|
||||
66, 4, 100, 0 // CHOOSE
|
||||
};
|
||||
RecordInputStream inp = new RecordInputStream(
|
||||
new ByteArrayInputStream(data)
|
||||
);
|
||||
RecordInputStream inp = new RecordInputStream( new ByteArrayInputStream(data));
|
||||
inp.nextRecord();
|
||||
|
||||
FormulaRecord fr = new FormulaRecord(inp);
|
||||
|
||||
assertEquals(14, fr.getNumberOfExpressionTokens());
|
||||
assertEquals(IntPtg.class, fr.getParsedExpression().get(0).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(1).getClass());
|
||||
assertEquals(ConcatPtg.class, fr.getParsedExpression().get(2).getClass());
|
||||
assertEquals(UnknownPtg.class, fr.getParsedExpression().get(3).getClass());
|
||||
assertEquals(RangePtg.class, fr.getParsedExpression().get(4).getClass());
|
||||
assertEquals(UnknownPtg.class, fr.getParsedExpression().get(5).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(6).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(7).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(8).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(9).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(10).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(11).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(12).getClass());
|
||||
assertEquals(FuncVarPtg.class, fr.getParsedExpression().get(13).getClass());
|
||||
List ptgs = fr.getParsedExpression();
|
||||
assertEquals(9, ptgs.size());
|
||||
assertEquals(IntPtg.class, ptgs.get(0).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(1).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(2).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(3).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(4).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(5).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(6).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(7).getClass());
|
||||
assertEquals(FuncVarPtg.class, ptgs.get(8).getClass());
|
||||
|
||||
FuncVarPtg choose = (FuncVarPtg)fr.getParsedExpression().get(13);
|
||||
FuncVarPtg choose = (FuncVarPtg)ptgs.get(8);
|
||||
assertEquals("CHOOSE", choose.getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,18 +17,19 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.ss.util.Region;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Testcases for bugs entered in bugzilla
|
||||
* the Test name contains the bugzilla bug id
|
||||
|
@ -81,13 +82,7 @@ public final class TestBugs extends TestCase {
|
|||
HSSFRow r = s.createRow(0);
|
||||
HSSFCell c = r.createCell((short)0);
|
||||
c.setCellValue(10);
|
||||
try {
|
||||
writeOutAndReadBack(wb);
|
||||
} catch (RecordFormatException e) {
|
||||
if (false) { // TODO (Apr-2008) this file does not read back ok. create bugzilla bug & fix.
|
||||
throw new AssertionFailedError("Identified bug XXXX");
|
||||
}
|
||||
}
|
||||
writeOutAndReadBack(wb);
|
||||
}
|
||||
/**Test writing a hyperlink
|
||||
* Open resulting sheet in Excel and check that A1 contains a hyperlink*/
|
||||
|
@ -758,9 +753,13 @@ public final class TestBugs extends TestCase {
|
|||
HSSFCell c2 = r2.getCell((short)1);
|
||||
assertEquals(25, (int)c2.getNumericCellValue());
|
||||
|
||||
if (false) { // TODO (Apr-2008) This will blow up with IllegalStateException (stack underflow)
|
||||
// excel function "CHOOSE" probably needs some special handling in FormulaParser.toFormulaString()
|
||||
assertEquals("=CHOOSE(2,A2,A3,A4)", c2.getCellFormula());
|
||||
try {
|
||||
assertEquals("CHOOSE(2,A2,A3,A4)", c2.getCellFormula());
|
||||
} catch (IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("Too few arguments")
|
||||
&& e.getMessage().indexOf("ConcatPtg") > 0) {
|
||||
throw new AssertionFailedError("identified bug 44306");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,7 +893,7 @@ public final class TestBugs extends TestCase {
|
|||
* works just fine...
|
||||
*/
|
||||
public void test44891() throws Exception {
|
||||
HSSFWorkbook wb = openSample("44891.xls");
|
||||
HSSFWorkbook wb = openSample("44891.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
|
@ -906,7 +905,7 @@ public final class TestBugs extends TestCase {
|
|||
* Works fine with poi-3.1-beta1.
|
||||
*/
|
||||
public void test44235() throws Exception {
|
||||
HSSFWorkbook wb = openSample("44235.xls");
|
||||
HSSFWorkbook wb = openSample("44235.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
|
@ -930,7 +929,7 @@ public final class TestBugs extends TestCase {
|
|||
}
|
||||
|
||||
public void test36947() throws Exception {
|
||||
HSSFWorkbook wb = openSample("36947.xls");
|
||||
HSSFWorkbook wb = openSample("36947.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
|
@ -947,7 +946,7 @@ public final class TestBugs extends TestCase {
|
|||
}
|
||||
|
||||
public void test39634() throws Exception {
|
||||
HSSFWorkbook wb = openSample("39634.xls");
|
||||
HSSFWorkbook wb = openSample("39634.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
|
|
|
@ -204,4 +204,64 @@ public final class TestHSSFRow extends TestCase {
|
|||
row.createCell((short) 255);
|
||||
assertEquals(256, row.getLastCellNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for the missing/blank cell policy stuff
|
||||
*/
|
||||
public void testGetCellPolicy() throws Exception {
|
||||
HSSFWorkbook book = new HSSFWorkbook();
|
||||
HSSFSheet sheet = book.createSheet("test");
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
|
||||
// 0 -> string
|
||||
// 1 -> num
|
||||
// 2 missing
|
||||
// 3 missing
|
||||
// 4 -> blank
|
||||
// 5 -> num
|
||||
row.createCell((short)0).setCellValue(new HSSFRichTextString("test"));
|
||||
row.createCell((short)1).setCellValue(3.2);
|
||||
row.createCell((short)4, HSSFCell.CELL_TYPE_BLANK);
|
||||
row.createCell((short)5).setCellValue(4);
|
||||
|
||||
// First up, no policy
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType());
|
||||
assertEquals(null, row.getCell(2));
|
||||
assertEquals(null, row.getCell(3));
|
||||
assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5).getCellType());
|
||||
|
||||
// RETURN_NULL_AND_BLANK - same as default
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(null, row.getCell(2, HSSFRow.RETURN_NULL_AND_BLANK));
|
||||
assertEquals(null, row.getCell(3, HSSFRow.RETURN_NULL_AND_BLANK));
|
||||
assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4, HSSFRow.RETURN_NULL_AND_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.RETURN_NULL_AND_BLANK).getCellType());
|
||||
|
||||
// RETURN_BLANK_AS_NULL - nearly the same
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
assertEquals(null, row.getCell(2, HSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(null, row.getCell(3, HSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(null, row.getCell(4, HSSFRow.RETURN_BLANK_AS_NULL));
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.RETURN_BLANK_AS_NULL).getCellType());
|
||||
|
||||
// CREATE_NULL_AS_BLANK - creates as needed
|
||||
assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(2, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(3, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.CREATE_NULL_AS_BLANK).getCellType());
|
||||
|
||||
// Check created ones get the right column
|
||||
assertEquals((short)0, row.getCell(0, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)1, row.getCell(1, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)2, row.getCell(2, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)3, row.getCell(3, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)4, row.getCell(4, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
assertEquals((short)5, row.getCell(5, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ public final class TestPOIFSFileSystem extends TestCase {
|
|||
* The other is to fix the handling of the last block in
|
||||
* POIFS, since it seems to be slight wrong
|
||||
*/
|
||||
public void DISABLEDtestShortLastBlock() throws Exception {
|
||||
public void testShortLastBlock() throws Exception {
|
||||
String[] files = new String[] {
|
||||
"ShortLastBlock.qwp", "ShortLastBlock.wps"
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue