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 --> <!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/> <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="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="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/> <person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/> <person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
@ -36,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.0.3-beta1" date="2008-04-??"> <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 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">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> <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 --> <!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/> <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="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="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/> <person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/> <person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
@ -33,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.0.3-beta1" date="2008-04-??"> <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 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">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> <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. limitations under the License.
==================================================================== */ ==================================================================== */
/*
* ConditionalFormattingHeaderRecord.java
*
* Created on January 17, 2008, 3:05 AM
*/
package org.apache.poi.hssf.record; 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.record.cf.CellRange;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -34,19 +26,27 @@ import org.apache.poi.util.LittleEndian;
* *
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public class CFHeaderRecord extends Record public final class CFHeaderRecord extends Record
{ {
public static final short sid = 0x1B0; public static final short sid = 0x1B0;
private static final CellRange[] EMPTY_CELL_RANGE_ARRAY = { };
private int field_1_numcf; private int field_1_numcf;
private int field_2_need_recalculation; private int field_2_need_recalculation;
private CellRange field_3_enclosing_cell_range; private CellRange field_3_enclosing_cell_range;
private List field_4_cell_ranges; private CellRange[] field_4_cell_ranges;
/** Creates new CFHeaderRecord */ /** Creates new CFHeaderRecord */
public 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) public CFHeaderRecord(RecordInputStream in)
@ -60,11 +60,12 @@ public class CFHeaderRecord extends Record
field_2_need_recalculation = in.readShort(); field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort()); field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
int numCellRanges = 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++) 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() public int getNumberOfConditionalFormats()
@ -101,28 +102,24 @@ public class CFHeaderRecord extends Record
* modify the enclosing cell range accordingly. * modify the enclosing cell range accordingly.
* @param List cellRanges - list of CellRange objects * @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; throw new IllegalArgumentException("cellRanges must not be null");
for( int i=0; i<cellRanges.size(); i++)
{
field_4_cell_ranges.add(cellRanges.get(i));
recalculateEnclosingRange((CellRange)cellRanges.get(i));
} }
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); return (CellRange[]) field_4_cell_ranges.clone();
}
public List getCellRanges()
{
return field_4_cell_ranges;
} }
public String toString() public String toString()
@ -134,12 +131,12 @@ public class CFHeaderRecord extends Record
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n"); buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n"); buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).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=["); 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"); 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, 10 + offset, (short) field_3_enclosing_cell_range.getLastRow());
LittleEndian.putShort(data, 12 + offset, (short) field_3_enclosing_cell_range.getFirstColumn()); 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, 14 + offset, (short) field_3_enclosing_cell_range.getLastColumn());
LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.size()); LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.length);
for( int i=0 ; i!=field_4_cell_ranges.size(); i++) for( int i=0 ; i!=field_4_cell_ranges.length; i++)
{ {
LittleEndian.putShort(data, 18 + 0 + 8 * i + offset, CellRange cr = field_4_cell_ranges[i];
(short) ((CellRange) field_4_cell_ranges.get(i)).getFirstRow()); LittleEndian.putShort(data, 18 + 0 + 8 * i + offset, (short) cr.getFirstRow());
LittleEndian.putShort(data, 18 + 2 + 8 * i + offset, LittleEndian.putShort(data, 18 + 2 + 8 * i + offset, (short) cr.getLastRow());
(short) ((CellRange) field_4_cell_ranges.get(i)).getLastRow()); LittleEndian.putShort(data, 18 + 4 + 8 * i + offset, (short) cr.getFirstColumn());
LittleEndian.putShort(data, 18 + 4 + 8 * i + offset, LittleEndian.putShort(data, 18 + 6 + 8 * i + offset, (short) cr.getLastColumn());
(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());
} }
return getRecordSize(); return getRecordSize();
} }
public int 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() public Object clone()
{ {
CFHeaderRecord rec = new CFHeaderRecord(); CFHeaderRecord result = new CFHeaderRecord();
rec.field_1_numcf = field_1_numcf; result.field_1_numcf = field_1_numcf;
rec.field_2_need_recalculation = field_2_need_recalculation; result.field_2_need_recalculation = field_2_need_recalculation;
rec.field_3_enclosing_cell_range = field_3_enclosing_cell_range; result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
rec.field_4_cell_ranges = new ArrayList(field_4_cell_ranges.size()); CellRange[] crs = new CellRange[field_4_cell_ranges.length];
Iterator iterator = field_4_cell_ranges.iterator(); for (int i = 0; i < crs.length; i++) {
while (iterator.hasNext()) crs[i] = field_4_cell_ranges[i].cloneCellRange();
{
CellRange oldRange = (CellRange)iterator.next();
rec.field_4_cell_ranges.add(oldRange.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 Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with 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; package org.apache.poi.hssf.record;
import java.util.List;
import java.util.Stack; 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.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting; import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting; import org.apache.poi.hssf.record.cf.PatternFormatting;
@ -39,64 +34,69 @@ import org.apache.poi.util.LittleEndian;
* Conditional Formatting Rule Record. * Conditional Formatting Rule Record.
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public final class CFRuleRecord extends Record
public class CFRuleRecord extends Record
{ {
public static final short sid = 0x01B1; 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; 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_CELL_VALUE_IS = 1;
public static final byte CONDITION_TYPE_FORMULA = 2; public static final byte CONDITION_TYPE_FORMULA = 2;
private byte field_2_comparison_operator; 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_3_formula1_len;
private short field_4_formula2_len; private short field_4_formula2_len;
private int field_5_options; private int field_5_options;
private static final BitField modificationBits = BitFieldFactory.getInstance(0x83FFFFFF); // Bits: font,align,bord,patt,prot private static final BitField modificationBits = bf(0x83FFFFFF); // Bits: font,align,bord,patt,prot
private static final BitField alignHor = BitFieldFactory.getInstance(0x00000001); // 0 = Horizontal alignment modified private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
private static final BitField alignVer = BitFieldFactory.getInstance(0x00000002); // 0 = Vertical alignment modified private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
private static final BitField alignWrap = BitFieldFactory.getInstance(0x00000004); // 0 = Text wrapped flag modified private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
private static final BitField alignRot = BitFieldFactory.getInstance(0x00000008); // 0 = Text rotation modified private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
private static final BitField alignJustLast = BitFieldFactory.getInstance(0x00000010); // 0 = Justify last line flag modified private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
private static final BitField alignIndent = BitFieldFactory.getInstance(0x00000020); // 0 = Indentation modified private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
private static final BitField alignShrink = BitFieldFactory.getInstance(0x00000040); // 0 = Shrink to fit flag modified private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
private static final BitField notUsed1 = BitFieldFactory.getInstance(0x00000080); // Always 1 private static final BitField notUsed1 = bf(0x00000080); // Always 1
private static final BitField protLocked = BitFieldFactory.getInstance(0x00000100); // 0 = Cell locked flag modified private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
private static final BitField protHidden = BitFieldFactory.getInstance(0x00000200); // 0 = Cell hidden flag modified private static final BitField protHidden = bf(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 bordLeft = bf(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 bordRight = bf(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 bordTop = bf(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 bordBot = bf(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 bordTlBr = bf(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 bordBlTr = bf(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 pattStyle = bf(0x00010000); // 0 = Pattern style modified
private static final BitField pattCol = BitFieldFactory.getInstance(0x00020000); // 0 = Pattern colour modified private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
private static final BitField pattBgCol = BitFieldFactory.getInstance(0x00040000); // 0 = Pattern background colour modified private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
private static final BitField notUsed2 = BitFieldFactory.getInstance(0x00380000); // Always 111 private static final BitField notUsed2 = bf(0x00380000); // Always 111
private static final BitField undocumented = BitFieldFactory.getInstance(0x03C00000); // Undocumented bits private static final BitField undocumented = bf(0x03C00000); // Undocumented bits
private static final BitField fmtBlockBits = BitFieldFactory.getInstance(0x7C000000); // Bits: font,align,bord,patt,prot private static final BitField fmtBlockBits = bf(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 font = bf(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 align = bf(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 bord = bf(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 patt = bf(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 prot = bf(0x40000000); // 1 = Record contains protection formatting block
private static final BitField alignTextDir = BitFieldFactory.getInstance(0x80000000); // 0 = Text direction modified 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 short field_6_not_used;
private FontFormatting fontFormatting; private FontFormatting fontFormatting;
@ -111,23 +111,24 @@ public class CFRuleRecord extends Record
private PatternFormatting patternFormatting; private PatternFormatting patternFormatting;
private Stack field_17_formula1; private Ptg[] field_17_formula1;
private Stack field_18_formula2; private Ptg[] field_18_formula2;
/** Creates new CFRuleRecord */ /** Creates new CFRuleRecord */
public CFRuleRecord() private CFRuleRecord(byte conditionType, byte comparisonOperation)
{ {
field_1_condition_type=CONDITION_TYPE_NO_CONDITION_TYPE; field_1_condition_type=conditionType;
field_2_comparison_operator=COMPARISON_OPERATOR_NO_COMPARISON; field_2_comparison_operator=comparisonOperation;
setExpression1Length((short)0); field_3_formula1_len = (short)0;
setExpression2Length((short)0); field_4_formula2_len = (short)0;
// Set modification flags to 1: by default options are not modified // 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) // 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; fontFormatting=null;
field_8_align_text_break = 0; field_8_align_text_break = 0;
field_9_align_text_rotation_angle = 0; field_9_align_text_rotation_angle = 0;
@ -140,6 +141,33 @@ public class CFRuleRecord extends Record
field_18_formula2=null; 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. * Constructs a Formula record and sets its fields appropriately.
* Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
@ -154,8 +182,9 @@ public class CFRuleRecord extends Record
super(in); super(in);
} }
protected void fillFields(RecordInputStream in)
{
protected void fillFields(RecordInputStream in) {
try { try {
field_1_condition_type = in.readByte(); field_1_condition_type = in.readByte();
field_2_comparison_operator = in.readByte(); field_2_comparison_operator = in.readByte();
@ -164,38 +193,30 @@ public class CFRuleRecord extends Record
field_5_options = in.readInt(); field_5_options = in.readInt();
field_6_not_used = in.readShort(); field_6_not_used = in.readShort();
if(containsFontFormattingBlock()) if (containsFontFormattingBlock()) {
{
fontFormatting = new FontFormatting(in); fontFormatting = new FontFormatting(in);
} }
if(containsBorderFormattingBlock()) if (containsBorderFormattingBlock()) {
{
borderFormatting = new BorderFormatting(in); borderFormatting = new BorderFormatting(in);
} }
if( containsPatternFormattingBlock()) if (containsPatternFormattingBlock()) {
{
patternFormatting = new PatternFormatting(in); patternFormatting = new PatternFormatting(in);
} }
if(field_3_formula1_len>0) if (field_3_formula1_len > 0) {
{ Stack ptgs = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
field_17_formula1 = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
// Now convert any fields as required // Now convert any fields as required
field_17_formula1 = SharedFormulaRecord.convertSharedFormulas( ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
field_17_formula1, 0, 0 field_17_formula1 = toArray(ptgs);
);
} }
if(field_4_formula2_len>0) if (field_4_formula2_len > 0) {
{ Stack ptgs = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
field_18_formula2 = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
// Now convert any fields as required // Now convert any fields as required
field_18_formula2 = SharedFormulaRecord.convertSharedFormulas( ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
field_18_formula2, 0, 0 field_18_formula2 = toArray(ptgs);
);
} }
} catch (java.lang.UnsupportedOperationException uoe) { } catch (java.lang.UnsupportedOperationException uoe) {
throw new RecordFormatException(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() public byte getConditionType()
{ {
return field_1_condition_type; return field_1_condition_type;
} }
/**
* set the option flags
*
* @param options bitmask
*/
public void setOptions(int options)
{
field_5_options = options;
}
public boolean containsFontFormattingBlock() public boolean containsFontFormattingBlock()
{ {
return getOptionFlag(font); return getOptionFlag(font);
@ -234,11 +236,7 @@ public class CFRuleRecord extends Record
public void setFontFormatting(FontFormatting fontFormatting) public void setFontFormatting(FontFormatting fontFormatting)
{ {
this.fontFormatting = fontFormatting; this.fontFormatting = fontFormatting;
setOptionFlag(true,font); setOptionFlag(fontFormatting != null, font);
}
public void setFontFormattingUnchanged()
{
setOptionFlag(false,font);
} }
public boolean containsAlignFormattingBlock() public boolean containsAlignFormattingBlock()
@ -257,11 +255,7 @@ public class CFRuleRecord extends Record
public void setBorderFormatting(BorderFormatting borderFormatting) public void setBorderFormatting(BorderFormatting borderFormatting)
{ {
this.borderFormatting = borderFormatting; this.borderFormatting = borderFormatting;
setOptionFlag(true,bord); setOptionFlag(borderFormatting != null, bord);
}
public void setBorderFormattingUnchanged()
{
setOptionFlag(false,bord);
} }
public boolean containsPatternFormattingBlock() public boolean containsPatternFormattingBlock()
@ -271,13 +265,10 @@ public class CFRuleRecord extends Record
public void setPatternFormatting(PatternFormatting patternFormatting) public void setPatternFormatting(PatternFormatting patternFormatting)
{ {
this.patternFormatting = patternFormatting; this.patternFormatting = patternFormatting;
setOptionFlag(true,patt); setOptionFlag(patternFormatting!=null, patt);
}
public void setPatternFormattingUnchanged()
{
setOptionFlag(false,patt);
} }
public boolean containsProtectionFormattingBlock() public boolean containsProtectionFormattingBlock()
{ {
return getOptionFlag(prot); return getOptionFlag(prot);
@ -297,42 +288,22 @@ public class CFRuleRecord extends Record
return field_2_comparison_operator; 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 * get the length (in number of tokens) of the expression 1
* @return expression length * @return expression length
*/ */
private short getExpression1Length()
public short getExpression1Length()
{ {
return field_3_formula1_len; 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 * get the length (in number of tokens) of the expression 2
* @return expression length * @return expression length
*/ */
private short getExpression2Length()
public short getExpression2Length()
{ {
return field_4_formula2_len; return field_4_formula2_len;
} }
@ -465,7 +436,7 @@ public class CFRuleRecord extends Record
* callers should check for null! * callers should check for null!
*/ */
public List getParsedExpression1() public Ptg[] getParsedExpression1()
{ {
return field_17_formula1; return field_17_formula1;
} }
@ -479,17 +450,19 @@ public class CFRuleRecord extends Record
* callers should check for null! * callers should check for null!
*/ */
public List getParsedExpression2() public Ptg[] getParsedExpression2()
{ {
return field_18_formula2; return field_18_formula2;
} }
public void setParsedExpression1(Stack ptgs) { private void setParsedExpression1(Ptg[] ptgs) {
setExpression1Length(getTotalPtgSize(field_17_formula1 = ptgs)); short len = getTotalPtgSize(field_17_formula1 = ptgs);
field_3_formula1_len = len;
} }
public void setParsedExpression2(Stack ptgs) { private void setParsedExpression2(Ptg[] ptgs) {
setExpression1Length(getTotalPtgSize(field_18_formula2 = 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 * @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(); int recordsize = getRecordSize();
LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4)); LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
@ -555,21 +530,22 @@ public class CFRuleRecord extends Record
if (getExpression1Length()>0) if (getExpression1Length()>0)
{ {
Ptg.serializePtgStack(this.field_17_formula1, data, offset); Ptg.serializePtgStack(convertToTokenStack(field_17_formula1), data, offset);
offset += getExpression1Length(); offset += getExpression1Length();
} }
if (getExpression2Length()>0) if (getExpression2Length()>0)
{ {
Ptg.serializePtgStack(this.field_18_formula2, data, offset); Ptg.serializePtgStack(convertToTokenStack(field_18_formula2), data, offset);
offset += getExpression2Length(); offset += getExpression2Length();
} }
if(offset - pOffset != recordsize) {
throw new IllegalStateException("write mismatch (" + (offset - pOffset) + "!=" + recordsize + ")");
}
return recordsize; return recordsize;
} }
public int getRecordSize() public int getRecordSize()
{ {
int retval =16+ int retval =16+
@ -582,17 +558,15 @@ public class CFRuleRecord extends Record
return retval; return retval;
} }
private short getTotalPtgSize(List list) private short getTotalPtgSize(Ptg[] ptgs)
{ {
short retval = 0; if( ptgs == null) {
if( list!=null) return 0;
{
for (int k = 0; k < list.size(); k++)
{
Ptg ptg = ( Ptg ) list.get(k);
retval += ptg.getSize();
} }
short retval = 0;
for (int i = 0; i < ptgs.length; i++)
{
retval += ptgs[i].getSize();
} }
return retval; return retval;
} }
@ -618,32 +592,25 @@ public class CFRuleRecord extends Record
} }
public Object clone() { public Object clone() {
CFRuleRecord rec = new CFRuleRecord(); CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
rec.field_1_condition_type= field_1_condition_type;
rec.field_2_comparison_operator = field_2_comparison_operator;
rec.field_3_formula1_len = field_3_formula1_len; rec.field_3_formula1_len = field_3_formula1_len;
rec.field_4_formula2_len = field_4_formula2_len; rec.field_4_formula2_len = field_4_formula2_len;
rec.field_5_options = field_5_options; rec.field_5_options = field_5_options;
rec.field_6_not_used = field_6_not_used; rec.field_6_not_used = field_6_not_used;
if( containsFontFormattingBlock()) if (containsFontFormattingBlock()) {
{ rec.fontFormatting = (FontFormatting) fontFormatting.clone();
rec.fontFormatting = (FontFormatting)fontFormatting.clone();
} }
if( containsBorderFormattingBlock()) if (containsBorderFormattingBlock()) {
{ rec.borderFormatting = (BorderFormatting) borderFormatting.clone();
rec.borderFormatting = (BorderFormatting)borderFormatting.clone();
} }
if( containsPatternFormattingBlock()) if (containsPatternFormattingBlock()) {
{ rec.patternFormatting = (PatternFormatting) patternFormatting.clone();
rec.patternFormatting = (PatternFormatting)patternFormatting.clone();
} }
if( field_3_formula1_len>0) if (field_3_formula1_len > 0) {
{ rec.field_17_formula1 = (Ptg[]) field_17_formula1.clone();
rec.field_17_formula1 = (Stack)field_17_formula1.clone();
} }
if( field_4_formula2_len>0) if (field_4_formula2_len > 0) {
{ rec.field_18_formula2 = (Ptg[]) field_18_formula2.clone();
rec.field_18_formula2 = (Stack)field_18_formula2.clone();
} }
return rec; return rec;
@ -654,4 +621,32 @@ public class CFRuleRecord extends Record
return fontFormatting; 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.CFRuleRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream; 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.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -37,19 +38,38 @@ import org.apache.poi.util.POILogger;
*/ */
public final class CFRecordsAggregate extends Record 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 public final static short sid = -2008; // not a real BIFF record
private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class); private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
private CFHeaderRecord header; private final CFHeaderRecord header;
// List of CFRuleRecord objects /** List of CFRuleRecord objects */
private final List rules; private final List rules;
public CFRecordsAggregate() private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) {
{ if(pHeader == null) {
header = 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); 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) public static CFRecordsAggregate createCFAggregate(List recs, int pOffset)
{ {
Record rec = ( Record ) recs.get(pOffset);
int offset = pOffset; if (rec.getSid() != CFHeaderRecord.sid) {
CFRecordsAggregate cfRecords = new CFRecordsAggregate(); throw new IllegalStateException("next record sid was " + rec.getSid()
ArrayList records = new ArrayList(4); + " instead of " + CFHeaderRecord.sid + " as expected");
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);
} }
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)) if (log.check(POILogger.DEBUG))
{ {
log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, " 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 new CFRecordsAggregate(header, rules);
}
return cfRecords;
} }
/** /**
@ -105,21 +129,16 @@ public final class CFRecordsAggregate extends Record
public CFRecordsAggregate cloneCFAggregate() public CFRecordsAggregate cloneCFAggregate()
{ {
ArrayList records = new ArrayList(this.rules.size()+1); CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
for (int i = 0; i < newRecs.length; i++) {
records.add(this.header.clone()); newRecs[i] = (CFRuleRecord) getRule(i).clone();
for (int i=0; i<this.rules.size();i++)
{
Record rec = (Record)((Record)this.rules.get(i)).clone();
records.add(rec);
} }
return createCFAggregate(records, 0); return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
} }
/** You never fill an aggregate */
protected void fillFields(RecordInputStream in) protected void fillFields(RecordInputStream in)
{ {
// You never fill an aggregate record
} }
public short getSid() public short getSid()
@ -139,17 +158,14 @@ public final class CFRecordsAggregate extends Record
public int serialize(int offset, byte[] data) public int serialize(int offset, byte[] data)
{ {
int nRules = rules.size();
header.setNumberOfConditionalFormats(nRules);
int pos = offset; int pos = offset;
if( header != null && rules.size()>0 )
{
header.setNumberOfConditionalFormats(rules.size());
pos += (( Record ) header).serialize(pos, data); pos += header.serialize(pos, data);
for(int i=0; i< nRules; i++) {
for(Iterator itr = rules.iterator(); itr.hasNext();) pos += getRule(i).serialize(pos, data);
{
pos += (( Record ) itr.next()).serialize(pos, data);
}
} }
return pos - offset; 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() public CFHeaderRecord getHeader()
{ {
return header; return header;
} }
/** private void checkRuleIndex(int idx) {
* @return the rules if(idx < 0 || idx >= rules.size()) {
*/ throw new IllegalArgumentException("Bad rule record index (" + idx
public List getRules() + ") nRules=" + rules.size());
{ }
return rules; }
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; 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 * @author Dmitriy Kumshayev
*/ */
public final class CellRange
public class CellRange
{ {
private int field_1_first_row; /**
private int field_2_last_row; * max index for both row and column<p/>
private short field_3_first_column; *
private short field_4_last_column; * 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; if(!isValid(firstRow, lastRow, firstColumn, lastColumn)) {
this.field_2_last_row = lastRow; throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
this.field_3_first_column = firstColumn; + ", " + firstColumn + ", " + lastColumn + ")");
this.field_4_last_column = lastColumn; }
validateRegion(); _firstRow = firstRow;
_lastRow = convertM1ToMax(lastRow);
_firstColumn = firstColumn;
_lastColumn = convertM1ToMax(lastColumn);
} }
private void validateRegion() private static int convertM1ToMax(int lastIx) {
{ if(lastIx < 0) {
if( field_1_first_row < 0 || return MAX_INDEX;
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());
} }
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() public int getFirstRow()
{ {
return field_1_first_row; return _firstRow;
}
private void setFirstRow(int firstRow)
{
this.field_1_first_row = firstRow;
} }
/**
* @return <tt>-1</tt> for whole column ranges
*/
public int getLastRow() 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; return convertMaxToM1(_lastColumn);
}
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;
} }
public static final int NO_INTERSECTION = 1; public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2; public static final int OVERLAP = 2;
/** first range is within the second range */
public static final int INSIDE = 3; public static final int INSIDE = 3;
/** first range encloses or is equal to the second */
public static final int ENCLOSES = 4; public static final int ENCLOSES = 4;
/** /**
@ -101,30 +149,31 @@ public class CellRange
* NO_INTERSECTION - the specified range is outside of this range;<br/> * NO_INTERSECTION - the specified range is outside of this range;<br/>
* OVERLAP - both ranges partially overlap;<br/> * OVERLAP - both ranges partially overlap;<br/>
* INSIDE - the specified range is inside of this one<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 ) public int intersect(CellRange another )
{ {
int firstRow = another.getFirstRow(); int firstRow = another.getFirstRow();
int lastRow = another.getLastRow(); int lastRow = another.getLastRow();
short firstCol = another.getFirstColumn(); int firstCol = another.getFirstColumn();
short lastCol = another.getLastColumn(); int lastCol = another.getLastColumn();
if if
( (
gt(this.getFirstRow(),lastRow) || gt(getFirstRow(),lastRow) ||
lt(this.getLastRow(),firstRow) || lt(getLastRow(),firstRow) ||
gt(this.getFirstColumn(),lastCol) || gt(getFirstColumn(),lastCol) ||
lt(this.getLastColumn(),firstCol) lt(getLastColumn(),firstCol)
) )
{ {
return NO_INTERSECTION; return NO_INTERSECTION;
} }
else if( this.contains(another) ) else if( contains(another) )
{ {
return INSIDE; return INSIDE;
} }
else if( another.contains(this) ) else if( another.contains(this))
{ {
return ENCLOSES; 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. * Check if the specified range is located inside of this cell range.
* *
@ -145,37 +421,45 @@ public class CellRange
{ {
int firstRow = range.getFirstRow(); int firstRow = range.getFirstRow();
int lastRow = range.getLastRow(); int lastRow = range.getLastRow();
short firstCol = range.getFirstColumn(); int firstCol = range.getFirstColumn();
short lastCol = range.getLastColumn(); int lastCol = range.getLastColumn();
return le(this.getFirstRow(), firstRow) && ge(this.getLastRow(), lastRow) return le(getFirstRow(), firstRow) && ge(getLastRow(), lastRow)
&& le(this.getFirstColumn(), firstCol) && ge(this.getLastColumn(), lastCol); && le(getFirstColumn(), firstCol) && ge(getLastColumn(), lastCol);
} }
public boolean contains(int row, short column) public boolean contains(int row, short column)
{ {
return le(this.getFirstRow(), row) && ge(this.getLastRow(), row) return le(getFirstRow(), row) && ge(getLastRow(), row)
&& le(this.getFirstColumn(), column) && ge(this.getLastColumn(), column); && le(getFirstColumn(), column) && ge(getLastColumn(), column);
} }
/** /**
* Check if the specified cell range has a shared border with the current range. * 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 oFirstRow = range._firstRow;
int lastRow = range.getLastRow(); int oLastRow = range._lastRow;
short firstCol = range.getFirstColumn(); int oFirstCol = range._firstColumn;
short lastCol = range.getLastColumn(); int oLastCol = range._lastColumn;
return
(this.getFirstRow()>0 && this.getFirstRow() - 1 == lastRow || firstRow>0 &&this.getLastRow() == firstRow -1)&& if (_firstRow > 0 && _firstRow-1 == oLastRow ||
(this.getFirstColumn() == firstCol) && oFirstRow > 0 && oFirstRow-1 == _lastRow) {
(this.getLastColumn() == lastCol) || // ranges have a horizontal border in common
(this.getFirstColumn()>0 && this.getFirstColumn() - 1 == lastCol || firstCol>0 && this.getLastColumn() == firstCol -1) && // make sure columns are identical:
(this.getFirstRow() == firstRow) && return _firstColumn == oFirstCol && _lastColumn == oLastCol;
(this.getLastRow() == lastRow) }
;
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()); 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 * @return true if a < b
*/ */
@ -253,7 +525,7 @@ public class CellRange
public String toString() 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 * @author Dmitriy Kumshayev
* *
*/ */
public class HSSFBorderFormatting public final class HSSFBorderFormatting
{ {
/** /** No border */
* No border
*/
public final static short BORDER_NONE = BorderFormatting.BORDER_NONE; public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;
/** Thin border */
/**
* Thin border
*/
public final static short BORDER_THIN = BorderFormatting.BORDER_THIN; public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
/** Medium border */
/**
* Medium border
*/
public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM; public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
/** dash border */
/**
* dash border
*/
public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED; public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
/** dot border */
/**
* dot border
*/
public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR; public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
/** Thick border */
/**
* Thick border
*/
public final static short BORDER_THICK = BorderFormatting.BORDER_THICK; public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
/** double-line border */
/**
* double-line border
*/
public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE; public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
/** hair-line border */
/**
* hair-line border
*/
public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED; 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; 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; 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; 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; 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; 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; public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
private BorderFormatting borderFormatting; private final BorderFormatting borderFormatting;
public HSSFBorderFormatting() public HSSFBorderFormatting()
{ {
@ -125,4 +70,123 @@ public class HSSFBorderFormatting
return borderFormatting; 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; package org.apache.poi.hssf.usermodel;
import java.util.ArrayList; import org.apache.poi.hssf.model.Workbook;
import java.util.List;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
@ -86,13 +84,9 @@ import org.apache.poi.hssf.util.Region;
*/ */
public final class HSSFConditionalFormatting public final class HSSFConditionalFormatting
{ {
private final HSSFSheet sheet; private final Workbook workbook;
private final CFRecordsAggregate cfAggregate; private final CFRecordsAggregate cfAggregate;
HSSFConditionalFormatting(HSSFSheet sheet) {
this(sheet, new CFRecordsAggregate());
}
HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate) HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
{ {
if(sheet == null) { if(sheet == null) {
@ -101,36 +95,25 @@ public final class HSSFConditionalFormatting
if(cfAggregate == null) { if(cfAggregate == null) {
throw new IllegalArgumentException("cfAggregate must not be null"); throw new IllegalArgumentException("cfAggregate must not be null");
} }
this.sheet = sheet; workbook = sheet.workbook.getWorkbook();
this.cfAggregate = cfAggregate; this.cfAggregate = cfAggregate;
} }
CFRecordsAggregate getCFRecordsAggregate() { CFRecordsAggregate getCFRecordsAggregate() {
return cfAggregate; return cfAggregate;
} }
public void setFormattingRegions(Region[] regions)
{
if( regions != null)
{
CFHeaderRecord header = cfAggregate.getHeader();
header.setCellRanges(mergeCellRanges(toCellRangeList(regions)));
}
}
/** /**
* @return array of <tt>Region</tt>s. never <code>null</code> * @return array of <tt>Region</tt>s. never <code>null</code>
*/ */
public Region[] getFormattingRegions() public Region[] getFormattingRegions()
{ {
CFHeaderRecord cfh = cfAggregate.getHeader(); CFHeaderRecord cfh = cfAggregate.getHeader();
CellRange[] cellRanges = cfh.getCellRanges();
List cellRanges = cfh.getCellRanges(); return CellRange.convertCellRangesToRegions(cellRanges);
return toRegionArray(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. * Excel allows to create up to 3 Conditional Formatting rules.
* This method can be useful to modify existing 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) public void setRule(int idx, HSSFConditionalFormattingRule cfRule)
{ {
if (idx < 0 || idx > 2) { cfAggregate.setRule(idx, cfRule.getCfRuleRecord());
throw new IllegalArgumentException("idx must be between 0 and 2 but was ("
+ idx + ")");
}
cfAggregate.getRules().set(idx, cfRule);
} }
/** /**
@ -153,136 +132,24 @@ public final class HSSFConditionalFormatting
*/ */
public void addRule(HSSFConditionalFormattingRule cfRule) public void addRule(HSSFConditionalFormattingRule cfRule)
{ {
cfAggregate.getRules().add(cfRule); cfAggregate.addRule(cfRule.getCfRuleRecord());
} }
/** /**
* get a Conditional Formatting rule at position idx. * @return the Conditional Formatting rule at position idx.
* @param idx
* @return a Conditional Formatting rule at position idx.
*/ */
public HSSFConditionalFormattingRule getRule(int idx) public HSSFConditionalFormattingRule getRule(int idx)
{ {
CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx); CFRuleRecord ruleRecord = cfAggregate.getRule(idx);
return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord); return new HSSFConditionalFormattingRule(workbook, ruleRecord);
} }
/** /**
* @return number of Conditional Formatting rules. * @return number of Conditional Formatting rules.
*/ */
public int getNumbOfRules() public int getNumberOfRules()
{ {
return cfAggregate.getRules().size(); return cfAggregate.getNumberOfRules();
}
/**
* 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;
} }
public String toString() public String toString()

View File

@ -18,166 +18,76 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.List; import java.util.List;
import java.util.Stack;
import org.apache.poi.hssf.model.FormulaParser; 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;
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; 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 * @author Dmitriy Kumshayev
*/ */
public class HSSFConditionalFormattingRule public final class HSSFConditionalFormattingRule
{ {
public static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS; private 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 CFRuleRecord cfRuleRecord;
private HSSFWorkbook workbook;
protected HSSFConditionalFormattingRule(HSSFWorkbook workbook) private final CFRuleRecord cfRuleRecord;
{ private final Workbook workbook;
this.workbook = workbook;
this.cfRuleRecord = new CFRuleRecord(); 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; return cfRuleRecord;
this.cfRuleRecord = 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(); PatternFormatting block = patternFmt==null ? null : patternFmt.getPatternFormattingBlock();
} cfRuleRecord.setPatternFormatting(block);
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);
}
} }
public String getFormula1() public String getFormula1()
@ -188,61 +98,25 @@ public class HSSFConditionalFormattingRule
public String getFormula2() public String getFormula2()
{ {
byte conditionType = cfRuleRecord.getConditionType(); byte conditionType = cfRuleRecord.getConditionType();
switch(conditionType) if (conditionType == CELL_COMPARISON) {
{
case CELL_COMPARISON:
{
byte comparisonOperation = cfRuleRecord.getComparisonOperation(); byte comparisonOperation = cfRuleRecord.getComparisonOperation();
switch(comparisonOperation) switch(comparisonOperation)
{ {
case COMPARISON_OPERATOR_BETWEEN: case ComparisonOperator.BETWEEN:
case COMPARISON_OPERATOR_NOT_BETWEEN: case ComparisonOperator.NOT_BETWEEN:
return toFormulaString(cfRuleRecord.getParsedExpression2()); return toFormulaString(cfRuleRecord.getParsedExpression2());
} }
} }
}
return null; return null;
} }
private String toFormulaString(List parsedExpression) private String toFormulaString(Ptg[] parsedExpression)
{ {
String formula = null; String formula = null;
if(parsedExpression!=null) if(parsedExpression!=null)
{ {
formula = FormulaParser.toFormulaString(workbook.getWorkbook(),parsedExpression); formula = FormulaParser.toFormulaString(workbook, parsedExpression);
} }
return formula; 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 * @param leftcol the left column to show in desktop window pane
*/ */
public void showInPane(short toprow, short leftcol){ public void showInPane(short toprow, short leftcol){
this.sheet.setTopRow((short)toprow); this.sheet.setTopRow(toprow);
this.sheet.setLeftCol((short)leftcol); this.sheet.setLeftCol(leftcol);
} }
/** /**
@ -1438,7 +1438,7 @@ public final class HSSFSheet {
int i = 0; int i = 0;
while (iterator.hasNext()) { while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
returnValue[i++] = (int)breakItem.main; returnValue[i++] = breakItem.main;
} }
return returnValue; return returnValue;
} }
@ -1806,7 +1806,7 @@ public final class HSSFSheet {
* *
* @return cell comment or <code>null</code> if not found * @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 // Don't call findCellComment directly, otherwise
// two calls to this method will result in two // two calls to this method will result in two
// new HSSFComment instances, which is bad // new HSSFComment instances, which is bad
@ -1830,25 +1830,26 @@ public final class HSSFSheet {
* with a cell comparison operator and * with a cell comparison operator and
* formatting rules such as font format, border format and pattern format * formatting rules such as font format, border format and pattern format
* *
* @param comparisonOperation - one of the following values: <p> * @param comparisonOperation - a constant value from
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li> * <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li> * <ul>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li> * <li>BETWEEN</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li> * <li>NOT_BETWEEN</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li> * <li>EQUAL</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li> * <li>NOT_EQUAL</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li> * <li>GT</li>
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li> * <li>LT</li>
* <li>GE</li>
* <li>LE</li>
* </ul>
* </p> * </p>
* @param formula1 - formula for the valued, compared with the cell * @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with * @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations) * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules * @param fontFmt - font formatting rules (may be <code>null</code>)
* @param bordFmt - border formatting rules * @param bordFmt - border formatting rules (may be <code>null</code>)
* @param patternFmt - pattern formatting rules * @param patternFmt - pattern formatting rules (may be <code>null</code>)
* @return
*
*/ */
public HSSFConditionalFormattingRule createConditionalFormattingRule( public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation, byte comparisonOperation,
@ -1856,14 +1857,11 @@ public final class HSSFSheet {
String formula2, String formula2,
HSSFFontFormatting fontFmt, HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt, HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt) HSSFPatternFormatting patternFmt) {
{
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook); Workbook wb = workbook.getWorkbook();
cf.setFontFormatting(fontFmt); CFRuleRecord rr = CFRuleRecord.create(wb, comparisonOperation, formula1, formula2);
cf.setBorderFormatting(bordFmt); return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
cf.setPatternFormatting(patternFmt);
cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
return cf;
} }
/** /**
@ -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. * 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> * @param formula - formula for the valued, compared with the cell
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li> * @param fontFmt - font formatting rules (may be <code>null</code>)
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li> * @param bordFmt - border formatting rules (may be <code>null</code>)
* <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li> * @param patternFmt - pattern formatting rules (may be <code>null</code>)
* <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
*
*/ */
public HSSFConditionalFormattingRule createConditionalFormattingRule( public HSSFConditionalFormattingRule createConditionalFormattingRule(
String formula, String formula,
HSSFFontFormatting fontFmt, HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt, HSSFBorderFormatting bordFmt,
HSSFPatternFormatting patternFmt) HSSFPatternFormatting patternFmt) {
{ Workbook wb = workbook.getWorkbook();
HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook); CFRuleRecord rr = CFRuleRecord.create(wb, formula);
cf.setFontFormatting(fontFmt); return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
cf.setBorderFormatting(bordFmt);
cf.setPatternFormatting(patternFmt);
cf.setFormulaCondition(formula);
return cf;
} }
/** /**
@ -1918,8 +1897,7 @@ public final class HSSFSheet {
* @param cf HSSFConditionalFormatting object * @param cf HSSFConditionalFormatting object
* @return index of the new Conditional Formatting object * @return index of the new Conditional Formatting object
*/ */
public int addConditionalFormatting( HSSFConditionalFormatting cf ) public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
{
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate(); CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
return sheet.addConditionalFormatting(cfraClone); return sheet.addConditionalFormatting(cfraClone);
@ -1929,46 +1907,46 @@ public final class HSSFSheet {
* Allows to add a new Conditional Formatting set to the sheet. * Allows to add a new Conditional Formatting set to the sheet.
* *
* @param regions - list of rectangular regions to apply conditional formatting rules * @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 * @return index of the newly created Conditional Formatting object
*/ */
public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules ) public int addConditionalFormatting(Region [] regions, HSSFConditionalFormattingRule [] hcfRules) {
{ if (regions == null) {
HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this); throw new IllegalArgumentException("regions must not be null");
cf.setFormattingRegions(regions);
if( cfRules != null )
{
for( int i=0; i!= cfRules.length; i++ )
{
cf.addRule(cfRules[i]);
} }
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 * 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 * @return Conditional Formatting object
*/ */
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index); CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null ) if (cf == null) {
{
return new HSSFConditionalFormatting(this,cf);
}
return null; return null;
} }
return new HSSFConditionalFormatting(this,cf);
}
/** /**
* @return number of Conditional Formatting objects of the sheet * @return number of Conditional Formatting objects of the sheet
*/ */
public int getNumConditionalFormattings() public int getNumConditionalFormattings() {
{
return sheet.getNumConditionalFormattings(); return sheet.getNumConditionalFormattings();
} }
@ -1976,8 +1954,7 @@ public final class HSSFSheet {
* removes a Conditional Formatting object by index * removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove * @param index of a Conditional Formatting object to remove
*/ */
public void removeConditionalFormatting(int index) public void removeConditionalFormatting(int index) {
{
sheet.removeConditionalFormatting(index); sheet.removeConditionalFormatting(index);
} }
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
import org.apache.poi.hssf.record.formula.AllFormulaTests; import org.apache.poi.hssf.record.formula.AllFormulaTests;
import junit.framework.Test; import junit.framework.Test;
@ -33,6 +34,7 @@ public final class AllRecordTests {
TestSuite result = new TestSuite(AllRecordTests.class.getName()); TestSuite result = new TestSuite(AllRecordTests.class.getName());
result.addTest(AllFormulaTests.suite()); result.addTest(AllFormulaTests.suite());
result.addTest(AllRecordAggregateTests.suite());
result.addTestSuite(TestAreaFormatRecord.class); result.addTestSuite(TestAreaFormatRecord.class);
result.addTestSuite(TestAreaRecord.class); result.addTestSuite(TestAreaRecord.class);
@ -45,6 +47,8 @@ public final class AllRecordTests {
result.addTestSuite(TestBarRecord.class); result.addTestSuite(TestBarRecord.class);
result.addTestSuite(TestBoundSheetRecord.class); result.addTestSuite(TestBoundSheetRecord.class);
result.addTestSuite(TestCategorySeriesAxisRecord.class); result.addTestSuite(TestCategorySeriesAxisRecord.class);
result.addTestSuite(TestCFHeaderRecord.class);
result.addTestSuite(TestCFRuleRecord.class);
result.addTestSuite(TestChartRecord.class); result.addTestSuite(TestChartRecord.class);
result.addTestSuite(TestChartTitleFormatRecord.class); result.addTestSuite(TestChartTitleFormatRecord.class);
result.addTestSuite(TestCommonObjectDataSubRecord.class); result.addTestSuite(TestCommonObjectDataSubRecord.class);

View File

@ -17,9 +17,6 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.record.cf.CellRange; import org.apache.poi.hssf.record.cf.CellRange;
@ -30,28 +27,23 @@ import org.apache.poi.hssf.record.cf.CellRange;
* *
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public class TestCFHeaderRecord public final class TestCFHeaderRecord extends TestCase
extends TestCase
{ {
public TestCFHeaderRecord(String name)
{
super(name);
}
public void testCreateCFHeaderRecord () public void testCreateCFHeaderRecord ()
{ {
CFHeaderRecord record = new CFHeaderRecord(); CFHeaderRecord record = new CFHeaderRecord();
List ranges = new ArrayList(); CellRange[] ranges = {
ranges.add(new CellRange(0,-1,(short)5,(short)5)); new CellRange(0,-1,5,5),
ranges.add(new CellRange(0,-1,(short)6,(short)6)); new CellRange(0,-1,6,6),
ranges.add(new CellRange(0,1,(short)0,(short)1)); new CellRange(0,1,0,1),
ranges.add(new CellRange(0,1,(short)2,(short)3)); new CellRange(0,1,2,3),
ranges.add(new CellRange(2,3,(short)0,(short)1)); new CellRange(2,3,0,1),
ranges.add(new CellRange(2,3,(short)2,(short)3)); new CellRange(2,3,2,3),
};
record.setCellRanges(ranges); record.setCellRanges(ranges);
ranges = record.getCellRanges(); ranges = record.getCellRanges();
assertEquals(6,ranges.size()); assertEquals(6,ranges.length);
CellRange enclosingCellRange = record.getEnclosingCellRange(); CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow()); assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(-1, enclosingCellRange.getLastRow()); assertEquals(-1, enclosingCellRange.getLastRow());
@ -106,23 +98,27 @@ public class TestCFHeaderRecord
assertEquals(3, enclosingCellRange.getLastRow()); assertEquals(3, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn()); assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(3, enclosingCellRange.getLastColumn()); assertEquals(3, enclosingCellRange.getLastColumn());
List ranges = record.getCellRanges(); CellRange[] ranges = record.getCellRanges();
assertEquals(0, ((CellRange)ranges.get(0)).getFirstRow()); CellRange range0 = ranges[0];
assertEquals(1, ((CellRange)ranges.get(0)).getLastRow()); assertEquals(0, range0.getFirstRow());
assertEquals(0, ((CellRange)ranges.get(0)).getFirstColumn()); assertEquals(1, range0.getLastRow());
assertEquals(1, ((CellRange)ranges.get(0)).getLastColumn()); assertEquals(0, range0.getFirstColumn());
assertEquals(0, ((CellRange)ranges.get(1)).getFirstRow()); assertEquals(1, range0.getLastColumn());
assertEquals(1, ((CellRange)ranges.get(1)).getLastRow()); CellRange range1 = ranges[1];
assertEquals(2, ((CellRange)ranges.get(1)).getFirstColumn()); assertEquals(0, range1.getFirstRow());
assertEquals(3, ((CellRange)ranges.get(1)).getLastColumn()); assertEquals(1, range1.getLastRow());
assertEquals(2, ((CellRange)ranges.get(2)).getFirstRow()); assertEquals(2, range1.getFirstColumn());
assertEquals(3, ((CellRange)ranges.get(2)).getLastRow()); assertEquals(3, range1.getLastColumn());
assertEquals(0, ((CellRange)ranges.get(2)).getFirstColumn()); CellRange range2 = ranges[2];
assertEquals(1, ((CellRange)ranges.get(2)).getLastColumn()); assertEquals(2, range2.getFirstRow());
assertEquals(2, ((CellRange)ranges.get(3)).getFirstRow()); assertEquals(3, range2.getLastRow());
assertEquals(3, ((CellRange)ranges.get(3)).getLastRow()); assertEquals(0, range2.getFirstColumn());
assertEquals(2, ((CellRange)ranges.get(3)).getFirstColumn()); assertEquals(1, range2.getLastColumn());
assertEquals(3, ((CellRange)ranges.get(3)).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()); assertEquals(recordData.length+4, record.getRecordSize());
byte[] output = record.serialize(); byte[] output = record.serialize();
@ -141,5 +137,4 @@ public class TestCFHeaderRecord
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord"); System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class); junit.textui.TestRunner.run(TestCFHeaderRecord.class);
} }
} }

View File

@ -19,10 +19,13 @@ package org.apache.poi.hssf.record;
import junit.framework.TestCase; 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.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting; import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting; import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.LittleEndian;
/** /**
* Tests the serialization and deserialization of the TestCFRuleRecord * Tests the serialization and deserialization of the TestCFRuleRecord
@ -30,18 +33,13 @@ import org.apache.poi.hssf.util.HSSFColor;
* *
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public class TestCFRuleRecord public final class TestCFRuleRecord extends TestCase
extends TestCase
{ {
public TestCFRuleRecord(String name)
{
super(name);
}
public void testCreateCFRuleRecord () public void testCreateCFRuleRecord ()
{ {
CFRuleRecord record = new CFRuleRecord(); Workbook workbook = Workbook.createWorkbook();
CFRuleRecord record = CFRuleRecord.create(workbook, "7");
testCFRuleRecord(record); testCFRuleRecord(record);
// Serialize // Serialize
@ -134,7 +132,6 @@ public class TestCFRuleRecord
patternFormatting.setFillPattern(PatternFormatting.DIAMONDS); patternFormatting.setFillPattern(PatternFormatting.DIAMONDS);
assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern()); assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern());
} }
private void testBorderFormattingAccessors(BorderFormatting borderFormatting) private void testBorderFormattingAccessors(BorderFormatting borderFormatting)
@ -286,11 +283,29 @@ public class TestCFRuleRecord
assertTrue(fontFormatting.isUnderlineTypeModified()); 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) public static void main(String[] ignored_args)
{ {
System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord"); System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord");
junit.textui.TestRunner.run(TestCFRuleRecord.class); 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 junit.framework.TestCase;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.RecordFactory; import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.CellRange; import org.apache.poi.hssf.record.cf.CellRange;
/** /**
@ -35,34 +37,28 @@ import org.apache.poi.hssf.record.cf.CellRange;
* *
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public class TestCFRecordsAggregate public final class TestCFRecordsAggregate extends TestCase
extends TestCase
{ {
public TestCFRecordsAggregate(String name)
{
super(name);
}
public void testCFRecordsAggregate() public void testCFRecordsAggregate()
{ {
CFRecordsAggregate record = new CFRecordsAggregate(); Workbook workbook = Workbook.createWorkbook();
List recs = new ArrayList(); List recs = new ArrayList();
CFHeaderRecord header = new CFHeaderRecord(); CFHeaderRecord header = new CFHeaderRecord();
CFRuleRecord rule1 = new CFRuleRecord(); CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
CFRuleRecord rule2 = new CFRuleRecord(); CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
CFRuleRecord rule3 = new CFRuleRecord(); CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.GE, "100", null);
header.setNumberOfConditionalFormats(3); header.setNumberOfConditionalFormats(3);
CellRange range1 = new CellRange(0,1,(short)0,(short)0); CellRange[] cellRanges = {
CellRange range2 = new CellRange(0,1,(short)2,(short)2); new CellRange(0,1,0,0),
List cellRanges = new ArrayList(); new CellRange(0,1,2,2),
cellRanges.add(range1); };
cellRanges.add(range2);
header.setCellRanges(cellRanges); header.setCellRanges(cellRanges);
recs.add(header); recs.add(header);
recs.add(rule1); recs.add(rule1);
recs.add(rule2); recs.add(rule2);
recs.add(rule3); recs.add(rule3);
CFRecordsAggregate record;
record = CFRecordsAggregate.createCFAggregate(recs, 0); record = CFRecordsAggregate.createCFAggregate(recs, 0);
// Serialize // Serialize
@ -82,7 +78,7 @@ public class TestCFRecordsAggregate
rule3 = (CFRuleRecord)recs.get(3); rule3 = (CFRuleRecord)recs.get(3);
cellRanges = header.getCellRanges(); cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size()); assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats()); assertEquals(3, header.getNumberOfConditionalFormats());
record = CFRecordsAggregate.createCFAggregate(recs, 0); record = CFRecordsAggregate.createCFAggregate(recs, 0);
@ -90,15 +86,15 @@ public class TestCFRecordsAggregate
record = record.cloneCFAggregate(); record = record.cloneCFAggregate();
assertNotNull(record.getHeader()); assertNotNull(record.getHeader());
assertEquals(3,record.getRules().size()); assertEquals(3,record.getNumberOfRules());
header = record.getHeader(); header = record.getHeader();
rule1 = (CFRuleRecord)record.getRules().get(0); rule1 = record.getRule(0);
rule2 = (CFRuleRecord)record.getRules().get(1); rule2 = record.getRule(1);
rule3 = (CFRuleRecord)record.getRules().get(2); rule3 = record.getRule(2);
cellRanges = header.getCellRanges(); cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.size()); assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats()); assertEquals(3, header.getNumberOfConditionalFormats());
} }

View File

@ -24,13 +24,13 @@ import junit.framework.TestCase;
*/ */
public class TestCellRange extends TestCase public class TestCellRange extends TestCase
{ {
private static final CellRange biggest = new CellRange(0, -1,(short) 0,(short)-1); private static final CellRange biggest = new CellRange( 0, -1, 0,-1);
private static final CellRange tenthColumn = new CellRange(0, -1,(short)10,(short)10); private static final CellRange tenthColumn = new CellRange( 0, -1,10,10);
private static final CellRange tenthRow = new CellRange(10,10,(short) 0,(short)-1); private static final CellRange tenthRow = new CellRange(10, 10, 0,-1);
private static final CellRange box10x10 = new CellRange(0, 10,(short) 0,(short)10); private static final CellRange box10x10 = new CellRange( 0, 10, 0,10);
private static final CellRange box9x9 = new CellRange(0, 9,(short) 0,(short) 9); private static final CellRange box9x9 = new CellRange( 0, 9, 0, 9);
private static final CellRange box10to20c = new CellRange(0, 10,(short)10,(short)20); private static final CellRange box10to20c = new CellRange( 0, 10,10,20);
private static final CellRange oneCell = new CellRange(10,10,(short)10,(short)10); private static final CellRange oneCell = new CellRange(10, 10,10,10);
boolean [][] contanis = new boolean[][] 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 col1 = new CellRange( 0, -1, 1,1);
private static final CellRange col2 = new CellRange(0, -1,(short) 2,(short)2); private static final CellRange col2 = new CellRange( 0, -1, 2,2);
private static final CellRange row1 = new CellRange(1, 1,(short) 0,(short)-1); private static final CellRange row1 = new CellRange( 1, 1, 0,-1);
private static final CellRange row2 = new CellRange(2, 2,(short) 0,(short)-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 box0 = new CellRange( 0, 2, 0,2);
private static final CellRange box1 = new CellRange( 0, 1,(short) 0,(short)1); private static final CellRange box1 = new CellRange( 0, 1, 0,1);
private static final CellRange box2 = new CellRange( 0, 1,(short) 2,(short)3); private static final CellRange box2 = new CellRange( 0, 1, 2,3);
private static final CellRange box3 = new CellRange( 2, 3,(short) 0,(short)1); private static final CellRange box3 = new CellRange( 2, 3, 0,1);
private static final CellRange box4 = new CellRange( 2, 3,(short) 2,(short)3); private static final CellRange box4 = new CellRange( 2, 3, 2,3);
private static final CellRange box5 = new CellRange( 1, 3,(short) 1,(short)3); private static final CellRange box5 = new CellRange( 1, 3, 1,3);
public void testHasSharedBorderMethod() public void testHasSharedBorderMethod()
{ {
assertFalse(col1.hasSharedBorder(col1)); assertFalse(col1.hasExactSharedBorder(col1));
assertFalse(col2.hasSharedBorder(col2)); assertFalse(col2.hasExactSharedBorder(col2));
assertTrue(col1.hasSharedBorder(col2)); assertTrue(col1.hasExactSharedBorder(col2));
assertTrue(col2.hasSharedBorder(col1)); assertTrue(col2.hasExactSharedBorder(col1));
assertFalse(row1.hasSharedBorder(row1)); assertFalse(row1.hasExactSharedBorder(row1));
assertFalse(row2.hasSharedBorder(row2)); assertFalse(row2.hasExactSharedBorder(row2));
assertTrue(row1.hasSharedBorder(row2)); assertTrue(row1.hasExactSharedBorder(row2));
assertTrue(row2.hasSharedBorder(row1)); assertTrue(row2.hasExactSharedBorder(row1));
assertFalse(row1.hasSharedBorder(col1)); assertFalse(row1.hasExactSharedBorder(col1));
assertFalse(row1.hasSharedBorder(col2)); assertFalse(row1.hasExactSharedBorder(col2));
assertFalse(col1.hasSharedBorder(row1)); assertFalse(col1.hasExactSharedBorder(row1));
assertFalse(col2.hasSharedBorder(row1)); assertFalse(col2.hasExactSharedBorder(row1));
assertFalse(row2.hasSharedBorder(col1)); assertFalse(row2.hasExactSharedBorder(col1));
assertFalse(row2.hasSharedBorder(col2)); assertFalse(row2.hasExactSharedBorder(col2));
assertFalse(col1.hasSharedBorder(row2)); assertFalse(col1.hasExactSharedBorder(row2));
assertFalse(col2.hasSharedBorder(row2)); assertFalse(col2.hasExactSharedBorder(row2));
assertTrue(col2.hasSharedBorder(col1)); assertTrue(col2.hasExactSharedBorder(col1));
assertFalse(box1.hasSharedBorder(box1)); assertFalse(box1.hasExactSharedBorder(box1));
assertTrue(box1.hasSharedBorder(box2)); assertTrue(box1.hasExactSharedBorder(box2));
assertTrue(box1.hasSharedBorder(box3)); assertTrue(box1.hasExactSharedBorder(box3));
assertFalse(box1.hasSharedBorder(box4)); assertFalse(box1.hasExactSharedBorder(box4));
assertTrue(box2.hasSharedBorder(box1)); assertTrue(box2.hasExactSharedBorder(box1));
assertFalse(box2.hasSharedBorder(box2)); assertFalse(box2.hasExactSharedBorder(box2));
assertFalse(box2.hasSharedBorder(box3)); assertFalse(box2.hasExactSharedBorder(box3));
assertTrue(box2.hasSharedBorder(box4)); assertTrue(box2.hasExactSharedBorder(box4));
assertTrue(box3.hasSharedBorder(box1)); assertTrue(box3.hasExactSharedBorder(box1));
assertFalse(box3.hasSharedBorder(box2)); assertFalse(box3.hasExactSharedBorder(box2));
assertFalse(box3.hasSharedBorder(box3)); assertFalse(box3.hasExactSharedBorder(box3));
assertTrue(box3.hasSharedBorder(box4)); assertTrue(box3.hasExactSharedBorder(box4));
assertFalse(box4.hasSharedBorder(box1)); assertFalse(box4.hasExactSharedBorder(box1));
assertTrue(box4.hasSharedBorder(box2)); assertTrue(box4.hasExactSharedBorder(box2));
assertTrue(box4.hasSharedBorder(box3)); assertTrue(box4.hasExactSharedBorder(box3));
assertFalse(box4.hasSharedBorder(box4)); assertFalse(box4.hasExactSharedBorder(box4));
} }
public void testIntersectMethod() public void testIntersectMethod()
@ -135,5 +135,4 @@ public class TestCellRange extends TestCase
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn)); assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow)); 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);
}
}
}