<!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/>
<person id="GJS" name="Glen Stampoultzis" email="user@poi.apache.org"/>
+ <person id="JM" name="Josh Micich" email="josh@apache.org"/>
<person id="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
<!-- Don't forget to update status.xml too! -->
<release version="3.0.3-beta1" date="2008-04-??">
+ <action dev="POI-DEVELOPERS" type="add">Implement Sheet.removeShape(Shape shape) in HSLF</action>
+ <action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
+ <action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>
<!-- in strict alphabetical order -->
<person id="AO" name="Andrew C. Oliver" email="acoliver2@users.sourceforge.net"/>
<person id="GJS" name="Glen Stampoultzis" email="user@poi.apache.org"/>
+ <person id="JM" name="Josh Micich" email="josh@apache.org"/>
<person id="MJ" name="Marc Johnson" email="mjohnson@apache.org"/>
<person id="NKB" name="Nicola Ken Barozzi" email="barozzi@nicolaken.com"/>
<person id="NB" name="Nick Burch" email="nick@torchbox.com"/>
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.0.3-beta1" date="2008-04-??">
+ <action dev="POI-DEVELOPERS" type="add">Implement Sheet.removeShape(Shape shape) in HSLF</action>
+ <action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
+ <action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
<action dev="POI-DEVELOPERS" type="add">44652 / 44603 - Improved handling of Pictures in Word Documents</action>
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
-
-
/**
* This class parses a formula string into a List of tokens in RPN order.
* Inspired by
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
public final class FormulaParser {
-
+
/**
* Specific exception thrown when a supplied formula does not parse properly.<br/>
* Primarily used by test cases when testing for specific parsing exceptions.</p>
- *
+ *
*/
static final class FormulaParseException extends RuntimeException {
// This class was given package scope until it would become clear that it is useful to
limitations under the License.
==================================================================== */
-/*
- * ConditionalFormattingHeaderRecord.java
- *
- * Created on January 17, 2008, 3:05 AM
- */
package org.apache.poi.hssf.record;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
import org.apache.poi.hssf.record.cf.CellRange;
+import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.LittleEndian;
/**
*
* @author Dmitriy Kumshayev
*/
-public class CFHeaderRecord extends Record
+public final class CFHeaderRecord extends Record
{
public static final short sid = 0x1B0;
+ private static final CellRange[] EMPTY_CELL_RANGE_ARRAY = { };
+
private int field_1_numcf;
private int field_2_need_recalculation;
private CellRange field_3_enclosing_cell_range;
- private List field_4_cell_ranges;
+ private CellRange[] field_4_cell_ranges;
/** Creates new CFHeaderRecord */
public CFHeaderRecord()
{
- field_4_cell_ranges = new ArrayList(5);
+ field_4_cell_ranges = EMPTY_CELL_RANGE_ARRAY;
+ }
+ public CFHeaderRecord(Region[] regions)
+ {
+ CellRange[] unmergedRanges = CellRange.convertRegionsToCellRanges(regions);
+ CellRange[] mergeCellRanges = CellRange.mergeCellRanges(unmergedRanges);
+ setCellRanges(mergeCellRanges);
}
public CFHeaderRecord(RecordInputStream in)
field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
int numCellRanges = in.readShort();
- field_4_cell_ranges = new ArrayList(5);
+ CellRange[] crs = new CellRange[numCellRanges];
for( int i=0; i<numCellRanges; i++)
{
- field_4_cell_ranges.add(new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort()));
+ crs[i] = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
}
+ field_4_cell_ranges = crs;
}
public int getNumberOfConditionalFormats()
* modify the enclosing cell range accordingly.
* @param List cellRanges - list of CellRange objects
*/
- public void setCellRanges( List cellRanges )
+ public void setCellRanges(CellRange[] cellRanges)
{
- field_4_cell_ranges.clear();
- if(cellRanges!=null)
+ if(cellRanges == null)
{
- field_3_enclosing_cell_range=null;
- for( int i=0; i<cellRanges.size(); i++)
- {
- field_4_cell_ranges.add(cellRanges.get(i));
- recalculateEnclosingRange((CellRange)cellRanges.get(i));
- }
+ throw new IllegalArgumentException("cellRanges must not be null");
}
- }
-
- private void recalculateEnclosingRange(CellRange cellRange)
- {
- field_3_enclosing_cell_range = cellRange.createEnclosingCellRange(field_3_enclosing_cell_range);
+ field_4_cell_ranges = (CellRange[]) cellRanges.clone();
+ CellRange enclosingRange = null;
+ for (int i = 0; i < cellRanges.length; i++)
+ {
+ enclosingRange = cellRanges[i].createEnclosingCellRange(enclosingRange);
+ }
+ field_3_enclosing_cell_range=enclosingRange;
}
- public List getCellRanges()
+ public CellRange[] getCellRanges()
{
- return field_4_cell_ranges;
+ return (CellRange[]) field_4_cell_ranges.clone();
}
public String toString()
StringBuffer buffer = new StringBuffer();
buffer.append("[CFHEADER]\n");
- buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
- buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
- buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
- buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
- if( field_4_cell_ranges.size()>0)
+ buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
+ buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
+ buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
+ buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
+ if( field_4_cell_ranges.length>0)
{
- buffer.append(" .cfranges=[");
- for( int i=0; i<field_4_cell_ranges.size(); i++)
+ buffer.append(" .cfranges=[");
+ for( int i=0; i<field_4_cell_ranges.length; i++)
{
- buffer.append(i==0?"":",").append(field_4_cell_ranges.get(i));
+ buffer.append(i==0?"":",").append(field_4_cell_ranges[i].toString());
}
buffer.append("]\n");
}
LittleEndian.putShort(data, 10 + offset, (short) field_3_enclosing_cell_range.getLastRow());
LittleEndian.putShort(data, 12 + offset, (short) field_3_enclosing_cell_range.getFirstColumn());
LittleEndian.putShort(data, 14 + offset, (short) field_3_enclosing_cell_range.getLastColumn());
- LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.size());
- for( int i=0 ; i!=field_4_cell_ranges.size(); i++)
+ LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.length);
+ for( int i=0 ; i!=field_4_cell_ranges.length; i++)
{
- LittleEndian.putShort(data, 18 + 0 + 8 * i + offset,
- (short) ((CellRange) field_4_cell_ranges.get(i)).getFirstRow());
- LittleEndian.putShort(data, 18 + 2 + 8 * i + offset,
- (short) ((CellRange) field_4_cell_ranges.get(i)).getLastRow());
- LittleEndian.putShort(data, 18 + 4 + 8 * i + offset,
- (short) ((CellRange) field_4_cell_ranges.get(i)).getFirstColumn());
- LittleEndian.putShort(data, 18 + 6 + 8 * i + offset,
- (short) ((CellRange) field_4_cell_ranges.get(i)).getLastColumn());
+ CellRange cr = field_4_cell_ranges[i];
+ LittleEndian.putShort(data, 18 + 0 + 8 * i + offset, (short) cr.getFirstRow());
+ LittleEndian.putShort(data, 18 + 2 + 8 * i + offset, (short) cr.getLastRow());
+ LittleEndian.putShort(data, 18 + 4 + 8 * i + offset, (short) cr.getFirstColumn());
+ LittleEndian.putShort(data, 18 + 6 + 8 * i + offset, (short) cr.getLastColumn());
}
return getRecordSize();
}
public int getRecordSize()
{
- return 18+8*field_4_cell_ranges.size();
+ return 18+8*field_4_cell_ranges.length;
}
/**
return sid;
}
- public Object clone()
- {
- CFHeaderRecord rec = new CFHeaderRecord();
- rec.field_1_numcf = field_1_numcf;
- rec.field_2_need_recalculation = field_2_need_recalculation;
- rec.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
- rec.field_4_cell_ranges = new ArrayList(field_4_cell_ranges.size());
- Iterator iterator = field_4_cell_ranges.iterator();
- while (iterator.hasNext())
- {
- CellRange oldRange = (CellRange)iterator.next();
- rec.field_4_cell_ranges.add(oldRange.cloneCellRange());
- }
- return rec;
- }
-
+ public Object clone()
+ {
+ CFHeaderRecord result = new CFHeaderRecord();
+ result.field_1_numcf = field_1_numcf;
+ result.field_2_need_recalculation = field_2_need_recalculation;
+ result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
+ CellRange[] crs = new CellRange[field_4_cell_ranges.length];
+ for (int i = 0; i < crs.length; i++) {
+ crs[i] = field_4_cell_ranges[i].cloneCellRange();
+ }
+ result.field_4_cell_ranges = crs;
+ return result;
+ }
}
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
==================================================================== */
-/*
- * ConditionalFormattingRuleRecord.java
- *
- * Created on January 23, 2008, 9:56 AM
- */
package org.apache.poi.hssf.record;
-import java.util.List;
import java.util.Stack;
+import org.apache.poi.hssf.model.FormulaParser;
+import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
* Conditional Formatting Rule Record.
* @author Dmitriy Kumshayev
*/
-
-public class CFRuleRecord extends Record
+public final class CFRuleRecord extends Record
{
-
- public static final short sid = 0x01B1;
-
- private byte field_1_condition_type;
- public static final byte CONDITION_TYPE_NO_CONDITION_TYPE = 0;
- public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
- public static final byte CONDITION_TYPE_FORMULA = 2;
-
- private byte field_2_comparison_operator;
- public static final byte COMPARISON_OPERATOR_NO_COMPARISON = 0;
- public static final byte COMPARISON_OPERATOR_BETWEEN = 1;
- public static final byte COMPARISON_OPERATOR_NOT_BETWEEN = 2;
- public static final byte COMPARISON_OPERATOR_EQUAL = 3;
- public static final byte COMPARISON_OPERATOR_NOT_EQUAL = 4;
- public static final byte COMPARISON_OPERATOR_GT = 5;
- public static final byte COMPARISON_OPERATOR_LT = 6;
- public static final byte COMPARISON_OPERATOR_GE = 7;
- public static final byte COMPARISON_OPERATOR_LE = 8;
-
- private short field_3_formula1_len;
- private short field_4_formula2_len;
-
- private int field_5_options;
-
- private static final BitField modificationBits = BitFieldFactory.getInstance(0x83FFFFFF); // Bits: font,align,bord,patt,prot
- private static final BitField alignHor = BitFieldFactory.getInstance(0x00000001); // 0 = Horizontal alignment modified
- private static final BitField alignVer = BitFieldFactory.getInstance(0x00000002); // 0 = Vertical alignment modified
- private static final BitField alignWrap = BitFieldFactory.getInstance(0x00000004); // 0 = Text wrapped flag modified
- private static final BitField alignRot = BitFieldFactory.getInstance(0x00000008); // 0 = Text rotation modified
- private static final BitField alignJustLast = BitFieldFactory.getInstance(0x00000010); // 0 = Justify last line flag modified
- private static final BitField alignIndent = BitFieldFactory.getInstance(0x00000020); // 0 = Indentation modified
- private static final BitField alignShrink = BitFieldFactory.getInstance(0x00000040); // 0 = Shrink to fit flag modified
- private static final BitField notUsed1 = BitFieldFactory.getInstance(0x00000080); // Always 1
- private static final BitField protLocked = BitFieldFactory.getInstance(0x00000100); // 0 = Cell locked flag modified
- private static final BitField protHidden = BitFieldFactory.getInstance(0x00000200); // 0 = Cell hidden flag modified
- private static final BitField bordLeft = BitFieldFactory.getInstance(0x00000400); // 0 = Left border style and colour modified
- private static final BitField bordRight = BitFieldFactory.getInstance(0x00000800); // 0 = Right border style and colour modified
- private static final BitField bordTop = BitFieldFactory.getInstance(0x00001000); // 0 = Top border style and colour modified
- private static final BitField bordBot = BitFieldFactory.getInstance(0x00002000); // 0 = Bottom border style and colour modified
- private static final BitField bordTlBr = BitFieldFactory.getInstance(0x00004000); // 0 = Top-left to bottom-right border flag modified
- private static final BitField bordBlTr = BitFieldFactory.getInstance(0x00008000); // 0 = Bottom-left to top-right border flag modified
- private static final BitField pattStyle = BitFieldFactory.getInstance(0x00010000); // 0 = Pattern style modified
- private static final BitField pattCol = BitFieldFactory.getInstance(0x00020000); // 0 = Pattern colour modified
- private static final BitField pattBgCol = BitFieldFactory.getInstance(0x00040000); // 0 = Pattern background colour modified
- private static final BitField notUsed2 = BitFieldFactory.getInstance(0x00380000); // Always 111
- private static final BitField undocumented = BitFieldFactory.getInstance(0x03C00000); // Undocumented bits
- private static final BitField fmtBlockBits = BitFieldFactory.getInstance(0x7C000000); // Bits: font,align,bord,patt,prot
- private static final BitField font = BitFieldFactory.getInstance(0x04000000); // 1 = Record contains font formatting block
- private static final BitField align = BitFieldFactory.getInstance(0x08000000); // 1 = Record contains alignment formatting block
- private static final BitField bord = BitFieldFactory.getInstance(0x10000000); // 1 = Record contains border formatting block
- private static final BitField patt = BitFieldFactory.getInstance(0x20000000); // 1 = Record contains pattern formatting block
- private static final BitField prot = BitFieldFactory.getInstance(0x40000000); // 1 = Record contains protection formatting block
- private static final BitField alignTextDir = BitFieldFactory.getInstance(0x80000000); // 0 = Text direction modified
-
-
- private short field_6_not_used;
-
- private FontFormatting fontFormatting;
-
- private byte field_8_align_text_break;
- private byte field_9_align_text_rotation_angle;
- private short field_10_align_indentation;
- private short field_11_relative_indentation;
- private short field_12_not_used;
-
- private BorderFormatting borderFormatting;
-
- private PatternFormatting patternFormatting;
-
- private Stack field_17_formula1;
- private Stack field_18_formula2;
-
- /** Creates new CFRuleRecord */
- public CFRuleRecord()
- {
- field_1_condition_type=CONDITION_TYPE_NO_CONDITION_TYPE;
- field_2_comparison_operator=COMPARISON_OPERATOR_NO_COMPARISON;
- setExpression1Length((short)0);
- setExpression2Length((short)0);
-
- // Set modification flags to 1: by default options are not modified
- setOptions(modificationBits.setValue(field_5_options, -1));
- // Set formatting block flags to 0 (no formatting blocks)
- setOptions(fmtBlockBits.setValue(field_5_options, 0));
-
- field_6_not_used = 0;
- fontFormatting=null;
- field_8_align_text_break = 0;
- field_9_align_text_rotation_angle = 0;
- field_10_align_indentation = 0;
- field_11_relative_indentation = 0;
- field_12_not_used = 0;
- borderFormatting=null;
- patternFormatting=null;
- field_17_formula1=null;
- field_18_formula2=null;
- }
-
- /**
- * Constructs a Formula record and sets its fields appropriately.
- * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
- * "explanation of this bug in the documentation) or an exception
- * will be throw upon validation
- *
- * @param in the RecordInputstream to read the record from
- */
-
- public CFRuleRecord(RecordInputStream in)
- {
- super(in);
- }
-
- protected void fillFields(RecordInputStream in)
- {
- try {
- field_1_condition_type = in.readByte();
- field_2_comparison_operator = in.readByte();
- field_3_formula1_len = in.readShort();
- field_4_formula2_len = in.readShort();
- field_5_options = in.readInt();
- field_6_not_used = in.readShort();
-
- if(containsFontFormattingBlock())
- {
- fontFormatting = new FontFormatting(in);
- }
-
- if(containsBorderFormattingBlock())
- {
- borderFormatting = new BorderFormatting(in);
- }
-
- if( containsPatternFormattingBlock())
- {
- patternFormatting = new PatternFormatting(in);
- }
-
- if(field_3_formula1_len>0)
- {
- field_17_formula1 = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
-
- // Now convert any fields as required
- field_17_formula1 = SharedFormulaRecord.convertSharedFormulas(
- field_17_formula1, 0, 0
- );
- }
- if(field_4_formula2_len>0)
- {
- field_18_formula2 = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
-
- // Now convert any fields as required
- field_18_formula2 = SharedFormulaRecord.convertSharedFormulas(
- field_18_formula2, 0, 0
- );
- }
- } catch (java.lang.UnsupportedOperationException uoe) {
- throw new RecordFormatException(uoe);
- }
-
- }
-
- public void setConditionType(byte conditionType)
- {
- field_1_condition_type =
- conditionType == CONDITION_TYPE_CELL_VALUE_IS ?
- CONDITION_TYPE_CELL_VALUE_IS :
- CONDITION_TYPE_FORMULA;
- }
-
- public byte getConditionType()
- {
- return field_1_condition_type;
- }
-
- /**
- * set the option flags
- *
- * @param options bitmask
- */
-
- public void setOptions(int options)
- {
- field_5_options = options;
- }
-
- public boolean containsFontFormattingBlock()
- {
- return getOptionFlag(font);
- }
- public void setFontFormatting(FontFormatting fontFormatting)
- {
- this.fontFormatting = fontFormatting;
- setOptionFlag(true,font);
- }
- public void setFontFormattingUnchanged()
- {
- setOptionFlag(false,font);
- }
-
- public boolean containsAlignFormattingBlock()
- {
- return getOptionFlag(align);
- }
- public void setAlignFormattingUnchanged()
- {
- setOptionFlag(false,align);
- }
-
- public boolean containsBorderFormattingBlock()
- {
- return getOptionFlag(bord);
- }
- public void setBorderFormatting(BorderFormatting borderFormatting)
- {
- this.borderFormatting = borderFormatting;
- setOptionFlag(true,bord);
- }
- public void setBorderFormattingUnchanged()
- {
- setOptionFlag(false,bord);
- }
-
- public boolean containsPatternFormattingBlock()
- {
- return getOptionFlag(patt);
- }
- public void setPatternFormatting(PatternFormatting patternFormatting)
- {
- this.patternFormatting = patternFormatting;
- setOptionFlag(true,patt);
- }
- public void setPatternFormattingUnchanged()
- {
- setOptionFlag(false,patt);
- }
-
- public boolean containsProtectionFormattingBlock()
- {
- return getOptionFlag(prot);
- }
- public void setProtectionFormattingUnchanged()
- {
- setOptionFlag(false,prot);
- }
-
- public void setComparisonOperation(byte operation)
- {
- field_2_comparison_operator = operation;
- }
-
- public byte getComparisonOperation()
- {
- return field_2_comparison_operator;
- }
-
- /**
- * set the length (in number of tokens) of the expression 1
- * @param len length
- */
-
- private void setExpression1Length(short len)
- {
- field_3_formula1_len = len;
- }
-
- /**
- * get the length (in number of tokens) of the expression 1
- * @return expression length
- */
-
- public short getExpression1Length()
- {
- return field_3_formula1_len;
- }
-
- /**
- * set the length (in number of tokens) of the expression 2
- * @param len length
- */
-
- private void setExpression2Length(short len)
- {
- field_4_formula2_len = len;
- }
-
- /**
- * get the length (in number of tokens) of the expression 2
- * @return expression length
- */
-
- public short getExpression2Length()
- {
- return field_4_formula2_len;
- }
- /**
- * get the option flags
- *
- * @return bit mask
- */
- public int getOptions()
- {
- return field_5_options;
- }
-
- private boolean isModified(BitField field)
- {
- return !field.isSet(field_5_options);
+
+ public static final short sid = 0x01B1;
+
+ public static final class ComparisonOperator {
+ public static final byte NO_COMPARISON = 0;
+ public static final byte BETWEEN = 1;
+ public static final byte NOT_BETWEEN = 2;
+ public static final byte EQUAL = 3;
+ public static final byte NOT_EQUAL = 4;
+ public static final byte GT = 5;
+ public static final byte LT = 6;
+ public static final byte GE = 7;
+ public static final byte LE = 8;
+ }
+
+ private byte field_1_condition_type;
+ public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
+ public static final byte CONDITION_TYPE_FORMULA = 2;
+
+ private byte field_2_comparison_operator;
+
+ private short field_3_formula1_len;
+ private short field_4_formula2_len;
+
+ private int field_5_options;
+
+ private static final BitField modificationBits = bf(0x83FFFFFF); // Bits: font,align,bord,patt,prot
+ private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
+ private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
+ private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
+ private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
+ private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
+ private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
+ private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
+ private static final BitField notUsed1 = bf(0x00000080); // Always 1
+ private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
+ private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
+ private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
+ private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified
+ private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified
+ private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified
+ private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
+ private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
+ private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
+ private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
+ private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
+ private static final BitField notUsed2 = bf(0x00380000); // Always 111
+ private static final BitField undocumented = bf(0x03C00000); // Undocumented bits
+ private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
+ private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block
+ private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block
+ private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block
+ private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block
+ private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block
+ private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified
+
+
+ private static BitField bf(int i) {
+ return BitFieldFactory.getInstance(i);
+ }
+
+ private short field_6_not_used;
+
+ private FontFormatting fontFormatting;
+
+ private byte field_8_align_text_break;
+ private byte field_9_align_text_rotation_angle;
+ private short field_10_align_indentation;
+ private short field_11_relative_indentation;
+ private short field_12_not_used;
+
+ private BorderFormatting borderFormatting;
+
+ private PatternFormatting patternFormatting;
+
+ private Ptg[] field_17_formula1;
+ private Ptg[] field_18_formula2;
+
+ /** Creates new CFRuleRecord */
+ private CFRuleRecord(byte conditionType, byte comparisonOperation)
+ {
+ field_1_condition_type=conditionType;
+ field_2_comparison_operator=comparisonOperation;
+ field_3_formula1_len = (short)0;
+ field_4_formula2_len = (short)0;
+
+ // Set modification flags to 1: by default options are not modified
+ field_5_options = modificationBits.setValue(field_5_options, -1);
+ // Set formatting block flags to 0 (no formatting blocks)
+ field_5_options = fmtBlockBits.setValue(field_5_options, 0);
+ field_5_options = undocumented.clear(field_5_options);
+
+ field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
+ fontFormatting=null;
+ field_8_align_text_break = 0;
+ field_9_align_text_rotation_angle = 0;
+ field_10_align_indentation = 0;
+ field_11_relative_indentation = 0;
+ field_12_not_used = 0;
+ borderFormatting=null;
+ patternFormatting=null;
+ field_17_formula1=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.
+ * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
+ * "explanation of this bug in the documentation) or an exception
+ * will be throw upon validation
+ *
+ * @param in the RecordInputstream to read the record from
+ */
+
+ public CFRuleRecord(RecordInputStream in)
+ {
+ super(in);
+ }
+
+
+
+ protected void fillFields(RecordInputStream in) {
+ try {
+ field_1_condition_type = in.readByte();
+ field_2_comparison_operator = in.readByte();
+ field_3_formula1_len = in.readShort();
+ field_4_formula2_len = in.readShort();
+ field_5_options = in.readInt();
+ field_6_not_used = in.readShort();
+
+ if (containsFontFormattingBlock()) {
+ fontFormatting = new FontFormatting(in);
+ }
+
+ if (containsBorderFormattingBlock()) {
+ borderFormatting = new BorderFormatting(in);
+ }
+
+ if (containsPatternFormattingBlock()) {
+ patternFormatting = new PatternFormatting(in);
+ }
+
+ if (field_3_formula1_len > 0) {
+ Stack ptgs = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
+ // Now convert any fields as required
+ ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
+ field_17_formula1 = toArray(ptgs);
+ }
+ if (field_4_formula2_len > 0) {
+ Stack ptgs = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
+
+ // Now convert any fields as required
+ ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
+ field_18_formula2 = toArray(ptgs);
+ }
+ } catch (java.lang.UnsupportedOperationException uoe) {
+ throw new RecordFormatException(uoe);
+ }
+
+ }
+
+ public byte getConditionType()
+ {
+ return field_1_condition_type;
+ }
+
+ public boolean containsFontFormattingBlock()
+ {
+ return getOptionFlag(font);
+ }
+ public void setFontFormatting(FontFormatting fontFormatting)
+ {
+ this.fontFormatting = fontFormatting;
+ setOptionFlag(fontFormatting != null, font);
+ }
+
+ public boolean containsAlignFormattingBlock()
+ {
+ return getOptionFlag(align);
+ }
+ public void setAlignFormattingUnchanged()
+ {
+ setOptionFlag(false,align);
+ }
+
+ public boolean containsBorderFormattingBlock()
+ {
+ return getOptionFlag(bord);
+ }
+ public void setBorderFormatting(BorderFormatting borderFormatting)
+ {
+ this.borderFormatting = borderFormatting;
+ setOptionFlag(borderFormatting != null, bord);
+ }
+
+ public boolean containsPatternFormattingBlock()
+ {
+ return getOptionFlag(patt);
+ }
+ public void setPatternFormatting(PatternFormatting patternFormatting)
+ {
+ this.patternFormatting = patternFormatting;
+ setOptionFlag(patternFormatting!=null, patt);
+ }
+
+
+ public boolean containsProtectionFormattingBlock()
+ {
+ return getOptionFlag(prot);
+ }
+ public void setProtectionFormattingUnchanged()
+ {
+ setOptionFlag(false,prot);
+ }
+
+ public void setComparisonOperation(byte operation)
+ {
+ field_2_comparison_operator = operation;
+ }
+
+ public byte getComparisonOperation()
+ {
+ return field_2_comparison_operator;
+ }
+
+
+ /**
+ * get the length (in number of tokens) of the expression 1
+ * @return expression length
+ */
+ private short getExpression1Length()
+ {
+ return field_3_formula1_len;
+ }
+
+
+ /**
+ * get the length (in number of tokens) of the expression 2
+ * @return expression length
+ */
+ private short getExpression2Length()
+ {
+ return field_4_formula2_len;
+ }
+ /**
+ * get the option flags
+ *
+ * @return bit mask
+ */
+ public int getOptions()
+ {
+ return field_5_options;
+ }
+
+ private boolean isModified(BitField field)
+ {
+ return !field.isSet(field_5_options);
}
private void setModified(boolean modified, BitField field)
{
setModified(modified,bordLeft);
}
-
+
public boolean isRightBorderModified()
{
return isModified(bordRight);
{
setModified(modified,bordRight);
}
-
+
public boolean isTopBorderModified()
{
return isModified(bordTop);
{
setModified(modified,bordTop);
}
-
+
public boolean isBottomBorderModified()
{
return isModified(bordBot);
{
setModified(modified,bordBot);
}
-
+
public boolean isTopLeftBottomRightBorderModified()
{
return isModified(bordTlBr);
{
setModified(modified,bordTlBr);
}
-
+
public boolean isBottomLeftTopRightBorderModified()
{
return isModified(bordBlTr);
{
setModified(modified,bordBlTr);
}
-
+
public boolean isPatternStyleModified()
{
return isModified(pattStyle);
setModified(modified,pattBgCol);
}
- private boolean getOptionFlag(BitField field)
+ private boolean getOptionFlag(BitField field)
{
- return field.isSet(field_5_options);
+ return field.isSet(field_5_options);
}
private void setOptionFlag(boolean flag, BitField field)
field_5_options = field.setBoolean(field_5_options, flag);
}
- /**
- * get the stack of the 1st expression as a list
- *
- * @return list of tokens (casts stack to a list and returns it!)
- * this method can return null is we are unable to create Ptgs from
- * existing excel file
- * callers should check for null!
- */
-
- public List getParsedExpression1()
- {
- return field_17_formula1;
- }
-
- /**
- * get the stack of the 2nd expression as a list
- *
- * @return list of tokens (casts stack to a list and returns it!)
- * this method can return null is we are unable to create Ptgs from
- * existing excel file
- * callers should check for null!
- */
-
- public List getParsedExpression2()
- {
- return field_18_formula2;
- }
-
- public void setParsedExpression1(Stack ptgs) {
- setExpression1Length(getTotalPtgSize(field_17_formula1 = ptgs));
- }
-
- public void setParsedExpression2(Stack ptgs) {
- setExpression1Length(getTotalPtgSize(field_18_formula2 = ptgs));
- }
-
- /**
- * called by constructor, should throw runtime exception in the event of a
- * record passed with a differing ID.
- *
- * @param id alleged id for this record
- */
-
- protected void validateSid(short id)
- {
- if (id != sid)
- {
- throw new RecordFormatException("NOT A CFRULE RECORD");
- }
- }
-
- public short getSid()
- {
- return sid;
- }
-
- /**
- * called by the class that is responsible for writing this sucker.
- * Subclasses should implement this so that their data is passed back in a
- * byte array.
- *
- * @param offset to begin writing at
- * @param data byte array containing instance data
- * @return number of bytes written
- */
-
- public int serialize(int offset, byte [] data)
- {
- int recordsize = getRecordSize();
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
- data[4 + offset] = field_1_condition_type;
- data[5 + offset] = field_2_comparison_operator;
- LittleEndian.putShort(data, 6 + offset, field_3_formula1_len);
- LittleEndian.putShort(data, 8 + offset, field_4_formula2_len);
- LittleEndian.putInt(data, 10 + offset, field_5_options);
- LittleEndian.putShort(data,14 + offset, field_6_not_used);
-
- offset += 16;
-
- if( containsFontFormattingBlock() )
- {
- byte[] fontFormattingRawRecord = fontFormatting.getRawRecord();
- System.arraycopy(fontFormattingRawRecord, 0, data, offset, fontFormattingRawRecord.length);
- offset += fontFormattingRawRecord.length;
- }
-
- if( containsBorderFormattingBlock())
- {
- offset += borderFormatting.serialize(offset, data);
- }
-
- if( containsPatternFormattingBlock() )
- {
- offset += patternFormatting.serialize(offset, data);
- }
-
- if (getExpression1Length()>0)
- {
- Ptg.serializePtgStack(this.field_17_formula1, data, offset);
- offset += getExpression1Length();
- }
-
- if (getExpression2Length()>0)
- {
- Ptg.serializePtgStack(this.field_18_formula2, data, offset);
- offset += getExpression2Length();
- }
- return recordsize;
- }
-
-
-
-
- public int getRecordSize()
- {
- int retval =16+
- (containsFontFormattingBlock()?fontFormatting.getRawRecord().length:0)+
- (containsBorderFormattingBlock()?8:0)+
- (containsPatternFormattingBlock()?4:0)+
- getExpression1Length()+
- getExpression2Length()
- ;
- return retval;
- }
-
- private short getTotalPtgSize(List list)
- {
- short retval = 0;
- if( list!=null)
- {
- for (int k = 0; k < list.size(); k++)
- {
- Ptg ptg = ( Ptg ) list.get(k);
-
- retval += ptg.getSize();
- }
- }
- return retval;
- }
-
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
- buffer.append("[CFRULE]\n");
- if( containsFontFormattingBlock())
- {
- buffer.append(fontFormatting.toString());
- }
- if( containsBorderFormattingBlock())
- {
- buffer.append(borderFormatting.toString());
- }
- if( containsPatternFormattingBlock())
- {
- buffer.append(patternFormatting.toString());
- }
- buffer.append("[/CFRULE]\n");
- return buffer.toString();
- }
-
- public Object clone() {
- CFRuleRecord rec = new CFRuleRecord();
- rec.field_1_condition_type= field_1_condition_type;
- rec.field_2_comparison_operator = field_2_comparison_operator;
- rec.field_3_formula1_len = field_3_formula1_len;
- rec.field_4_formula2_len = field_4_formula2_len;
- rec.field_5_options = field_5_options;
- rec.field_6_not_used = field_6_not_used;
- if( containsFontFormattingBlock())
- {
- rec.fontFormatting = (FontFormatting)fontFormatting.clone();
- }
- if( containsBorderFormattingBlock())
- {
- rec.borderFormatting = (BorderFormatting)borderFormatting.clone();
- }
- if( containsPatternFormattingBlock())
- {
- rec.patternFormatting = (PatternFormatting)patternFormatting.clone();
- }
- if( field_3_formula1_len>0)
- {
- rec.field_17_formula1 = (Stack)field_17_formula1.clone();
- }
- if( field_4_formula2_len>0)
- {
- rec.field_18_formula2 = (Stack)field_18_formula2.clone();
- }
-
- return rec;
- }
+ /**
+ * get the stack of the 1st expression as a list
+ *
+ * @return list of tokens (casts stack to a list and returns it!)
+ * this method can return null is we are unable to create Ptgs from
+ * existing excel file
+ * callers should check for null!
+ */
+
+ public Ptg[] getParsedExpression1()
+ {
+ return field_17_formula1;
+ }
+
+ /**
+ * get the stack of the 2nd expression as a list
+ *
+ * @return list of tokens (casts stack to a list and returns it!)
+ * this method can return null is we are unable to create Ptgs from
+ * existing excel file
+ * callers should check for null!
+ */
+
+ public Ptg[] getParsedExpression2()
+ {
+ return field_18_formula2;
+ }
+
+ private void setParsedExpression1(Ptg[] ptgs) {
+ short len = getTotalPtgSize(field_17_formula1 = ptgs);
+ field_3_formula1_len = len;
+ }
+
+ private void setParsedExpression2(Ptg[] ptgs) {
+ short len = getTotalPtgSize(field_18_formula2 = ptgs);
+ field_4_formula2_len = len;
+ }
+
+ /**
+ * called by constructor, should throw runtime exception in the event of a
+ * record passed with a differing ID.
+ *
+ * @param id alleged id for this record
+ */
+
+ protected void validateSid(short id)
+ {
+ if (id != sid)
+ {
+ throw new RecordFormatException("NOT A CFRULE RECORD");
+ }
+ }
+
+ public short getSid()
+ {
+ return sid;
+ }
+
+ /**
+ * called by the class that is responsible for writing this sucker.
+ * Subclasses should implement this so that their data is passed back in a
+ * byte array.
+ *
+ * @param offset to begin writing at
+ * @param data byte array containing instance data
+ * @return number of bytes written
+ */
+
+ public int serialize(int pOffset, byte [] data)
+ {
+
+ int offset = pOffset;
+ int recordsize = getRecordSize();
+ LittleEndian.putShort(data, 0 + offset, sid);
+ LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
+ data[4 + offset] = field_1_condition_type;
+ data[5 + offset] = field_2_comparison_operator;
+ LittleEndian.putShort(data, 6 + offset, field_3_formula1_len);
+ LittleEndian.putShort(data, 8 + offset, field_4_formula2_len);
+ LittleEndian.putInt(data, 10 + offset, field_5_options);
+ LittleEndian.putShort(data,14 + offset, field_6_not_used);
+
+ offset += 16;
+
+ if( containsFontFormattingBlock() )
+ {
+ byte[] fontFormattingRawRecord = fontFormatting.getRawRecord();
+ System.arraycopy(fontFormattingRawRecord, 0, data, offset, fontFormattingRawRecord.length);
+ offset += fontFormattingRawRecord.length;
+ }
+
+ if( containsBorderFormattingBlock())
+ {
+ offset += borderFormatting.serialize(offset, data);
+ }
+
+ if( containsPatternFormattingBlock() )
+ {
+ offset += patternFormatting.serialize(offset, data);
+ }
+
+ if (getExpression1Length()>0)
+ {
+ Ptg.serializePtgStack(convertToTokenStack(field_17_formula1), data, offset);
+ offset += getExpression1Length();
+ }
+
+ if (getExpression2Length()>0)
+ {
+ Ptg.serializePtgStack(convertToTokenStack(field_18_formula2), data, offset);
+ offset += getExpression2Length();
+ }
+ if(offset - pOffset != recordsize) {
+ throw new IllegalStateException("write mismatch (" + (offset - pOffset) + "!=" + recordsize + ")");
+ }
+ return recordsize;
+ }
+
+
+ public int getRecordSize()
+ {
+ int retval =16+
+ (containsFontFormattingBlock()?fontFormatting.getRawRecord().length:0)+
+ (containsBorderFormattingBlock()?8:0)+
+ (containsPatternFormattingBlock()?4:0)+
+ getExpression1Length()+
+ getExpression2Length()
+ ;
+ return retval;
+ }
+
+ private short getTotalPtgSize(Ptg[] ptgs)
+ {
+ if( ptgs == null) {
+ return 0;
+ }
+ short retval = 0;
+ for (int i = 0; i < ptgs.length; i++)
+ {
+ retval += ptgs[i].getSize();
+ }
+ return retval;
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[CFRULE]\n");
+ if( containsFontFormattingBlock())
+ {
+ buffer.append(fontFormatting.toString());
+ }
+ if( containsBorderFormattingBlock())
+ {
+ buffer.append(borderFormatting.toString());
+ }
+ if( containsPatternFormattingBlock())
+ {
+ buffer.append(patternFormatting.toString());
+ }
+ buffer.append("[/CFRULE]\n");
+ return buffer.toString();
+ }
+
+ public Object clone() {
+ CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
+ rec.field_3_formula1_len = field_3_formula1_len;
+ rec.field_4_formula2_len = field_4_formula2_len;
+ rec.field_5_options = field_5_options;
+ rec.field_6_not_used = field_6_not_used;
+ if (containsFontFormattingBlock()) {
+ rec.fontFormatting = (FontFormatting) fontFormatting.clone();
+ }
+ if (containsBorderFormattingBlock()) {
+ rec.borderFormatting = (BorderFormatting) borderFormatting.clone();
+ }
+ if (containsPatternFormattingBlock()) {
+ rec.patternFormatting = (PatternFormatting) patternFormatting.clone();
+ }
+ if (field_3_formula1_len > 0) {
+ rec.field_17_formula1 = (Ptg[]) field_17_formula1.clone();
+ }
+ if (field_4_formula2_len > 0) {
+ rec.field_18_formula2 = (Ptg[]) field_18_formula2.clone();
+ }
+
+ return rec;
+ }
public FontFormatting getFontFormatting()
{
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;
+ }
}
private static final int OPT_PICTURE_LINK = 0x0004;
private static final int OPT_STD_DOCUMENT_NAME = 0x0008;
private static final int OPT_OLE_LINK = 0x0010;
-// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
+// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
*/
public final class CFRecordsAggregate extends Record
{
+ /** Excel allows up to 3 conditional formating rules */
+ private static final int MAX_CONDTIONAL_FORMAT_RULES = 3;
+
public final static short sid = -2008; // not a real BIFF record
- private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
+ private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
- private CFHeaderRecord header;
+ private final CFHeaderRecord header;
- // List of CFRuleRecord objects
+ /** List of CFRuleRecord objects */
private final List rules;
- public CFRecordsAggregate()
- {
- header = null;
- rules = new ArrayList(3);
+ private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) {
+ if(pHeader == null) {
+ throw new IllegalArgumentException("header must not be null");
+ }
+ if(pRules == null) {
+ throw new IllegalArgumentException("rules must not be null");
+ }
+ if(pRules.length > MAX_CONDTIONAL_FORMAT_RULES) {
+ throw new IllegalArgumentException("No more than "
+ + MAX_CONDTIONAL_FORMAT_RULES + " rules may be specified");
+ }
+ header = pHeader;
+ rules = new ArrayList(3);
+ for (int i = 0; i < pRules.length; i++) {
+ rules.add(pRules[i]);
+ }
+ }
+
+ public CFRecordsAggregate(Region[] regions, CFRuleRecord[] rules) {
+ this(new CFHeaderRecord(regions), rules);
}
/**
*/
public static CFRecordsAggregate createCFAggregate(List recs, int pOffset)
{
+ Record rec = ( Record ) recs.get(pOffset);
+ if (rec.getSid() != CFHeaderRecord.sid) {
+ throw new IllegalStateException("next record sid was " + rec.getSid()
+ + " instead of " + CFHeaderRecord.sid + " as expected");
+ }
- int offset = pOffset;
- CFRecordsAggregate cfRecords = new CFRecordsAggregate();
- ArrayList records = new ArrayList(4);
-
- Record rec = ( Record ) recs.get(offset++);
+ CFHeaderRecord header = (CFHeaderRecord)rec;
+ int nRules = header.getNumberOfConditionalFormats();
- if (rec.getSid() == CFHeaderRecord.sid)
- {
- records.add(rec);
- cfRecords.header = (CFHeaderRecord)rec;
-
- int nRules = cfRecords.header.getNumberOfConditionalFormats();
- int rulesCount = 0;
- while( offset<recs.size() &&
- (rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
- rec instanceof CFRuleRecord &&
- rulesCount++ < nRules
- )
- {
- records.add(rec);
- cfRecords.rules.add(rec);
+ CFRuleRecord[] rules = new CFRuleRecord[nRules];
+ int offset = pOffset;
+ int countFound = 0;
+ while (countFound < rules.length) {
+ offset++;
+ if(offset>=recs.size()) {
+ break;
}
+ rec = (Record)recs.get(offset);
+ if(rec instanceof CFRuleRecord) {
+ rules[countFound] = (CFRuleRecord) rec;
+ countFound++;
+ } else {
+ break;
+ }
+ }
- if (nRules != cfRecords.rules.size())
+ if (countFound < nRules)
+ { // TODO -(MAR-2008) can this ever happen? write junit
+
+ if (log.check(POILogger.DEBUG))
{
- if (log.check(POILogger.DEBUG))
- {
- log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
- + "but found " + cfRecords.rules.size() + " rules");
- }
- cfRecords.header.setNumberOfConditionalFormats(nRules);
+ log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
+ + "but found " + countFound + " rules");
}
-
+ header.setNumberOfConditionalFormats(nRules);
+ CFRuleRecord[] lessRules = new CFRuleRecord[countFound];
+ System.arraycopy(rules, 0, lessRules, 0, countFound);
+ rules = lessRules;
}
- return cfRecords;
+ return new CFRecordsAggregate(header, rules);
}
/**
*/
public CFRecordsAggregate cloneCFAggregate()
{
-
- ArrayList records = new ArrayList(this.rules.size()+1);
- records.add(this.header.clone());
-
- for (int i=0; i<this.rules.size();i++)
- {
- Record rec = (Record)((Record)this.rules.get(i)).clone();
- records.add(rec);
- }
- return createCFAggregate(records, 0);
+ CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
+ for (int i = 0; i < newRecs.length; i++) {
+ newRecs[i] = (CFRuleRecord) getRule(i).clone();
+ }
+ return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
}
- /** You never fill an aggregate */
protected void fillFields(RecordInputStream in)
{
+ // You never fill an aggregate record
}
public short getSid()
public int serialize(int offset, byte[] data)
{
- int pos = offset;
- if( header != null && rules.size()>0 )
- {
- header.setNumberOfConditionalFormats(rules.size());
+ int nRules = rules.size();
+ header.setNumberOfConditionalFormats(nRules);
- pos += (( Record ) header).serialize(pos, data);
+ int pos = offset;
- for(Iterator itr = rules.iterator(); itr.hasNext();)
- {
- pos += (( Record ) itr.next()).serialize(pos, data);
- }
+ pos += header.serialize(pos, data);
+ for(int i=0; i< nRules; i++) {
+ pos += getRule(i).serialize(pos, data);
}
return pos - offset;
}
}
/**
- * @return the header
+ * @return the header. Never <code>null</code>.
*/
public CFHeaderRecord getHeader()
{
return header;
}
-
- /**
- * @return the rules
- */
- public List getRules()
- {
- return rules;
+
+ private void checkRuleIndex(int idx) {
+ if(idx < 0 || idx >= rules.size()) {
+ throw new IllegalArgumentException("Bad rule record index (" + idx
+ + ") nRules=" + rules.size());
+ }
+ }
+ public CFRuleRecord getRule(int idx) {
+ checkRuleIndex(idx);
+ return (CFRuleRecord) rules.get(idx);
+ }
+ public void setRule(int idx, CFRuleRecord r) {
+ checkRuleIndex(idx);
+ rules.set(idx, r);
+ }
+ public void addRule(CFRuleRecord r) {
+ if(rules.size() >= MAX_CONDTIONAL_FORMAT_RULES) {
+ throw new IllegalStateException("Cannot have more than "
+ + MAX_CONDTIONAL_FORMAT_RULES + " conditional format rules");
+ }
+ rules.add(r);
+ header.setNumberOfConditionalFormats(rules.size());
+ }
+ public int getNumberOfRules() {
+ return rules.size();
}
/**
package org.apache.poi.hssf.record.cf;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.poi.hssf.util.Region;
+
/**
- * CellRange.java
- * Created on January 22, 2008, 10:05 PM
*
* @author Dmitriy Kumshayev
*/
-
-public class CellRange
+public final class CellRange
{
- private int field_1_first_row;
- private int field_2_last_row;
- private short field_3_first_column;
- private short field_4_last_column;
-
- public CellRange(int firstRow, int lastRow, short firstColumn, short lastColumn)
- {
- this.field_1_first_row = firstRow;
- this.field_2_last_row = lastRow;
- this.field_3_first_column = firstColumn;
- this.field_4_last_column = lastColumn;
- validateRegion();
- }
-
- private void validateRegion()
- {
- if( field_1_first_row < 0 ||
- field_2_last_row < -1 ||
- field_3_first_column < 0 ||
- field_4_last_column < -1 ||
- field_2_last_row>=0 && field_2_last_row<field_1_first_row ||
- field_4_last_column>=0 && field_4_last_column<field_3_first_column
- )
- {
- throw new IllegalArgumentException("Invalid cell region "+toString());
- }
- }
-
- public int getFirstRow()
+ /**
+ * max index for both row and column<p/>
+ *
+ * Note - this value converts to <tt>-1</tt> when cast to a <tt>short</tt>
+ */
+ private static final int MAX_INDEX = Integer.MAX_VALUE;
+
+ private static final Region[] EMPTY_REGION_ARRAY = { };
+
+ private int _firstRow;
+ private int _lastRow;
+ private int _firstColumn;
+ private int _lastColumn;
+
+ /**
+ *
+ * @param firstRow
+ * @param lastRow pass <tt>-1</tt> for full column ranges
+ * @param firstColumn
+ * @param lastColumn pass <tt>-1</tt> for full row ranges
+ */
+ public CellRange(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
- return field_1_first_row;
+ if(!isValid(firstRow, lastRow, firstColumn, lastColumn)) {
+ throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
+ + ", " + firstColumn + ", " + lastColumn + ")");
+ }
+ _firstRow = firstRow;
+ _lastRow = convertM1ToMax(lastRow);
+ _firstColumn = firstColumn;
+ _lastColumn = convertM1ToMax(lastColumn);
}
- private void setFirstRow(int firstRow)
- {
- this.field_1_first_row = firstRow;
+
+ private static int convertM1ToMax(int lastIx) {
+ if(lastIx < 0) {
+ return MAX_INDEX;
+ }
+ return lastIx;
}
- public int getLastRow()
- {
- return field_2_last_row;
+ private static int convertMaxToM1(int lastIx) {
+ if(lastIx == MAX_INDEX) {
+ return -1;
+ }
+ return lastIx;
+ }
+
+ public boolean isFullColumnRange() {
+ return _firstColumn == 0 && _lastColumn == MAX_INDEX;
+ }
+ public boolean isFullRowRange() {
+ return _firstRow == 0 && _lastRow == MAX_INDEX;
+ }
+
+ public CellRange(Region r) {
+ this(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
}
- private void setLastRow(int lastRow)
+
+
+
+ private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
- this.field_2_last_row = lastRow;
+ if(lastRow == -1) {
+ if(firstRow !=0) {
+ return false;
+ }
+ }
+ if(firstRow < 0 || lastRow < -1) {
+ return false;
+ }
+
+ if(lastColumn == -1) {
+ if(firstColumn !=0) {
+ return false;
+ }
+ }
+ if(firstColumn < 0 || lastColumn < -1) {
+ return false;
+ }
+ return true;
}
- public short getFirstColumn()
+
+ public int getFirstRow()
{
- return field_3_first_column;
+ return _firstRow;
}
- private void setFirstColumn(short firstColumn)
+ /**
+ * @return <tt>-1</tt> for whole column ranges
+ */
+ public int getLastRow()
{
- this.field_3_first_column = firstColumn;
+ return convertMaxToM1(_lastRow);
}
- public short getLastColumn()
+ public int getFirstColumn()
{
- return field_4_last_column;
+ return _firstColumn;
}
- private void setLastColumn(short lastColumn)
+ /**
+ * @return <tt>-1</tt> for whole row ranges
+ */
+ public int getLastColumn()
{
- this.field_4_last_column = lastColumn;
+ return convertMaxToM1(_lastColumn);
}
public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2;
+ /** first range is within the second range */
public static final int INSIDE = 3;
+ /** first range encloses or is equal to the second */
public static final int ENCLOSES = 4;
/**
* NO_INTERSECTION - the specified range is outside of this range;<br/>
* OVERLAP - both ranges partially overlap;<br/>
* INSIDE - the specified range is inside of this one<br/>
- * ENCLOSES - the specified range encloses this range<br/>
+ * ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
*/
public int intersect(CellRange another )
{
- int firstRow = another.getFirstRow();
- int lastRow = another.getLastRow();
- short firstCol = another.getFirstColumn();
- short lastCol = another.getLastColumn();
+
+ int firstRow = another.getFirstRow();
+ int lastRow = another.getLastRow();
+ int firstCol = another.getFirstColumn();
+ int lastCol = another.getLastColumn();
if
(
- gt(this.getFirstRow(),lastRow) ||
- lt(this.getLastRow(),firstRow) ||
- gt(this.getFirstColumn(),lastCol) ||
- lt(this.getLastColumn(),firstCol)
+ gt(getFirstRow(),lastRow) ||
+ lt(getLastRow(),firstRow) ||
+ gt(getFirstColumn(),lastCol) ||
+ lt(getLastColumn(),firstCol)
)
{
return NO_INTERSECTION;
}
- else if( this.contains(another) )
+ else if( contains(another) )
{
return INSIDE;
}
- else if( another.contains(this) )
+ else if( another.contains(this))
{
return ENCLOSES;
}
}
}
+
+ /**
+ * 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.
*
{
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
- short firstCol = range.getFirstColumn();
- short lastCol = range.getLastColumn();
- return le(this.getFirstRow(), firstRow) && ge(this.getLastRow(), lastRow)
- && le(this.getFirstColumn(), firstCol) && ge(this.getLastColumn(), lastCol);
+ int firstCol = range.getFirstColumn();
+ int lastCol = range.getLastColumn();
+ return le(getFirstRow(), firstRow) && ge(getLastRow(), lastRow)
+ && le(getFirstColumn(), firstCol) && ge(getLastColumn(), lastCol);
}
public boolean contains(int row, short column)
{
- return le(this.getFirstRow(), row) && ge(this.getLastRow(), row)
- && le(this.getFirstColumn(), column) && ge(this.getLastColumn(), column);
+ return le(getFirstRow(), row) && ge(getLastRow(), row)
+ && le(getFirstColumn(), column) && ge(getLastColumn(), column);
}
/**
- * Check if the specified cell range has a shared border with the current range.
- *
- * @return true if the ranges have a shared border.
- */
- public boolean hasSharedBorder(CellRange range)
+ * Check if the specified cell range has a shared border with the current range.
+ *
+ * @return <code>true</code> if the ranges have a complete shared border (i.e.
+ * the two ranges together make a simple rectangular region.
+ */
+ public boolean hasExactSharedBorder(CellRange range)
{
- int firstRow = range.getFirstRow();
- int lastRow = range.getLastRow();
- short firstCol = range.getFirstColumn();
- short lastCol = range.getLastColumn();
- return
- (this.getFirstRow()>0 && this.getFirstRow() - 1 == lastRow || firstRow>0 &&this.getLastRow() == firstRow -1)&&
- (this.getFirstColumn() == firstCol) &&
- (this.getLastColumn() == lastCol) ||
- (this.getFirstColumn()>0 && this.getFirstColumn() - 1 == lastCol || firstCol>0 && this.getLastColumn() == firstCol -1) &&
- (this.getFirstRow() == firstRow) &&
- (this.getLastRow() == lastRow)
- ;
+ int oFirstRow = range._firstRow;
+ int oLastRow = range._lastRow;
+ int oFirstCol = range._firstColumn;
+ int oLastCol = range._lastColumn;
+
+ if (_firstRow > 0 && _firstRow-1 == oLastRow ||
+ oFirstRow > 0 && oFirstRow-1 == _lastRow) {
+ // ranges have a horizontal border in common
+ // make sure columns are identical:
+ return _firstColumn == oFirstCol && _lastColumn == oLastCol;
+ }
+
+ if (_firstColumn>0 && _firstColumn - 1 == oLastCol ||
+ oFirstCol>0 && _lastColumn == oFirstCol -1) {
+ // ranges have a vertical border in common
+ // make sure rows are identical:
+ return _firstRow == oFirstRow && _lastRow == oLastRow;
+ }
+ return false;
}
- /**
- * Create an enclosing CellRange for the two cell ranges.
- *
- * @return enclosing CellRange
- */
+ /**
+ * Create an enclosing CellRange for the two cell ranges.
+ *
+ * @return enclosing CellRange
+ */
public CellRange createEnclosingCellRange(CellRange range)
{
if( range == null)
{
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
public String toString()
{
- return "("+this.getFirstRow()+","+this.getLastRow()+","+this.getFirstColumn()+","+this.getLastColumn()+")";
+ return "("+getFirstRow()+","+getLastRow()+","+getFirstColumn()+","+getLastColumn()+")";
}
-
+
}
/**
- * This class provides the base functionality for Excel sheet functions
+ * This class provides the base functionality for Excel sheet functions
* There are two kinds of function Ptgs - tFunc and tFuncVar
* Therefore, this class will have ONLY two subclasses
* @author Avik Sengupta
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public abstract class AbstractFunctionPtg extends OperationPtg {
-
+
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
- */
+ */
public static final String FUNCTION_NAME_IF = "IF";
/** All external functions have function index 255 */
private static final short FUNCTION_INDEX_EXTERNAL = 255;
-
+
protected byte returnClass;
protected byte[] paramClass;
-
+
protected byte field_1_num_args;
protected short field_2_fnc_index;
-
+
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append("]");
return sb.toString();
}
-
+
public int getType() {
return -1;
- }
-
-
-
+ }
+
+
+
public short getFunctionIndex() {
return field_2_fnc_index;
}
-
+
public String getName() {
return lookupName(field_2_fnc_index);
}
public boolean isExternalFunction() {
return field_2_fnc_index == FUNCTION_INDEX_EXTERNAL;
}
-
+
public String toFormulaString(Workbook book) {
return getName();
}
-
+
public String toFormulaString(String[] operands) {
- StringBuffer buf = new StringBuffer();
-
+ StringBuffer buf = new StringBuffer();
+
if(isExternalFunction()) {
buf.append(operands[0]); // first operand is actually the function name
appendArgs(buf, 1, operands);
}
buf.append(")");
}
-
+
public abstract void writeBytes(byte[] array, int offset);
public abstract int getSize();
-
-
+
+
/**
* Used to detect whether a function name found in a formula is one of the standard excel functions
* <p>
* The name matching is case insensitive.
- * @return <code>true</code> if the name specifies a standard worksheet function,
+ * @return <code>true</code> if the name specifies a standard worksheet function,
* <code>false</code> if the name should be assumed to be an external function.
*/
public static final boolean isInternalFunctionName(String name) {
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
return ix >= 0;
}
-
+
protected String lookupName(short index) {
if(index == FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL) {
return "#external#";
}
return fm.getName();
}
-
+
/**
* Resolves internal function names into function indexes.
* <p>
public byte getDefaultOperandClass() {
return returnClass;
}
-
+
public byte getParameterClass(int index) {
try {
return paramClass[index];
* @author Danny Mui (dmui at apache dot org) (Leftover handling)
*/
public final class FuncPtg extends AbstractFunctionPtg {
-
+
public final static byte sid = 0x21;
public final static int SIZE = 3;
private int numParams=0;
-
+
/**
* FuncPtgs are defined to be 4 bytes but the actual FuncPtg uses only 2 bytes.
* If we have leftOvers that are read from the file we should serialize them back out.
* If the leftovers are removed, a prompt "Warning: Data may have been lost occurs in Excel"
*/
//protected byte[] leftOvers = null;
-
+
private FuncPtg() {
- //Required for clone methods
+ //Required for clone methods
}
- /**Creates new function pointer from a byte array
- * usually called while reading an excel file.
+ /**Creates new function pointer from a byte array
+ * usually called while reading an excel file.
*/
public FuncPtg(RecordInputStream in) {
//field_1_num_args = data[ offset + 0 ];
field_2_fnc_index = in.readShort();
-
+
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if(fm == null) {
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
numParams = numberOfParameters;
paramClass = new byte[] { Ptg.CLASS_VALUE, }; // TODO
}
-
+
public void writeBytes(byte[] array, int offset) {
array[offset+0]= (byte) (sid + ptgClass);
LittleEndian.putShort(array,offset+1,field_2_fnc_index);
}
-
+
public int getNumberOfOperands() {
return numParams;
}
ptg.setClass(ptgClass);
return ptg;
}
-
+
public int getSize() {
return SIZE;
}
-
+
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.RecordInputStream;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public final class FuncVarPtg extends AbstractFunctionPtg{
-
+
public final static byte sid = 0x22;
- private final static int SIZE = 4;
-
+ private final static int SIZE = 4;
+
private FuncVarPtg() {
//Required for clone methods
}
- /**Creates new function pointer from a byte array
- * usually called while reading an excel file.
+ /**Creates new function pointer from a byte array
+ * usually called while reading an excel file.
*/
public FuncVarPtg(RecordInputStream in) {
field_1_num_args = in.readByte();
field_2_fnc_index = in.readShort();
}
-
+
/**
* Create a function ptg from a string tokenised by the parser
*/
paramClass = new byte[] {Ptg.CLASS_VALUE};
}
}
-
+
public void writeBytes(byte[] array, int offset) {
array[offset+0]=(byte) (sid + ptgClass);
array[offset+1]=field_1_num_args;
LittleEndian.putShort(array,offset+2,field_2_fnc_index);
}
-
+
public int getNumberOfOperands() {
return field_1_num_args;
}
-
+
public Object clone() {
FuncVarPtg ptg = new FuncVarPtg();
ptg.field_1_num_args = field_1_num_args;
ptg.setClass(ptgClass);
return ptg;
}
-
+
public int getSize() {
return SIZE;
}
-
+
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
import java.util.Set;
/**
- * Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
+ * Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
* <tt>FunctionMetadataRegistry</tt>.
*
* @author Josh Micich
package org.apache.poi.hssf.record.formula.function;
/**
+ * Holds information about Excel built-in functions.
*
* @author Josh Micich
*/
return _maxParams;
}
public boolean hasFixedArgsLength() {
- return _minParams == _maxParams;
+ return _minParams == _maxParams;
}
public String toString() {
StringBuffer sb = new StringBuffer(64);
public static FunctionMetadataRegistry createRegistry() {
InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
- if(is == null) {
+ if (is == null) {
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
}
import java.util.Map;
import java.util.Set;
-
+/**
+ * Allows clients to get <tt>FunctionMetadata</tt> instances for any built-in function of Excel.
+ *
+ * @author Josh Micich
+ */
public final class FunctionMetadataRegistry {
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
private static FunctionMetadataRegistry getInstance() {
if (_instance == null) {
_instance = FunctionMetadataReader.createRegistry();
-// _instance = POIFunctionMetadataCreator.createInstance();
}
return _instance;
}
if(args.length < 3 || args.length > 5) {
return ErrorEval.VALUE_INVALID;
}
-
- try {
- // evaluate first three (always present) args
+
+ try {
+ // evaluate first three (always present) args
double rate = evalArg(args[0], srcRow, srcCol);
double nper = evalArg(args[1], srcRow, srcCol);
- double pv = evalArg(args[2], srcRow, srcCol);
+ double pv = evalArg(args[2], srcRow, srcCol);
double fv = 0;
boolean arePaymentsAtPeriodBeginning = false;
-
+
switch (args.length) {
case 5:
ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol);
}
double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning);
if (Double.isNaN(d)) {
- return (ValueEval) ErrorEval.VALUE_INVALID;
+ return ErrorEval.VALUE_INVALID;
}
if (Double.isInfinite(d)) {
- return (ValueEval) ErrorEval.NUM_ERROR;
+ return ErrorEval.NUM_ERROR;
}
return new NumberEval(d);
} catch (EvaluationException e) {
* @author Dmitriy Kumshayev
*
*/
-public class HSSFBorderFormatting
+public final class HSSFBorderFormatting
{
- /**
- * No border
- */
+ /** No border */
+ public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;
+ /** Thin border */
+ public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
+ /** Medium border */
+ public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
+ /** dash border */
+ public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
+ /** dot border */
+ public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
+ /** Thick border */
+ public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
+ /** double-line border */
+ public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
+ /** hair-line border */
+ public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
+ /** Medium dashed border */
+ public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
+ /** dash-dot border */
+ public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
+ /** medium dash-dot border */
+ public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
+ /** dash-dot-dot border */
+ public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
+ /** medium dash-dot-dot border */
+ public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
+ /** slanted dash-dot border */
+ public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
- public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;
-
- /**
- * Thin border
- */
-
- public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
-
- /**
- * Medium border
- */
+
+ private final BorderFormatting borderFormatting;
+
+ public HSSFBorderFormatting()
+ {
+ borderFormatting = new BorderFormatting();
+ }
- public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
+ protected BorderFormatting getBorderFormattingBlock()
+ {
+ return borderFormatting;
+ }
- /**
- * dash border
- */
+ public short getBorderBottom()
+ {
+ return borderFormatting.getBorderBottom();
+ }
- public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
+ public short getBorderDiagonal()
+ {
+ return borderFormatting.getBorderDiagonal();
+ }
- /**
- * dot border
- */
+ public short getBorderLeft()
+ {
+ return borderFormatting.getBorderLeft();
+ }
- public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
+ public short getBorderRight()
+ {
+ return borderFormatting.getBorderRight();
+ }
- /**
- * Thick border
- */
+ public short getBorderTop()
+ {
+ return borderFormatting.getBorderTop();
+ }
- public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
+ public short getBottomBorderColor()
+ {
+ return borderFormatting.getBottomBorderColor();
+ }
- /**
- * double-line border
- */
+ public short getDiagonalBorderColor()
+ {
+ return borderFormatting.getDiagonalBorderColor();
+ }
- public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
+ public short getLeftBorderColor()
+ {
+ return borderFormatting.getLeftBorderColor();
+ }
- /**
- * hair-line border
- */
+ public short getRightBorderColor()
+ {
+ return borderFormatting.getRightBorderColor();
+ }
- public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
+ public short getTopBorderColor()
+ {
+ return borderFormatting.getTopBorderColor();
+ }
- /**
- * Medium dashed border
- */
+ public boolean isBackwardDiagonalOn()
+ {
+ return borderFormatting.isBackwardDiagonalOn();
+ }
- public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
+ public boolean isForwardDiagonalOn()
+ {
+ return borderFormatting.isForwardDiagonalOn();
+ }
- /**
- * dash-dot border
- */
+ public void setBackwardDiagonalOn(boolean on)
+ {
+ borderFormatting.setBackwardDiagonalOn(on);
+ }
- public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
+ public void setBorderBottom(short border)
+ {
+ borderFormatting.setBorderBottom(border);
+ }
- /**
- * medium dash-dot border
- */
+ public void setBorderDiagonal(short border)
+ {
+ borderFormatting.setBorderDiagonal(border);
+ }
- public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
+ public void setBorderLeft(short border)
+ {
+ borderFormatting.setBorderLeft(border);
+ }
- /**
- * dash-dot-dot border
- */
+ public void setBorderRight(short border)
+ {
+ borderFormatting.setBorderRight(border);
+ }
- public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
+ public void setBorderTop(short border)
+ {
+ borderFormatting.setBorderTop(border);
+ }
- /**
- * medium dash-dot-dot border
- */
+ public void setBottomBorderColor(short color)
+ {
+ borderFormatting.setBottomBorderColor(color);
+ }
- public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
+ public void setDiagonalBorderColor(short color)
+ {
+ borderFormatting.setDiagonalBorderColor(color);
+ }
- /**
- * slanted dash-dot border
- */
+ public void setForwardDiagonalOn(boolean on)
+ {
+ borderFormatting.setForwardDiagonalOn(on);
+ }
- public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
+ public void setLeftBorderColor(short color)
+ {
+ borderFormatting.setLeftBorderColor(color);
+ }
-
- private BorderFormatting borderFormatting;
-
- public HSSFBorderFormatting()
+ public void setRightBorderColor(short color)
{
- borderFormatting = new BorderFormatting();
+ borderFormatting.setRightBorderColor(color);
}
- protected BorderFormatting getBorderFormattingBlock()
+ public void setTopBorderColor(short color)
{
- return borderFormatting;
+ borderFormatting.setTopBorderColor(color);
}
-
}
==================================================================== */
package org.apache.poi.hssf.usermodel;
-import java.util.ArrayList;
-import java.util.List;
-
+import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
*/
public final class HSSFConditionalFormatting
{
- private final HSSFSheet sheet;
+ private final Workbook workbook;
private final CFRecordsAggregate cfAggregate;
- HSSFConditionalFormatting(HSSFSheet sheet) {
- this(sheet, new CFRecordsAggregate());
- }
-
HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
{
if(sheet == null) {
if(cfAggregate == null) {
throw new IllegalArgumentException("cfAggregate must not be null");
}
- this.sheet = sheet;
+ workbook = sheet.workbook.getWorkbook();
this.cfAggregate = cfAggregate;
}
CFRecordsAggregate getCFRecordsAggregate() {
return cfAggregate;
}
- public void setFormattingRegions(Region[] regions)
- {
- if( regions != null)
- {
- CFHeaderRecord header = cfAggregate.getHeader();
- header.setCellRanges(mergeCellRanges(toCellRangeList(regions)));
- }
- }
-
/**
- * @return array of <tt>Region</tt>s. never <code>null</code>
+ * @return array of <tt>Region</tt>s. never <code>null</code>
*/
public Region[] getFormattingRegions()
{
CFHeaderRecord cfh = cfAggregate.getHeader();
-
- List cellRanges = cfh.getCellRanges();
-
- return toRegionArray(cellRanges);
+ CellRange[] cellRanges = cfh.getCellRanges();
+ return CellRange.convertCellRangesToRegions(cellRanges);
}
/**
- * set a Conditional Formatting rule at position idx.
+ * Replaces an existing Conditional Formatting rule at position idx.
* Excel allows to create up to 3 Conditional Formatting rules.
* This method can be useful to modify existing Conditional Formatting rules.
*
*/
public void setRule(int idx, HSSFConditionalFormattingRule cfRule)
{
- if (idx < 0 || idx > 2) {
- throw new IllegalArgumentException("idx must be between 0 and 2 but was ("
- + idx + ")");
- }
- cfAggregate.getRules().set(idx, cfRule);
+ cfAggregate.setRule(idx, cfRule.getCfRuleRecord());
}
/**
*/
public void addRule(HSSFConditionalFormattingRule cfRule)
{
- cfAggregate.getRules().add(cfRule);
+ cfAggregate.addRule(cfRule.getCfRuleRecord());
}
/**
- * get a Conditional Formatting rule at position idx.
- * @param idx
- * @return a Conditional Formatting rule at position idx.
+ * @return the Conditional Formatting rule at position idx.
*/
public HSSFConditionalFormattingRule getRule(int idx)
{
- CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx);
- return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord);
+ CFRuleRecord ruleRecord = cfAggregate.getRule(idx);
+ return new HSSFConditionalFormattingRule(workbook, ruleRecord);
}
/**
* @return number of Conditional Formatting rules.
*/
- public int getNumbOfRules()
+ public int getNumberOfRules()
{
- return cfAggregate.getRules().size();
- }
-
-
- /**
- * Do all possible cell merges between cells of the list so that:<br>
- * <li>if a cell range is completely inside of another cell range, it gets removed from the list
- * <li>if two cells have a shared border, merge them into one bigger cell range
- * @param cellRangeList
- * @return updated List of cell ranges
- */
- private static List mergeCellRanges(List cellRangeList)
- {
- boolean merged = false;
-
- do
- {
- merged = false;
-
- if( cellRangeList.size()>1 )
- {
- for( int i=0; i<cellRangeList.size(); i++)
- {
- CellRange range1 = (CellRange)cellRangeList.get(i);
- for( int j=i+1; j<cellRangeList.size(); j++)
- {
- CellRange range2 = (CellRange)cellRangeList.get(j);
-
- switch(range1.intersect(range2))
- {
- case CellRange.NO_INTERSECTION:
- {
- if( range1.hasSharedBorder(range2))
- {
- cellRangeList.set(i, range1.createEnclosingCellRange(range2));
- cellRangeList.remove(j--);
- merged = true;
- }
- else
- {
- // No intersection and no shared border: do nothing
- }
- break;
- }
- case CellRange.OVERLAP:
- {
- // TODO split and re-merge the intersected area
- break;
- }
- case CellRange.INSIDE:
- {
- // Remove range2, since it is completely inside of range1
- cellRangeList.remove(j--);
- merged = true;
- break;
- }
- case CellRange.ENCLOSES:
- {
- // range2 encloses range1, so replace it with the enclosing one
- cellRangeList.set(i, range2);
- cellRangeList.remove(j--);
- merged = true;
- break;
- }
- }
- }
- }
- }
- }
- while( merged );
-
- return cellRangeList;
- }
-
- /**
- * Convert a List of CellRange objects to an array of regions
- *
- * @param List of CellRange objects
- * @return regions
- */
- private static Region[] toRegionArray(List cellRanges)
- {
- int size = cellRanges.size();
- Region[] regions = new Region[size];
-
- for (int i = 0; i != size; i++)
- {
- CellRange cr = (CellRange) cellRanges.get(i);
- regions[i] = new Region(cr.getFirstRow(), cr.getFirstColumn(),
- cr.getLastRow(), cr.getLastColumn());
- }
- return regions;
- }
-
- /**
- * Convert array of regions to a List of CellRange objects
- *
- * @param regions
- * @return List of CellRange objects
- */
- private static List toCellRangeList(Region[] regions)
- {
- List cellRangeList = new ArrayList();
- for( int i=0; i<regions.length; i++)
- {
- Region r = regions[i];
- CellRange cr = new CellRange(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r
- .getColumnTo());
- cellRangeList.add(cr);
- }
- return cellRangeList;
+ return cfAggregate.getNumberOfRules();
}
public String toString()
package org.apache.poi.hssf.usermodel;
import java.util.List;
-import java.util.Stack;
import org.apache.poi.hssf.model.FormulaParser;
+import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFRuleRecord;
+import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
+import org.apache.poi.hssf.record.cf.BorderFormatting;
+import org.apache.poi.hssf.record.cf.FontFormatting;
+import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.record.formula.Ptg;
/**
*
- * High level representation of Conditional Format
+ * High level representation of Conditional Formatting Rule.
+ * It allows to specify formula based conditions for the Conditional Formatting
+ * and the formatting settings such as font, border and pattern.
*
* @author Dmitriy Kumshayev
*/
-public class HSSFConditionalFormattingRule
+public final class HSSFConditionalFormattingRule
{
- public static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
- public static final byte FORMULA = CFRuleRecord.CONDITION_TYPE_FORMULA;
+ private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
+
- public static final byte COMPARISON_OPERATOR_NO_COMPARISON = CFRuleRecord.COMPARISON_OPERATOR_NO_COMPARISON;
- public static final byte COMPARISON_OPERATOR_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_BETWEEN;
- public static final byte COMPARISON_OPERATOR_NOT_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_NOT_BETWEEN;
- public static final byte COMPARISON_OPERATOR_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_EQUAL;
- public static final byte COMPARISON_OPERATOR_NOT_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_NOT_EQUAL;
- public static final byte COMPARISON_OPERATOR_GT = CFRuleRecord.COMPARISON_OPERATOR_GT;
- public static final byte COMPARISON_OPERATOR_LT = CFRuleRecord.COMPARISON_OPERATOR_LT;
- public static final byte COMPARISON_OPERATOR_GE = CFRuleRecord.COMPARISON_OPERATOR_GE;
- public static final byte COMPARISON_OPERATOR_LE = CFRuleRecord.COMPARISON_OPERATOR_LE;
-
-
- private CFRuleRecord cfRuleRecord;
- private HSSFWorkbook workbook;
-
- protected HSSFConditionalFormattingRule(HSSFWorkbook workbook)
- {
- this.workbook = workbook;
- this.cfRuleRecord = new CFRuleRecord();
- }
- protected HSSFConditionalFormattingRule(HSSFWorkbook workbook, CFRuleRecord cfRuleRecord)
- {
- this.workbook = workbook;
- this.cfRuleRecord = cfRuleRecord;
- }
+ private final CFRuleRecord cfRuleRecord;
+ private final Workbook workbook;
- /**
- * Keep Font Formatting unchanged for this Conditional Formatting Rule
- */
- public void setFontFormattingUnchanged()
- {
- cfRuleRecord.setFontFormattingUnchanged();
- }
- /**
- * Keep Border Formatting unchanged for this Conditional Formatting Rule
- */
- public void setBorderFormattingUnchanged()
- {
- cfRuleRecord.setBorderFormattingUnchanged();
+ HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord) {
+ workbook = pWorkbook;
+ cfRuleRecord = pRuleRecord;
}
- /**
- * Keep Pattern Formatting unchanged for this Conditional Formatting Rule
- */
- public void setPatternFormattingUnchanged()
- {
- cfRuleRecord.setPatternFormattingUnchanged();
+ HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord,
+ HSSFFontFormatting fontFmt, HSSFBorderFormatting bordFmt, HSSFPatternFormatting patternFmt) {
+ this(pWorkbook, pRuleRecord);
+ setFontFormatting(fontFmt);
+ setBorderFormatting(bordFmt);
+ setPatternFormatting(patternFmt);
}
-
- public void setFontFormatting(HSSFFontFormatting fontFormatting)
- {
- if( fontFormatting!=null )
- {
- cfRuleRecord.setFontFormatting(fontFormatting.getFontFormattingBlock());
- }
- else
- {
- setFontFormattingUnchanged();
- }
- }
- public void setBorderFormatting(HSSFBorderFormatting borderFormatting)
+
+ CFRuleRecord getCfRuleRecord()
{
- if( borderFormatting != null )
- {
- cfRuleRecord.setBorderFormatting(borderFormatting.getBorderFormattingBlock());
- }
- else
- {
- setBorderFormattingUnchanged();
- }
- }
- public void setPatternFormatting(HSSFPatternFormatting patternFormatting)
- {
- if( patternFormatting != null)
- {
- cfRuleRecord.setPatternFormatting(patternFormatting.getPatternFormattingBlock());
- }
- else
- {
- setPatternFormattingUnchanged();
- }
+ return cfRuleRecord;
}
- public void setCellComparisonCondition(byte comparisonOperation, String formula1, String formula2)
- {
- cfRuleRecord.setConditionType(CELL_COMPARISON);
- cfRuleRecord.setComparisonOperation(comparisonOperation);
-
- // Formula 1
- setFormula1(formula1);
-
- // Formula 2
- setFormula1(formula2);
- }
- public void setFormulaCondition(String formula)
+ /**
+ * @param fontFmt pass <code>null</code> to signify 'font unchanged'
+ */
+ public void setFontFormatting(HSSFFontFormatting fontFmt)
{
- cfRuleRecord.setConditionType(FORMULA);
- // Formula 1
- setFormula1(formula);
+ FontFormatting block = fontFmt==null ? null : fontFmt.getFontFormattingBlock();
+ cfRuleRecord.setFontFormatting(block);
}
-
- public void setFormula1(String formula)
+ /**
+ * @param borderFmt pass <code>null</code> to signify 'border unchanged'
+ */
+ public void setBorderFormatting(HSSFBorderFormatting borderFmt)
{
- // Formula 1
- if( formula != null)
- {
- Stack parsedExpression = parseFormula(formula);
- if( parsedExpression != null )
- {
- cfRuleRecord.setParsedExpression1(parsedExpression);
- }
- else
- {
- cfRuleRecord.setParsedExpression1(null);
- }
- }
- else
- {
- cfRuleRecord.setParsedExpression1(null);
- }
+ BorderFormatting block = borderFmt==null ? null : borderFmt.getBorderFormattingBlock();
+ cfRuleRecord.setBorderFormatting(block);
}
-
- public void setFormula2(String formula)
+ /**
+ * @param patternFmt pass <code>null</code> to signify 'pattern unchanged'
+ */
+ public void setPatternFormatting(HSSFPatternFormatting patternFmt)
{
- // Formula 2
- if( formula != null)
- {
- Stack parsedExpression = parseFormula(formula);
- if( parsedExpression != null )
- {
- cfRuleRecord.setParsedExpression2(parsedExpression);
- }
- else
- {
- cfRuleRecord.setParsedExpression2(null);
- }
- }
- else
- {
- cfRuleRecord.setParsedExpression2(null);
- }
+ PatternFormatting block = patternFmt==null ? null : patternFmt.getPatternFormattingBlock();
+ cfRuleRecord.setPatternFormatting(block);
}
public String getFormula1()
{
- return toFormulaString(cfRuleRecord.getParsedExpression1());
+ return toFormulaString(cfRuleRecord.getParsedExpression1());
}
public String getFormula2()
{
byte conditionType = cfRuleRecord.getConditionType();
- switch(conditionType)
- {
- case CELL_COMPARISON:
+ if (conditionType == CELL_COMPARISON) {
+ byte comparisonOperation = cfRuleRecord.getComparisonOperation();
+ switch(comparisonOperation)
{
- byte comparisonOperation = cfRuleRecord.getComparisonOperation();
- switch(comparisonOperation)
- {
- case COMPARISON_OPERATOR_BETWEEN:
- case COMPARISON_OPERATOR_NOT_BETWEEN:
- return toFormulaString(cfRuleRecord.getParsedExpression2());
- }
+ case ComparisonOperator.BETWEEN:
+ case ComparisonOperator.NOT_BETWEEN:
+ return toFormulaString(cfRuleRecord.getParsedExpression2());
}
}
return null;
}
- private String toFormulaString(List parsedExpression)
+ private String toFormulaString(Ptg[] parsedExpression)
{
String formula = null;
if(parsedExpression!=null)
{
- formula = FormulaParser.toFormulaString(workbook.getWorkbook(),parsedExpression);
+ formula = FormulaParser.toFormulaString(workbook, parsedExpression);
}
return formula;
}
-
-
- private Stack parseFormula(String formula2)
- {
- FormulaParser parser =
- new FormulaParser(formula2, workbook.getWorkbook());
- parser.parse();
-
- Stack parsedExpression = convertToTokenStack(parser.getRPNPtg());
- parsedExpression = convertToTokenStack(parser.getRPNPtg());
- return parsedExpression;
- }
-
- private static Stack convertToTokenStack(Ptg[] ptgs)
- {
- if( ptgs != null)
- {
- Stack parsedExpression = new Stack();
- // fill the Ptg Stack with Ptgs of new formula
- for (int k = 0; k < ptgs.length; k++)
- {
- parsedExpression.push(ptgs[ k ]);
- }
- return parsedExpression;
- }
- else
- {
- return null;
- }
- }
-
-
}
*/
HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate)
{
- this.boundAggregate = boundAggregate;
+ this.boundAggregate = boundAggregate;
this.sheet = sheet;
}
* to work on some charts so far)
*/
public boolean containsChart() {
- // TODO - support charts properly in usermodel
-
- // We're looking for a EscherOptRecord
- EscherOptRecord optRecord = (EscherOptRecord)
- boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
- if(optRecord == null) {
- // No opt record, can't have chart
- return false;
- }
-
- for(Iterator it = optRecord.getEscherProperties().iterator(); it.hasNext();) {
- EscherProperty prop = (EscherProperty)it.next();
- if(prop.getPropertyNumber() == 896 && prop.isComplex()) {
- EscherComplexProperty cp = (EscherComplexProperty)prop;
- String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
- System.err.println(str);
- if(str.equals("Chart 1\0")) {
- return true;
- }
- }
- }
+ // TODO - support charts properly in usermodel
+
+ // We're looking for a EscherOptRecord
+ EscherOptRecord optRecord = (EscherOptRecord)
+ boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
+ if(optRecord == null) {
+ // No opt record, can't have chart
+ return false;
+ }
+
+ for(Iterator it = optRecord.getEscherProperties().iterator(); it.hasNext();) {
+ EscherProperty prop = (EscherProperty)it.next();
+ if(prop.getPropertyNumber() == 896 && prop.isComplex()) {
+ EscherComplexProperty cp = (EscherComplexProperty)prop;
+ String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
+ //System.err.println(str);
+ if(str.equals("Chart 1\0")) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
/**
* Returns the aggregate escher record we're bound to
*/
protected EscherAggregate _getBoundAggregate() {
- return boundAggregate;
+ return boundAggregate;
}
}
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CellValueRecordInterface;
+import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.EOFRecord;
* @param leftcol the left column to show in desktop window pane
*/
public void showInPane(short toprow, short leftcol){
- this.sheet.setTopRow((short)toprow);
- this.sheet.setLeftCol((short)leftcol);
+ this.sheet.setTopRow(toprow);
+ this.sheet.setLeftCol(leftcol);
}
/**
int i = 0;
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
- returnValue[i++] = (int)breakItem.main;
+ returnValue[i++] = breakItem.main;
}
return returnValue;
}
*
* @return cell comment or <code>null</code> if not found
*/
- public HSSFComment getCellComment(int row, int column){
+ public HSSFComment getCellComment(int row, int column) {
// Don't call findCellComment directly, otherwise
// two calls to this method will result in two
// new HSSFComment instances, which is bad
* with a cell comparison operator and
* formatting rules such as font format, border format and pattern format
*
- * @param comparisonOperation - one of the following values: <p>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
+ * @param comparisonOperation - a constant value from
+ * <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
+ * <ul>
+ * <li>BETWEEN</li>
+ * <li>NOT_BETWEEN</li>
+ * <li>EQUAL</li>
+ * <li>NOT_EQUAL</li>
+ * <li>GT</li>
+ * <li>LT</li>
+ * <li>GE</li>
+ * <li>LE</li>
+ * </ul>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
- * @param fontFmt - font formatting rules
- * @param bordFmt - border formatting rules
- * @param patternFmt - pattern formatting rules
- * @return
- *
+ * @param fontFmt - font formatting rules (may be <code>null</code>)
+ * @param bordFmt - border formatting rules (may be <code>null</code>)
+ * @param patternFmt - pattern formatting rules (may be <code>null</code>)
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation,
String formula2,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
- HSSFPatternFormatting patternFmt)
- {
- HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
- cf.setFontFormatting(fontFmt);
- cf.setBorderFormatting(bordFmt);
- cf.setPatternFormatting(patternFmt);
- cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
- return cf;
+ HSSFPatternFormatting patternFmt) {
+
+ Workbook wb = workbook.getWorkbook();
+ CFRuleRecord rr = CFRuleRecord.create(wb, comparisonOperation, formula1, formula2);
+ return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
}
/**
*
* The formatting rules are applied by Excel when the value of the formula not equal to 0.
*
- * @param comparisonOperation - one of the following values: <p>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}</li>
- * <li>{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}</li>
- * </p>
- * @param formula1 - formula for the valued, compared with the cell
- * @param formula2 - second formula (only used with
- * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
- * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
- * @param fontFmt - font formatting rules
- * @param bordFmt - border formatting rules
- * @param patternFmt - pattern formatting rules
- * @return
- *
+ * @param formula - formula for the valued, compared with the cell
+ * @param fontFmt - font formatting rules (may be <code>null</code>)
+ * @param bordFmt - border formatting rules (may be <code>null</code>)
+ * @param patternFmt - pattern formatting rules (may be <code>null</code>)
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
String formula,
HSSFFontFormatting fontFmt,
HSSFBorderFormatting bordFmt,
- HSSFPatternFormatting patternFmt)
- {
- HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
- cf.setFontFormatting(fontFmt);
- cf.setBorderFormatting(bordFmt);
- cf.setPatternFormatting(patternFmt);
- cf.setFormulaCondition(formula);
- return cf;
+ HSSFPatternFormatting patternFmt) {
+ Workbook wb = workbook.getWorkbook();
+ CFRuleRecord rr = CFRuleRecord.create(wb, formula);
+ return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
}
/**
* @param cf HSSFConditionalFormatting object
* @return index of the new Conditional Formatting object
*/
- public int addConditionalFormatting( HSSFConditionalFormatting cf )
- {
+ public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
return sheet.addConditionalFormatting(cfraClone);
* Allows to add a new Conditional Formatting set to the sheet.
*
* @param regions - list of rectangular regions to apply conditional formatting rules
- * @param cfRules - set of up to three conditional formatting rules
+ * @param hcfRules - set of up to three conditional formatting rules
*
* @return index of the newly created Conditional Formatting object
*/
- public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules )
- {
- HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
- cf.setFormattingRegions(regions);
- if( cfRules != null )
- {
- for( int i=0; i!= cfRules.length; i++ )
- {
- cf.addRule(cfRules[i]);
- }
- }
- return sheet.addConditionalFormatting(cf.getCFRecordsAggregate());
+ public int addConditionalFormatting(Region [] regions, HSSFConditionalFormattingRule [] hcfRules) {
+ if (regions == null) {
+ throw new IllegalArgumentException("regions must not be null");
+ }
+ if (hcfRules == null) {
+ throw new IllegalArgumentException("hcfRules must not be null");
+ }
+
+ CFRuleRecord[] rules = new CFRuleRecord[hcfRules.length];
+ for (int i = 0; i != hcfRules.length; i++) {
+ rules[i] = hcfRules[i].getCfRuleRecord();
+ }
+ CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
+ return sheet.addConditionalFormatting(cfra);
}
/**
* gets Conditional Formatting object at a particular index
- * @param index of the Conditional Formatting object to fetch
+ *
+ * @param index
+ * of the Conditional Formatting object to fetch
* @return Conditional Formatting object
*/
-
- public HSSFConditionalFormatting getConditionalFormattingAt(int index)
- {
+ public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
- if( cf != null )
- {
- return new HSSFConditionalFormatting(this,cf);
+ if (cf == null) {
+ return null;
}
- return null;
+ return new HSSFConditionalFormatting(this,cf);
}
/**
* @return number of Conditional Formatting objects of the sheet
*/
- public int getNumConditionalFormattings()
- {
+ public int getNumConditionalFormattings() {
return sheet.getNumConditionalFormattings();
}
* removes a Conditional Formatting object by index
* @param index of a Conditional Formatting object to remove
*/
- public void removeConditionalFormatting(int index)
- {
+ public void removeConditionalFormatting(int index) {
sheet.removeConditionalFormatting(index);
}
}
}
}
+ /**
+ * Removes the specified shape from this sheet.
+ *
+ * @param shape shape to be removed from this sheet, if present.
+ * @return <tt>true</tt> if the shape was deleted.
+ */
+ public boolean removeShape(Shape shape) {
+ PPDrawing ppdrawing = getPPDrawing();
+
+ EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+ EscherContainerRecord spgr = null;
+
+ for (Iterator it = dg.getChildRecords().iterator(); it.hasNext();) {
+ EscherRecord rec = (EscherRecord) it.next();
+ if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
+ spgr = (EscherContainerRecord) rec;
+ break;
+ }
+ }
+ if(spgr == null) return false;
+
+ List lst = spgr.getChildRecords();
+ return lst.remove(shape.getSpContainer());
+ }
+
/**
* Return the master sheet .
*/
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
/**
line = (Line)grshape[1];
assertEquals(new Rectangle(300, 300, 500, 0), line.getAnchor());
}
+
+ /**
+ * Test functionality of Sheet.removeShape(Shape shape)
+ */
+ public void testRemoveShapes() throws IOException {
+ String file = System.getProperty("HSLF.testdata.path")+ "/with_textbox.ppt";
+ SlideShow ppt = new SlideShow(new HSLFSlideShow(file));
+ Slide sl = ppt.getSlides()[0];
+ Shape[] sh = sl.getShapes();
+ assertEquals("expected four shaped in " + file, 4, sh.length);
+ //remove all
+ for (int i = 0; i < sh.length; i++) {
+ boolean ok = sl.removeShape(sh[i]);
+ assertTrue("Failed to delete shape #" + i, ok);
+ }
+ //now Slide.getShapes() should return an empty array
+ assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().length);
+
+ //serialize and read again. The file should be readable and contain no shapes
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ppt.write(out);
+ out.close();
+
+ ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray()));
+ sl = ppt.getSlides()[0];
+ assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().length);
+ }
}
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
+
package org.apache.poi.hssf.model;
import junit.framework.AssertionFailedError;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
- * Test the low level formula parser functionality. High level tests are to
+ * Test the low level formula parser functionality. High level tests are to
* be done via usermodel/HSSFCell.setFormulaValue() .
* Some tests are also done in scratchpad, if they need
* HSSFFormulaEvaluator, which is there
assertNotNull("Ptg array should not be null", result);
return result;
}
-
+
public void testSimpleFormula() {
FormulaParser fp = new FormulaParser("2+2",null);
fp.parse();
assertTrue("",(ptgs[0] instanceof IntPtg));
assertTrue("",(ptgs[1] instanceof IntPtg));
assertTrue("",(ptgs[2] instanceof AddPtg));
-
+
}
-
+
public void testFormulaWithSpace2() {
Ptg[] ptgs;
FormulaParser fp;
ptgs = fp.getRPNPtg();
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
}
-
+
public void testFormulaWithSpaceNRef() {
Ptg[] ptgs;
FormulaParser fp;
ptgs = fp.getRPNPtg();
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
}
-
+
public void testFormulaWithString() {
Ptg[] ptgs;
FormulaParser fp;
}
-
+
/**
* Make sure the ptgs are generated properly with two functions embedded
*
assertEquals("4 Ptgs expected", 4, asts.length);
}
-
+
/**
* Bug Reported by xt-jens.riis@nokia.com (Jens Riis)
* Refers to Bug <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17582">#17582</a>
}
-
+
public void testSimpleLogical() {
FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
fp.parse();
assertTrue("Ptg array should not be null", ptgs !=null);
assertEquals("Ptg array length", 9, ptgs.length);
assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
-
-
+
+
}
-
+
public void testParenIf() {
FormulaParser fp=new FormulaParser("IF((A1+A2)<=3,\"yes\",\"no\")",null);
fp.parse();
assertEquals("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
}
-
+
public void testMacroFunction() {
Workbook w = Workbook.createWorkbook();
FormulaParser fp = new FormulaParser("FOO()", w);
// the name gets encoded as the first arg
NamePtg tname = (NamePtg) ptg[0];
assertEquals("FOO", tname.toFormulaString(w));
-
+
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertTrue(tfunc.isExternalFunction());
}
Ptg[] ptg = fp.getRPNPtg();
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
-
+
}
-
+
public void testConcatenate(){
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")",null);
fp.parse();
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
}
-
+
public void testWorksheetReferences()
{
HSSFWorkbook wb = new HSSFWorkbook();
cell = row.createCell((short)1);
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
}
-
+
public void testUnaryMinus()
{
FormulaParser fp = new FormulaParser("-A1", null);
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
assertTrue("second ptg is Minus",ptg[1] instanceof UnaryMinusPtg);
}
-
+
public void testUnaryPlus()
{
FormulaParser fp = new FormulaParser("+A1", null);
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
assertTrue("second ptg is Plus",ptg[1] instanceof UnaryPlusPtg);
}
-
+
public void testLeadingSpaceInString()
{
String value = " hi ";
FormulaParser fp = new FormulaParser("\"" + value + "\"", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
-
+
assertTrue("got 1 ptg", ptg.length == 1);
assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
-
+
assertTrue("got 4 ptg", ptg.length == 4);
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
fp = new FormulaParser("match(A1, A3:A52)", null);
fp.parse();
ptg = fp.getRPNPtg();
-
+
assertTrue("got 3 ptg", ptg.length == 3);
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
}
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
junit.textui.TestRunner.run(TestFormulaParser.class);
}
-
+
public void testNumbers() {
HSSFWorkbook wb = new HSSFWorkbook();
-
+
wb.createSheet("Cash_Flow");
-
+
HSSFSheet sheet = wb.createSheet("Test");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
String formula = null;
-
+
// starts from decimal point
-
+
cell.setCellFormula(".1");
formula = cell.getCellFormula();
assertEquals("0.1", formula);
-
+
cell.setCellFormula("+.1");
formula = cell.getCellFormula();
assertEquals("+0.1", formula);
-
+
cell.setCellFormula("-.1");
formula = cell.getCellFormula();
assertEquals("-0.1", formula);
-
+
// has exponent
-
+
cell.setCellFormula("10E1");
formula = cell.getCellFormula();
assertEquals("100.0", formula);
-
+
cell.setCellFormula("10E+1");
formula = cell.getCellFormula();
assertEquals("100.0", formula);
-
+
cell.setCellFormula("10E-1");
formula = cell.getCellFormula();
assertEquals("1.0", formula);
}
-
+
public void testRanges() {
HSSFWorkbook wb = new HSSFWorkbook();
-
+
wb.createSheet("Cash_Flow");
-
+
HSSFSheet sheet = wb.createSheet("Test");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
String formula = null;
-
+
cell.setCellFormula("A1.A2");
formula = cell.getCellFormula();
assertEquals("A1:A2", formula);
-
+
cell.setCellFormula("A1..A2");
formula = cell.getCellFormula();
assertEquals("A1:A2", formula);
-
+
cell.setCellFormula("A1...A2");
formula = cell.getCellFormula();
assertEquals("A1:A2", formula);
}
-
+
/**
* Test for bug observable at svn revision 618865 (5-Feb-2008)<br/>
* a formula consisting of a single no-arg function got rendered without the function braces
*/
public void testToFormulaStringZeroArgFunction() {
-
+
Workbook book = Workbook.createWorkbook(); // not really used in this test
-
+
Ptg[] ptgs = {
new FuncPtg(10, 0),
};
assertEquals(2, ptgs.length);
assertEquals(ptgs[0].getClass(), IntPtg.class);
assertEquals(ptgs[1].getClass(), PercentPtg.class);
-
-
- // double percent OK
+
+
+ // double percent OK
ptgs = parseFormula("12345.678%%");
assertEquals(3, ptgs.length);
assertEquals(ptgs[0].getClass(), NumberPtg.class);
assertEquals(ptgs[1].getClass(), PercentPtg.class);
assertEquals(ptgs[2].getClass(), PercentPtg.class);
-
+
// percent of a bracketed expression
ptgs = parseFormula("(A1+35)%*B1%");
assertEquals(8, ptgs.length);
assertEquals(ptgs[4].getClass(), PercentPtg.class);
assertEquals(ptgs[6].getClass(), PercentPtg.class);
-
+
// percent of a text quantity
ptgs = parseFormula("\"8.75\"%");
assertEquals(2, ptgs.length);
//
// things that parse OK but would *evaluate* to an error
-
+
ptgs = parseFormula("\"abc\"%");
assertEquals(2, ptgs.length);
assertEquals(ptgs[0].getClass(), StringPtg.class);
assertEquals(ptgs[1].getClass(), PercentPtg.class);
-
+
ptgs = parseFormula("#N/A%");
assertEquals(2, ptgs.length);
assertEquals(ptgs[0].getClass(), ErrPtg.class);
assertEquals(ptgs[1].getClass(), PercentPtg.class);
}
-
+
/**
* Tests combinations of various operators in the absence of brackets
*/
public void testPrecedenceAndAssociativity() {
Class[] expClss;
-
+
// TRUE=TRUE=2=2 evaluates to FALSE
- expClss = new Class[] { BoolPtg.class, BoolPtg.class, EqualPtg.class,
+ expClss = new Class[] { BoolPtg.class, BoolPtg.class, EqualPtg.class,
IntPtg.class, EqualPtg.class, IntPtg.class, EqualPtg.class, };
confirmTokenClasses("TRUE=TRUE=2=2", expClss);
-
+
// 2^3^2 evaluates to 64 not 512
- expClss = new Class[] { IntPtg.class, IntPtg.class, PowerPtg.class,
+ expClss = new Class[] { IntPtg.class, IntPtg.class, PowerPtg.class,
IntPtg.class, PowerPtg.class, };
confirmTokenClasses("2^3^2", expClss);
-
+
// "abc" & 2 + 3 & "def" evaluates to "abc5def"
- expClss = new Class[] { StringPtg.class, IntPtg.class, IntPtg.class,
+ expClss = new Class[] { StringPtg.class, IntPtg.class, IntPtg.class,
AddPtg.class, ConcatPtg.class, StringPtg.class, ConcatPtg.class, };
confirmTokenClasses("\"abc\"&2+3&\"def\"", expClss);
-
-
+
+
// (1 / 2) - (3 * 4)
- expClss = new Class[] { IntPtg.class, IntPtg.class, DividePtg.class,
+ expClss = new Class[] { IntPtg.class, IntPtg.class, DividePtg.class,
IntPtg.class, IntPtg.class, MultiplyPtg.class, SubtractPtg.class, };
confirmTokenClasses("1/2-3*4", expClss);
-
+
// 2 * (2^2)
expClss = new Class[] { IntPtg.class, IntPtg.class, IntPtg.class, PowerPtg.class, MultiplyPtg.class, };
// NOT: (2 *2) ^ 2 -> int int multiply int power
confirmTokenClasses("2*2^2", expClss);
-
+
// 2^200% -> 2 not 1.6E58
expClss = new Class[] { IntPtg.class, IntPtg.class, PercentPtg.class, PowerPtg.class, };
confirmTokenClasses("2^200%", expClss);
}
-
+
private static void confirmTokenClasses(String formula, Class[] expectedClasses) {
Ptg[] ptgs = parseFormula(formula);
assertEquals(expectedClasses.length, ptgs.length);
for (int i = 0; i < expectedClasses.length; i++) {
if(expectedClasses[i] != ptgs[i].getClass()) {
fail("difference at token[" + i + "]: expected ("
- + expectedClasses[i].getName() + ") but got ("
+ + expectedClasses[i].getName() + ") but got ("
+ ptgs[i].getClass().getName() + ")");
}
}
public void testParseNumber() {
IntPtg ip;
-
+
// bug 33160
ip = (IntPtg) parseSingleToken("40", IntPtg.class);
assertEquals(40, ip.getValue());
ip = (IntPtg) parseSingleToken("40000", IntPtg.class);
assertEquals(40000, ip.getValue());
-
+
// check the upper edge of the IntPtg range:
ip = (IntPtg) parseSingleToken("65535", IntPtg.class);
assertEquals(65535, ip.getValue());
NumberPtg np = (NumberPtg) parseSingleToken("65536", NumberPtg.class);
assertEquals(65536, np.getValue(), 0);
-
+
np = (NumberPtg) parseSingleToken("65534.6", NumberPtg.class);
assertEquals(65534.6, np.getValue(), 0);
}
-
+
public void testMissingArgs() {
-
+
Class[] expClss;
-
- expClss = new Class[] { ReferencePtg.class, MissingArgPtg.class, ReferencePtg.class,
+
+ expClss = new Class[] { ReferencePtg.class, MissingArgPtg.class, ReferencePtg.class,
FuncVarPtg.class, };
confirmTokenClasses("if(A1, ,C1)", expClss);
-
+
expClss = new Class[] { MissingArgPtg.class, AreaPtg.class, MissingArgPtg.class,
FuncVarPtg.class, };
confirmTokenClasses("counta( , A1:B2, )", expClss);
}
public void testParseErrorLiterals() {
-
+
confirmParseErrorLiteral(ErrPtg.NULL_INTERSECTION, "#NULL!");
confirmParseErrorLiteral(ErrPtg.DIV_ZERO, "#DIV/0!");
confirmParseErrorLiteral(ErrPtg.VALUE_INVALID, "#VALUE!");
private static void confirmParseErrorLiteral(ErrPtg expectedToken, String formula) {
assertEquals(expectedToken, parseSingleToken(formula, ErrPtg.class));
}
-
+
/**
* To aid readability the parameters have been encoded with single quotes instead of double
* quotes. This method converts single quotes to double quotes before performing the parse
// formula: internal quotes become double double, surround with double quotes
String formula = '"' + singleQuotedValue.replaceAll("'", "\"\"") + '"';
String expectedValue = singleQuotedValue.replace('\'', '"');
-
+
StringPtg sp = (StringPtg) parseSingleToken(formula, StringPtg.class);
assertEquals(expectedValue, sp.getValue());
}
-
+
public void testPaseStringLiterals() {
confirmStringParse("goto considered harmful");
-
+
confirmStringParse("goto 'considered' harmful");
-
+
confirmStringParse("");
confirmStringParse("'");
confirmStringParse("''");
confirmStringParse("' '");
confirmStringParse(" ' ");
}
-
+
public void testParseSumIfSum() {
String formulaString;
Ptg[] ptgs;
parseExpectedException("1 + #N / A * 2");
parseExpectedException("#value?");
parseExpectedException("#DIV/ 0+2");
-
-
+
+
if (false) { // TODO - add functionality to detect func arg count mismatch
parseExpectedException("IF(TRUE)");
parseExpectedException("countif(A1:B5, C1, D1)");
}
}
-
+
private static void parseExpectedException(String formula) {
try {
parseFormula(formula);
}
public void testSetFormulaWithRowBeyond32768_Bug44539() {
-
+
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
-
+
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
cell.setCellFormula("SUM(A32769:A32770)");
throw e;
}
// FormulaParser strips spaces anyway
- assertEquals("4", formulaString);
+ assertEquals("4", formulaString);
ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, new AddPtg()};
formulaString = FormulaParser.toFormulaString(null, ptgs);
- assertEquals("3+4", formulaString);
+ assertEquals("3+4", formulaString);
}
/**
public void testTooFewOperandArgs() {
// Simulating badly encoded cell formula of "=/1"
// Not sure if Excel could ever produce this
- Ptg[] ptgs = {
+ Ptg[] ptgs = {
// Excel would probably have put tMissArg here
new IntPtg(1),
new DividePtg(),
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.functions.AllIndividualFunctionEvaluationTests;
import junit.framework.Test;
import junit.framework.TestSuite;
TestSuite result = new TestSuite(AllRecordTests.class.getName());
result.addTest(AllFormulaTests.suite());
-
+ result.addTest(AllRecordAggregateTests.suite());
+
result.addTestSuite(TestAreaFormatRecord.class);
result.addTestSuite(TestAreaRecord.class);
result.addTestSuite(TestAxisLineFormatRecord.class);
result.addTestSuite(TestBarRecord.class);
result.addTestSuite(TestBoundSheetRecord.class);
result.addTestSuite(TestCategorySeriesAxisRecord.class);
+ result.addTestSuite(TestCFHeaderRecord.class);
+ result.addTestSuite(TestCFRuleRecord.class);
result.addTestSuite(TestChartRecord.class);
result.addTestSuite(TestChartTitleFormatRecord.class);
result.addTestSuite(TestCommonObjectDataSubRecord.class);
package org.apache.poi.hssf.record;
-import java.util.ArrayList;
-import java.util.List;
-
import junit.framework.TestCase;
import org.apache.poi.hssf.record.cf.CellRange;
*
* @author Dmitriy Kumshayev
*/
-public class TestCFHeaderRecord
- extends TestCase
+public final class TestCFHeaderRecord extends TestCase
{
- public TestCFHeaderRecord(String name)
- {
- super(name);
- }
+ public void testCreateCFHeaderRecord ()
+ {
+ CFHeaderRecord record = new CFHeaderRecord();
+ CellRange[] ranges = {
+ new CellRange(0,-1,5,5),
+ new CellRange(0,-1,6,6),
+ new CellRange(0,1,0,1),
+ new CellRange(0,1,2,3),
+ new CellRange(2,3,0,1),
+ new CellRange(2,3,2,3),
+ };
+ record.setCellRanges(ranges);
+ ranges = record.getCellRanges();
+ assertEquals(6,ranges.length);
+ CellRange enclosingCellRange = record.getEnclosingCellRange();
+ assertEquals(0, enclosingCellRange.getFirstRow());
+ assertEquals(-1, enclosingCellRange.getLastRow());
+ assertEquals(0, enclosingCellRange.getFirstColumn());
+ assertEquals(6, enclosingCellRange.getLastColumn());
+ record.setNeedRecalculation(true);
+ assertTrue(record.getNeedRecalculation());
+ record.setNeedRecalculation(false);
+ assertFalse(record.getNeedRecalculation());
+ }
+
+ public void testSerialization() {
+ byte[] recordData = new byte[]
+ {
+ (byte)0x03, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+
+ (byte)0x04, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ };
+
+ CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
+
+ assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
+ assertTrue(record.getNeedRecalculation());
+ CellRange enclosingCellRange = record.getEnclosingCellRange();
+ assertEquals(0, enclosingCellRange.getFirstRow());
+ assertEquals(3, enclosingCellRange.getLastRow());
+ assertEquals(0, enclosingCellRange.getFirstColumn());
+ assertEquals(3, enclosingCellRange.getLastColumn());
+ CellRange[] ranges = record.getCellRanges();
+ CellRange range0 = ranges[0];
+ assertEquals(0, range0.getFirstRow());
+ assertEquals(1, range0.getLastRow());
+ assertEquals(0, range0.getFirstColumn());
+ assertEquals(1, range0.getLastColumn());
+ CellRange range1 = ranges[1];
+ assertEquals(0, range1.getFirstRow());
+ assertEquals(1, range1.getLastRow());
+ assertEquals(2, range1.getFirstColumn());
+ assertEquals(3, range1.getLastColumn());
+ CellRange range2 = ranges[2];
+ assertEquals(2, range2.getFirstRow());
+ assertEquals(3, range2.getLastRow());
+ assertEquals(0, range2.getFirstColumn());
+ assertEquals(1, range2.getLastColumn());
+ CellRange range3 = ranges[3];
+ assertEquals(2, range3.getFirstRow());
+ assertEquals(3, range3.getLastRow());
+ assertEquals(2, range3.getFirstColumn());
+ assertEquals(3, range3.getLastColumn());
+ assertEquals(recordData.length+4, record.getRecordSize());
- public void testCreateCFHeaderRecord ()
- {
- CFHeaderRecord record = new CFHeaderRecord();
- List ranges = new ArrayList();
- ranges.add(new CellRange(0,-1,(short)5,(short)5));
- ranges.add(new CellRange(0,-1,(short)6,(short)6));
- ranges.add(new CellRange(0,1,(short)0,(short)1));
- ranges.add(new CellRange(0,1,(short)2,(short)3));
- ranges.add(new CellRange(2,3,(short)0,(short)1));
- ranges.add(new CellRange(2,3,(short)2,(short)3));
- record.setCellRanges(ranges);
- ranges = record.getCellRanges();
- assertEquals(6,ranges.size());
- CellRange enclosingCellRange = record.getEnclosingCellRange();
- assertEquals(0, enclosingCellRange.getFirstRow());
- assertEquals(-1, enclosingCellRange.getLastRow());
- assertEquals(0, enclosingCellRange.getFirstColumn());
- assertEquals(6, enclosingCellRange.getLastColumn());
- record.setNeedRecalculation(true);
- assertTrue(record.getNeedRecalculation());
- record.setNeedRecalculation(false);
- assertFalse(record.getNeedRecalculation());
- }
-
- public void testSerialization() {
- byte[] recordData = new byte[]
- {
- (byte)0x03, (byte)0x00,
- (byte)0x01, (byte)0x00,
-
- (byte)0x00, (byte)0x00,
- (byte)0x03, (byte)0x00,
- (byte)0x00, (byte)0x00,
- (byte)0x03, (byte)0x00,
-
- (byte)0x04, (byte)0x00,
-
- (byte)0x00, (byte)0x00,
- (byte)0x01, (byte)0x00,
- (byte)0x00, (byte)0x00,
- (byte)0x01, (byte)0x00,
-
- (byte)0x00, (byte)0x00,
- (byte)0x01, (byte)0x00,
- (byte)0x02, (byte)0x00,
- (byte)0x03, (byte)0x00,
-
- (byte)0x02, (byte)0x00,
- (byte)0x03, (byte)0x00,
- (byte)0x00, (byte)0x00,
- (byte)0x01, (byte)0x00,
-
- (byte)0x02, (byte)0x00,
- (byte)0x03, (byte)0x00,
- (byte)0x02, (byte)0x00,
- (byte)0x03, (byte)0x00,
- };
-
- CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
-
- assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
- assertTrue(record.getNeedRecalculation());
- CellRange enclosingCellRange = record.getEnclosingCellRange();
- assertEquals(0, enclosingCellRange.getFirstRow());
- assertEquals(3, enclosingCellRange.getLastRow());
- assertEquals(0, enclosingCellRange.getFirstColumn());
- assertEquals(3, enclosingCellRange.getLastColumn());
- List ranges = record.getCellRanges();
- assertEquals(0, ((CellRange)ranges.get(0)).getFirstRow());
- assertEquals(1, ((CellRange)ranges.get(0)).getLastRow());
- assertEquals(0, ((CellRange)ranges.get(0)).getFirstColumn());
- assertEquals(1, ((CellRange)ranges.get(0)).getLastColumn());
- assertEquals(0, ((CellRange)ranges.get(1)).getFirstRow());
- assertEquals(1, ((CellRange)ranges.get(1)).getLastRow());
- assertEquals(2, ((CellRange)ranges.get(1)).getFirstColumn());
- assertEquals(3, ((CellRange)ranges.get(1)).getLastColumn());
- assertEquals(2, ((CellRange)ranges.get(2)).getFirstRow());
- assertEquals(3, ((CellRange)ranges.get(2)).getLastRow());
- assertEquals(0, ((CellRange)ranges.get(2)).getFirstColumn());
- assertEquals(1, ((CellRange)ranges.get(2)).getLastColumn());
- assertEquals(2, ((CellRange)ranges.get(3)).getFirstRow());
- assertEquals(3, ((CellRange)ranges.get(3)).getLastRow());
- assertEquals(2, ((CellRange)ranges.get(3)).getFirstColumn());
- assertEquals(3, ((CellRange)ranges.get(3)).getLastColumn());
- assertEquals(recordData.length+4, record.getRecordSize());
-
byte[] output = record.serialize();
-
+
assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
-
+
for (int i = 0; i < recordData.length;i++)
{
assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
}
- }
-
-
- public static void main(String[] ignored_args)
+ }
+
+
+ public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class);
}
-
}
import junit.framework.TestCase;
+import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.util.LittleEndian;
/**
* Tests the serialization and deserialization of the TestCFRuleRecord
- * class works correctly.
+ * class works correctly.
*
* @author Dmitriy Kumshayev
*/
-public class TestCFRuleRecord
- extends TestCase
+public final class TestCFRuleRecord extends TestCase
{
- public TestCFRuleRecord(String name)
- {
- super(name);
- }
-
- public void testCreateCFRuleRecord ()
- {
- CFRuleRecord record = new CFRuleRecord();
- testCFRuleRecord(record);
-
- // Serialize
- byte [] serializedRecord = record.serialize();
-
- // Strip header
- byte [] recordData = new byte[serializedRecord.length-4];
- System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);
-
- // Deserialize
- record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));
-
- // Serialize again
+ public void testCreateCFRuleRecord ()
+ {
+ Workbook workbook = Workbook.createWorkbook();
+ CFRuleRecord record = CFRuleRecord.create(workbook, "7");
+ testCFRuleRecord(record);
+
+ // Serialize
+ byte [] serializedRecord = record.serialize();
+
+ // Strip header
+ byte [] recordData = new byte[serializedRecord.length-4];
+ System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);
+
+ // Deserialize
+ record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));
+
+ // Serialize again
byte[] output = record.serialize();
-
+
// Compare
assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
-
+
for (int i = 0; i < recordData.length;i++)
{
assertEquals("CFRuleRecord doesn't match", recordData[i], output[i+4]);
}
- }
+ }
private void testCFRuleRecord(CFRuleRecord record)
{
FontFormatting fontFormatting = new FontFormatting();
- testFontFormattingAccessors(fontFormatting);
- assertFalse(record.containsFontFormattingBlock());
- record.setFontFormatting(fontFormatting);
- assertTrue(record.containsFontFormattingBlock());
-
- BorderFormatting borderFormatting = new BorderFormatting();
- testBorderFormattingAccessors(borderFormatting);
- assertFalse(record.containsBorderFormattingBlock());
- record.setBorderFormatting(borderFormatting);
- assertTrue(record.containsBorderFormattingBlock());
-
- assertFalse(record.isLeftBorderModified());
- record.setLeftBorderModified(true);
- assertTrue(record.isLeftBorderModified());
-
- assertFalse(record.isRightBorderModified());
- record.setRightBorderModified(true);
- assertTrue(record.isRightBorderModified());
-
- assertFalse(record.isTopBorderModified());
- record.setTopBorderModified(true);
- assertTrue(record.isTopBorderModified());
-
- assertFalse(record.isBottomBorderModified());
- record.setBottomBorderModified(true);
- assertTrue(record.isBottomBorderModified());
-
- assertFalse(record.isTopLeftBottomRightBorderModified());
- record.setTopLeftBottomRightBorderModified(true);
- assertTrue(record.isTopLeftBottomRightBorderModified());
-
- assertFalse(record.isBottomLeftTopRightBorderModified());
- record.setBottomLeftTopRightBorderModified(true);
- assertTrue(record.isBottomLeftTopRightBorderModified());
-
-
- PatternFormatting patternFormatting = new PatternFormatting();
- testPatternFormattingAccessors(patternFormatting);
- assertFalse(record.containsPatternFormattingBlock());
- record.setPatternFormatting(patternFormatting);
- assertTrue(record.containsPatternFormattingBlock());
-
- assertFalse(record.isPatternBackgroundColorModified());
- record.setPatternBackgroundColorModified(true);
- assertTrue(record.isPatternBackgroundColorModified());
-
- assertFalse(record.isPatternColorModified());
- record.setPatternColorModified(true);
- assertTrue(record.isPatternColorModified());
-
- assertFalse(record.isPatternStyleModified());
- record.setPatternStyleModified(true);
- assertTrue(record.isPatternStyleModified());
+ testFontFormattingAccessors(fontFormatting);
+ assertFalse(record.containsFontFormattingBlock());
+ record.setFontFormatting(fontFormatting);
+ assertTrue(record.containsFontFormattingBlock());
+
+ BorderFormatting borderFormatting = new BorderFormatting();
+ testBorderFormattingAccessors(borderFormatting);
+ assertFalse(record.containsBorderFormattingBlock());
+ record.setBorderFormatting(borderFormatting);
+ assertTrue(record.containsBorderFormattingBlock());
+
+ assertFalse(record.isLeftBorderModified());
+ record.setLeftBorderModified(true);
+ assertTrue(record.isLeftBorderModified());
+
+ assertFalse(record.isRightBorderModified());
+ record.setRightBorderModified(true);
+ assertTrue(record.isRightBorderModified());
+
+ assertFalse(record.isTopBorderModified());
+ record.setTopBorderModified(true);
+ assertTrue(record.isTopBorderModified());
+
+ assertFalse(record.isBottomBorderModified());
+ record.setBottomBorderModified(true);
+ assertTrue(record.isBottomBorderModified());
+
+ assertFalse(record.isTopLeftBottomRightBorderModified());
+ record.setTopLeftBottomRightBorderModified(true);
+ assertTrue(record.isTopLeftBottomRightBorderModified());
+
+ assertFalse(record.isBottomLeftTopRightBorderModified());
+ record.setBottomLeftTopRightBorderModified(true);
+ assertTrue(record.isBottomLeftTopRightBorderModified());
+
+
+ PatternFormatting patternFormatting = new PatternFormatting();
+ testPatternFormattingAccessors(patternFormatting);
+ assertFalse(record.containsPatternFormattingBlock());
+ record.setPatternFormatting(patternFormatting);
+ assertTrue(record.containsPatternFormattingBlock());
+
+ assertFalse(record.isPatternBackgroundColorModified());
+ record.setPatternBackgroundColorModified(true);
+ assertTrue(record.isPatternBackgroundColorModified());
+
+ assertFalse(record.isPatternColorModified());
+ record.setPatternColorModified(true);
+ assertTrue(record.isPatternColorModified());
+
+ assertFalse(record.isPatternStyleModified());
+ record.setPatternStyleModified(true);
+ assertTrue(record.isPatternStyleModified());
}
private void testPatternFormattingAccessors(PatternFormatting patternFormatting)
patternFormatting.setFillForegroundColor(HSSFColor.INDIGO.index);
assertEquals(HSSFColor.INDIGO.index,patternFormatting.getFillForegroundColor());
-
+
patternFormatting.setFillPattern(PatternFormatting.DIAMONDS);
assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern());
-
}
private void testBorderFormattingAccessors(BorderFormatting borderFormatting)
assertFalse(borderFormatting.isBackwardDiagonalOn());
borderFormatting.setBackwardDiagonalOn(true);
assertTrue(borderFormatting.isBackwardDiagonalOn());
-
+
borderFormatting.setBorderBottom(BorderFormatting.BORDER_DOTTED);
assertEquals(BorderFormatting.BORDER_DOTTED, borderFormatting.getBorderBottom());
-
+
borderFormatting.setBorderDiagonal(BorderFormatting.BORDER_MEDIUM);
assertEquals(BorderFormatting.BORDER_MEDIUM, borderFormatting.getBorderDiagonal());
-
+
borderFormatting.setBorderLeft(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT);
assertEquals(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT, borderFormatting.getBorderLeft());
borderFormatting.setTopBorderColor(HSSFColor.GOLD.index);
assertEquals(HSSFColor.GOLD.index, borderFormatting.getTopBorderColor());
}
-
-
+
+
private void testFontFormattingAccessors(FontFormatting fontFormatting)
{
// Check for defaults
- assertFalse(fontFormatting.isEscapementTypeModified());
- assertFalse(fontFormatting.isFontCancellationModified());
- assertFalse(fontFormatting.isFontCondenseModified());
- assertFalse(fontFormatting.isFontOutlineModified());
- assertFalse(fontFormatting.isFontShadowModified());
- assertFalse(fontFormatting.isFontStyleModified());
- assertFalse(fontFormatting.isUnderlineTypeModified());
-
- assertFalse(fontFormatting.isBold());
- assertFalse(fontFormatting.isCondenseOn());
- assertFalse(fontFormatting.isItalic());
- assertFalse(fontFormatting.isOutlineOn());
- assertFalse(fontFormatting.isShadowOn());
- assertFalse(fontFormatting.isStruckout());
-
- assertEquals(0, fontFormatting.getEscapementType());
- assertEquals(-1, fontFormatting.getFontColorIndex());
- assertEquals(-1, fontFormatting.getFontHeight());
- assertEquals(400, fontFormatting.getFontWeight());
- assertEquals(0, fontFormatting.getUnderlineType());
-
- fontFormatting.setBold(true);
- assertTrue(fontFormatting.isBold());
- fontFormatting.setBold(false);
- assertFalse(fontFormatting.isBold());
-
- fontFormatting.setCondense(true);
- assertTrue(fontFormatting.isCondenseOn());
- fontFormatting.setCondense(false);
- assertFalse(fontFormatting.isCondenseOn());
-
- fontFormatting.setEscapementType(FontFormatting.SS_SUB);
- assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType());
- fontFormatting.setEscapementType(FontFormatting.SS_SUPER);
- assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType());
- fontFormatting.setEscapementType(FontFormatting.SS_NONE);
- assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType());
-
- fontFormatting.setEscapementTypeModified(false);
- assertFalse(fontFormatting.isEscapementTypeModified());
- fontFormatting.setEscapementTypeModified(true);
- assertTrue(fontFormatting.isEscapementTypeModified());
-
- fontFormatting.setFontCancellationModified(false);
- assertFalse(fontFormatting.isFontCancellationModified());
- fontFormatting.setFontCancellationModified(true);
- assertTrue(fontFormatting.isFontCancellationModified());
-
- fontFormatting.setFontColorIndex((short)10);
- assertEquals(10,fontFormatting.getFontColorIndex());
-
- fontFormatting.setFontCondenseModified(false);
- assertFalse(fontFormatting.isFontCondenseModified());
- fontFormatting.setFontCondenseModified(true);
- assertTrue(fontFormatting.isFontCondenseModified());
-
- fontFormatting.setFontHeight((short)100);
- assertEquals(100,fontFormatting.getFontHeight());
-
- fontFormatting.setFontOutlineModified(false);
- assertFalse(fontFormatting.isFontOutlineModified());
- fontFormatting.setFontOutlineModified(true);
- assertTrue(fontFormatting.isFontOutlineModified());
-
- fontFormatting.setFontShadowModified(false);
- assertFalse(fontFormatting.isFontShadowModified());
- fontFormatting.setFontShadowModified(true);
- assertTrue(fontFormatting.isFontShadowModified());
-
- fontFormatting.setFontStyleModified(false);
- assertFalse(fontFormatting.isFontStyleModified());
- fontFormatting.setFontStyleModified(true);
- assertTrue(fontFormatting.isFontStyleModified());
-
- fontFormatting.setItalic(false);
- assertFalse(fontFormatting.isItalic());
- fontFormatting.setItalic(true);
- assertTrue(fontFormatting.isItalic());
-
- fontFormatting.setOutline(false);
- assertFalse(fontFormatting.isOutlineOn());
- fontFormatting.setOutline(true);
- assertTrue(fontFormatting.isOutlineOn());
-
- fontFormatting.setShadow(false);
- assertFalse(fontFormatting.isShadowOn());
- fontFormatting.setShadow(true);
- assertTrue(fontFormatting.isShadowOn());
-
- fontFormatting.setStrikeout(false);
- assertFalse(fontFormatting.isStruckout());
- fontFormatting.setStrikeout(true);
- assertTrue(fontFormatting.isStruckout());
-
- fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING);
- assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType());
-
- fontFormatting.setUnderlineTypeModified(false);
- assertFalse(fontFormatting.isUnderlineTypeModified());
- fontFormatting.setUnderlineTypeModified(true);
- assertTrue(fontFormatting.isUnderlineTypeModified());
+ assertFalse(fontFormatting.isEscapementTypeModified());
+ assertFalse(fontFormatting.isFontCancellationModified());
+ assertFalse(fontFormatting.isFontCondenseModified());
+ assertFalse(fontFormatting.isFontOutlineModified());
+ assertFalse(fontFormatting.isFontShadowModified());
+ assertFalse(fontFormatting.isFontStyleModified());
+ assertFalse(fontFormatting.isUnderlineTypeModified());
+
+ assertFalse(fontFormatting.isBold());
+ assertFalse(fontFormatting.isCondenseOn());
+ assertFalse(fontFormatting.isItalic());
+ assertFalse(fontFormatting.isOutlineOn());
+ assertFalse(fontFormatting.isShadowOn());
+ assertFalse(fontFormatting.isStruckout());
+
+ assertEquals(0, fontFormatting.getEscapementType());
+ assertEquals(-1, fontFormatting.getFontColorIndex());
+ assertEquals(-1, fontFormatting.getFontHeight());
+ assertEquals(400, fontFormatting.getFontWeight());
+ assertEquals(0, fontFormatting.getUnderlineType());
+
+ fontFormatting.setBold(true);
+ assertTrue(fontFormatting.isBold());
+ fontFormatting.setBold(false);
+ assertFalse(fontFormatting.isBold());
+
+ fontFormatting.setCondense(true);
+ assertTrue(fontFormatting.isCondenseOn());
+ fontFormatting.setCondense(false);
+ assertFalse(fontFormatting.isCondenseOn());
+
+ fontFormatting.setEscapementType(FontFormatting.SS_SUB);
+ assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType());
+ fontFormatting.setEscapementType(FontFormatting.SS_SUPER);
+ assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType());
+ fontFormatting.setEscapementType(FontFormatting.SS_NONE);
+ assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType());
+
+ fontFormatting.setEscapementTypeModified(false);
+ assertFalse(fontFormatting.isEscapementTypeModified());
+ fontFormatting.setEscapementTypeModified(true);
+ assertTrue(fontFormatting.isEscapementTypeModified());
+
+ fontFormatting.setFontCancellationModified(false);
+ assertFalse(fontFormatting.isFontCancellationModified());
+ fontFormatting.setFontCancellationModified(true);
+ assertTrue(fontFormatting.isFontCancellationModified());
+
+ fontFormatting.setFontColorIndex((short)10);
+ assertEquals(10,fontFormatting.getFontColorIndex());
+
+ fontFormatting.setFontCondenseModified(false);
+ assertFalse(fontFormatting.isFontCondenseModified());
+ fontFormatting.setFontCondenseModified(true);
+ assertTrue(fontFormatting.isFontCondenseModified());
+
+ fontFormatting.setFontHeight((short)100);
+ assertEquals(100,fontFormatting.getFontHeight());
+
+ fontFormatting.setFontOutlineModified(false);
+ assertFalse(fontFormatting.isFontOutlineModified());
+ fontFormatting.setFontOutlineModified(true);
+ assertTrue(fontFormatting.isFontOutlineModified());
+
+ fontFormatting.setFontShadowModified(false);
+ assertFalse(fontFormatting.isFontShadowModified());
+ fontFormatting.setFontShadowModified(true);
+ assertTrue(fontFormatting.isFontShadowModified());
+
+ fontFormatting.setFontStyleModified(false);
+ assertFalse(fontFormatting.isFontStyleModified());
+ fontFormatting.setFontStyleModified(true);
+ assertTrue(fontFormatting.isFontStyleModified());
+
+ fontFormatting.setItalic(false);
+ assertFalse(fontFormatting.isItalic());
+ fontFormatting.setItalic(true);
+ assertTrue(fontFormatting.isItalic());
+
+ fontFormatting.setOutline(false);
+ assertFalse(fontFormatting.isOutlineOn());
+ fontFormatting.setOutline(true);
+ assertTrue(fontFormatting.isOutlineOn());
+
+ fontFormatting.setShadow(false);
+ assertFalse(fontFormatting.isShadowOn());
+ fontFormatting.setShadow(true);
+ assertTrue(fontFormatting.isShadowOn());
+
+ fontFormatting.setStrikeout(false);
+ assertFalse(fontFormatting.isStruckout());
+ fontFormatting.setStrikeout(true);
+ assertTrue(fontFormatting.isStruckout());
+
+ fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING);
+ assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType());
+
+ fontFormatting.setUnderlineTypeModified(false);
+ assertFalse(fontFormatting.isUnderlineTypeModified());
+ fontFormatting.setUnderlineTypeModified(true);
+ assertTrue(fontFormatting.isUnderlineTypeModified());
}
-
-
- public static void main(String[] ignored_args)
+
+ public void testWrite() {
+ Workbook workbook = Workbook.createWorkbook();
+ CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10");
+
+ PatternFormatting patternFormatting = new PatternFormatting();
+ patternFormatting.setFillPattern(PatternFormatting.BRICKS);
+ rr.setPatternFormatting(patternFormatting);
+
+ byte[] data = rr.serialize();
+ assertEquals(26, data.length);
+ assertEquals(3, LittleEndian.getShort(data, 6));
+ assertEquals(3, LittleEndian.getShort(data, 8));
+
+ int flags = LittleEndian.getInt(data, 10);
+ assertEquals("unused flags should be 111", 0x00380000, flags & 0x00380000);
+ assertEquals("undocumented flags should be 0000", 0, flags & 0x03C00000); // Otherwise Excel gets unhappy
+ assertEquals(0xA03FFFFF, flags);
+ }
+
+
+ public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord");
junit.textui.TestRunner.run(TestCFRuleRecord.class);
}
-
}
}\r
}\r
}\r
- \r
+\r
public void testBasicSize() {\r
ExternalNameRecord enr = createSimpleENR();\r
if(enr.getRecordSize() == 13) {\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hssf.record.aggregates;\r
+\r
+import junit.framework.Test;\r
+import junit.framework.TestSuite;\r
+\r
+/**\r
+ * Collects all tests for package <tt>org.apache.poi.hssf.record.aggregates</tt>.\r
+ * \r
+ * @author Josh Micich\r
+ */\r
+public final class AllRecordAggregateTests {\r
+ \r
+ public static Test suite() {\r
+ TestSuite result = new TestSuite(AllRecordAggregateTests.class.getName());\r
+\r
+ result.addTestSuite(TestCFRecordsAggregate.class);\r
+ result.addTestSuite(TestColumnInfoRecordsAggregate.class);\r
+ result.addTestSuite(TestFormulaRecordAggregate.class);\r
+ result.addTestSuite(TestRowRecordsAggregate.class);\r
+ result.addTestSuite(TestValueRecordsAggregate.class);\r
+ return result;\r
+ }\r
+}\r
import junit.framework.TestCase;
+import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.RecordFactory;
+import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.CellRange;
/**
*
* @author Dmitriy Kumshayev
*/
-public class TestCFRecordsAggregate
- extends TestCase
+public final class TestCFRecordsAggregate extends TestCase
{
- public TestCFRecordsAggregate(String name)
- {
- super(name);
- }
-
- public void testCFRecordsAggregate()
- {
- CFRecordsAggregate record = new CFRecordsAggregate();
- List recs = new ArrayList();
- CFHeaderRecord header = new CFHeaderRecord();
- CFRuleRecord rule1 = new CFRuleRecord();
- CFRuleRecord rule2 = new CFRuleRecord();
- CFRuleRecord rule3 = new CFRuleRecord();
- header.setNumberOfConditionalFormats(3);
- CellRange range1 = new CellRange(0,1,(short)0,(short)0);
- CellRange range2 = new CellRange(0,1,(short)2,(short)2);
- List cellRanges = new ArrayList();
- cellRanges.add(range1);
- cellRanges.add(range2);
- header.setCellRanges(cellRanges);
- recs.add(header);
- recs.add(rule1);
- recs.add(rule2);
- recs.add(rule3);
- record = CFRecordsAggregate.createCFAggregate(recs, 0);
-
- // Serialize
- byte [] serializedRecord = record.serialize();
- InputStream in = new ByteArrayInputStream(serializedRecord);
-
- //Parse
- recs = RecordFactory.createRecords(in);
-
- // Verify
- assertNotNull(recs);
- assertEquals(4, recs.size());
-
- header = (CFHeaderRecord)recs.get(0);
- rule1 = (CFRuleRecord)recs.get(1);
- rule2 = (CFRuleRecord)recs.get(2);
- rule3 = (CFRuleRecord)recs.get(3);
- cellRanges = header.getCellRanges();
-
- assertEquals(2, cellRanges.size());
- assertEquals(3, header.getNumberOfConditionalFormats());
-
- record = CFRecordsAggregate.createCFAggregate(recs, 0);
-
- record = record.cloneCFAggregate();
-
- assertNotNull(record.getHeader());
- assertEquals(3,record.getRules().size());
-
- header = record.getHeader();
- rule1 = (CFRuleRecord)record.getRules().get(0);
- rule2 = (CFRuleRecord)record.getRules().get(1);
- rule3 = (CFRuleRecord)record.getRules().get(2);
- cellRanges = header.getCellRanges();
-
- assertEquals(2, cellRanges.size());
- assertEquals(3, header.getNumberOfConditionalFormats());
- }
-
- public static void main(String[] ignored_args)
+ public void testCFRecordsAggregate()
+ {
+ Workbook workbook = Workbook.createWorkbook();
+ List recs = new ArrayList();
+ CFHeaderRecord header = new CFHeaderRecord();
+ CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
+ CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
+ CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.GE, "100", null);
+ header.setNumberOfConditionalFormats(3);
+ CellRange[] cellRanges = {
+ new CellRange(0,1,0,0),
+ new CellRange(0,1,2,2),
+ };
+ header.setCellRanges(cellRanges);
+ recs.add(header);
+ recs.add(rule1);
+ recs.add(rule2);
+ recs.add(rule3);
+ CFRecordsAggregate record;
+ record = CFRecordsAggregate.createCFAggregate(recs, 0);
+
+ // Serialize
+ byte [] serializedRecord = record.serialize();
+ InputStream in = new ByteArrayInputStream(serializedRecord);
+
+ //Parse
+ recs = RecordFactory.createRecords(in);
+
+ // Verify
+ assertNotNull(recs);
+ assertEquals(4, recs.size());
+
+ header = (CFHeaderRecord)recs.get(0);
+ rule1 = (CFRuleRecord)recs.get(1);
+ rule2 = (CFRuleRecord)recs.get(2);
+ rule3 = (CFRuleRecord)recs.get(3);
+ cellRanges = header.getCellRanges();
+
+ assertEquals(2, cellRanges.length);
+ assertEquals(3, header.getNumberOfConditionalFormats());
+
+ record = CFRecordsAggregate.createCFAggregate(recs, 0);
+
+ record = record.cloneCFAggregate();
+
+ assertNotNull(record.getHeader());
+ assertEquals(3,record.getNumberOfRules());
+
+ header = record.getHeader();
+ rule1 = record.getRule(0);
+ rule2 = record.getRule(1);
+ rule3 = record.getRule(2);
+ cellRanges = header.getCellRanges();
+
+ assertEquals(2, cellRanges.length);
+ assertEquals(3, header.getNumberOfConditionalFormats());
+ }
+
+ public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.aggregates.CFRecordsAggregate");
junit.textui.TestRunner.run(TestCFRecordsAggregate.class);
}
-
+
}
/**
* @author Glen Stampoultzis
*/
-public class TestColumnInfoRecordsAggregate extends TestCase
+public final class TestColumnInfoRecordsAggregate extends TestCase
{
ColumnInfoRecordsAggregate columnInfoRecordsAggregate;
columnInfoRecordsAggregate.insertColumn( createColumn( (short)8, (short)8 ));
// columnInfoRecordsAggregate.setColumn( (short)2, new Short( (short)200 ), new Integer( 1 ), new Boolean( true ), null);
columnInfoRecordsAggregate.groupColumnRange( (short)2, (short)5, true );
- System.out.println( "columnInfoRecordsAggregate = " + columnInfoRecordsAggregate.getNumColumns() );
+ assertEquals(6, columnInfoRecordsAggregate.getNumColumns());
assertEquals(columnInfoRecordsAggregate.getRecordSize(), columnInfoRecordsAggregate.serialize().length);
*/
public class TestCellRange extends TestCase
{
- private static final CellRange biggest = new CellRange(0, -1,(short) 0,(short)-1);
- private static final CellRange tenthColumn = new CellRange(0, -1,(short)10,(short)10);
- private static final CellRange tenthRow = new CellRange(10,10,(short) 0,(short)-1);
- private static final CellRange box10x10 = new CellRange(0, 10,(short) 0,(short)10);
- private static final CellRange box9x9 = new CellRange(0, 9,(short) 0,(short) 9);
- private static final CellRange box10to20c = new CellRange(0, 10,(short)10,(short)20);
- private static final CellRange oneCell = new CellRange(10,10,(short)10,(short)10);
+ private static final CellRange biggest = new CellRange( 0, -1, 0,-1);
+ private static final CellRange tenthColumn = new CellRange( 0, -1,10,10);
+ private static final CellRange tenthRow = new CellRange(10, 10, 0,-1);
+ private static final CellRange box10x10 = new CellRange( 0, 10, 0,10);
+ private static final CellRange box9x9 = new CellRange( 0, 9, 0, 9);
+ private static final CellRange box10to20c = new CellRange( 0, 10,10,20);
+ private static final CellRange oneCell = new CellRange(10, 10,10,10);
boolean [][] contanis = new boolean[][]
{
}
}
}
-
- private static final CellRange col1 = new CellRange(0, -1,(short) 1,(short)1);
- private static final CellRange col2 = new CellRange(0, -1,(short) 2,(short)2);
- private static final CellRange row1 = new CellRange(1, 1,(short) 0,(short)-1);
- private static final CellRange row2 = new CellRange(2, 2,(short) 0,(short)-1);
- private static final CellRange box0 = new CellRange( 0, 2,(short) 0,(short)2);
- private static final CellRange box1 = new CellRange( 0, 1,(short) 0,(short)1);
- private static final CellRange box2 = new CellRange( 0, 1,(short) 2,(short)3);
- private static final CellRange box3 = new CellRange( 2, 3,(short) 0,(short)1);
- private static final CellRange box4 = new CellRange( 2, 3,(short) 2,(short)3);
- private static final CellRange box5 = new CellRange( 1, 3,(short) 1,(short)3);
+ private static final CellRange col1 = new CellRange( 0, -1, 1,1);
+ private static final CellRange col2 = new CellRange( 0, -1, 2,2);
+ private static final CellRange row1 = new CellRange( 1, 1, 0,-1);
+ private static final CellRange row2 = new CellRange( 2, 2, 0,-1);
+
+ private static final CellRange box0 = new CellRange( 0, 2, 0,2);
+ private static final CellRange box1 = new CellRange( 0, 1, 0,1);
+ private static final CellRange box2 = new CellRange( 0, 1, 2,3);
+ private static final CellRange box3 = new CellRange( 2, 3, 0,1);
+ private static final CellRange box4 = new CellRange( 2, 3, 2,3);
+ private static final CellRange box5 = new CellRange( 1, 3, 1,3);
public void testHasSharedBorderMethod()
{
- assertFalse(col1.hasSharedBorder(col1));
- assertFalse(col2.hasSharedBorder(col2));
- assertTrue(col1.hasSharedBorder(col2));
- assertTrue(col2.hasSharedBorder(col1));
+ assertFalse(col1.hasExactSharedBorder(col1));
+ assertFalse(col2.hasExactSharedBorder(col2));
+ assertTrue(col1.hasExactSharedBorder(col2));
+ assertTrue(col2.hasExactSharedBorder(col1));
- assertFalse(row1.hasSharedBorder(row1));
- assertFalse(row2.hasSharedBorder(row2));
- assertTrue(row1.hasSharedBorder(row2));
- assertTrue(row2.hasSharedBorder(row1));
+ assertFalse(row1.hasExactSharedBorder(row1));
+ assertFalse(row2.hasExactSharedBorder(row2));
+ assertTrue(row1.hasExactSharedBorder(row2));
+ assertTrue(row2.hasExactSharedBorder(row1));
- assertFalse(row1.hasSharedBorder(col1));
- assertFalse(row1.hasSharedBorder(col2));
- assertFalse(col1.hasSharedBorder(row1));
- assertFalse(col2.hasSharedBorder(row1));
- assertFalse(row2.hasSharedBorder(col1));
- assertFalse(row2.hasSharedBorder(col2));
- assertFalse(col1.hasSharedBorder(row2));
- assertFalse(col2.hasSharedBorder(row2));
- assertTrue(col2.hasSharedBorder(col1));
+ assertFalse(row1.hasExactSharedBorder(col1));
+ assertFalse(row1.hasExactSharedBorder(col2));
+ assertFalse(col1.hasExactSharedBorder(row1));
+ assertFalse(col2.hasExactSharedBorder(row1));
+ assertFalse(row2.hasExactSharedBorder(col1));
+ assertFalse(row2.hasExactSharedBorder(col2));
+ assertFalse(col1.hasExactSharedBorder(row2));
+ assertFalse(col2.hasExactSharedBorder(row2));
+ assertTrue(col2.hasExactSharedBorder(col1));
- assertFalse(box1.hasSharedBorder(box1));
- assertTrue(box1.hasSharedBorder(box2));
- assertTrue(box1.hasSharedBorder(box3));
- assertFalse(box1.hasSharedBorder(box4));
+ assertFalse(box1.hasExactSharedBorder(box1));
+ assertTrue(box1.hasExactSharedBorder(box2));
+ assertTrue(box1.hasExactSharedBorder(box3));
+ assertFalse(box1.hasExactSharedBorder(box4));
- assertTrue(box2.hasSharedBorder(box1));
- assertFalse(box2.hasSharedBorder(box2));
- assertFalse(box2.hasSharedBorder(box3));
- assertTrue(box2.hasSharedBorder(box4));
+ assertTrue(box2.hasExactSharedBorder(box1));
+ assertFalse(box2.hasExactSharedBorder(box2));
+ assertFalse(box2.hasExactSharedBorder(box3));
+ assertTrue(box2.hasExactSharedBorder(box4));
- assertTrue(box3.hasSharedBorder(box1));
- assertFalse(box3.hasSharedBorder(box2));
- assertFalse(box3.hasSharedBorder(box3));
- assertTrue(box3.hasSharedBorder(box4));
+ assertTrue(box3.hasExactSharedBorder(box1));
+ assertFalse(box3.hasExactSharedBorder(box2));
+ assertFalse(box3.hasExactSharedBorder(box3));
+ assertTrue(box3.hasExactSharedBorder(box4));
- assertFalse(box4.hasSharedBorder(box1));
- assertTrue(box4.hasSharedBorder(box2));
- assertTrue(box4.hasSharedBorder(box3));
- assertFalse(box4.hasSharedBorder(box4));
+ assertFalse(box4.hasExactSharedBorder(box1));
+ assertTrue(box4.hasExactSharedBorder(box2));
+ assertTrue(box4.hasExactSharedBorder(box3));
+ assertFalse(box4.hasExactSharedBorder(box4));
}
-
+
public void testIntersectMethod()
{
assertEquals( CellRange.OVERLAP,box0.intersect(box5));
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
}
-
}
package org.apache.poi.hssf.record.formula;
+import org.apache.poi.hssf.record.formula.eval.AllFormulaEvalTests;
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
+import org.apache.poi.hssf.record.formula.functions.AllIndividualFunctionEvaluationTests;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
- * Collects all tests for this package.
+ * Collects all tests for <tt>org.apache.poi.hssf.record.formula</tt>.
*
* @author Josh Micich
*/
public static Test suite() {
TestSuite result = new TestSuite(AllFormulaTests.class.getName());
+ result.addTest(AllFormulaEvalTests.suite());
+ result.addTest(AllFormulaFunctionTests.suite());
+ result.addTest(AllIndividualFunctionEvaluationTests.suite());
+
result.addTestSuite(TestArea3DPtg.class);
result.addTestSuite(TestAreaErrPtg.class);
result.addTestSuite(TestAreaPtg.class);
import junit.framework.TestSuite;
/**
- * Collects all tests for this package.
+ * Collects all tests for this <tt>org.apache.poi.hssf.record.formula.function</tt>.
*
* @author Josh Micich
*/
import org.xml.sax.helpers.XMLReaderFactory;
/**
- * This class is not used during normal POI run-time but is used at development time to generate
+ * This class is not used during normal POI run-time but is used at development time to generate
* the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the
* intention of this class is to make it easier to maintain the metadata, by extracting it from
* a reliable source.
*
* @author Josh Micich
*/
-public class ExcelFileFormatDocFunctionExtractor {
+public final class ExcelFileFormatDocFunctionExtractor {
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
};
-
+
private final Stack _elemNameStack;
/** <code>true</code> only when parsing the target tables */
private boolean _isInsideTable;
-
+
private final List _rowData;
private final StringBuffer _textNodeBuffer;
private final List _rowNoteFlags;
private boolean _cellHasNote;
-
+
private final FunctionDataCollector _fdc;
private String _lastHeadingText;
-
+
public EFFDocHandler(FunctionDataCollector fdc) {
_fdc = fdc;
_elemNameStack = new Stack();
_textNodeBuffer = new StringBuffer();
_rowNoteFlags = new ArrayList();
}
-
+
private boolean matchesTargetPath() {
return matchesPath(0, TABLE_BASE_PATH_NAMES);
}
xr.setContentHandler(new EFFDocHandler(fdc));
InputSource inSrc = new InputSource(is);
-
+
try {
xr.parse(inSrc);
is.close();
}
private static void outputLicenseHeader(PrintStream ps) {
- String[] lines= {
- "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.",
- };
- for (int i = 0; i < lines.length; i++) {
- ps.print("# ");
- ps.println(lines[i]);
- }
- ps.println();
- }
-
- /**
+ String[] lines= {
+ "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.",
+ };
+ for (int i = 0; i < lines.length; i++) {
+ ps.print("# ");
+ ps.println(lines[i]);
+ }
+ ps.println();
+ }
+
+ /**
* Helps identify the source file
*/
private static String getFileCRC(File f) {
}
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
}
-
+
private static File getSourceFile() {
- if (true) {
- File dir = new File("c:/josh/ref-docs");
+ if (false) {
+ File dir = new File("c:/temp");
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
return effDocFile;
}
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
-
+
File result;
byte[]buf = new byte[2048];
try {
System.out.println("file downloaded ok");
return result;
}
-
+
public static void main(String[] args) {
-
+
File effDocFile = getSourceFile();
if(!effDocFile.exists()) {
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
}
-
+
File outFile = new File("functionMetadata-asGenerated.txt");
processFile(effDocFile, outFile);
}
-
}
package org.apache.poi.hssf.record.formula.function;
import junit.framework.TestCase;
+
/**
*
* @author Josh Micich
*/
public final class TestFunctionMetadataRegistry extends TestCase {
- public void testWellKnownFunctions() {
- confirmFunction(0, "COUNT");
- confirmFunction(1, "IF");
-
- }
-
- private static void confirmFunction(int index, String funcName) {
- FunctionMetadata fm;
- fm = FunctionMetadataRegistry.getFunctionByIndex(index);
- assertNotNull(fm);
- assertEquals(funcName, fm.getName());
-
- fm = FunctionMetadataRegistry.getFunctionByName(funcName);
- assertNotNull(fm);
- assertEquals(index, fm.getIndex());
- }
+ public void testWellKnownFunctions() {
+ confirmFunction(0, "COUNT");
+ confirmFunction(1, "IF");
+
+ }
+
+ private static void confirmFunction(int index, String funcName) {
+ FunctionMetadata fm;
+ fm = FunctionMetadataRegistry.getFunctionByIndex(index);
+ assertNotNull(fm);
+ assertEquals(funcName, fm.getName());
+
+ fm = FunctionMetadataRegistry.getFunctionByName(funcName);
+ assertNotNull(fm);
+ assertEquals(index, fm.getIndex());
+ }
}
}
AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
if(func.getFunctionIndex() == 255) {
- throw new AssertionFailedError("Failed to recognise built-in function in formula '"
- + formula + "'");
+ throw new AssertionFailedError("Failed to recognise built-in function in formula '"
+ + formula + "'");
}
assertEquals(expPtgArraySize, ptgs.length);
}
sht = wb.getSheetAt(0);
}
-
+
public void testDatedif() {
String formula;
formula = getCellFormula(0);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("Too few arguments")) {
- if(e.getMessage().indexOf("AttrPtg") > 0) {
- throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
- }
+ if(e.getMessage().indexOf("AttrPtg") > 0) {
+ throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
+ }
throw afe("NOW() registered with 1 arg instead of 0");
}
if(e.getMessage().startsWith("too much stuff")) {
assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
}
public void testDdb() {
-
+
String formula = getCellFormula(1);
if("externalflag(1,1,1,1,1)".equals(formula)) {
throw afe("DDB() not registered");
assertEquals("DDB(1,1,1,1,1)", formula);
}
public void testAtan() {
-
+
String formula = getCellFormula(2);
if(formula.equals("ARCTAN(1)")) {
throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
}
assertEquals("ATAN(1)", formula);
}
-
+
public void testUsdollar() {
String formula = getCellFormula(3);
}
assertEquals("ISNONTEXT(\"abc\")", formula);
}
-
+
private String getCellFormula(int rowIx) {
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
if (false) {
*/
public final class AllIndividualFunctionEvaluationTests {
- // TODO - have this suite incorporated into a higher level one
public static Test suite() {
- TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula.functions");
+ TestSuite result = new TestSuite(AllIndividualFunctionEvaluationTests.class.getName());
result.addTestSuite(TestAverage.class);
result.addTestSuite(TestCountFuncs.class);
result.addTestSuite(TestDate.class);
* @author Josh Micich
*/
public final class TestPmt extends TestCase {
-
+
private static void confirm(double expected, NumberEval ne) {
// only asserting accuracy to 4 fractional digits
assertEquals(expected, ne.getNumberValue(), 0.00005);
confirm(expected, invokeNormal(args));
}
-
+
public void testBasic() {
confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
}
-
+
public void test3args() {
Eval[] args = {
book.createSheet("TEST");
HSSFSheet sheet = book.cloneSheet(0);
book.setSheetName(1,"CLONE");
- sheet.createRow(0).createCell((short)0).setCellValue("Test");
+ sheet.createRow(0).createCell((short)0).setCellValue(new HSSFRichTextString("Test"));
book.write(out);
book = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
sheet = book.getSheet("CLONE");
HSSFRow row = sheet.getRow(0);
HSSFCell cell = row.getCell((short)0);
- System.out.println(cell.getStringCellValue());
+ assertEquals("Test", cell.getRichStringCellValue().getString());
}
/**
--- /dev/null
+/* ====================================================================
+ 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 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 testLastAndFirstColumns()
+ {
+ 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());
+ }
+}