Browse Source

More work on Conditional Formatting (bug 30311) junit and fixes from Dmitriy. Some other clean-up.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@642878 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_0_3_BETA1
Josh Micich 16 years ago
parent
commit
622ff5c3dd

+ 2
- 0
src/documentation/content/xdocs/changes.xml View File

@@ -26,6 +26,7 @@
<!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/>
<person id="GJS" name="Glen Stampoultzis" email="user@poi.apache.org"/>
<person id="JM" name="Josh Micich" email="josh@apache.org"/>
<person id="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
@@ -36,6 +37,7 @@

<!-- Don't forget to update status.xml too! -->
<release version="3.0.3-beta1" date="2008-04-??">
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>

+ 2
- 0
src/documentation/content/xdocs/status.xml View File

@@ -22,6 +22,7 @@
<!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/>
<person id="GJS" name="Glen Stampoultzis" email="user@poi.apache.org"/>
<person id="JM" name="Josh Micich" email="josh@apache.org"/>
<person id="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
@@ -33,6 +34,7 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.0.3-beta1" date="2008-04-??">
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>

+ 56
- 65
src/java/org/apache/poi/hssf/record/CFHeaderRecord.java View File

@@ -15,18 +15,10 @@
limitations under the License.
==================================================================== */

/*
* ConditionalFormattingHeaderRecord.java
*
* Created on January 17, 2008, 3:05 AM
*/
package org.apache.poi.hssf.record;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.LittleEndian;

/**
@@ -34,19 +26,27 @@ import org.apache.poi.util.LittleEndian;
*
* @author Dmitriy Kumshayev
*/
public class CFHeaderRecord extends Record
public final class CFHeaderRecord extends Record
{
public static final short sid = 0x1B0;

private static final CellRange[] EMPTY_CELL_RANGE_ARRAY = { };

private int field_1_numcf;
private int field_2_need_recalculation;
private CellRange field_3_enclosing_cell_range;
private List field_4_cell_ranges;
private CellRange[] field_4_cell_ranges;

/** Creates new CFHeaderRecord */
public CFHeaderRecord()
{
field_4_cell_ranges = new ArrayList(5);
field_4_cell_ranges = EMPTY_CELL_RANGE_ARRAY;
}
public CFHeaderRecord(Region[] regions)
{
CellRange[] unmergedRanges = CellRange.convertRegionsToCellRanges(regions);
CellRange[] mergeCellRanges = CellRange.mergeCellRanges(unmergedRanges);
setCellRanges(mergeCellRanges);
}

public CFHeaderRecord(RecordInputStream in)
@@ -60,11 +60,12 @@ public class CFHeaderRecord extends Record
field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
int numCellRanges = in.readShort();
field_4_cell_ranges = new ArrayList(5);
CellRange[] crs = new CellRange[numCellRanges];
for( int i=0; i<numCellRanges; i++)
{
field_4_cell_ranges.add(new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort()));
crs[i] = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
}
field_4_cell_ranges = crs;
}
public int getNumberOfConditionalFormats()
@@ -101,28 +102,24 @@ public class CFHeaderRecord extends Record
* modify the enclosing cell range accordingly.
* @param List cellRanges - list of CellRange objects
*/
public void setCellRanges( List cellRanges )
public void setCellRanges(CellRange[] cellRanges)
{
field_4_cell_ranges.clear();
if(cellRanges!=null)
if(cellRanges == null)
{
field_3_enclosing_cell_range=null;
for( int i=0; i<cellRanges.size(); i++)
{
field_4_cell_ranges.add(cellRanges.get(i));
recalculateEnclosingRange((CellRange)cellRanges.get(i));
}
throw new IllegalArgumentException("cellRanges must not be null");
}
}

private void recalculateEnclosingRange(CellRange cellRange)
{
field_3_enclosing_cell_range = cellRange.createEnclosingCellRange(field_3_enclosing_cell_range);
field_4_cell_ranges = (CellRange[]) cellRanges.clone();
CellRange enclosingRange = null;
for (int i = 0; i < cellRanges.length; i++)
{
enclosingRange = cellRanges[i].createEnclosingCellRange(enclosingRange);
}
field_3_enclosing_cell_range=enclosingRange;
}
public List getCellRanges()
public CellRange[] getCellRanges()
{
return field_4_cell_ranges;
return (CellRange[]) field_4_cell_ranges.clone();
}

public String toString()
@@ -130,16 +127,16 @@ public class CFHeaderRecord extends Record
StringBuffer buffer = new StringBuffer();

buffer.append("[CFHEADER]\n");
buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
if( field_4_cell_ranges.size()>0)
buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
if( field_4_cell_ranges.length>0)
{
buffer.append(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.size(); i++)
buffer.append(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.length; i++)
{
buffer.append(i==0?"":",").append(field_4_cell_ranges.get(i));
buffer.append(i==0?"":",").append(field_4_cell_ranges[i].toString());
}
buffer.append("]\n");
}
@@ -163,24 +160,21 @@ public class CFHeaderRecord extends Record
LittleEndian.putShort(data, 10 + offset, (short) field_3_enclosing_cell_range.getLastRow());
LittleEndian.putShort(data, 12 + offset, (short) field_3_enclosing_cell_range.getFirstColumn());
LittleEndian.putShort(data, 14 + offset, (short) field_3_enclosing_cell_range.getLastColumn());
LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.size());
for( int i=0 ; i!=field_4_cell_ranges.size(); i++)
LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.length);
for( int i=0 ; i!=field_4_cell_ranges.length; i++)
{
LittleEndian.putShort(data, 18 + 0 + 8 * i + offset,
(short) ((CellRange) field_4_cell_ranges.get(i)).getFirstRow());
LittleEndian.putShort(data, 18 + 2 + 8 * i + offset,
(short) ((CellRange) field_4_cell_ranges.get(i)).getLastRow());
LittleEndian.putShort(data, 18 + 4 + 8 * i + offset,
(short) ((CellRange) field_4_cell_ranges.get(i)).getFirstColumn());
LittleEndian.putShort(data, 18 + 6 + 8 * i + offset,
(short) ((CellRange) field_4_cell_ranges.get(i)).getLastColumn());
CellRange cr = field_4_cell_ranges[i];
LittleEndian.putShort(data, 18 + 0 + 8 * i + offset, (short) cr.getFirstRow());
LittleEndian.putShort(data, 18 + 2 + 8 * i + offset, (short) cr.getLastRow());
LittleEndian.putShort(data, 18 + 4 + 8 * i + offset, (short) cr.getFirstColumn());
LittleEndian.putShort(data, 18 + 6 + 8 * i + offset, (short) cr.getLastColumn());
}
return getRecordSize();
}

public int getRecordSize()
{
return 18+8*field_4_cell_ranges.size();
return 18+8*field_4_cell_ranges.length;
}

/**
@@ -204,20 +198,17 @@ public class CFHeaderRecord extends Record
return sid;
}

public Object clone()
{
CFHeaderRecord rec = new CFHeaderRecord();
rec.field_1_numcf = field_1_numcf;
rec.field_2_need_recalculation = field_2_need_recalculation;
rec.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
rec.field_4_cell_ranges = new ArrayList(field_4_cell_ranges.size());
Iterator iterator = field_4_cell_ranges.iterator();
while (iterator.hasNext())
{
CellRange oldRange = (CellRange)iterator.next();
rec.field_4_cell_ranges.add(oldRange.cloneCellRange());
}
return rec;
}

public Object clone()
{
CFHeaderRecord result = new CFHeaderRecord();
result.field_1_numcf = field_1_numcf;
result.field_2_need_recalculation = field_2_need_recalculation;
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
CellRange[] crs = new CellRange[field_4_cell_ranges.length];
for (int i = 0; i < crs.length; i++) {
crs[i] = field_4_cell_ranges[i].cloneCellRange();
}
result.field_4_cell_ranges = crs;
return result;
}
}

+ 511
- 516
src/java/org/apache/poi/hssf/record/CFRuleRecord.java
File diff suppressed because it is too large
View File


+ 98
- 64
src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java View File

@@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -37,19 +38,38 @@ import org.apache.poi.util.POILogger;
*/
public final class CFRecordsAggregate extends Record
{
/** Excel allows up to 3 conditional formating rules */
private static final int MAX_CONDTIONAL_FORMAT_RULES = 3;

public final static short sid = -2008; // not a real BIFF record

private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);

private CFHeaderRecord header;
private final CFHeaderRecord header;

// List of CFRuleRecord objects
/** List of CFRuleRecord objects */
private final List rules;

public CFRecordsAggregate()
{
header = null;
rules = new ArrayList(3);
private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) {
if(pHeader == null) {
throw new IllegalArgumentException("header must not be null");
}
if(pRules == null) {
throw new IllegalArgumentException("rules must not be null");
}
if(pRules.length > MAX_CONDTIONAL_FORMAT_RULES) {
throw new IllegalArgumentException("No more than "
+ MAX_CONDTIONAL_FORMAT_RULES + " rules may be specified");
}
header = pHeader;
rules = new ArrayList(3);
for (int i = 0; i < pRules.length; i++) {
rules.add(pRules[i]);
}
}

public CFRecordsAggregate(Region[] regions, CFRuleRecord[] rules) {
this(new CFHeaderRecord(regions), rules);
}

/**
@@ -60,42 +80,46 @@ public final class CFRecordsAggregate extends Record
*/
public static CFRecordsAggregate createCFAggregate(List recs, int pOffset)
{
Record rec = ( Record ) recs.get(pOffset);
if (rec.getSid() != CFHeaderRecord.sid) {
throw new IllegalStateException("next record sid was " + rec.getSid()
+ " instead of " + CFHeaderRecord.sid + " as expected");
}

int offset = pOffset;
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);

Record rec = ( Record ) recs.get(offset++);
CFHeaderRecord header = (CFHeaderRecord)rec;
int nRules = header.getNumberOfConditionalFormats();

if (rec.getSid() == CFHeaderRecord.sid)
{
records.add(rec);
cfRecords.header = (CFHeaderRecord)rec;

int nRules = cfRecords.header.getNumberOfConditionalFormats();
int rulesCount = 0;
while( offset<recs.size() &&
(rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
rec instanceof CFRuleRecord &&
rulesCount++ < nRules
)
{
records.add(rec);
cfRecords.rules.add(rec);
CFRuleRecord[] rules = new CFRuleRecord[nRules];
int offset = pOffset;
int countFound = 0;
while (countFound < rules.length) {
offset++;
if(offset>=recs.size()) {
break;
}
rec = (Record)recs.get(offset);
if(rec instanceof CFRuleRecord) {
rules[countFound] = (CFRuleRecord) rec;
countFound++;
} else {
break;
}
}

if (nRules != cfRecords.rules.size())
if (countFound < nRules)
{ // TODO -(MAR-2008) can this ever happen? write junit
if (log.check(POILogger.DEBUG))
{
if (log.check(POILogger.DEBUG))
{
log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
+ "but found " + cfRecords.rules.size() + " rules");
}
cfRecords.header.setNumberOfConditionalFormats(nRules);
log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
+ "but found " + countFound + " rules");
}

header.setNumberOfConditionalFormats(nRules);
CFRuleRecord[] lessRules = new CFRuleRecord[countFound];
System.arraycopy(rules, 0, lessRules, 0, countFound);
rules = lessRules;
}
return cfRecords;
return new CFRecordsAggregate(header, rules);
}

/**
@@ -104,22 +128,17 @@ public final class CFRecordsAggregate extends Record
*/
public CFRecordsAggregate cloneCFAggregate()
{

ArrayList records = new ArrayList(this.rules.size()+1);
records.add(this.header.clone());
for (int i=0; i<this.rules.size();i++)
{
Record rec = (Record)((Record)this.rules.get(i)).clone();
records.add(rec);
}
return createCFAggregate(records, 0);
CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
for (int i = 0; i < newRecs.length; i++) {
newRecs[i] = (CFRuleRecord) getRule(i).clone();
}
return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
}

/** You never fill an aggregate */
protected void fillFields(RecordInputStream in)
{
// You never fill an aggregate record
}

public short getSid()
@@ -139,17 +158,14 @@ public final class CFRecordsAggregate extends Record

public int serialize(int offset, byte[] data)
{
int pos = offset;
if( header != null && rules.size()>0 )
{
header.setNumberOfConditionalFormats(rules.size());
int nRules = rules.size();
header.setNumberOfConditionalFormats(nRules);

pos += (( Record ) header).serialize(pos, data);
int pos = offset;

for(Iterator itr = rules.iterator(); itr.hasNext();)
{
pos += (( Record ) itr.next()).serialize(pos, data);
}
pos += header.serialize(pos, data);
for(int i=0; i< nRules; i++) {
pos += getRule(i).serialize(pos, data);
}
return pos - offset;
}
@@ -160,19 +176,37 @@ public final class CFRecordsAggregate extends Record
}

/**
* @return the header
* @return the header. Never <code>null</code>.
*/
public CFHeaderRecord getHeader()
{
return header;
}

/**
* @return the rules
*/
public List getRules()
{
return rules;
private void checkRuleIndex(int idx) {
if(idx < 0 || idx >= rules.size()) {
throw new IllegalArgumentException("Bad rule record index (" + idx
+ ") nRules=" + rules.size());
}
}
public CFRuleRecord getRule(int idx) {
checkRuleIndex(idx);
return (CFRuleRecord) rules.get(idx);
}
public void setRule(int idx, CFRuleRecord r) {
checkRuleIndex(idx);
rules.set(idx, r);
}
public void addRule(CFRuleRecord r) {
if(rules.size() >= MAX_CONDTIONAL_FORMAT_RULES) {
throw new IllegalStateException("Cannot have more than "
+ MAX_CONDTIONAL_FORMAT_RULES + " conditional format rules");
}
rules.add(r);
header.setNumberOfConditionalFormats(rules.size());
}
public int getNumberOfRules() {
return rules.size();
}

/**

+ 375
- 103
src/java/org/apache/poi/hssf/record/cf/CellRange.java View File

@@ -17,79 +17,127 @@

package org.apache.poi.hssf.record.cf;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.poi.hssf.util.Region;

/**
* CellRange.java
* Created on January 22, 2008, 10:05 PM
*
* @author Dmitriy Kumshayev
*/

public class CellRange
public final class CellRange
{
private int field_1_first_row;
private int field_2_last_row;
private short field_3_first_column;
private short field_4_last_column;
public CellRange(int firstRow, int lastRow, short firstColumn, short lastColumn)
{
this.field_1_first_row = firstRow;
this.field_2_last_row = lastRow;
this.field_3_first_column = firstColumn;
this.field_4_last_column = lastColumn;
validateRegion();
}
private void validateRegion()
{
if( field_1_first_row < 0 ||
field_2_last_row < -1 ||
field_3_first_column < 0 ||
field_4_last_column < -1 ||
field_2_last_row>=0 && field_2_last_row<field_1_first_row ||
field_4_last_column>=0 && field_4_last_column<field_3_first_column
)
{
throw new IllegalArgumentException("Invalid cell region "+toString());
}
}
public int getFirstRow()
/**
* max index for both row and column<p/>
*
* Note - this value converts to <tt>-1</tt> when cast to a <tt>short</tt>
*/
private static final int MAX_INDEX = Integer.MAX_VALUE;

private static final Region[] EMPTY_REGION_ARRAY = { };
private int _firstRow;
private int _lastRow;
private int _firstColumn;
private int _lastColumn;
/**
*
* @param firstRow
* @param lastRow pass <tt>-1</tt> for full column ranges
* @param firstColumn
* @param lastColumn pass <tt>-1</tt> for full row ranges
*/
public CellRange(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
return field_1_first_row;
if(!isValid(firstRow, lastRow, firstColumn, lastColumn)) {
throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
+ ", " + firstColumn + ", " + lastColumn + ")");
}
_firstRow = firstRow;
_lastRow = convertM1ToMax(lastRow);
_firstColumn = firstColumn;
_lastColumn = convertM1ToMax(lastColumn);
}
private void setFirstRow(int firstRow)
{
this.field_1_first_row = firstRow;
private static int convertM1ToMax(int lastIx) {
if(lastIx < 0) {
return MAX_INDEX;
}
return lastIx;
}
public int getLastRow()
{
return field_2_last_row;
private static int convertMaxToM1(int lastIx) {
if(lastIx == MAX_INDEX) {
return -1;
}
return lastIx;
}

public boolean isFullColumnRange() {
return _firstColumn == 0 && _lastColumn == MAX_INDEX;
}
public boolean isFullRowRange() {
return _firstRow == 0 && _lastRow == MAX_INDEX;
}
public CellRange(Region r) {
this(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
}
private void setLastRow(int lastRow)

private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
this.field_2_last_row = lastRow;
if(lastRow == -1) {
if(firstRow !=0) {
return false;
}
}
if(firstRow < 0 || lastRow < -1) {
return false;
}
if(lastColumn == -1) {
if(firstColumn !=0) {
return false;
}
}
if(firstColumn < 0 || lastColumn < -1) {
return false;
}
return true;
}
public short getFirstColumn()
public int getFirstRow()
{
return field_3_first_column;
return _firstRow;
}
private void setFirstColumn(short firstColumn)
/**
* @return <tt>-1</tt> for whole column ranges
*/
public int getLastRow()
{
this.field_3_first_column = firstColumn;
return convertMaxToM1(_lastRow);
}
public short getLastColumn()
public int getFirstColumn()
{
return field_4_last_column;
return _firstColumn;
}
private void setLastColumn(short lastColumn)
/**
* @return <tt>-1</tt> for whole row ranges
*/
public int getLastColumn()
{
this.field_4_last_column = lastColumn;
return convertMaxToM1(_lastColumn);
}
public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2;
/** first range is within the second range */
public static final int INSIDE = 3;
/** first range encloses or is equal to the second */
public static final int ENCLOSES = 4;
/**
@@ -101,30 +149,31 @@ public class CellRange
* NO_INTERSECTION - the specified range is outside of this range;<br/>
* OVERLAP - both ranges partially overlap;<br/>
* INSIDE - the specified range is inside of this one<br/>
* ENCLOSES - the specified range encloses this range<br/>
* ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
*/
public int intersect(CellRange another )
{
int firstRow = another.getFirstRow();
int lastRow = another.getLastRow();
short firstCol = another.getFirstColumn();
short lastCol = another.getLastColumn();
int firstRow = another.getFirstRow();
int lastRow = another.getLastRow();
int firstCol = another.getFirstColumn();
int lastCol = another.getLastColumn();
if
(
gt(this.getFirstRow(),lastRow) ||
lt(this.getLastRow(),firstRow) ||
gt(this.getFirstColumn(),lastCol) ||
lt(this.getLastColumn(),firstCol)
gt(getFirstRow(),lastRow) ||
lt(getLastRow(),firstRow) ||
gt(getFirstColumn(),lastCol) ||
lt(getLastColumn(),firstCol)
)
{
return NO_INTERSECTION;
}
else if( this.contains(another) )
else if( contains(another) )
{
return INSIDE;
}
else if( another.contains(this) )
else if( another.contains(this))
{
return ENCLOSES;
}
@@ -134,7 +183,234 @@ public class CellRange
}
}
/**
* Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
* <li>if two cells have a shared border, merge them into one bigger cell range
* @param cellRangeList
* @return updated List of cell ranges
*/
public static CellRange[] mergeCellRanges(CellRange[] cellRanges) {
if(cellRanges.length < 1) {
return cellRanges;
}
List temp = mergeCellRanges(Arrays.asList(cellRanges));
return toArray(temp);
}
private static List mergeCellRanges(List cellRangeList)
{

while(cellRangeList.size() > 1)
{
boolean somethingGotMerged = false;
for( int i=0; i<cellRangeList.size(); i++)
{
CellRange range1 = (CellRange)cellRangeList.get(i);
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRange range2 = (CellRange)cellRangeList.get(j);
CellRange[] mergeResult = mergeRanges(range1, range2);
if(mergeResult == null) {
continue;
}
somethingGotMerged = true;
// overwrite range1 with first result
cellRangeList.set(i, mergeResult[0]);
// remove range2
cellRangeList.remove(j--);
// add any extra results beyond the first
for(int k=1; k<mergeResult.length; k++) {
j++;
cellRangeList.add(j, mergeResult[k]);
}
}
}
if(!somethingGotMerged) {
break;
}
}

return cellRangeList;
}
/**
* @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible
*/
private static CellRange[] mergeRanges(CellRange range1, CellRange range2) {
int x = range1.intersect(range2);
switch(x)
{
case CellRange.NO_INTERSECTION:
if( range1.hasExactSharedBorder(range2))
{
return new CellRange[] { range1.createEnclosingCellRange(range2), };
}
// else - No intersection and no shared border: do nothing
return null;
case CellRange.OVERLAP:
return resolveRangeOverlap(range1, range2);
case CellRange.INSIDE:
// Remove range2, since it is completely inside of range1
return new CellRange[] { range1, };
case CellRange.ENCLOSES:
// range2 encloses range1, so replace it with the enclosing one
return new CellRange[] { range2, };
}
throw new RuntimeException("unexpected intersection result (" + x + ")");
}
// TODO - write junit test for this
static CellRange[] resolveRangeOverlap(CellRange rangeA, CellRange rangeB) {
if(rangeA.isFullColumnRange()) {
if(rangeB.isFullRowRange()) {
// Excel seems to leave these unresolved
return null;
}
return rangeA.sliceUp(rangeB);
}
if(rangeA.isFullRowRange()) {
if(rangeB.isFullColumnRange()) {
// Excel seems to leave these unresolved
return null;
}
return rangeA.sliceUp(rangeB);
}
if(rangeB.isFullColumnRange()) {
return rangeB.sliceUp(rangeA);
}
if(rangeB.isFullRowRange()) {
return rangeB.sliceUp(rangeA);
}
return rangeA.sliceUp(rangeB);
}

/**
* @param range never a full row or full column range
* @return an array including <b>this</b> <tt>CellRange</tt> and all parts of <tt>range</tt>
* outside of this range
*/
private CellRange[] sliceUp(CellRange range) {
List temp = new ArrayList();
// Chop up range horizontally and vertically
temp.add(range);
if(!isFullColumnRange()) {
temp = cutHorizontally(_firstRow, temp);
temp = cutHorizontally(_lastRow+1, temp);
}
if(!isFullRowRange()) {
temp = cutVertically(_firstColumn, temp);
temp = cutVertically(_lastColumn+1, temp);
}
CellRange[] crParts = toArray(temp);

// form result array
temp.clear();
temp.add(this);
for (int i = 0; i < crParts.length; i++) {
CellRange crPart = crParts[i];
// only include parts that are not enclosed by this
if(intersect(crPart) != ENCLOSES) {
temp.add(crPart);
}
}
return toArray(temp);
}

private static List cutHorizontally(int cutRow, List input) {
List result = new ArrayList();
CellRange[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRange cr = crs[i];
if(cr._firstRow < cutRow && cutRow < cr._lastRow) {
result.add(new CellRange(cr._firstRow, cutRow, cr._firstColumn, cr._lastColumn));
result.add(new CellRange(cutRow+1, cr._lastRow, cr._firstColumn, cr._lastColumn));
} else {
result.add(cr);
}
}
return result;
}
private static List cutVertically(int cutColumn, List input) {
List result = new ArrayList();
CellRange[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRange cr = crs[i];
if(cr._firstColumn < cutColumn && cutColumn < cr._lastColumn) {
result.add(new CellRange(cr._firstRow, cr._lastRow, cr._firstColumn, cutColumn));
result.add(new CellRange(cr._firstRow, cr._lastRow, cutColumn+1, cr._lastColumn));
} else {
result.add(cr);
}
}
return result;
}


private static CellRange[] toArray(List temp) {
CellRange[] result = new CellRange[temp.size()];
temp.toArray(result);
return result;
}

/**
* Convert array of regions to a List of CellRange objects
*
* @param regions
* @return List of CellRange objects
*/
public static CellRange[] convertRegionsToCellRanges(Region[] regions)
{
CellRange[] result = new CellRange[regions.length];
for( int i=0; i<regions.length; i++)
{
result[i] = new CellRange(regions[i]);
}
return result;
}
/**
* Convert a List of CellRange objects to an array of regions
*
* @param List of CellRange objects
* @return regions
*/
public static Region[] convertCellRangesToRegions(CellRange[] cellRanges)
{
int size = cellRanges.length;
if(size < 1) {
return EMPTY_REGION_ARRAY;
}
Region[] result = new Region[size];

for (int i = 0; i != size; i++)
{
result[i] = cellRanges[i].convertToRegion();
}
return result;
}


private Region convertToRegion() {
int lastRow = convertMaxToM1(_lastRow);
int lastColumn = convertMaxToM1(_lastColumn);
return new Region(_firstRow, (short)_firstColumn, lastRow, (short)lastColumn);
}


/**
* Check if the specified range is located inside of this cell range.
*
@@ -145,44 +421,52 @@ public class CellRange
{
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
short firstCol = range.getFirstColumn();
short lastCol = range.getLastColumn();
return le(this.getFirstRow(), firstRow) && ge(this.getLastRow(), lastRow)
&& le(this.getFirstColumn(), firstCol) && ge(this.getLastColumn(), lastCol);
int firstCol = range.getFirstColumn();
int lastCol = range.getLastColumn();
return le(getFirstRow(), firstRow) && ge(getLastRow(), lastRow)
&& le(getFirstColumn(), firstCol) && ge(getLastColumn(), lastCol);
}
public boolean contains(int row, short column)
{
return le(this.getFirstRow(), row) && ge(this.getLastRow(), row)
&& le(this.getFirstColumn(), column) && ge(this.getLastColumn(), column);
return le(getFirstRow(), row) && ge(getLastRow(), row)
&& le(getFirstColumn(), column) && ge(getLastColumn(), column);
}
/**
* Check if the specified cell range has a shared border with the current range.
*
* @return true if the ranges have a shared border.
*/
public boolean hasSharedBorder(CellRange range)
* Check if the specified cell range has a shared border with the current range.
*
* @return <code>true</code> if the ranges have a complete shared border (i.e.
* the two ranges together make a simple rectangular region.
*/
public boolean hasExactSharedBorder(CellRange range)
{
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
short firstCol = range.getFirstColumn();
short lastCol = range.getLastColumn();
return
(this.getFirstRow()>0 && this.getFirstRow() - 1 == lastRow || firstRow>0 &&this.getLastRow() == firstRow -1)&&
(this.getFirstColumn() == firstCol) &&
(this.getLastColumn() == lastCol) ||
(this.getFirstColumn()>0 && this.getFirstColumn() - 1 == lastCol || firstCol>0 && this.getLastColumn() == firstCol -1) &&
(this.getFirstRow() == firstRow) &&
(this.getLastRow() == lastRow)
;
int oFirstRow = range._firstRow;
int oLastRow = range._lastRow;
int oFirstCol = range._firstColumn;
int oLastCol = range._lastColumn;
if (_firstRow > 0 && _firstRow-1 == oLastRow ||
oFirstRow > 0 && oFirstRow-1 == _lastRow) {
// ranges have a horizontal border in common
// make sure columns are identical:
return _firstColumn == oFirstCol && _lastColumn == oLastCol;
}

if (_firstColumn>0 && _firstColumn - 1 == oLastCol ||
oFirstCol>0 && _lastColumn == oFirstCol -1) {
// ranges have a vertical border in common
// make sure rows are identical:
return _firstRow == oFirstRow && _lastRow == oLastRow;
}
return false;
}
/**
* Create an enclosing CellRange for the two cell ranges.
*
* @return enclosing CellRange
*/
/**
* Create an enclosing CellRange for the two cell ranges.
*
* @return enclosing CellRange
*/
public CellRange createEnclosingCellRange(CellRange range)
{
if( range == null)
@@ -206,18 +490,6 @@ public class CellRange
{
return new CellRange(getFirstRow(),getLastRow(),getFirstColumn(),getLastColumn());
}
/**
* Copy data from antother cell range to this cell range
* @param cr - another cell range
*/
public void setCellRange(CellRange cr)
{
setFirstRow(cr.getFirstRow());
setLastRow(cr.getLastRow());
setFirstColumn(cr.getFirstColumn());
setLastColumn(cr.getLastColumn());
}

/**
* @return true if a < b
@@ -253,7 +525,7 @@ public class CellRange
public String toString()
{
return "("+this.getFirstRow()+","+this.getLastRow()+","+this.getFirstColumn()+","+this.getLastColumn()+")";
return "("+getFirstRow()+","+getLastRow()+","+getFirstColumn()+","+getLastColumn()+")";
}
}

+ 132
- 68
src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java View File

@@ -26,103 +26,167 @@ import org.apache.poi.hssf.record.cf.BorderFormatting;
* @author Dmitriy Kumshayev
*
*/
public class HSSFBorderFormatting
public final class HSSFBorderFormatting
{
/**
* No border
*/
/** No border */
public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;
/** Thin border */
public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
/** Medium border */
public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
/** dash border */
public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
/** dot border */
public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
/** Thick border */
public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
/** double-line border */
public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
/** hair-line border */
public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
/** Medium dashed border */
public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
/** dash-dot border */
public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
/** medium dash-dot border */
public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
/** dash-dot-dot border */
public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
/** medium dash-dot-dot border */
public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
/** slanted dash-dot border */
public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;

public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;

/**
* Thin border
*/

public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;

/**
* Medium border
*/
private final BorderFormatting borderFormatting;
public HSSFBorderFormatting()
{
borderFormatting = new BorderFormatting();
}

public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
protected BorderFormatting getBorderFormattingBlock()
{
return borderFormatting;
}

/**
* dash border
*/
public short getBorderBottom()
{
return borderFormatting.getBorderBottom();
}

public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
public short getBorderDiagonal()
{
return borderFormatting.getBorderDiagonal();
}

/**
* dot border
*/
public short getBorderLeft()
{
return borderFormatting.getBorderLeft();
}

public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
public short getBorderRight()
{
return borderFormatting.getBorderRight();
}

/**
* Thick border
*/
public short getBorderTop()
{
return borderFormatting.getBorderTop();
}

public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
public short getBottomBorderColor()
{
return borderFormatting.getBottomBorderColor();
}

/**
* double-line border
*/
public short getDiagonalBorderColor()
{
return borderFormatting.getDiagonalBorderColor();
}

public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
public short getLeftBorderColor()
{
return borderFormatting.getLeftBorderColor();
}

/**
* hair-line border
*/
public short getRightBorderColor()
{
return borderFormatting.getRightBorderColor();
}

public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
public short getTopBorderColor()
{
return borderFormatting.getTopBorderColor();
}

/**
* Medium dashed border
*/
public boolean isBackwardDiagonalOn()
{
return borderFormatting.isBackwardDiagonalOn();
}

public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
public boolean isForwardDiagonalOn()
{
return borderFormatting.isForwardDiagonalOn();
}

/**
* dash-dot border
*/
public void setBackwardDiagonalOn(boolean on)
{
borderFormatting.setBackwardDiagonalOn(on);
}

public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
public void setBorderBottom(short border)
{
borderFormatting.setBorderBottom(border);
}

/**
* medium dash-dot border
*/
public void setBorderDiagonal(short border)
{
borderFormatting.setBorderDiagonal(border);
}

public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
public void setBorderLeft(short border)
{
borderFormatting.setBorderLeft(border);
}

/**
* dash-dot-dot border
*/
public void setBorderRight(short border)
{
borderFormatting.setBorderRight(border);
}

public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
public void setBorderTop(short border)
{
borderFormatting.setBorderTop(border);
}

/**
* medium dash-dot-dot border
*/
public void setBottomBorderColor(short color)
{
borderFormatting.setBottomBorderColor(color);
}

public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
public void setDiagonalBorderColor(short color)
{
borderFormatting.setDiagonalBorderColor(color);
}

/**
* slanted dash-dot border
*/
public void setForwardDiagonalOn(boolean on)
{
borderFormatting.setForwardDiagonalOn(on);
}

public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
public void setLeftBorderColor(short color)
{
borderFormatting.setLeftBorderColor(color);
}

private BorderFormatting borderFormatting;
public HSSFBorderFormatting()
public void setRightBorderColor(short color)
{
borderFormatting = new BorderFormatting();
borderFormatting.setRightBorderColor(color);
}

protected BorderFormatting getBorderFormattingBlock()
public void setTopBorderColor(short color)
{
return borderFormatting;
borderFormatting.setTopBorderColor(color);
}
}

+ 14
- 147
src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java View File

@@ -16,9 +16,7 @@
==================================================================== */
package org.apache.poi.hssf.usermodel;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
@@ -86,13 +84,9 @@ import org.apache.poi.hssf.util.Region;
*/
public final class HSSFConditionalFormatting
{
private final HSSFSheet sheet;
private final Workbook workbook;
private final CFRecordsAggregate cfAggregate;

HSSFConditionalFormatting(HSSFSheet sheet) {
this(sheet, new CFRecordsAggregate());
}

HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
{
if(sheet == null) {
@@ -101,36 +95,25 @@ public final class HSSFConditionalFormatting
if(cfAggregate == null) {
throw new IllegalArgumentException("cfAggregate must not be null");
}
this.sheet = sheet;
workbook = sheet.workbook.getWorkbook();
this.cfAggregate = cfAggregate;
}
CFRecordsAggregate getCFRecordsAggregate() {
return cfAggregate;
}

public void setFormattingRegions(Region[] regions)
{
if( regions != null)
{
CFHeaderRecord header = cfAggregate.getHeader();
header.setCellRanges(mergeCellRanges(toCellRangeList(regions)));
}
}

/**
* @return array of <tt>Region</tt>s. never <code>null</code>
* @return array of <tt>Region</tt>s. never <code>null</code>
*/
public Region[] getFormattingRegions()
{
CFHeaderRecord cfh = cfAggregate.getHeader();

List cellRanges = cfh.getCellRanges();

return toRegionArray(cellRanges);
CellRange[] cellRanges = cfh.getCellRanges();
return CellRange.convertCellRangesToRegions(cellRanges);
}

/**
* set a Conditional Formatting rule at position idx.
* Replaces an existing Conditional Formatting rule at position idx.
* Excel allows to create up to 3 Conditional Formatting rules.
* This method can be useful to modify existing Conditional Formatting rules.
*
@@ -139,11 +122,7 @@ public final class HSSFConditionalFormatting
*/
public void setRule(int idx, HSSFConditionalFormattingRule cfRule)
{
if (idx < 0 || idx > 2) {
throw new IllegalArgumentException("idx must be between 0 and 2 but was ("
+ idx + ")");
}
cfAggregate.getRules().set(idx, cfRule);
cfAggregate.setRule(idx, cfRule.getCfRuleRecord());
}

/**
@@ -153,136 +132,24 @@ public final class HSSFConditionalFormatting
*/
public void addRule(HSSFConditionalFormattingRule cfRule)
{
cfAggregate.getRules().add(cfRule);
cfAggregate.addRule(cfRule.getCfRuleRecord());
}

/**
* get a Conditional Formatting rule at position idx.
* @param idx
* @return a Conditional Formatting rule at position idx.
* @return the Conditional Formatting rule at position idx.
*/
public HSSFConditionalFormattingRule getRule(int idx)
{
CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx);
return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord);
CFRuleRecord ruleRecord = cfAggregate.getRule(idx);
return new HSSFConditionalFormattingRule(workbook, ruleRecord);
}

/**
* @return number of Conditional Formatting rules.
*/
public int getNumbOfRules()
public int getNumberOfRules()
{
return cfAggregate.getRules().size();
}


/**
* Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
* <li>if two cells have a shared border, merge them into one bigger cell range
* @param cellRangeList
* @return updated List of cell ranges
*/
private static List mergeCellRanges(List cellRangeList)
{
boolean merged = false;

do
{
merged = false;

if( cellRangeList.size()>1 )
{
for( int i=0; i<cellRangeList.size(); i++)
{
CellRange range1 = (CellRange)cellRangeList.get(i);
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRange range2 = (CellRange)cellRangeList.get(j);

switch(range1.intersect(range2))
{
case CellRange.NO_INTERSECTION:
{
if( range1.hasSharedBorder(range2))
{
cellRangeList.set(i, range1.createEnclosingCellRange(range2));
cellRangeList.remove(j--);
merged = true;
}
else
{
// No intersection and no shared border: do nothing
}
break;
}
case CellRange.OVERLAP:
{
// TODO split and re-merge the intersected area
break;
}
case CellRange.INSIDE:
{
// Remove range2, since it is completely inside of range1
cellRangeList.remove(j--);
merged = true;
break;
}
case CellRange.ENCLOSES:
{
// range2 encloses range1, so replace it with the enclosing one
cellRangeList.set(i, range2);
cellRangeList.remove(j--);
merged = true;
break;
}
}
}
}
}
}
while( merged );

return cellRangeList;
}

/**
* Convert a List of CellRange objects to an array of regions
*
* @param List of CellRange objects
* @return regions
*/
private static Region[] toRegionArray(List cellRanges)
{
int size = cellRanges.size();
Region[] regions = new Region[size];

for (int i = 0; i != size; i++)
{
CellRange cr = (CellRange) cellRanges.get(i);
regions[i] = new Region(cr.getFirstRow(), cr.getFirstColumn(),
cr.getLastRow(), cr.getLastColumn());
}
return regions;
}

/**
* Convert array of regions to a List of CellRange objects
*
* @param regions
* @return List of CellRange objects
*/
private static List toCellRangeList(Region[] regions)
{
List cellRangeList = new ArrayList();
for( int i=0; i<regions.length; i++)
{
Region r = regions[i];
CellRange cr = new CellRange(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r
.getColumnTo());
cellRangeList.add(cr);
}
return cellRangeList;
return cfAggregate.getNumberOfRules();
}

public String toString()

+ 52
- 178
src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java View File

@@ -18,231 +18,105 @@
package org.apache.poi.hssf.usermodel;

import java.util.List;
import java.util.Stack;

import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.record.formula.Ptg;

/**
*
* High level representation of Conditional Format
* High level representation of Conditional Formatting Rule.
* It allows to specify formula based conditions for the Conditional Formatting
* and the formatting settings such as font, border and pattern.
*
* @author Dmitriy Kumshayev
*/

public class HSSFConditionalFormattingRule
public final class HSSFConditionalFormattingRule
{
public static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
public static final byte FORMULA = CFRuleRecord.CONDITION_TYPE_FORMULA;
private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;

public static final byte COMPARISON_OPERATOR_NO_COMPARISON = CFRuleRecord.COMPARISON_OPERATOR_NO_COMPARISON;
public static final byte COMPARISON_OPERATOR_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_BETWEEN;
public static final byte COMPARISON_OPERATOR_NOT_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_NOT_BETWEEN;
public static final byte COMPARISON_OPERATOR_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_EQUAL;
public static final byte COMPARISON_OPERATOR_NOT_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_NOT_EQUAL;
public static final byte COMPARISON_OPERATOR_GT = CFRuleRecord.COMPARISON_OPERATOR_GT;
public static final byte COMPARISON_OPERATOR_LT = CFRuleRecord.COMPARISON_OPERATOR_LT;
public static final byte COMPARISON_OPERATOR_GE = CFRuleRecord.COMPARISON_OPERATOR_GE;
public static final byte COMPARISON_OPERATOR_LE = CFRuleRecord.COMPARISON_OPERATOR_LE;

private CFRuleRecord cfRuleRecord;
private HSSFWorkbook workbook;
protected HSSFConditionalFormattingRule(HSSFWorkbook workbook)
{
this.workbook = workbook;
this.cfRuleRecord = new CFRuleRecord();
}

protected HSSFConditionalFormattingRule(HSSFWorkbook workbook, CFRuleRecord cfRuleRecord)
{
this.workbook = workbook;
this.cfRuleRecord = cfRuleRecord;
}
private final CFRuleRecord cfRuleRecord;
private final Workbook workbook;

/**
* Keep Font Formatting unchanged for this Conditional Formatting Rule
*/
public void setFontFormattingUnchanged()
{
cfRuleRecord.setFontFormattingUnchanged();
}
/**
* Keep Border Formatting unchanged for this Conditional Formatting Rule
*/
public void setBorderFormattingUnchanged()
{
cfRuleRecord.setBorderFormattingUnchanged();
HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord) {
workbook = pWorkbook;
cfRuleRecord = pRuleRecord;
}
/**
* Keep Pattern Formatting unchanged for this Conditional Formatting Rule
*/
public void setPatternFormattingUnchanged()
{
cfRuleRecord.setPatternFormattingUnchanged();
HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord,
HSSFFontFormatting fontFmt, HSSFBorderFormatting bordFmt, HSSFPatternFormatting patternFmt) {
this(pWorkbook, pRuleRecord);
setFontFormatting(fontFmt);
setBorderFormatting(bordFmt);
setPatternFormatting(patternFmt);
}
public void setFontFormatting(HSSFFontFormatting fontFormatting)
{
if( fontFormatting!=null )
{
cfRuleRecord.setFontFormatting(fontFormatting.getFontFormattingBlock());
}
else
{
setFontFormattingUnchanged();
}
}
public void setBorderFormatting(HSSFBorderFormatting borderFormatting)

CFRuleRecord getCfRuleRecord()
{
if( borderFormatting != null )
{
cfRuleRecord.setBorderFormatting(borderFormatting.getBorderFormattingBlock());
}
else
{
setBorderFormattingUnchanged();
}
}
public void setPatternFormatting(HSSFPatternFormatting patternFormatting)
{
if( patternFormatting != null)
{
cfRuleRecord.setPatternFormatting(patternFormatting.getPatternFormattingBlock());
}
else
{
setPatternFormattingUnchanged();
}
return cfRuleRecord;
}
public void setCellComparisonCondition(byte comparisonOperation, String formula1, String formula2)
{
cfRuleRecord.setConditionType(CELL_COMPARISON);
cfRuleRecord.setComparisonOperation(comparisonOperation);
// Formula 1
setFormula1(formula1);
// Formula 2
setFormula1(formula2);
}
public void setFormulaCondition(String formula)
/**
* @param fontFmt pass <code>null</code> to signify 'font unchanged'
*/
public void setFontFormatting(HSSFFontFormatting fontFmt)
{
cfRuleRecord.setConditionType(FORMULA);
// Formula 1
setFormula1(formula);
FontFormatting block = fontFmt==null ? null : fontFmt.getFontFormattingBlock();
cfRuleRecord.setFontFormatting(block);
}
public void setFormula1(String formula)
/**
* @param borderFmt pass <code>null</code> to signify 'border unchanged'
*/
public void setBorderFormatting(HSSFBorderFormatting borderFmt)
{
// Formula 1
if( formula != null)
{
Stack parsedExpression = parseFormula(formula);
if( parsedExpression != null )
{
cfRuleRecord.setParsedExpression1(parsedExpression);
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
BorderFormatting block = borderFmt==null ? null : borderFmt.getBorderFormattingBlock();
cfRuleRecord.setBorderFormatting(block);
}
public void setFormula2(String formula)
/**
* @param patternFmt pass <code>null</code> to signify 'pattern unchanged'
*/
public void setPatternFormatting(HSSFPatternFormatting patternFmt)
{
// Formula 2
if( formula != null)
{
Stack parsedExpression = parseFormula(formula);
if( parsedExpression != null )
{
cfRuleRecord.setParsedExpression2(parsedExpression);
}
else
{
cfRuleRecord.setParsedExpression2(null);
}
}
else
{
cfRuleRecord.setParsedExpression2(null);
}
PatternFormatting block = patternFmt==null ? null : patternFmt.getPatternFormattingBlock();
cfRuleRecord.setPatternFormatting(block);
}
public String getFormula1()
{
return toFormulaString(cfRuleRecord.getParsedExpression1());
return toFormulaString(cfRuleRecord.getParsedExpression1());
}

public String getFormula2()
{
byte conditionType = cfRuleRecord.getConditionType();
switch(conditionType)
{
case CELL_COMPARISON:
if (conditionType == CELL_COMPARISON) {
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
switch(comparisonOperation)
{
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
switch(comparisonOperation)
{
case COMPARISON_OPERATOR_BETWEEN:
case COMPARISON_OPERATOR_NOT_BETWEEN:
return toFormulaString(cfRuleRecord.getParsedExpression2());
}
case ComparisonOperator.BETWEEN:
case ComparisonOperator.NOT_BETWEEN:
return toFormulaString(cfRuleRecord.getParsedExpression2());
}
}
return null;
}

private String toFormulaString(List parsedExpression)
private String toFormulaString(Ptg[] parsedExpression)
{
String formula = null;
if(parsedExpression!=null)
{
formula = FormulaParser.toFormulaString(workbook.getWorkbook(),parsedExpression);
formula = FormulaParser.toFormulaString(workbook, parsedExpression);
}
return formula;
}

private Stack parseFormula(String formula2)
{
FormulaParser parser =
new FormulaParser(formula2, workbook.getWorkbook());
parser.parse();

Stack parsedExpression = convertToTokenStack(parser.getRPNPtg());
parsedExpression = convertToTokenStack(parser.getRPNPtg());
return parsedExpression;
}

private static Stack convertToTokenStack(Ptg[] ptgs)
{
if( ptgs != null)
{
Stack parsedExpression = new Stack();
// fill the Ptg Stack with Ptgs of new formula
for (int k = 0; k < ptgs.length; k++)
{
parsedExpression.push(ptgs[ k ]);
}
return parsedExpression;
}
else
{
return null;
}
}
}

+ 57
- 80
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java View File

@@ -1090,8 +1090,8 @@ public final class HSSFSheet {
* @param leftcol the left column to show in desktop window pane
*/
public void showInPane(short toprow, short leftcol){
this.sheet.setTopRow((short)toprow);
this.sheet.setLeftCol((short)leftcol);
this.sheet.setTopRow(toprow);
this.sheet.setLeftCol(leftcol);
}

/**
@@ -1438,7 +1438,7 @@ public final class HSSFSheet {
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = (int)breakItem.main;
returnValue[i++] = breakItem.main;
}
return returnValue;
}
@@ -1806,7 +1806,7 @@ public final class HSSFSheet {
*
* @return cell comment or <code>null</code> if not found
*/
public HSSFComment getCellComment(int row, int column){
public HSSFComment getCellComment(int row, int column) {
// Don't call findCellComment directly, otherwise
// two calls to this method will result in two
// new HSSFComment instances, which is bad
@@ -1830,25 +1830,26 @@ public final class HSSFSheet {
* with a cell comparison operator and
* formatting rules such as font format, border format and pattern format
*
* @param comparisonOperation - one of the following values: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* @param comparisonOperation - a constant value from
* <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
* <ul>
* <li>BETWEEN</li>
* <li>NOT_BETWEEN</li>
* <li>EQUAL</li>
* <li>NOT_EQUAL</li>
* <li>GT</li>
* <li>LT</li>
* <li>GE</li>
* <li>LE</li>
* </ul>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules
* @param bordFmt - border formatting rules
* @param patternFmt - pattern formatting rules
* @return
*
* @param fontFmt - font formatting rules (may be <code>null</code>)
* @param bordFmt - border formatting rules (may be <code>null</code>)
* @param patternFmt - pattern formatting rules (may be <code>null</code>)
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation,
@@ -1856,14 +1857,11 @@ public final class HSSFSheet {
String formula2,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
{
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
return cf;
HSSFPatternFormatting patternFmt) {
Workbook wb = workbook.getWorkbook();
CFRuleRecord rr = CFRuleRecord.create(wb, comparisonOperation, formula1, formula2);
return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
}

/**
@@ -1872,38 +1870,19 @@ public final class HSSFSheet {
*
* The formatting rules are applied by Excel when the value of the formula not equal to 0.
*
* @param comparisonOperation - one of the following values: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules
* @param bordFmt - border formatting rules
* @param patternFmt - pattern formatting rules
* @return
*
* @param formula - formula for the valued, compared with the cell
* @param fontFmt - font formatting rules (may be <code>null</code>)
* @param bordFmt - border formatting rules (may be <code>null</code>)
* @param patternFmt - pattern formatting rules (may be <code>null</code>)
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
String formula,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt)
{
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
cf.setFontFormatting(fontFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setFormulaCondition(formula);
return cf;
HSSFPatternFormatting patternFmt) {
Workbook wb = workbook.getWorkbook();
CFRuleRecord rr = CFRuleRecord.create(wb, formula);
return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
}

/**
@@ -1918,8 +1897,7 @@ public final class HSSFSheet {
* @param cf HSSFConditionalFormatting object
* @return index of the new Conditional Formatting object
*/
public int addConditionalFormatting( HSSFConditionalFormatting cf )
{
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();

return sheet.addConditionalFormatting(cfraClone);
@@ -1929,46 +1907,46 @@ public final class HSSFSheet {
* Allows to add a new Conditional Formatting set to the sheet.
*
* @param regions - list of rectangular regions to apply conditional formatting rules
* @param cfRules - set of up to three conditional formatting rules
* @param hcfRules - set of up to three conditional formatting rules
*
* @return index of the newly created Conditional Formatting object
*/

public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules )
{
HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
cf.setFormattingRegions(regions);
if( cfRules != null )
{
for( int i=0; i!= cfRules.length; i++ )
{
cf.addRule(cfRules[i]);
}
}
return sheet.addConditionalFormatting(cf.getCFRecordsAggregate());
public int addConditionalFormatting(Region [] regions, HSSFConditionalFormattingRule [] hcfRules) {
if (regions == null) {
throw new IllegalArgumentException("regions must not be null");
}
if (hcfRules == null) {
throw new IllegalArgumentException("hcfRules must not be null");
}

CFRuleRecord[] rules = new CFRuleRecord[hcfRules.length];
for (int i = 0; i != hcfRules.length; i++) {
rules[i] = hcfRules[i].getCfRuleRecord();
}
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
return sheet.addConditionalFormatting(cfra);
}

/**
* gets Conditional Formatting object at a particular index
* @param index of the Conditional Formatting object to fetch
*
* @param index
* of the Conditional Formatting object to fetch
* @return Conditional Formatting object
*/

public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null )
{
return new HSSFConditionalFormatting(this,cf);
if (cf == null) {
return null;
}
return null;
return new HSSFConditionalFormatting(this,cf);
}

/**
* @return number of Conditional Formatting objects of the sheet
*/
public int getNumConditionalFormattings()
{
public int getNumConditionalFormattings() {
return sheet.getNumConditionalFormattings();
}

@@ -1976,8 +1954,7 @@ public final class HSSFSheet {
* removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove
*/
public void removeConditionalFormatting(int index)
{
public void removeConditionalFormatting(int index) {
sheet.removeConditionalFormatting(index);
}
}

+ 4
- 0
src/testcases/org/apache/poi/hssf/record/AllRecordTests.java View File

@@ -17,6 +17,7 @@

package org.apache.poi.hssf.record;

import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
import org.apache.poi.hssf.record.formula.AllFormulaTests;

import junit.framework.Test;
@@ -33,6 +34,7 @@ public final class AllRecordTests {
TestSuite result = new TestSuite(AllRecordTests.class.getName());

result.addTest(AllFormulaTests.suite());
result.addTest(AllRecordAggregateTests.suite());
result.addTestSuite(TestAreaFormatRecord.class);
result.addTestSuite(TestAreaRecord.class);
@@ -45,6 +47,8 @@ public final class AllRecordTests {
result.addTestSuite(TestBarRecord.class);
result.addTestSuite(TestBoundSheetRecord.class);
result.addTestSuite(TestCategorySeriesAxisRecord.class);
result.addTestSuite(TestCFHeaderRecord.class);
result.addTestSuite(TestCFRuleRecord.class);
result.addTestSuite(TestChartRecord.class);
result.addTestSuite(TestChartTitleFormatRecord.class);
result.addTestSuite(TestCommonObjectDataSubRecord.class);

+ 97
- 102
src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java View File

@@ -17,9 +17,6 @@

package org.apache.poi.hssf.record;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.apache.poi.hssf.record.cf.CellRange;
@@ -30,116 +27,114 @@ import org.apache.poi.hssf.record.cf.CellRange;
*
* @author Dmitriy Kumshayev
*/
public class TestCFHeaderRecord
extends TestCase
public final class TestCFHeaderRecord extends TestCase
{

public TestCFHeaderRecord(String name)
{
super(name);
}
public void testCreateCFHeaderRecord ()
{
CFHeaderRecord record = new CFHeaderRecord();
CellRange[] ranges = {
new CellRange(0,-1,5,5),
new CellRange(0,-1,6,6),
new CellRange(0,1,0,1),
new CellRange(0,1,2,3),
new CellRange(2,3,0,1),
new CellRange(2,3,2,3),
};
record.setCellRanges(ranges);
ranges = record.getCellRanges();
assertEquals(6,ranges.length);
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(-1, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(6, enclosingCellRange.getLastColumn());
record.setNeedRecalculation(true);
assertTrue(record.getNeedRecalculation());
record.setNeedRecalculation(false);
assertFalse(record.getNeedRecalculation());
}
public void testSerialization() {
byte[] recordData = new byte[]
{
(byte)0x03, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x04, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
};

CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));

assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
assertTrue(record.getNeedRecalculation());
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(3, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(3, enclosingCellRange.getLastColumn());
CellRange[] ranges = record.getCellRanges();
CellRange range0 = ranges[0];
assertEquals(0, range0.getFirstRow());
assertEquals(1, range0.getLastRow());
assertEquals(0, range0.getFirstColumn());
assertEquals(1, range0.getLastColumn());
CellRange range1 = ranges[1];
assertEquals(0, range1.getFirstRow());
assertEquals(1, range1.getLastRow());
assertEquals(2, range1.getFirstColumn());
assertEquals(3, range1.getLastColumn());
CellRange range2 = ranges[2];
assertEquals(2, range2.getFirstRow());
assertEquals(3, range2.getLastRow());
assertEquals(0, range2.getFirstColumn());
assertEquals(1, range2.getLastColumn());
CellRange range3 = ranges[3];
assertEquals(2, range3.getFirstRow());
assertEquals(3, range3.getLastRow());
assertEquals(2, range3.getFirstColumn());
assertEquals(3, range3.getLastColumn());
assertEquals(recordData.length+4, record.getRecordSize());

public void testCreateCFHeaderRecord ()
{
CFHeaderRecord record = new CFHeaderRecord();
List ranges = new ArrayList();
ranges.add(new CellRange(0,-1,(short)5,(short)5));
ranges.add(new CellRange(0,-1,(short)6,(short)6));
ranges.add(new CellRange(0,1,(short)0,(short)1));
ranges.add(new CellRange(0,1,(short)2,(short)3));
ranges.add(new CellRange(2,3,(short)0,(short)1));
ranges.add(new CellRange(2,3,(short)2,(short)3));
record.setCellRanges(ranges);
ranges = record.getCellRanges();
assertEquals(6,ranges.size());
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(-1, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(6, enclosingCellRange.getLastColumn());
record.setNeedRecalculation(true);
assertTrue(record.getNeedRecalculation());
record.setNeedRecalculation(false);
assertFalse(record.getNeedRecalculation());
}
public void testSerialization() {
byte[] recordData = new byte[]
{
(byte)0x03, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x04, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x03, (byte)0x00,
};
CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
assertTrue(record.getNeedRecalculation());
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(3, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(3, enclosingCellRange.getLastColumn());
List ranges = record.getCellRanges();
assertEquals(0, ((CellRange)ranges.get(0)).getFirstRow());
assertEquals(1, ((CellRange)ranges.get(0)).getLastRow());
assertEquals(0, ((CellRange)ranges.get(0)).getFirstColumn());
assertEquals(1, ((CellRange)ranges.get(0)).getLastColumn());
assertEquals(0, ((CellRange)ranges.get(1)).getFirstRow());
assertEquals(1, ((CellRange)ranges.get(1)).getLastRow());
assertEquals(2, ((CellRange)ranges.get(1)).getFirstColumn());
assertEquals(3, ((CellRange)ranges.get(1)).getLastColumn());
assertEquals(2, ((CellRange)ranges.get(2)).getFirstRow());
assertEquals(3, ((CellRange)ranges.get(2)).getLastRow());
assertEquals(0, ((CellRange)ranges.get(2)).getFirstColumn());
assertEquals(1, ((CellRange)ranges.get(2)).getLastColumn());
assertEquals(2, ((CellRange)ranges.get(3)).getFirstRow());
assertEquals(3, ((CellRange)ranges.get(3)).getLastRow());
assertEquals(2, ((CellRange)ranges.get(3)).getFirstColumn());
assertEquals(3, ((CellRange)ranges.get(3)).getLastColumn());
assertEquals(recordData.length+4, record.getRecordSize());
byte[] output = record.serialize();

assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength

for (int i = 0; i < recordData.length;i++)
{
assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
}
}
public static void main(String[] ignored_args)
}

public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class);
}
}

+ 207
- 192
src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java View File

@@ -19,109 +19,107 @@ package org.apache.poi.hssf.record;

import junit.framework.TestCase;

import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.LittleEndian;

/**
* Tests the serialization and deserialization of the TestCFRuleRecord
* class works correctly.
* class works correctly.
*
* @author Dmitriy Kumshayev
*/
public class TestCFRuleRecord
extends TestCase
public final class TestCFRuleRecord extends TestCase
{

public TestCFRuleRecord(String name)
{
super(name);
}

public void testCreateCFRuleRecord ()
{
CFRuleRecord record = new CFRuleRecord();
testCFRuleRecord(record);
// Serialize
byte [] serializedRecord = record.serialize();

// Strip header
byte [] recordData = new byte[serializedRecord.length-4];
System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);
// Deserialize
record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));
// Serialize again
public void testCreateCFRuleRecord ()
{
Workbook workbook = Workbook.createWorkbook();
CFRuleRecord record = CFRuleRecord.create(workbook, "7");
testCFRuleRecord(record);

// Serialize
byte [] serializedRecord = record.serialize();

// Strip header
byte [] recordData = new byte[serializedRecord.length-4];
System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);

// Deserialize
record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));

// Serialize again
byte[] output = record.serialize();

// Compare
assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
for (int i = 0; i < recordData.length;i++)
{
assertEquals("CFRuleRecord doesn't match", recordData[i], output[i+4]);
}
}
}

private void testCFRuleRecord(CFRuleRecord record)
{
FontFormatting fontFormatting = new FontFormatting();
testFontFormattingAccessors(fontFormatting);
assertFalse(record.containsFontFormattingBlock());
record.setFontFormatting(fontFormatting);
assertTrue(record.containsFontFormattingBlock());
BorderFormatting borderFormatting = new BorderFormatting();
testBorderFormattingAccessors(borderFormatting);
assertFalse(record.containsBorderFormattingBlock());
record.setBorderFormatting(borderFormatting);
assertTrue(record.containsBorderFormattingBlock());
assertFalse(record.isLeftBorderModified());
record.setLeftBorderModified(true);
assertTrue(record.isLeftBorderModified());
assertFalse(record.isRightBorderModified());
record.setRightBorderModified(true);
assertTrue(record.isRightBorderModified());
assertFalse(record.isTopBorderModified());
record.setTopBorderModified(true);
assertTrue(record.isTopBorderModified());
assertFalse(record.isBottomBorderModified());
record.setBottomBorderModified(true);
assertTrue(record.isBottomBorderModified());
assertFalse(record.isTopLeftBottomRightBorderModified());
record.setTopLeftBottomRightBorderModified(true);
assertTrue(record.isTopLeftBottomRightBorderModified());
assertFalse(record.isBottomLeftTopRightBorderModified());
record.setBottomLeftTopRightBorderModified(true);
assertTrue(record.isBottomLeftTopRightBorderModified());
PatternFormatting patternFormatting = new PatternFormatting();
testPatternFormattingAccessors(patternFormatting);
assertFalse(record.containsPatternFormattingBlock());
record.setPatternFormatting(patternFormatting);
assertTrue(record.containsPatternFormattingBlock());
assertFalse(record.isPatternBackgroundColorModified());
record.setPatternBackgroundColorModified(true);
assertTrue(record.isPatternBackgroundColorModified());
assertFalse(record.isPatternColorModified());
record.setPatternColorModified(true);
assertTrue(record.isPatternColorModified());
assertFalse(record.isPatternStyleModified());
record.setPatternStyleModified(true);
assertTrue(record.isPatternStyleModified());
testFontFormattingAccessors(fontFormatting);
assertFalse(record.containsFontFormattingBlock());
record.setFontFormatting(fontFormatting);
assertTrue(record.containsFontFormattingBlock());
BorderFormatting borderFormatting = new BorderFormatting();
testBorderFormattingAccessors(borderFormatting);
assertFalse(record.containsBorderFormattingBlock());
record.setBorderFormatting(borderFormatting);
assertTrue(record.containsBorderFormattingBlock());
assertFalse(record.isLeftBorderModified());
record.setLeftBorderModified(true);
assertTrue(record.isLeftBorderModified());
assertFalse(record.isRightBorderModified());
record.setRightBorderModified(true);
assertTrue(record.isRightBorderModified());
assertFalse(record.isTopBorderModified());
record.setTopBorderModified(true);
assertTrue(record.isTopBorderModified());
assertFalse(record.isBottomBorderModified());
record.setBottomBorderModified(true);
assertTrue(record.isBottomBorderModified());
assertFalse(record.isTopLeftBottomRightBorderModified());
record.setTopLeftBottomRightBorderModified(true);
assertTrue(record.isTopLeftBottomRightBorderModified());
assertFalse(record.isBottomLeftTopRightBorderModified());
record.setBottomLeftTopRightBorderModified(true);
assertTrue(record.isBottomLeftTopRightBorderModified());
PatternFormatting patternFormatting = new PatternFormatting();
testPatternFormattingAccessors(patternFormatting);
assertFalse(record.containsPatternFormattingBlock());
record.setPatternFormatting(patternFormatting);
assertTrue(record.containsPatternFormattingBlock());
assertFalse(record.isPatternBackgroundColorModified());
record.setPatternBackgroundColorModified(true);
assertTrue(record.isPatternBackgroundColorModified());
assertFalse(record.isPatternColorModified());
record.setPatternColorModified(true);
assertTrue(record.isPatternColorModified());
assertFalse(record.isPatternStyleModified());
record.setPatternStyleModified(true);
assertTrue(record.isPatternStyleModified());
}

private void testPatternFormattingAccessors(PatternFormatting patternFormatting)
@@ -131,10 +129,9 @@ public class TestCFRuleRecord

patternFormatting.setFillForegroundColor(HSSFColor.INDIGO.index);
assertEquals(HSSFColor.INDIGO.index,patternFormatting.getFillForegroundColor());
patternFormatting.setFillPattern(PatternFormatting.DIAMONDS);
assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern());
}
private void testBorderFormattingAccessors(BorderFormatting borderFormatting)
@@ -143,13 +140,13 @@ public class TestCFRuleRecord
assertFalse(borderFormatting.isBackwardDiagonalOn());
borderFormatting.setBackwardDiagonalOn(true);
assertTrue(borderFormatting.isBackwardDiagonalOn());
borderFormatting.setBorderBottom(BorderFormatting.BORDER_DOTTED);
assertEquals(BorderFormatting.BORDER_DOTTED, borderFormatting.getBorderBottom());
borderFormatting.setBorderDiagonal(BorderFormatting.BORDER_MEDIUM);
assertEquals(BorderFormatting.BORDER_MEDIUM, borderFormatting.getBorderDiagonal());
borderFormatting.setBorderLeft(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT);
assertEquals(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT, borderFormatting.getBorderLeft());

@@ -178,119 +175,137 @@ public class TestCFRuleRecord
borderFormatting.setTopBorderColor(HSSFColor.GOLD.index);
assertEquals(HSSFColor.GOLD.index, borderFormatting.getTopBorderColor());
}
private void testFontFormattingAccessors(FontFormatting fontFormatting)
{
// Check for defaults
assertFalse(fontFormatting.isEscapementTypeModified());
assertFalse(fontFormatting.isFontCancellationModified());
assertFalse(fontFormatting.isFontCondenseModified());
assertFalse(fontFormatting.isFontOutlineModified());
assertFalse(fontFormatting.isFontShadowModified());
assertFalse(fontFormatting.isFontStyleModified());
assertFalse(fontFormatting.isUnderlineTypeModified());
assertFalse(fontFormatting.isBold());
assertFalse(fontFormatting.isCondenseOn());
assertFalse(fontFormatting.isItalic());
assertFalse(fontFormatting.isOutlineOn());
assertFalse(fontFormatting.isShadowOn());
assertFalse(fontFormatting.isStruckout());
assertEquals(0, fontFormatting.getEscapementType());
assertEquals(-1, fontFormatting.getFontColorIndex());
assertEquals(-1, fontFormatting.getFontHeight());
assertEquals(400, fontFormatting.getFontWeight());
assertEquals(0, fontFormatting.getUnderlineType());
fontFormatting.setBold(true);
assertTrue(fontFormatting.isBold());
fontFormatting.setBold(false);
assertFalse(fontFormatting.isBold());
fontFormatting.setCondense(true);
assertTrue(fontFormatting.isCondenseOn());
fontFormatting.setCondense(false);
assertFalse(fontFormatting.isCondenseOn());
fontFormatting.setEscapementType(FontFormatting.SS_SUB);
assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType());
fontFormatting.setEscapementType(FontFormatting.SS_SUPER);
assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType());
fontFormatting.setEscapementType(FontFormatting.SS_NONE);
assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType());
fontFormatting.setEscapementTypeModified(false);
assertFalse(fontFormatting.isEscapementTypeModified());
fontFormatting.setEscapementTypeModified(true);
assertTrue(fontFormatting.isEscapementTypeModified());
fontFormatting.setFontCancellationModified(false);
assertFalse(fontFormatting.isFontCancellationModified());
fontFormatting.setFontCancellationModified(true);
assertTrue(fontFormatting.isFontCancellationModified());
fontFormatting.setFontColorIndex((short)10);
assertEquals(10,fontFormatting.getFontColorIndex());
fontFormatting.setFontCondenseModified(false);
assertFalse(fontFormatting.isFontCondenseModified());
fontFormatting.setFontCondenseModified(true);
assertTrue(fontFormatting.isFontCondenseModified());
fontFormatting.setFontHeight((short)100);
assertEquals(100,fontFormatting.getFontHeight());
fontFormatting.setFontOutlineModified(false);
assertFalse(fontFormatting.isFontOutlineModified());
fontFormatting.setFontOutlineModified(true);
assertTrue(fontFormatting.isFontOutlineModified());
fontFormatting.setFontShadowModified(false);
assertFalse(fontFormatting.isFontShadowModified());
fontFormatting.setFontShadowModified(true);
assertTrue(fontFormatting.isFontShadowModified());
fontFormatting.setFontStyleModified(false);
assertFalse(fontFormatting.isFontStyleModified());
fontFormatting.setFontStyleModified(true);
assertTrue(fontFormatting.isFontStyleModified());
fontFormatting.setItalic(false);
assertFalse(fontFormatting.isItalic());
fontFormatting.setItalic(true);
assertTrue(fontFormatting.isItalic());
fontFormatting.setOutline(false);
assertFalse(fontFormatting.isOutlineOn());
fontFormatting.setOutline(true);
assertTrue(fontFormatting.isOutlineOn());
fontFormatting.setShadow(false);
assertFalse(fontFormatting.isShadowOn());
fontFormatting.setShadow(true);
assertTrue(fontFormatting.isShadowOn());
fontFormatting.setStrikeout(false);
assertFalse(fontFormatting.isStruckout());
fontFormatting.setStrikeout(true);
assertTrue(fontFormatting.isStruckout());
fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING);
assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType());
fontFormatting.setUnderlineTypeModified(false);
assertFalse(fontFormatting.isUnderlineTypeModified());
fontFormatting.setUnderlineTypeModified(true);
assertTrue(fontFormatting.isUnderlineTypeModified());
assertFalse(fontFormatting.isEscapementTypeModified());
assertFalse(fontFormatting.isFontCancellationModified());
assertFalse(fontFormatting.isFontCondenseModified());
assertFalse(fontFormatting.isFontOutlineModified());
assertFalse(fontFormatting.isFontShadowModified());
assertFalse(fontFormatting.isFontStyleModified());
assertFalse(fontFormatting.isUnderlineTypeModified());
assertFalse(fontFormatting.isBold());
assertFalse(fontFormatting.isCondenseOn());
assertFalse(fontFormatting.isItalic());
assertFalse(fontFormatting.isOutlineOn());
assertFalse(fontFormatting.isShadowOn());
assertFalse(fontFormatting.isStruckout());
assertEquals(0, fontFormatting.getEscapementType());
assertEquals(-1, fontFormatting.getFontColorIndex());
assertEquals(-1, fontFormatting.getFontHeight());
assertEquals(400, fontFormatting.getFontWeight());
assertEquals(0, fontFormatting.getUnderlineType());
fontFormatting.setBold(true);
assertTrue(fontFormatting.isBold());
fontFormatting.setBold(false);
assertFalse(fontFormatting.isBold());
fontFormatting.setCondense(true);
assertTrue(fontFormatting.isCondenseOn());
fontFormatting.setCondense(false);
assertFalse(fontFormatting.isCondenseOn());
fontFormatting.setEscapementType(FontFormatting.SS_SUB);
assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType());
fontFormatting.setEscapementType(FontFormatting.SS_SUPER);
assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType());
fontFormatting.setEscapementType(FontFormatting.SS_NONE);
assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType());
fontFormatting.setEscapementTypeModified(false);
assertFalse(fontFormatting.isEscapementTypeModified());
fontFormatting.setEscapementTypeModified(true);
assertTrue(fontFormatting.isEscapementTypeModified());
fontFormatting.setFontCancellationModified(false);
assertFalse(fontFormatting.isFontCancellationModified());
fontFormatting.setFontCancellationModified(true);
assertTrue(fontFormatting.isFontCancellationModified());
fontFormatting.setFontColorIndex((short)10);
assertEquals(10,fontFormatting.getFontColorIndex());
fontFormatting.setFontCondenseModified(false);
assertFalse(fontFormatting.isFontCondenseModified());
fontFormatting.setFontCondenseModified(true);
assertTrue(fontFormatting.isFontCondenseModified());
fontFormatting.setFontHeight((short)100);
assertEquals(100,fontFormatting.getFontHeight());
fontFormatting.setFontOutlineModified(false);
assertFalse(fontFormatting.isFontOutlineModified());
fontFormatting.setFontOutlineModified(true);
assertTrue(fontFormatting.isFontOutlineModified());
fontFormatting.setFontShadowModified(false);
assertFalse(fontFormatting.isFontShadowModified());
fontFormatting.setFontShadowModified(true);
assertTrue(fontFormatting.isFontShadowModified());
fontFormatting.setFontStyleModified(false);
assertFalse(fontFormatting.isFontStyleModified());
fontFormatting.setFontStyleModified(true);
assertTrue(fontFormatting.isFontStyleModified());
fontFormatting.setItalic(false);
assertFalse(fontFormatting.isItalic());
fontFormatting.setItalic(true);
assertTrue(fontFormatting.isItalic());
fontFormatting.setOutline(false);
assertFalse(fontFormatting.isOutlineOn());
fontFormatting.setOutline(true);
assertTrue(fontFormatting.isOutlineOn());
fontFormatting.setShadow(false);
assertFalse(fontFormatting.isShadowOn());
fontFormatting.setShadow(true);
assertTrue(fontFormatting.isShadowOn());
fontFormatting.setStrikeout(false);
assertFalse(fontFormatting.isStruckout());
fontFormatting.setStrikeout(true);
assertTrue(fontFormatting.isStruckout());
fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING);
assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType());
fontFormatting.setUnderlineTypeModified(false);
assertFalse(fontFormatting.isUnderlineTypeModified());
fontFormatting.setUnderlineTypeModified(true);
assertTrue(fontFormatting.isUnderlineTypeModified());
}
public static void main(String[] ignored_args)

public void testWrite() {
Workbook workbook = Workbook.createWorkbook();
CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10");

PatternFormatting patternFormatting = new PatternFormatting();
patternFormatting.setFillPattern(PatternFormatting.BRICKS);
rr.setPatternFormatting(patternFormatting);

byte[] data = rr.serialize();
assertEquals(26, data.length);
assertEquals(3, LittleEndian.getShort(data, 6));
assertEquals(3, LittleEndian.getShort(data, 8));

int flags = LittleEndian.getInt(data, 10);
assertEquals("unused flags should be 111", 0x00380000, flags & 0x00380000);
assertEquals("undocumented flags should be 0000", 0, flags & 0x03C00000); // Otherwise Excel gets unhappy
assertEquals(0xA03FFFFF, flags);
}


public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord");
junit.textui.TestRunner.run(TestCFRuleRecord.class);
}
}

+ 40
- 0
src/testcases/org/apache/poi/hssf/record/aggregates/AllRecordAggregateTests.java View File

@@ -0,0 +1,40 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.aggregates;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Collects all tests for package <tt>org.apache.poi.hssf.record.aggregates</tt>.
*
* @author Josh Micich
*/
public final class AllRecordAggregateTests {
public static Test suite() {
TestSuite result = new TestSuite(AllRecordAggregateTests.class.getName());
result.addTestSuite(TestCFRecordsAggregate.class);
result.addTestSuite(TestColumnInfoRecordsAggregate.class);
result.addTestSuite(TestFormulaRecordAggregate.class);
result.addTestSuite(TestRowRecordsAggregate.class);
result.addTestSuite(TestValueRecordsAggregate.class);
return result;
}
}

+ 63
- 67
src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java View File

@@ -24,9 +24,11 @@ import java.util.List;

import junit.framework.TestCase;

import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.CellRange;

/**
@@ -35,77 +37,71 @@ import org.apache.poi.hssf.record.cf.CellRange;
*
* @author Dmitriy Kumshayev
*/
public class TestCFRecordsAggregate
extends TestCase
public final class TestCFRecordsAggregate extends TestCase
{

public TestCFRecordsAggregate(String name)
{
super(name);
}

public void testCFRecordsAggregate()
{
CFRecordsAggregate record = new CFRecordsAggregate();
List recs = new ArrayList();
CFHeaderRecord header = new CFHeaderRecord();
CFRuleRecord rule1 = new CFRuleRecord();
CFRuleRecord rule2 = new CFRuleRecord();
CFRuleRecord rule3 = new CFRuleRecord();
header.setNumberOfConditionalFormats(3);
CellRange range1 = new CellRange(0,1,(short)0,(short)0);
CellRange range2 = new CellRange(0,1,(short)2,(short)2);
List cellRanges = new ArrayList();
cellRanges.add(range1);
cellRanges.add(range2);
header.setCellRanges(cellRanges);
recs.add(header);
recs.add(rule1);
recs.add(rule2);
recs.add(rule3);
record = CFRecordsAggregate.createCFAggregate(recs, 0);
// Serialize
byte [] serializedRecord = record.serialize();
InputStream in = new ByteArrayInputStream(serializedRecord);
//Parse
recs = RecordFactory.createRecords(in);
// Verify
assertNotNull(recs);
assertEquals(4, recs.size());
header = (CFHeaderRecord)recs.get(0);
rule1 = (CFRuleRecord)recs.get(1);
rule2 = (CFRuleRecord)recs.get(2);
rule3 = (CFRuleRecord)recs.get(3);
cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size());
assertEquals(3, header.getNumberOfConditionalFormats());
record = CFRecordsAggregate.createCFAggregate(recs, 0);
record = record.cloneCFAggregate();
assertNotNull(record.getHeader());
assertEquals(3,record.getRules().size());
header = record.getHeader();
rule1 = (CFRuleRecord)record.getRules().get(0);
rule2 = (CFRuleRecord)record.getRules().get(1);
rule3 = (CFRuleRecord)record.getRules().get(2);
cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size());
assertEquals(3, header.getNumberOfConditionalFormats());
}

public static void main(String[] ignored_args)
public void testCFRecordsAggregate()
{
Workbook workbook = Workbook.createWorkbook();
List recs = new ArrayList();
CFHeaderRecord header = new CFHeaderRecord();
CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.GE, "100", null);
header.setNumberOfConditionalFormats(3);
CellRange[] cellRanges = {
new CellRange(0,1,0,0),
new CellRange(0,1,2,2),
};
header.setCellRanges(cellRanges);
recs.add(header);
recs.add(rule1);
recs.add(rule2);
recs.add(rule3);
CFRecordsAggregate record;
record = CFRecordsAggregate.createCFAggregate(recs, 0);

// Serialize
byte [] serializedRecord = record.serialize();
InputStream in = new ByteArrayInputStream(serializedRecord);

//Parse
recs = RecordFactory.createRecords(in);

// Verify
assertNotNull(recs);
assertEquals(4, recs.size());

header = (CFHeaderRecord)recs.get(0);
rule1 = (CFRuleRecord)recs.get(1);
rule2 = (CFRuleRecord)recs.get(2);
rule3 = (CFRuleRecord)recs.get(3);
cellRanges = header.getCellRanges();

assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats());

record = CFRecordsAggregate.createCFAggregate(recs, 0);

record = record.cloneCFAggregate();

assertNotNull(record.getHeader());
assertEquals(3,record.getNumberOfRules());

header = record.getHeader();
rule1 = record.getRule(0);
rule2 = record.getRule(1);
rule3 = record.getRule(2);
cellRanges = header.getCellRanges();

assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats());
}

public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.aggregates.CFRecordsAggregate");
junit.textui.TestRunner.run(TestCFRecordsAggregate.class);
}
}

+ 52
- 53
src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java View File

@@ -24,13 +24,13 @@ import junit.framework.TestCase;
*/
public class TestCellRange extends TestCase
{
private static final CellRange biggest = new CellRange(0, -1,(short) 0,(short)-1);
private static final CellRange tenthColumn = new CellRange(0, -1,(short)10,(short)10);
private static final CellRange tenthRow = new CellRange(10,10,(short) 0,(short)-1);
private static final CellRange box10x10 = new CellRange(0, 10,(short) 0,(short)10);
private static final CellRange box9x9 = new CellRange(0, 9,(short) 0,(short) 9);
private static final CellRange box10to20c = new CellRange(0, 10,(short)10,(short)20);
private static final CellRange oneCell = new CellRange(10,10,(short)10,(short)10);
private static final CellRange biggest = new CellRange( 0, -1, 0,-1);
private static final CellRange tenthColumn = new CellRange( 0, -1,10,10);
private static final CellRange tenthRow = new CellRange(10, 10, 0,-1);
private static final CellRange box10x10 = new CellRange( 0, 10, 0,10);
private static final CellRange box9x9 = new CellRange( 0, 9, 0, 9);
private static final CellRange box10to20c = new CellRange( 0, 10,10,20);
private static final CellRange oneCell = new CellRange(10, 10,10,10);

boolean [][] contanis = new boolean[][]
{
@@ -61,62 +61,62 @@ public class TestCellRange extends TestCase
}
}
}
private static final CellRange col1 = new CellRange(0, -1,(short) 1,(short)1);
private static final CellRange col2 = new CellRange(0, -1,(short) 2,(short)2);
private static final CellRange row1 = new CellRange(1, 1,(short) 0,(short)-1);
private static final CellRange row2 = new CellRange(2, 2,(short) 0,(short)-1);

private static final CellRange box0 = new CellRange( 0, 2,(short) 0,(short)2);
private static final CellRange box1 = new CellRange( 0, 1,(short) 0,(short)1);
private static final CellRange box2 = new CellRange( 0, 1,(short) 2,(short)3);
private static final CellRange box3 = new CellRange( 2, 3,(short) 0,(short)1);
private static final CellRange box4 = new CellRange( 2, 3,(short) 2,(short)3);
private static final CellRange box5 = new CellRange( 1, 3,(short) 1,(short)3);
private static final CellRange col1 = new CellRange( 0, -1, 1,1);
private static final CellRange col2 = new CellRange( 0, -1, 2,2);
private static final CellRange row1 = new CellRange( 1, 1, 0,-1);
private static final CellRange row2 = new CellRange( 2, 2, 0,-1);

private static final CellRange box0 = new CellRange( 0, 2, 0,2);
private static final CellRange box1 = new CellRange( 0, 1, 0,1);
private static final CellRange box2 = new CellRange( 0, 1, 2,3);
private static final CellRange box3 = new CellRange( 2, 3, 0,1);
private static final CellRange box4 = new CellRange( 2, 3, 2,3);
private static final CellRange box5 = new CellRange( 1, 3, 1,3);

public void testHasSharedBorderMethod()
{
assertFalse(col1.hasSharedBorder(col1));
assertFalse(col2.hasSharedBorder(col2));
assertTrue(col1.hasSharedBorder(col2));
assertTrue(col2.hasSharedBorder(col1));
assertFalse(col1.hasExactSharedBorder(col1));
assertFalse(col2.hasExactSharedBorder(col2));
assertTrue(col1.hasExactSharedBorder(col2));
assertTrue(col2.hasExactSharedBorder(col1));

assertFalse(row1.hasSharedBorder(row1));
assertFalse(row2.hasSharedBorder(row2));
assertTrue(row1.hasSharedBorder(row2));
assertTrue(row2.hasSharedBorder(row1));
assertFalse(row1.hasExactSharedBorder(row1));
assertFalse(row2.hasExactSharedBorder(row2));
assertTrue(row1.hasExactSharedBorder(row2));
assertTrue(row2.hasExactSharedBorder(row1));
assertFalse(row1.hasSharedBorder(col1));
assertFalse(row1.hasSharedBorder(col2));
assertFalse(col1.hasSharedBorder(row1));
assertFalse(col2.hasSharedBorder(row1));
assertFalse(row2.hasSharedBorder(col1));
assertFalse(row2.hasSharedBorder(col2));
assertFalse(col1.hasSharedBorder(row2));
assertFalse(col2.hasSharedBorder(row2));
assertTrue(col2.hasSharedBorder(col1));
assertFalse(row1.hasExactSharedBorder(col1));
assertFalse(row1.hasExactSharedBorder(col2));
assertFalse(col1.hasExactSharedBorder(row1));
assertFalse(col2.hasExactSharedBorder(row1));
assertFalse(row2.hasExactSharedBorder(col1));
assertFalse(row2.hasExactSharedBorder(col2));
assertFalse(col1.hasExactSharedBorder(row2));
assertFalse(col2.hasExactSharedBorder(row2));
assertTrue(col2.hasExactSharedBorder(col1));
assertFalse(box1.hasSharedBorder(box1));
assertTrue(box1.hasSharedBorder(box2));
assertTrue(box1.hasSharedBorder(box3));
assertFalse(box1.hasSharedBorder(box4));
assertFalse(box1.hasExactSharedBorder(box1));
assertTrue(box1.hasExactSharedBorder(box2));
assertTrue(box1.hasExactSharedBorder(box3));
assertFalse(box1.hasExactSharedBorder(box4));
assertTrue(box2.hasSharedBorder(box1));
assertFalse(box2.hasSharedBorder(box2));
assertFalse(box2.hasSharedBorder(box3));
assertTrue(box2.hasSharedBorder(box4));
assertTrue(box2.hasExactSharedBorder(box1));
assertFalse(box2.hasExactSharedBorder(box2));
assertFalse(box2.hasExactSharedBorder(box3));
assertTrue(box2.hasExactSharedBorder(box4));
assertTrue(box3.hasSharedBorder(box1));
assertFalse(box3.hasSharedBorder(box2));
assertFalse(box3.hasSharedBorder(box3));
assertTrue(box3.hasSharedBorder(box4));
assertTrue(box3.hasExactSharedBorder(box1));
assertFalse(box3.hasExactSharedBorder(box2));
assertFalse(box3.hasExactSharedBorder(box3));
assertTrue(box3.hasExactSharedBorder(box4));
assertFalse(box4.hasSharedBorder(box1));
assertTrue(box4.hasSharedBorder(box2));
assertTrue(box4.hasSharedBorder(box3));
assertFalse(box4.hasSharedBorder(box4));
assertFalse(box4.hasExactSharedBorder(box1));
assertTrue(box4.hasExactSharedBorder(box2));
assertTrue(box4.hasExactSharedBorder(box3));
assertFalse(box4.hasExactSharedBorder(box4));
}
public void testIntersectMethod()
{
assertEquals( CellRange.OVERLAP,box0.intersect(box5));
@@ -135,5 +135,4 @@ public class TestCellRange extends TestCase
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
}
}

+ 203
- 0
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConfditionalFormatting.java View File

@@ -0,0 +1,203 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package org.apache.poi.hssf.usermodel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import junit.framework.TestCase;

import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
/**
*
* @author Dmitriy Kumshayev
*/
public final class TestHSSFConfditionalFormatting extends TestCase
{
public void XtestLastAndFirstColumns()
{
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
String formula = "7";

HSSFFontFormatting fontFmt = new HSSFFontFormatting();
fontFmt.setFontStyle(true, false);

HSSFBorderFormatting bordFmt = new HSSFBorderFormatting();
bordFmt.setBorderBottom(HSSFBorderFormatting.BORDER_THIN);
bordFmt.setBorderTop(HSSFBorderFormatting.BORDER_THICK);
bordFmt.setBorderLeft(HSSFBorderFormatting.BORDER_DASHED);
bordFmt.setBorderRight(HSSFBorderFormatting.BORDER_DOTTED);

HSSFPatternFormatting patternFmt = new HSSFPatternFormatting();
patternFmt.setFillBackgroundColor(HSSFColor.RED.index);

HSSFConditionalFormattingRule [] cfRules =
{
sheet.createConditionalFormattingRule(formula, fontFmt, bordFmt, patternFmt),
sheet.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2", fontFmt, bordFmt, patternFmt)
};

short col = 1;
Region [] regions =
{
new Region(0,col,-1,col)
};

sheet.addConditionalFormatting(regions, cfRules);
sheet.addConditionalFormatting(regions, cfRules);

// Verification
assertEquals(2, sheet.getNumConditionalFormattings());
sheet.removeConditionalFormatting(1);
assertEquals(1, sheet.getNumConditionalFormattings());
HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(0);
assertNotNull(cf);

regions = cf.getFormattingRegions();
assertNotNull(regions);
assertEquals(1, regions.length);
Region r = regions[0];
assertEquals(1, r.getColumnFrom());
assertEquals(1, r.getColumnTo());
assertEquals(0, r.getRowFrom());
assertEquals(-1, r.getRowTo());

assertEquals(2, cf.getNumberOfRules());

HSSFConditionalFormattingRule rule1 = cf.getRule(0);
assertEquals("7",rule1.getFormula1());
assertNull(rule1.getFormula2());

HSSFConditionalFormattingRule rule2 = cf.getRule(1);
assertEquals("2",rule2.getFormula2());
assertEquals("1",rule2.getFormula1());
}
public void XtestOutput() {

HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
String formula = "7";

HSSFFontFormatting fontFmt = new HSSFFontFormatting();
fontFmt.setFontStyle(true, false);

HSSFBorderFormatting bordFmt = new HSSFBorderFormatting();
bordFmt.setBorderBottom(HSSFBorderFormatting.BORDER_THIN);
bordFmt.setBorderTop(HSSFBorderFormatting.BORDER_THICK);
bordFmt.setBorderLeft(HSSFBorderFormatting.BORDER_DASHED);
bordFmt.setBorderRight(HSSFBorderFormatting.BORDER_DOTTED);

HSSFPatternFormatting patternFmt = new HSSFPatternFormatting();
patternFmt.setFillBackgroundColor(HSSFColor.RED.index);

HSSFConditionalFormattingRule [] cfRules =
{
sheet.createConditionalFormattingRule(formula, fontFmt, bordFmt, patternFmt),
sheet.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2", fontFmt, bordFmt, patternFmt)
};

short col = 1;
Region [] regions =
{
new Region(0,col,-1,col)
};

sheet.addConditionalFormatting(regions, cfRules);

try {
OutputStream os = new FileOutputStream("C:/josh/temp/cfExample.xls");
wb.write(os);
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void testReadWrite() {
HSSFWorkbook wb;
try {
InputStream is = new FileInputStream("C:/josh/temp/cfEx.xls");
wb = new HSSFWorkbook(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
HSSFSheet sheet = wb.getSheetAt(0);
int nCFs = sheet.getNumConditionalFormattings();
HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(0);
Region[] regions = cf.getFormattingRegions();

sheet.removeConditionalFormatting(0);

HSSFFontFormatting fontFmt = new HSSFFontFormatting();
fontFmt.setFontStyle(false, true);
HSSFConditionalFormattingRule rule1 = cf.getRule(0);
HSSFConditionalFormattingRule rule = sheet.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "5", "10", fontFmt, null, null);

byte[] rawRecord1 = rule1.getCfRuleRecord().getFontFormatting().getRawRecord();
for (int i = 0; i < rawRecord1.length; i++) {
System.out.print(rawRecord1[i] + ",");
}
System.out.println();
byte[] rawRecord = fontFmt.getFontFormattingBlock().getRawRecord();
for (int i = 0; i < rawRecord.length; i++) {
System.out.print(rawRecord[i]+ ",");
}
System.out.println();
rule.getCfRuleRecord().setFontFormatting(rule1.getCfRuleRecord().getFontFormatting());
sheet.addConditionalFormatting(regions, new HSSFConditionalFormattingRule[] { rule, });
HSSFWorkbook wb2;
if(false) try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
wb.write(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
wb2 = new HSSFWorkbook(bais);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
OutputStream os = new FileOutputStream("C:/josh/temp/cfEx3.xls");
wb.write(os);
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

Loading…
Cancel
Save