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
This commit is contained in:
Josh Micich 2008-03-31 05:10:35 +00:00
parent 37e1487670
commit 05fb78c5d4
17 changed files with 1956 additions and 1626 deletions

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>

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>

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");
}
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;
}
private void recalculateEnclosingRange(CellRange cellRange)
public CellRange[] getCellRanges()
{
field_3_enclosing_cell_range = cellRange.createEnclosingCellRange(field_3_enclosing_cell_range);
}
public List getCellRanges()
{
return field_4_cell_ranges;
return (CellRange[]) field_4_cell_ranges.clone();
}
public String toString()
@ -134,12 +131,12 @@ public class CFHeaderRecord extends Record
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)
if( field_4_cell_ranges.length>0)
{
buffer.append(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.size(); i++)
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;
}
/**
@ -206,18 +200,15 @@ public class CFHeaderRecord extends Record
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());
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();
}
return rec;
result.field_4_cell_ranges = crs;
return result;
}
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -17,16 +16,12 @@
==================================================================== */
/*
* ConditionalFormattingRuleRecord.java
*
* Created on January 23, 2008, 9:56 AM
*/
package org.apache.poi.hssf.record;
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.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
@ -39,64 +34,69 @@ import org.apache.poi.util.LittleEndian;
* Conditional Formatting Rule Record.
* @author Dmitriy Kumshayev
*/
public class CFRuleRecord extends Record
public final class CFRuleRecord extends Record
{
public static final short sid = 0x01B1;
public static final class ComparisonOperator {
public static final byte NO_COMPARISON = 0;
public static final byte BETWEEN = 1;
public static final byte NOT_BETWEEN = 2;
public static final byte EQUAL = 3;
public static final byte NOT_EQUAL = 4;
public static final byte GT = 5;
public static final byte LT = 6;
public static final byte GE = 7;
public static final byte LE = 8;
}
private byte field_1_condition_type;
public static final byte CONDITION_TYPE_NO_CONDITION_TYPE = 0;
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
public static final byte CONDITION_TYPE_FORMULA = 2;
private byte field_2_comparison_operator;
public static final byte COMPARISON_OPERATOR_NO_COMPARISON = 0;
public static final byte COMPARISON_OPERATOR_BETWEEN = 1;
public static final byte COMPARISON_OPERATOR_NOT_BETWEEN = 2;
public static final byte COMPARISON_OPERATOR_EQUAL = 3;
public static final byte COMPARISON_OPERATOR_NOT_EQUAL = 4;
public static final byte COMPARISON_OPERATOR_GT = 5;
public static final byte COMPARISON_OPERATOR_LT = 6;
public static final byte COMPARISON_OPERATOR_GE = 7;
public static final byte COMPARISON_OPERATOR_LE = 8;
private short field_3_formula1_len;
private short field_4_formula2_len;
private int field_5_options;
private static final BitField modificationBits = BitFieldFactory.getInstance(0x83FFFFFF); // Bits: font,align,bord,patt,prot
private static final BitField alignHor = BitFieldFactory.getInstance(0x00000001); // 0 = Horizontal alignment modified
private static final BitField alignVer = BitFieldFactory.getInstance(0x00000002); // 0 = Vertical alignment modified
private static final BitField alignWrap = BitFieldFactory.getInstance(0x00000004); // 0 = Text wrapped flag modified
private static final BitField alignRot = BitFieldFactory.getInstance(0x00000008); // 0 = Text rotation modified
private static final BitField alignJustLast = BitFieldFactory.getInstance(0x00000010); // 0 = Justify last line flag modified
private static final BitField alignIndent = BitFieldFactory.getInstance(0x00000020); // 0 = Indentation modified
private static final BitField alignShrink = BitFieldFactory.getInstance(0x00000040); // 0 = Shrink to fit flag modified
private static final BitField notUsed1 = BitFieldFactory.getInstance(0x00000080); // Always 1
private static final BitField protLocked = BitFieldFactory.getInstance(0x00000100); // 0 = Cell locked flag modified
private static final BitField protHidden = BitFieldFactory.getInstance(0x00000200); // 0 = Cell hidden flag modified
private static final BitField bordLeft = BitFieldFactory.getInstance(0x00000400); // 0 = Left border style and colour modified
private static final BitField bordRight = BitFieldFactory.getInstance(0x00000800); // 0 = Right border style and colour modified
private static final BitField bordTop = BitFieldFactory.getInstance(0x00001000); // 0 = Top border style and colour modified
private static final BitField bordBot = BitFieldFactory.getInstance(0x00002000); // 0 = Bottom border style and colour modified
private static final BitField bordTlBr = BitFieldFactory.getInstance(0x00004000); // 0 = Top-left to bottom-right border flag modified
private static final BitField bordBlTr = BitFieldFactory.getInstance(0x00008000); // 0 = Bottom-left to top-right border flag modified
private static final BitField pattStyle = BitFieldFactory.getInstance(0x00010000); // 0 = Pattern style modified
private static final BitField pattCol = BitFieldFactory.getInstance(0x00020000); // 0 = Pattern colour modified
private static final BitField pattBgCol = BitFieldFactory.getInstance(0x00040000); // 0 = Pattern background colour modified
private static final BitField notUsed2 = BitFieldFactory.getInstance(0x00380000); // Always 111
private static final BitField undocumented = BitFieldFactory.getInstance(0x03C00000); // Undocumented bits
private static final BitField fmtBlockBits = BitFieldFactory.getInstance(0x7C000000); // Bits: font,align,bord,patt,prot
private static final BitField font = BitFieldFactory.getInstance(0x04000000); // 1 = Record contains font formatting block
private static final BitField align = BitFieldFactory.getInstance(0x08000000); // 1 = Record contains alignment formatting block
private static final BitField bord = BitFieldFactory.getInstance(0x10000000); // 1 = Record contains border formatting block
private static final BitField patt = BitFieldFactory.getInstance(0x20000000); // 1 = Record contains pattern formatting block
private static final BitField prot = BitFieldFactory.getInstance(0x40000000); // 1 = Record contains protection formatting block
private static final BitField alignTextDir = BitFieldFactory.getInstance(0x80000000); // 0 = Text direction modified
private static final BitField modificationBits = bf(0x83FFFFFF); // Bits: font,align,bord,patt,prot
private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
private static final BitField notUsed1 = bf(0x00000080); // Always 1
private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified
private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified
private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified
private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
private static final BitField notUsed2 = bf(0x00380000); // Always 111
private static final BitField undocumented = bf(0x03C00000); // Undocumented bits
private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block
private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block
private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block
private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block
private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block
private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified
private static BitField bf(int i) {
return BitFieldFactory.getInstance(i);
}
private short field_6_not_used;
private FontFormatting fontFormatting;
@ -111,23 +111,24 @@ public class CFRuleRecord extends Record
private PatternFormatting patternFormatting;
private Stack field_17_formula1;
private Stack field_18_formula2;
private Ptg[] field_17_formula1;
private Ptg[] field_18_formula2;
/** Creates new CFRuleRecord */
public CFRuleRecord()
private CFRuleRecord(byte conditionType, byte comparisonOperation)
{
field_1_condition_type=CONDITION_TYPE_NO_CONDITION_TYPE;
field_2_comparison_operator=COMPARISON_OPERATOR_NO_COMPARISON;
setExpression1Length((short)0);
setExpression2Length((short)0);
field_1_condition_type=conditionType;
field_2_comparison_operator=comparisonOperation;
field_3_formula1_len = (short)0;
field_4_formula2_len = (short)0;
// Set modification flags to 1: by default options are not modified
setOptions(modificationBits.setValue(field_5_options, -1));
field_5_options = modificationBits.setValue(field_5_options, -1);
// Set formatting block flags to 0 (no formatting blocks)
setOptions(fmtBlockBits.setValue(field_5_options, 0));
field_5_options = fmtBlockBits.setValue(field_5_options, 0);
field_5_options = undocumented.clear(field_5_options);
field_6_not_used = 0;
field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
fontFormatting=null;
field_8_align_text_break = 0;
field_9_align_text_rotation_angle = 0;
@ -140,6 +141,33 @@ public class CFRuleRecord extends Record
field_18_formula2=null;
}
private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
this(conditionType, comparisonOperation);
field_1_condition_type = CONDITION_TYPE_CELL_VALUE_IS;
field_2_comparison_operator = comparisonOperation;
setParsedExpression1(formula1);
setParsedExpression2(formula2);
}
/**
* Creates a new comparison operation rule
*/
public static CFRuleRecord create(Workbook workbook, String formulaText) {
Ptg[] formula1 = parseFormula(formulaText, workbook);
return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
formula1, null);
}
/**
* Creates a new comparison operation rule
*/
public static CFRuleRecord create(Workbook workbook, byte comparisonOperation,
String formulaText1, String formulaText2) {
Ptg[] formula1 = parseFormula(formulaText1, workbook);
Ptg[] formula2 = parseFormula(formulaText2, workbook);
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
}
/**
* Constructs a Formula record and sets its fields appropriately.
* Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
@ -154,8 +182,9 @@ public class CFRuleRecord extends Record
super(in);
}
protected void fillFields(RecordInputStream in)
{
protected void fillFields(RecordInputStream in) {
try {
field_1_condition_type = in.readByte();
field_2_comparison_operator = in.readByte();
@ -164,38 +193,30 @@ public class CFRuleRecord extends Record
field_5_options = in.readInt();
field_6_not_used = in.readShort();
if(containsFontFormattingBlock())
{
if (containsFontFormattingBlock()) {
fontFormatting = new FontFormatting(in);
}
if(containsBorderFormattingBlock())
{
if (containsBorderFormattingBlock()) {
borderFormatting = new BorderFormatting(in);
}
if( containsPatternFormattingBlock())
{
if (containsPatternFormattingBlock()) {
patternFormatting = new PatternFormatting(in);
}
if(field_3_formula1_len>0)
{
field_17_formula1 = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
if (field_3_formula1_len > 0) {
Stack ptgs = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
// Now convert any fields as required
field_17_formula1 = SharedFormulaRecord.convertSharedFormulas(
field_17_formula1, 0, 0
);
ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
field_17_formula1 = toArray(ptgs);
}
if(field_4_formula2_len>0)
{
field_18_formula2 = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
if (field_4_formula2_len > 0) {
Stack ptgs = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
// Now convert any fields as required
field_18_formula2 = SharedFormulaRecord.convertSharedFormulas(
field_18_formula2, 0, 0
);
ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
field_18_formula2 = toArray(ptgs);
}
} catch (java.lang.UnsupportedOperationException uoe) {
throw new RecordFormatException(uoe);
@ -203,30 +224,11 @@ public class CFRuleRecord extends Record
}
public void setConditionType(byte conditionType)
{
field_1_condition_type =
conditionType == CONDITION_TYPE_CELL_VALUE_IS ?
CONDITION_TYPE_CELL_VALUE_IS :
CONDITION_TYPE_FORMULA;
}
public byte getConditionType()
{
return field_1_condition_type;
}
/**
* set the option flags
*
* @param options bitmask
*/
public void setOptions(int options)
{
field_5_options = options;
}
public boolean containsFontFormattingBlock()
{
return getOptionFlag(font);
@ -234,11 +236,7 @@ public class CFRuleRecord extends Record
public void setFontFormatting(FontFormatting fontFormatting)
{
this.fontFormatting = fontFormatting;
setOptionFlag(true,font);
}
public void setFontFormattingUnchanged()
{
setOptionFlag(false,font);
setOptionFlag(fontFormatting != null, font);
}
public boolean containsAlignFormattingBlock()
@ -257,11 +255,7 @@ public class CFRuleRecord extends Record
public void setBorderFormatting(BorderFormatting borderFormatting)
{
this.borderFormatting = borderFormatting;
setOptionFlag(true,bord);
}
public void setBorderFormattingUnchanged()
{
setOptionFlag(false,bord);
setOptionFlag(borderFormatting != null, bord);
}
public boolean containsPatternFormattingBlock()
@ -271,13 +265,10 @@ public class CFRuleRecord extends Record
public void setPatternFormatting(PatternFormatting patternFormatting)
{
this.patternFormatting = patternFormatting;
setOptionFlag(true,patt);
}
public void setPatternFormattingUnchanged()
{
setOptionFlag(false,patt);
setOptionFlag(patternFormatting!=null, patt);
}
public boolean containsProtectionFormattingBlock()
{
return getOptionFlag(prot);
@ -297,42 +288,22 @@ public class CFRuleRecord extends Record
return field_2_comparison_operator;
}
/**
* set the length (in number of tokens) of the expression 1
* @param len length
*/
private void setExpression1Length(short len)
{
field_3_formula1_len = len;
}
/**
* get the length (in number of tokens) of the expression 1
* @return expression length
*/
public short getExpression1Length()
private short getExpression1Length()
{
return field_3_formula1_len;
}
/**
* set the length (in number of tokens) of the expression 2
* @param len length
*/
private void setExpression2Length(short len)
{
field_4_formula2_len = len;
}
/**
* get the length (in number of tokens) of the expression 2
* @return expression length
*/
public short getExpression2Length()
private short getExpression2Length()
{
return field_4_formula2_len;
}
@ -465,7 +436,7 @@ public class CFRuleRecord extends Record
* callers should check for null!
*/
public List getParsedExpression1()
public Ptg[] getParsedExpression1()
{
return field_17_formula1;
}
@ -479,17 +450,19 @@ public class CFRuleRecord extends Record
* callers should check for null!
*/
public List getParsedExpression2()
public Ptg[] getParsedExpression2()
{
return field_18_formula2;
}
public void setParsedExpression1(Stack ptgs) {
setExpression1Length(getTotalPtgSize(field_17_formula1 = ptgs));
private void setParsedExpression1(Ptg[] ptgs) {
short len = getTotalPtgSize(field_17_formula1 = ptgs);
field_3_formula1_len = len;
}
public void setParsedExpression2(Stack ptgs) {
setExpression1Length(getTotalPtgSize(field_18_formula2 = ptgs));
private void setParsedExpression2(Ptg[] ptgs) {
short len = getTotalPtgSize(field_18_formula2 = ptgs);
field_4_formula2_len = len;
}
/**
@ -522,8 +495,10 @@ public class CFRuleRecord extends Record
* @return number of bytes written
*/
public int serialize(int offset, byte [] data)
public int serialize(int pOffset, byte [] data)
{
int offset = pOffset;
int recordsize = getRecordSize();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
@ -555,21 +530,22 @@ public class CFRuleRecord extends Record
if (getExpression1Length()>0)
{
Ptg.serializePtgStack(this.field_17_formula1, data, offset);
Ptg.serializePtgStack(convertToTokenStack(field_17_formula1), data, offset);
offset += getExpression1Length();
}
if (getExpression2Length()>0)
{
Ptg.serializePtgStack(this.field_18_formula2, data, offset);
Ptg.serializePtgStack(convertToTokenStack(field_18_formula2), data, offset);
offset += getExpression2Length();
}
if(offset - pOffset != recordsize) {
throw new IllegalStateException("write mismatch (" + (offset - pOffset) + "!=" + recordsize + ")");
}
return recordsize;
}
public int getRecordSize()
{
int retval =16+
@ -582,17 +558,15 @@ public class CFRuleRecord extends Record
return retval;
}
private short getTotalPtgSize(List list)
private short getTotalPtgSize(Ptg[] ptgs)
{
short retval = 0;
if( list!=null)
{
for (int k = 0; k < list.size(); k++)
{
Ptg ptg = ( Ptg ) list.get(k);
retval += ptg.getSize();
if( ptgs == null) {
return 0;
}
short retval = 0;
for (int i = 0; i < ptgs.length; i++)
{
retval += ptgs[i].getSize();
}
return retval;
}
@ -618,32 +592,25 @@ public class CFRuleRecord extends Record
}
public Object clone() {
CFRuleRecord rec = new CFRuleRecord();
rec.field_1_condition_type= field_1_condition_type;
rec.field_2_comparison_operator = field_2_comparison_operator;
CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
rec.field_3_formula1_len = field_3_formula1_len;
rec.field_4_formula2_len = field_4_formula2_len;
rec.field_5_options = field_5_options;
rec.field_6_not_used = field_6_not_used;
if( containsFontFormattingBlock())
{
rec.fontFormatting = (FontFormatting)fontFormatting.clone();
if (containsFontFormattingBlock()) {
rec.fontFormatting = (FontFormatting) fontFormatting.clone();
}
if( containsBorderFormattingBlock())
{
rec.borderFormatting = (BorderFormatting)borderFormatting.clone();
if (containsBorderFormattingBlock()) {
rec.borderFormatting = (BorderFormatting) borderFormatting.clone();
}
if( containsPatternFormattingBlock())
{
rec.patternFormatting = (PatternFormatting)patternFormatting.clone();
if (containsPatternFormattingBlock()) {
rec.patternFormatting = (PatternFormatting) patternFormatting.clone();
}
if( field_3_formula1_len>0)
{
rec.field_17_formula1 = (Stack)field_17_formula1.clone();
if (field_3_formula1_len > 0) {
rec.field_17_formula1 = (Ptg[]) field_17_formula1.clone();
}
if( field_4_formula2_len>0)
{
rec.field_18_formula2 = (Stack)field_18_formula2.clone();
if (field_4_formula2_len > 0) {
rec.field_18_formula2 = (Ptg[]) field_18_formula2.clone();
}
return rec;
@ -654,4 +621,32 @@ public class CFRuleRecord extends Record
return fontFormatting;
}
/**
* @return <code>null</code> if <tt>formula</tt> was null.
*/
private static Ptg[] parseFormula(String formula, Workbook workbook)
{
if(formula == null) {
return null;
}
return FormulaParser.parse(formula, workbook);
}
// TODO - treat formulas as token arrays instead of Stacks throughout the rest of POI
private static Stack convertToTokenStack(Ptg[] ptgs)
{
Stack parsedExpression = new Stack();
// fill the Ptg Stack with Ptgs of new formula
for (int k = 0; k < ptgs.length; k++)
{
parsedExpression.push(ptgs[ k ]);
}
return parsedExpression;
}
private static Ptg[] toArray(Stack ptgs) {
Ptg[] result = new Ptg[ptgs.size()];
ptgs.toArray(result);
return result;
}
}

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 CFHeaderRecord header;
private final CFHeaderRecord header;
// List of CFRuleRecord objects
/** List of CFRuleRecord objects */
private final List rules;
public CFRecordsAggregate()
{
header = null;
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)
{
int offset = pOffset;
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
Record rec = ( Record ) recs.get(offset++);
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);
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");
}
if (nRules != cfRecords.rules.size())
{
CFHeaderRecord header = (CFHeaderRecord)rec;
int nRules = header.getNumberOfConditionalFormats();
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 (countFound < nRules)
{ // TODO -(MAR-2008) can this ever happen? write junit
if (log.check(POILogger.DEBUG))
{
log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
+ "but found " + cfRecords.rules.size() + " rules");
+ "but found " + countFound + " rules");
}
cfRecords.header.setNumberOfConditionalFormats(nRules);
header.setNumberOfConditionalFormats(nRules);
CFRuleRecord[] lessRules = new CFRuleRecord[countFound];
System.arraycopy(rules, 0, lessRules, 0, countFound);
rules = lessRules;
}
}
return cfRecords;
return new CFRecordsAggregate(header, rules);
}
/**
@ -105,21 +129,16 @@ 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);
CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
for (int i = 0; i < newRecs.length; i++) {
newRecs[i] = (CFRuleRecord) getRule(i).clone();
}
return createCFAggregate(records, 0);
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 nRules = rules.size();
header.setNumberOfConditionalFormats(nRules);
int pos = offset;
if( header != null && rules.size()>0 )
{
header.setNumberOfConditionalFormats(rules.size());
pos += (( Record ) header).serialize(pos, data);
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();
}
/**

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;
/**
* 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;
public CellRange(int firstRow, int lastRow, short firstColumn, short lastColumn)
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)
{
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();
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 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());
private static int convertM1ToMax(int lastIx) {
if(lastIx < 0) {
return MAX_INDEX;
}
return lastIx;
}
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 static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
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 int getFirstRow()
{
return field_1_first_row;
}
private void setFirstRow(int firstRow)
{
this.field_1_first_row = firstRow;
return _firstRow;
}
/**
* @return <tt>-1</tt> for whole column ranges
*/
public int getLastRow()
{
return field_2_last_row;
return convertMaxToM1(_lastRow);
}
private void setLastRow(int lastRow)
public int getFirstColumn()
{
this.field_2_last_row = lastRow;
return _firstColumn;
}
public short getFirstColumn()
/**
* @return <tt>-1</tt> for whole row ranges
*/
public int getLastColumn()
{
return field_3_first_column;
}
private void setFirstColumn(short firstColumn)
{
this.field_3_first_column = firstColumn;
}
public short getLastColumn()
{
return field_4_last_column;
}
private void setLastColumn(short lastColumn)
{
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 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;
}
@ -135,6 +184,233 @@ 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,37 +421,45 @@ 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.
* @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 hasSharedBorder(CellRange range)
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;
}
/**
@ -207,18 +491,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()+")";
}
}

View File

@ -26,94 +26,39 @@ 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
*/
/** Thin border */
public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
/**
* Medium border
*/
/** Medium border */
public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
/**
* dash border
*/
/** dash border */
public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
/**
* dot border
*/
/** dot border */
public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
/**
* Thick border
*/
/** Thick border */
public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
/**
* double-line border
*/
/** double-line border */
public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
/**
* hair-line border
*/
/** hair-line border */
public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
/**
* Medium dashed border
*/
/** Medium dashed border */
public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
/**
* dash-dot border
*/
/** dash-dot border */
public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
/**
* medium dash-dot border
*/
/** medium dash-dot border */
public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
/**
* dash-dot-dot border
*/
/** dash-dot-dot border */
public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
/**
* medium dash-dot-dot border
*/
/** medium dash-dot-dot border */
public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
/**
* slanted dash-dot border
*/
/** slanted dash-dot border */
public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
private BorderFormatting borderFormatting;
private final BorderFormatting borderFormatting;
public HSSFBorderFormatting()
{
@ -125,4 +70,123 @@ public class HSSFBorderFormatting
return borderFormatting;
}
public short getBorderBottom()
{
return borderFormatting.getBorderBottom();
}
public short getBorderDiagonal()
{
return borderFormatting.getBorderDiagonal();
}
public short getBorderLeft()
{
return borderFormatting.getBorderLeft();
}
public short getBorderRight()
{
return borderFormatting.getBorderRight();
}
public short getBorderTop()
{
return borderFormatting.getBorderTop();
}
public short getBottomBorderColor()
{
return borderFormatting.getBottomBorderColor();
}
public short getDiagonalBorderColor()
{
return borderFormatting.getDiagonalBorderColor();
}
public short getLeftBorderColor()
{
return borderFormatting.getLeftBorderColor();
}
public short getRightBorderColor()
{
return borderFormatting.getRightBorderColor();
}
public short getTopBorderColor()
{
return borderFormatting.getTopBorderColor();
}
public boolean isBackwardDiagonalOn()
{
return borderFormatting.isBackwardDiagonalOn();
}
public boolean isForwardDiagonalOn()
{
return borderFormatting.isForwardDiagonalOn();
}
public void setBackwardDiagonalOn(boolean on)
{
borderFormatting.setBackwardDiagonalOn(on);
}
public void setBorderBottom(short border)
{
borderFormatting.setBorderBottom(border);
}
public void setBorderDiagonal(short border)
{
borderFormatting.setBorderDiagonal(border);
}
public void setBorderLeft(short border)
{
borderFormatting.setBorderLeft(border);
}
public void setBorderRight(short border)
{
borderFormatting.setBorderRight(border);
}
public void setBorderTop(short border)
{
borderFormatting.setBorderTop(border);
}
public void setBottomBorderColor(short color)
{
borderFormatting.setBottomBorderColor(color);
}
public void setDiagonalBorderColor(short color)
{
borderFormatting.setDiagonalBorderColor(color);
}
public void setForwardDiagonalOn(boolean on)
{
borderFormatting.setForwardDiagonalOn(on);
}
public void setLeftBorderColor(short color)
{
borderFormatting.setLeftBorderColor(color);
}
public void setRightBorderColor(short color)
{
borderFormatting.setRightBorderColor(color);
}
public void setTopBorderColor(short color)
{
borderFormatting.setTopBorderColor(color);
}
}

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>
*/
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()

View File

@ -18,166 +18,76 @@
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;
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 static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
private CFRuleRecord cfRuleRecord;
private HSSFWorkbook workbook;
protected HSSFConditionalFormattingRule(HSSFWorkbook workbook)
{
this.workbook = workbook;
this.cfRuleRecord = new CFRuleRecord();
private final CFRuleRecord cfRuleRecord;
private final Workbook workbook;
HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord) {
workbook = pWorkbook;
cfRuleRecord = pRuleRecord;
}
HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord,
HSSFFontFormatting fontFmt, HSSFBorderFormatting bordFmt, HSSFPatternFormatting patternFmt) {
this(pWorkbook, pRuleRecord);
setFontFormatting(fontFmt);
setBorderFormatting(bordFmt);
setPatternFormatting(patternFmt);
}
protected HSSFConditionalFormattingRule(HSSFWorkbook workbook, CFRuleRecord cfRuleRecord)
CFRuleRecord getCfRuleRecord()
{
this.workbook = workbook;
this.cfRuleRecord = cfRuleRecord;
return cfRuleRecord;
}
/**
* Keep Font Formatting unchanged for this Conditional Formatting Rule
* @param fontFmt pass <code>null</code> to signify 'font unchanged'
*/
public void setFontFormattingUnchanged()
public void setFontFormatting(HSSFFontFormatting fontFmt)
{
cfRuleRecord.setFontFormattingUnchanged();
FontFormatting block = fontFmt==null ? null : fontFmt.getFontFormattingBlock();
cfRuleRecord.setFontFormatting(block);
}
/**
* Keep Border Formatting unchanged for this Conditional Formatting Rule
* @param borderFmt pass <code>null</code> to signify 'border unchanged'
*/
public void setBorderFormattingUnchanged()
public void setBorderFormatting(HSSFBorderFormatting borderFmt)
{
cfRuleRecord.setBorderFormattingUnchanged();
BorderFormatting block = borderFmt==null ? null : borderFmt.getBorderFormattingBlock();
cfRuleRecord.setBorderFormatting(block);
}
/**
* Keep Pattern Formatting unchanged for this Conditional Formatting Rule
* @param patternFmt pass <code>null</code> to signify 'pattern unchanged'
*/
public void setPatternFormattingUnchanged()
public void setPatternFormatting(HSSFPatternFormatting patternFmt)
{
cfRuleRecord.setPatternFormattingUnchanged();
}
public void setFontFormatting(HSSFFontFormatting fontFormatting)
{
if( fontFormatting!=null )
{
cfRuleRecord.setFontFormatting(fontFormatting.getFontFormattingBlock());
}
else
{
setFontFormattingUnchanged();
}
}
public void setBorderFormatting(HSSFBorderFormatting borderFormatting)
{
if( borderFormatting != null )
{
cfRuleRecord.setBorderFormatting(borderFormatting.getBorderFormattingBlock());
}
else
{
setBorderFormattingUnchanged();
}
}
public void setPatternFormatting(HSSFPatternFormatting patternFormatting)
{
if( patternFormatting != null)
{
cfRuleRecord.setPatternFormatting(patternFormatting.getPatternFormattingBlock());
}
else
{
setPatternFormattingUnchanged();
}
}
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)
{
cfRuleRecord.setConditionType(FORMULA);
// Formula 1
setFormula1(formula);
}
public void setFormula1(String formula)
{
// Formula 1
if( formula != null)
{
Stack parsedExpression = parseFormula(formula);
if( parsedExpression != null )
{
cfRuleRecord.setParsedExpression1(parsedExpression);
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
}
public void setFormula2(String formula)
{
// 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()
@ -188,61 +98,25 @@ public class HSSFConditionalFormattingRule
public String getFormula2()
{
byte conditionType = cfRuleRecord.getConditionType();
switch(conditionType)
{
case CELL_COMPARISON:
{
if (conditionType == CELL_COMPARISON) {
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
switch(comparisonOperation)
{
case COMPARISON_OPERATOR_BETWEEN:
case COMPARISON_OPERATOR_NOT_BETWEEN:
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;
}
}
}

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]);
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");
}
return sheet.addConditionalFormatting(cf.getCFRecordsAggregate());
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 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);
}
}

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

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,28 +27,23 @@ 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();
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));
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.size());
assertEquals(6,ranges.length);
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(-1, enclosingCellRange.getLastRow());
@ -106,23 +98,27 @@ public class TestCFHeaderRecord
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());
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());
byte[] output = record.serialize();
@ -141,5 +137,4 @@ public class TestCFHeaderRecord
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class);
}
}

View File

@ -19,10 +19,13 @@ 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
@ -30,18 +33,13 @@ import org.apache.poi.hssf.util.HSSFColor;
*
* @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();
Workbook workbook = Workbook.createWorkbook();
CFRuleRecord record = CFRuleRecord.create(workbook, "7");
testCFRuleRecord(record);
// Serialize
@ -134,7 +132,6 @@ public class TestCFRuleRecord
patternFormatting.setFillPattern(PatternFormatting.DIAMONDS);
assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern());
}
private void testBorderFormattingAccessors(BorderFormatting borderFormatting)
@ -286,11 +283,29 @@ public class TestCFRuleRecord
assertTrue(fontFormatting.isUnderlineTypeModified());
}
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);
}
}

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

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,34 +37,28 @@ 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();
Workbook workbook = Workbook.createWorkbook();
List recs = new ArrayList();
CFHeaderRecord header = new CFHeaderRecord();
CFRuleRecord rule1 = new CFRuleRecord();
CFRuleRecord rule2 = new CFRuleRecord();
CFRuleRecord rule3 = new CFRuleRecord();
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 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);
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
@ -82,7 +78,7 @@ public class TestCFRecordsAggregate
rule3 = (CFRuleRecord)recs.get(3);
cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size());
assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats());
record = CFRecordsAggregate.createCFAggregate(recs, 0);
@ -90,15 +86,15 @@ public class TestCFRecordsAggregate
record = record.cloneCFAggregate();
assertNotNull(record.getHeader());
assertEquals(3,record.getRules().size());
assertEquals(3,record.getNumberOfRules());
header = record.getHeader();
rule1 = (CFRuleRecord)record.getRules().get(0);
rule2 = (CFRuleRecord)record.getRules().get(1);
rule3 = (CFRuleRecord)record.getRules().get(2);
rule1 = record.getRule(0);
rule2 = record.getRule(1);
rule3 = record.getRule(2);
cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size());
assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats());
}

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[][]
{
@ -62,59 +62,59 @@ 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 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,(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 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()
@ -135,5 +135,4 @@ public class TestCellRange extends TestCase
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
}
}

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