Patch from Dmitriy from bug #30311 - Support for conditional formatting records

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@638812 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-03-19 12:28:56 +00:00
parent 870c5e1889
commit f7e7b20f2e
22 changed files with 4841 additions and 14 deletions

View File

@ -36,6 +36,7 @@
<!-- Don't forget to update status.xml too! -->
<release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="fix">44609 - Handle leading spaces in formulas, such as '= 4'</action>
<action dev="POI-DEVELOPERS" type="add">44608 - Support for PercentPtg in the formula evaluator</action>
<action dev="POI-DEVELOPERS" type="fix">44606 - Support calculated string values for evaluated formulas</action>

View File

@ -33,6 +33,7 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">30311 - Initial support for Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="fix">44609 - Handle leading spaces in formulas, such as '= 4'</action>
<action dev="POI-DEVELOPERS" type="add">44608 - Support for PercentPtg in the formula evaluator</action>
<action dev="POI-DEVELOPERS" type="fix">44606 - Support calculated string values for evaluated formulas</action>

View File

@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.util.PaneInformation;
@ -96,6 +97,7 @@ public class Sheet implements Model
protected ObjectProtectRecord objprotect = null;
protected ScenarioProtectRecord scenprotect = null;
protected PasswordRecord password = null;
protected List condFormatting = new ArrayList();;
/** Add an UncalcedRecord if not true indicating formulas have not been calculated */
protected boolean uncalced = false;
@ -184,6 +186,17 @@ public class Sheet implements Model
retval.merged = ( MergeCellsRecord ) rec;
retval.numMergedRegions += retval.merged.getNumAreas();
}
else if ( rec.getSid() == CFHeaderRecord.sid )
{
CFRecordsAggregate cfAgg = CFRecordsAggregate.createCFAggregate(recs, k);
retval.condFormatting.add(cfAgg);
rec = cfAgg;
}
else if ( rec.getSid() == CFRuleRecord.sid )
{
// Skip it since it is processed by CFRecordsAggregate
rec = null;
}
else if (rec.getSid() == ColumnInfoRecord.sid)
{
ColumnInfoRecord col = (ColumnInfoRecord)rec;
@ -604,6 +617,66 @@ public class Sheet implements Model
{
return numMergedRegions;
}
// Find correct position to add new CF record
private int findConditionalFormattingPosition()
{
// This is default.
// If the algorithm does not find the right position,
// this one will be used (this is a position before EOF record)
int index = records.size()-2;
for( int i=index; i>=0; i-- )
{
Record rec = (Record)records.get(i);
short sid = rec.getSid();
// CFRecordsAggregate records already exist, just add to the end
if (rec instanceof CFRecordsAggregate) { return i+1; }
if( sid == (short)0x00ef ) { return i+1; }// PHONETICPR
if( sid == (short)0x015f ) { return i+1; }// LABELRANGES
if( sid == MergeCellsRecord.sid ) { return i+1; }
if( sid == (short)0x0099 ) { return i+1; }// STANDARDWIDTH
if( sid == SelectionRecord.sid ) { return i+1; }
if( sid == PaneRecord.sid ) { return i+1; }
if( sid == SCLRecord.sid ) { return i+1; }
if( sid == WindowTwoRecord.sid ) { return i+1; }
}
return index;
}
public int addConditionalFormatting(CFRecordsAggregate cfAggregate)
{
int index = findConditionalFormattingPosition();
records.add(index, cfAggregate);
condFormatting.add(cfAggregate);
return condFormatting.size()-1;
}
public void removeConditionalFormatting(int index)
{
if (index >= 0 && index <= condFormatting.size()-1 )
{
CFRecordsAggregate cfAggregate = getCFRecordsAggregateAt(index);
records.remove(cfAggregate);
condFormatting.remove(index);
}
}
public CFRecordsAggregate getCFRecordsAggregateAt(int index)
{
if (index >= 0 && index <= condFormatting.size()-1 )
{
return (CFRecordsAggregate) condFormatting.get(index);
}
return null;
}
public int getNumConditionalFormattings()
{
return condFormatting.size();
}
/**
* Returns the number of low level binary records in this sheet. This adjusts things for the so called

View File

@ -0,0 +1,223 @@
/* ====================================================================
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.
==================================================================== */
/*
* 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.util.LittleEndian;
/**
* Conditional Formatting Header record (CFHEADER)
*
* @author Dmitriy Kumshayev
*/
public class CFHeaderRecord extends Record
{
public static final short sid = 0x1B0;
private int field_1_numcf;
private int field_2_need_recalculation;
private CellRange field_3_enclosing_cell_range;
private List field_4_cell_ranges;
/** Creates new CFHeaderRecord */
public CFHeaderRecord()
{
field_4_cell_ranges = new ArrayList(5);
}
public CFHeaderRecord(RecordInputStream in)
{
super(in);
}
protected void fillFields(RecordInputStream in)
{
field_1_numcf = in.readShort();
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);
for( int i=0; i<numCellRanges; i++)
{
field_4_cell_ranges.add(new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort()));
}
}
public int getNumberOfConditionalFormats()
{
return field_1_numcf;
}
public void setNumberOfConditionalFormats(int n)
{
field_1_numcf=n;
}
public boolean getNeedRecalculation()
{
return field_2_need_recalculation==1?true:false;
}
public void setNeedRecalculation(boolean b)
{
field_2_need_recalculation=b?1:0;
}
public CellRange getEnclosingCellRange()
{
return field_3_enclosing_cell_range;
}
public void setEnclosingCellRange( CellRange cr)
{
field_3_enclosing_cell_range = cr.cloneCellRange();
}
/**
* Set cell ranges list to a single cell range and
* modify the enclosing cell range accordingly.
* @param List cellRanges - list of CellRange objects
*/
public void setCellRanges( List cellRanges )
{
field_4_cell_ranges.clear();
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));
}
}
}
private void recalculateEnclosingRange(CellRange cellRange)
{
field_3_enclosing_cell_range = cellRange.createEnclosingCellRange(field_3_enclosing_cell_range);
}
public List getCellRanges()
{
return field_4_cell_ranges;
}
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(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.size(); i++)
{
buffer.append(i==0?"":",").append(field_4_cell_ranges.get(i));
}
buffer.append("]\n");
}
buffer.append("[/CFHEADER]\n");
return buffer.toString();
}
/**
* @return byte array containing instance data
*/
public int serialize(int offset, byte[] data)
{
int recordsize = getRecordSize();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short) (recordsize-4));
LittleEndian.putShort(data, 4 + offset, (short) field_1_numcf);
LittleEndian.putShort(data, 6 + offset, (short) field_2_need_recalculation);
LittleEndian.putShort(data, 8 + offset, (short) field_3_enclosing_cell_range.getFirstRow());
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, 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());
}
return getRecordSize();
}
public int getRecordSize()
{
return 18+8*field_4_cell_ranges.size();
}
/**
* 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 ConditionalFormattingHeaderRecord RECORD");
}
}
public short getSid()
{
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;
}
}

View File

@ -0,0 +1,657 @@
/* ====================================================================
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.
==================================================================== */
/*
* 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.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
* Conditional Formatting Rule Record.
* @author Dmitriy Kumshayev
*/
public 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);
}
private void setModified(boolean modified, BitField field)
{
field_5_options = field.setBoolean(field_5_options, !modified);
}
public boolean isLeftBorderModified()
{
return isModified(bordLeft);
}
public void setLeftBorderModified(boolean modified)
{
setModified(modified,bordLeft);
}
public boolean isRightBorderModified()
{
return isModified(bordRight);
}
public void setRightBorderModified(boolean modified)
{
setModified(modified,bordRight);
}
public boolean isTopBorderModified()
{
return isModified(bordTop);
}
public void setTopBorderModified(boolean modified)
{
setModified(modified,bordTop);
}
public boolean isBottomBorderModified()
{
return isModified(bordBot);
}
public void setBottomBorderModified(boolean modified)
{
setModified(modified,bordBot);
}
public boolean isTopLeftBottomRightBorderModified()
{
return isModified(bordTlBr);
}
public void setTopLeftBottomRightBorderModified(boolean modified)
{
setModified(modified,bordTlBr);
}
public boolean isBottomLeftTopRightBorderModified()
{
return isModified(bordBlTr);
}
public void setBottomLeftTopRightBorderModified(boolean modified)
{
setModified(modified,bordBlTr);
}
public boolean isPatternStyleModified()
{
return isModified(pattStyle);
}
public void setPatternStyleModified(boolean modified)
{
setModified(modified,pattStyle);
}
public boolean isPatternColorModified()
{
return isModified(pattCol);
}
public void setPatternColorModified(boolean modified)
{
setModified(modified,pattCol);
}
public boolean isPatternBackgroundColorModified()
{
return isModified(pattBgCol);
}
public void setPatternBackgroundColorModified(boolean modified)
{
setModified(modified,pattBgCol);
}
private boolean getOptionFlag(BitField field)
{
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;
}
public FontFormatting getFontFormatting()
{
return fontFormatting;
}
}

View File

@ -82,6 +82,8 @@ public class RecordFactory
SupBookRecord.class,
CRNCountRecord.class,
CRNRecord.class,
CFHeaderRecord.class,
CFRuleRecord.class,
};
}
private static Map recordsMap = recordsToMap(records);

View File

@ -180,19 +180,17 @@ public final class SharedFormulaRecord extends Record {
return ((getFirstRow() <= formulaRow) && (getLastRow() >= formulaRow) &&
(getFirstColumn() <= formulaColumn) && (getLastColumn() >= formulaColumn));
}
/** Creates a non shared formula from the shared formula counter part*/
public void convertSharedFormulaRecord(FormulaRecord formula) {
//Sanity checks
final int formulaRow = formula.getRow();
final int formulaColumn = formula.getColumn();
if (isFormulaInShared(formula)) {
formula.setExpressionLength(getExpressionLength());
/**
* Creates a non shared formula from the shared formula
* counter part
*/
protected static Stack convertSharedFormulas(Stack ptgs, int formulaRow, int formulaColumn) {
Stack newPtgStack = new Stack();
if (field_7_parsed_expr != null)
for (int k = 0; k < field_7_parsed_expr.size(); k++) {
Ptg ptg = (Ptg) field_7_parsed_expr.get(k);
if (ptgs != null)
for (int k = 0; k < ptgs.size(); k++) {
Ptg ptg = (Ptg) ptgs.get(k);
if (ptg instanceof RefNPtg) {
RefNPtg refNPtg = (RefNPtg)ptg;
ptg = new ReferencePtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
@ -243,7 +241,23 @@ public final class SharedFormulaRecord extends Record {
areaNAPtg.isLastColRelative());
}
newPtgStack.add(ptg);
}
}
return newPtgStack;
}
/**
* Creates a non shared formula from the shared formula
* counter part
*/
public void convertSharedFormulaRecord(FormulaRecord formula) {
//Sanity checks
final int formulaRow = formula.getRow();
final int formulaColumn = formula.getColumn();
if (isFormulaInShared(formula)) {
formula.setExpressionLength(getExpressionLength());
Stack newPtgStack =
convertSharedFormulas(field_7_parsed_expr, formulaRow, formulaColumn);
formula.setParsedExpression(newPtgStack);
//Now its not shared!
formula.setSharedFormula(false);
@ -252,7 +266,7 @@ public final class SharedFormulaRecord extends Record {
}
}
private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
private static int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at column 256 ("IV")
return (column + currentcolumn) & 0x00FF;
@ -260,7 +274,7 @@ public final class SharedFormulaRecord extends Record {
return column;
}
private int fixupRelativeRow(int currentrow, int row, boolean relative) {
private static int fixupRelativeRow(int currentrow, int row, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at row 65536
return (row+currentrow) & 0x00FFFF;

View File

@ -0,0 +1,224 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.aggregates;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/**
* CFRecordsAggregate - aggregates Conditional Formatting records CFHeaderRecord
* and number of up to three CFRuleRecord records together to simplify
* access to them.
*
* @author Dmitriy Kumshayev
*
*/
public class CFRecordsAggregate extends Record
{
public final static short sid = -2008;
private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
private CFHeaderRecord header;
// List of CFRuleRecord objects
private List rules;
public CFRecordsAggregate()
{
header = null;
rules = new ArrayList(3);
}
/**
* Create CFRecordsAggregate from a list of CF Records
* @param recs - list of {@link Record} objects
* @param offset - position of {@link CFHeaderRecord} object in the list of Record objects
* @return CFRecordsAggregate object
*/
public static CFRecordsAggregate createCFAggregate(List recs, int offset)
{
CFRecordsAggregate cfRecords = new CFRecordsAggregate();
ArrayList records = new ArrayList(4);
int count = 0;
Record rec = ( Record ) recs.get(offset++);
if (rec.getSid() == CFHeaderRecord.sid)
{
records.add(rec);
cfRecords.header = (CFHeaderRecord)rec;
int nRules = cfRecords.header.getNumberOfConditionalFormats();
int rulesCount = 0;
while( offset<recs.size() &&
(rec = (Record)recs.get(offset++)).getSid() == CFRuleRecord.sid &&
rec instanceof CFRuleRecord &&
rulesCount++ < nRules
)
{
records.add(rec);
cfRecords.rules.add(rec);
}
if (nRules != cfRecords.rules.size())
{
if (log.check(POILogger.DEBUG))
{
log.log(POILogger.DEBUG, "Expected " + nRules + " Conditional Formats, "
+ "but found " + cfRecords.rules.size() + " rules");
}
cfRecords.header.setNumberOfConditionalFormats(nRules);
}
}
return cfRecords;
}
/**
* Create a deep clone of the record
* @return
*/
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);
}
/** You never fill an aggregate */
protected void fillFields(RecordInputStream in)
{
}
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 pos = offset;
if( header != null && rules.size()>0 )
{
header.setNumberOfConditionalFormats(rules.size());
pos += (( Record ) header).serialize(pos, data);
for(Iterator itr = rules.iterator(); itr.hasNext();)
{
pos += (( Record ) itr.next()).serialize(pos, data);
}
}
return pos - offset;
}
protected void validateSid(short id)
{
// do nothing here
}
/**
* @return the header
*/
public CFHeaderRecord getHeader()
{
return header;
}
/**
* @return the rules
*/
public List getRules()
{
return rules;
}
/**
* @return sum of sizes of all aggregated records
*/
public int getRecordSize()
{
int size = 0;
if( header != null)
{
size += header.getRecordSize();
}
if( rules != null)
{
for(Iterator irecs = rules.iterator(); irecs.hasNext(); )
{
size += (( Record ) irecs.next()).getRecordSize();
}
}
return size;
}
/**
* String representation of CFRecordsAggregate
*/
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[CF]\n");
if( header != null )
{
buffer.append(header.toString());
}
if( rules != null )
{
for(int i=0; i<rules.size(); i++)
{
CFRuleRecord cfRule = (CFRuleRecord)rules.get(i);
if(cfRule!=null)
{
buffer.append(cfRule.toString());
}
}
}
buffer.append("[/CF]\n");
return buffer.toString();
}
}

View File

@ -0,0 +1,560 @@
/* ====================================================================
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.
==================================================================== */
/*
* FontFormatting.java
*
* Created on January 22, 2008, 10:05 PM
*/
package org.apache.poi.hssf.record.cf;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
* Border Formatting Block of the Conditional Formatting Rule Record.
*
* @author Dmitriy Kumshayev
*/
public class BorderFormatting
{
/**
* No border
*/
public final static short BORDER_NONE = 0x0;
/**
* Thin border
*/
public final static short BORDER_THIN = 0x1;
/**
* Medium border
*/
public final static short BORDER_MEDIUM = 0x2;
/**
* dash border
*/
public final static short BORDER_DASHED = 0x3;
/**
* dot border
*/
public final static short BORDER_HAIR = 0x4;
/**
* Thick border
*/
public final static short BORDER_THICK = 0x5;
/**
* double-line border
*/
public final static short BORDER_DOUBLE = 0x6;
/**
* hair-line border
*/
public final static short BORDER_DOTTED = 0x7;
/**
* Medium dashed border
*/
public final static short BORDER_MEDIUM_DASHED = 0x8;
/**
* dash-dot border
*/
public final static short BORDER_DASH_DOT = 0x9;
/**
* medium dash-dot border
*/
public final static short BORDER_MEDIUM_DASH_DOT = 0xA;
/**
* dash-dot-dot border
*/
public final static short BORDER_DASH_DOT_DOT = 0xB;
/**
* medium dash-dot-dot border
*/
public final static short BORDER_MEDIUM_DASH_DOT_DOT = 0xC;
/**
* slanted dash-dot border
*/
public final static short BORDER_SLANTED_DASH_DOT = 0xD;
public BorderFormatting()
{
field_13_border_styles1 = (short)0;
field_14_border_styles2 = (short)0;
}
/** Creates new FontFormatting */
public BorderFormatting(RecordInputStream in)
{
field_13_border_styles1 = in.readInt();
field_14_border_styles2 = in.readInt();
}
// BORDER FORMATTING BLOCK
// For Border Line Style codes see HSSFCellStyle.BORDER_XXXXXX
private int field_13_border_styles1;
private static final BitField bordLeftLineStyle = BitFieldFactory.getInstance(0x0000000F);
private static final BitField bordRightLineStyle = BitFieldFactory.getInstance(0x000000F0);
private static final BitField bordTopLineStyle = BitFieldFactory.getInstance(0x00000F00);
private static final BitField bordBottomLineStyle= BitFieldFactory.getInstance(0x0000F000);
private static final BitField bordLeftLineColor = BitFieldFactory.getInstance(0x007F0000);
private static final BitField bordRightLineColor = BitFieldFactory.getInstance(0x3F800000);
private static final BitField bordTlBrLineOnOff = BitFieldFactory.getInstance(0x40000000);
private static final BitField bordBlTrtLineOnOff = BitFieldFactory.getInstance(0x80000000);
private int field_14_border_styles2;
private static final BitField bordTopLineColor = BitFieldFactory.getInstance(0x0000007F);
private static final BitField bordBottomLineColor= BitFieldFactory.getInstance(0x00003f80);
private static final BitField bordDiagLineColor = BitFieldFactory.getInstance(0x001FC000);
private static final BitField bordDiagLineStyle = BitFieldFactory.getInstance(0x01E00000);
/**
* set the type of border to use for the left border of the cell
* @param border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public void setBorderLeft(short border)
{
field_13_border_styles1 = bordLeftLineStyle.setValue(field_13_border_styles1, border);
}
/**
* get the type of border to use for the left border of the cell
* @return border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public short getBorderLeft()
{
return (short)bordLeftLineStyle.getValue(field_13_border_styles1);
}
/**
* set the type of border to use for the right border of the cell
* @param border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public void setBorderRight(short border)
{
field_13_border_styles1 = bordRightLineStyle.setValue(field_13_border_styles1, border);
}
/**
* get the type of border to use for the right border of the cell
* @return border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public short getBorderRight()
{
return (short)bordRightLineStyle.getValue(field_13_border_styles1);
}
/**
* set the type of border to use for the top border of the cell
* @param border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public void setBorderTop(short border)
{
field_13_border_styles1 = bordTopLineStyle.setValue(field_13_border_styles1, border);
}
/**
* get the type of border to use for the top border of the cell
* @return border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public short getBorderTop()
{
return (short)bordTopLineStyle.getValue(field_13_border_styles1);
}
/**
* set the type of border to use for the bottom border of the cell
* @param border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public void setBorderBottom(short border)
{
field_13_border_styles1 = bordBottomLineStyle.setValue(field_13_border_styles1, border);
}
/**
* get the type of border to use for the bottom border of the cell
* @return border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public short getBorderBottom()
{
return (short)bordBottomLineStyle.getValue(field_13_border_styles1);
}
/**
* set the type of border to use for the diagonal border of the cell
* @param border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public void setBorderDiagonal(short border)
{
field_14_border_styles2 = bordDiagLineStyle.setValue(field_14_border_styles2, border);
}
/**
* get the type of border to use for the diagonal border of the cell
* @return border type
* @see #BORDER_NONE
* @see #BORDER_THIN
* @see #BORDER_MEDIUM
* @see #BORDER_DASHED
* @see #BORDER_DOTTED
* @see #BORDER_THICK
* @see #BORDER_DOUBLE
* @see #BORDER_HAIR
* @see #BORDER_MEDIUM_DASHED
* @see #BORDER_DASH_DOT
* @see #BORDER_MEDIUM_DASH_DOT
* @see #BORDER_DASH_DOT_DOT
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
public short getBorderDiagonal()
{
return (short)bordDiagLineStyle.getValue(field_14_border_styles2);
}
/**
* set the color to use for the left border
* @param color The index of the color definition
*/
public void setLeftBorderColor(short color)
{
field_13_border_styles1 = bordLeftLineColor.setValue(field_13_border_styles1, color);
}
/**
* get the color to use for the left border
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/
public short getLeftBorderColor()
{
return (short)bordLeftLineColor.getValue(field_13_border_styles1);
}
/**
* set the color to use for the right border
* @param color The index of the color definition
*/
public void setRightBorderColor(short color)
{
field_13_border_styles1 = bordRightLineColor.setValue(field_13_border_styles1, color);
}
/**
* get the color to use for the right border
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/
public short getRightBorderColor()
{
return (short)bordRightLineColor.getValue(field_13_border_styles1);
}
/**
* set the color to use for the top border
* @param color The index of the color definition
*/
public void setTopBorderColor(short color)
{
field_14_border_styles2 = bordTopLineColor.setValue(field_14_border_styles2, color);
}
/**
* get the color to use for the top border
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/
public short getTopBorderColor()
{
return (short)bordTopLineColor.getValue(field_14_border_styles2);
}
/**
* set the color to use for the bottom border
* @param color The index of the color definition
*/
public void setBottomBorderColor(short color)
{
field_14_border_styles2 = bordBottomLineColor.setValue(field_14_border_styles2, color);
}
/**
* get the color to use for the bottom border
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/
public short getBottomBorderColor()
{
return (short)bordBottomLineColor.getValue(field_14_border_styles2);
}
/**
* set the color to use for the diagonal borders
* @param color The index of the color definition
*/
public void setDiagonalBorderColor(short color)
{
field_14_border_styles2 = bordDiagLineColor.setValue(field_14_border_styles2, color);
}
/**
* get the color to use for the diagonal border
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/
public short getDiagonalBorderColor()
{
return (short)bordDiagLineColor.getValue(field_14_border_styles2);
}
/**
* Of/off bottom left to top right line
*
* @param on - if true - on, otherwise off
*/
public void setForwardDiagonalOn(boolean on)
{
field_13_border_styles1 = bordBlTrtLineOnOff.setBoolean(field_13_border_styles1, on);
}
/**
* Of/off top left to bottom right line
*
* @param on - if true - on, otherwise off
*/
public void setBackwardDiagonalOn(boolean on)
{
field_13_border_styles1 = bordTlBrLineOnOff.setBoolean(field_13_border_styles1, on);
}
/**
* @return true if forward diagonal is on
*/
public boolean isForwardDiagonalOn()
{
return bordBlTrtLineOnOff.isSet(field_13_border_styles1);
}
/**
* @return true if backward diagonal is on
*/
public boolean isBackwardDiagonalOn()
{
return bordTlBrLineOnOff.isSet(field_13_border_styles1);
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append(" [Border Formatting]\n");
buffer.append(" .lftln = ").append(Integer.toHexString(getBorderLeft())).append("\n");
buffer.append(" .rgtln = ").append(Integer.toHexString(getBorderRight())).append("\n");
buffer.append(" .topln = ").append(Integer.toHexString(getBorderTop())).append("\n");
buffer.append(" .btmln = ").append(Integer.toHexString(getBorderBottom())).append("\n");
buffer.append(" .leftborder= ").append(Integer.toHexString(getLeftBorderColor())).append("\n");
buffer.append(" .rghtborder= ").append(Integer.toHexString(getRightBorderColor())).append("\n");
buffer.append(" .topborder= ").append(Integer.toHexString(getTopBorderColor())).append("\n");
buffer.append(" .bottomborder= ").append(Integer.toHexString(getBottomBorderColor())).append("\n");
buffer.append(" .fwdiag= ").append(isForwardDiagonalOn()).append("\n");
buffer.append(" .bwdiag= ").append(isBackwardDiagonalOn()).append("\n");
buffer.append(" [/Border Formatting]\n");
return buffer.toString();
}
public Object clone()
{
BorderFormatting rec = new BorderFormatting();
rec.field_13_border_styles1 = field_13_border_styles1;
rec.field_14_border_styles2 = field_14_border_styles2;
return rec;
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putInt(data, offset, field_13_border_styles1);
offset += 4;
LittleEndian.putInt(data, offset, field_14_border_styles2);
offset += 4;
return 8;
}
}

View File

@ -0,0 +1,259 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.cf;
/**
* CellRange.java
* Created on January 22, 2008, 10:05 PM
*
* @author Dmitriy Kumshayev
*/
public 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()
{
return field_1_first_row;
}
private void setFirstRow(int firstRow)
{
this.field_1_first_row = firstRow;
}
public int getLastRow()
{
return field_2_last_row;
}
private void setLastRow(int lastRow)
{
this.field_2_last_row = lastRow;
}
public short getFirstColumn()
{
return field_3_first_column;
}
private void setFirstColumn(short firstColumn)
{
this.field_3_first_column = firstColumn;
}
public short getLastColumn()
{
return field_4_last_column;
}
private void setLastColumn(short lastColumn)
{
this.field_4_last_column = lastColumn;
}
public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2;
public static final int INSIDE = 3;
public static final int ENCLOSES = 4;
/**
* Intersect this range with the specified range.
*
* @param another - the specified range
* @return code which reflects how the specified range is related to this range.<br/>
* Possible return codes are:
* 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/>
*/
public int intersect(CellRange another )
{
int firstRow = another.getFirstRow();
int lastRow = another.getLastRow();
short firstCol = another.getFirstColumn();
short lastCol = another.getLastColumn();
if
(
gt(this.getFirstRow(),lastRow) ||
lt(this.getLastRow(),firstRow) ||
gt(this.getFirstColumn(),lastCol) ||
lt(this.getLastColumn(),firstCol)
)
{
return NO_INTERSECTION;
}
else if( this.contains(another) )
{
return INSIDE;
}
else if( another.contains(this) )
{
return ENCLOSES;
}
else
{
return OVERLAP;
}
}
/**
* Check if the specified range is located inside of this cell range.
*
* @param range
* @return true if this cell range contains the argument range inside if it's area
*/
public boolean contains(CellRange 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);
}
public boolean contains(int row, short column)
{
return le(this.getFirstRow(), row) && ge(this.getLastRow(), row)
&& le(this.getFirstColumn(), column) && ge(this.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)
{
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)
;
}
/**
* Create an enclosing CellRange for the two cell ranges.
*
* @return enclosing CellRange
*/
public CellRange createEnclosingCellRange(CellRange range)
{
if( range == null)
{
return cloneCellRange();
}
else
{
CellRange cellRange =
new CellRange(
lt(range.getFirstRow(),getFirstRow())?range.getFirstRow():getFirstRow(),
gt(range.getLastRow(),getLastRow())?range.getLastRow():getLastRow(),
lt(range.getFirstColumn(),getFirstColumn())?range.getFirstColumn():getFirstColumn(),
gt(range.getLastColumn(),getLastColumn())?range.getLastColumn():getLastColumn()
);
return cellRange;
}
}
public CellRange cloneCellRange()
{
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
*/
private static boolean lt(int a, int b)
{
return a == -1 ? false : (b == -1 ? true : a < b);
}
/**
* @return true if a <= b
*/
private static boolean le(int a, int b)
{
return a == b || lt(a,b);
}
/**
* @return true if a > b
*/
private static boolean gt(int a, int b)
{
return lt(b,a);
}
/**
* @return true if a >= b
*/
private static boolean ge(int a, int b)
{
return !lt(a,b);
}
public String toString()
{
return "("+this.getFirstRow()+","+this.getLastRow()+","+this.getFirstColumn()+","+this.getLastColumn()+")";
}
}

View File

@ -0,0 +1,591 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.cf;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
* Font Formatting Block of the Conditional Formatting Rule Record.
*
* Created on January 22, 2008, 10:05 PM
*
* @author Dmitriy Kumshayev
*/
public class FontFormatting
{
private byte [] record;
private static final int OFFSET_FONT_NAME = 0;
private static final int OFFSET_FONT_HEIGHT = 64;
private static final int OFFSET_FONT_OPTIONS = 68;
private static final int OFFSET_FONT_WEIGHT = 72;
private static final int OFFSET_ESCAPEMENT_TYPE = 74;
private static final int OFFSET_UNDERLINE_TYPE = 76;
private static final int OFFSET_FONT_COLOR_INDEX = 80;
private static final int OFFSET_OPTION_FLAGS = 88;
private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92;
private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96;
private static final int OFFSET_NOT_USED1 = 100;
private static final int OFFSET_NOT_USED2 = 104;
private static final int OFFSET_FONT_FORMATING_END = 116;
public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF;
// FONT OPTIONS MASKS
private static final BitField posture = BitFieldFactory.getInstance(0x00000002);
private static final BitField outline = BitFieldFactory.getInstance(0x00000008);
private static final BitField shadow = BitFieldFactory.getInstance(0x00000010);
private static final BitField condense = BitFieldFactory.getInstance(0x00000020);
private static final BitField cancellation = BitFieldFactory.getInstance(0x00000080);
// OPTION FLAGS MASKS
private static final BitField styleModified = BitFieldFactory.getInstance(0x00000002);
private static final BitField outlineModified = BitFieldFactory.getInstance(0x00000008);
private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010);
private static final BitField condenseModified = BitFieldFactory.getInstance(0x00000020);
private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080);
/**
* Escapement type - None
*/
public final static short SS_NONE = 0;
/**
* Escapement type - Superscript
*/
public final static short SS_SUPER = 1;
/**
* Escapement type - Subscript
*/
public final static short SS_SUB = 2;
/**
* Underline type - None
*/
public final static byte U_NONE = 0;
/**
* Underline type - Single
*/
public final static byte U_SINGLE = 1;
/**
* Underline type - Double
*/
public final static byte U_DOUBLE = 2;
/**
* Underline type - Single Accounting
*/
public final static byte U_SINGLE_ACCOUNTING = 0x21;
/**
* Underline type - Double Accounting
*/
public final static byte U_DOUBLE_ACCOUNTING = 0x22;
/**
* Normal boldness (not bold)
*/
protected final static short FONT_WEIGHT_NORMAL = 0x190;
/**
* Bold boldness (bold)
*/
protected final static short FONT_WEIGHT_BOLD = 0x2bc;
public FontFormatting()
{
this(new byte[118]);
this.setFontHeight((short)-1);
this.setItalic(false);
this.setBold(false);
this.setOutline(false);
this.setShadow(false);
this.setCondense(false);
this.setStrikeout(false);
this.setEscapementType((short)0);
this.setUnderlineType((byte)0);
this.setFontColorIndex((short)-1);
this.setFontStyleModified(false);
this.setFontOutlineModified(false);
this.setFontShadowModified(false);
this.setFontCondenseModified(false);
this.setFontCancellationModified(false);
this.setEscapementTypeModified(false);
this.setUnderlineTypeModified(false);
LittleEndian.putShort(record, OFFSET_FONT_NAME, (short)0);
LittleEndian.putInt(record, OFFSET_NOT_USED1, 0x00000001);
LittleEndian.putInt(record, OFFSET_NOT_USED2, 0x00000001);
LittleEndian.putShort(record, OFFSET_FONT_FORMATING_END, (short)0x0001);
}
/** Creates new FontFormatting */
private FontFormatting(byte[] record)
{
this.record = record;
}
/** Creates new FontFormatting */
public FontFormatting(RecordInputStream in)
{
record = new byte[118];
for (int i = 0; i != record.length; i++)
{
record[i] = in.readByte();
}
}
public byte[] getRawRecord()
{
return record;
}
/**
* sets the height of the font in 1/20th point units
*
*
* @param height fontheight (in points/20); or -1 to preserve the cell font height
*/
public void setFontHeight(short height)
{
LittleEndian.putInt(record, OFFSET_FONT_HEIGHT, height);
}
/**
* gets the height of the font in 1/20th point units
*
* @return fontheight (in points/20); or -1 if not modified
*/
public short getFontHeight()
{
return (short) LittleEndian.getInt(record, OFFSET_FONT_HEIGHT);
}
private void setFontOption(boolean option, BitField field)
{
int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS);
options = field.setBoolean(options, option);
LittleEndian.putInt(record,OFFSET_FONT_OPTIONS, options);
}
private boolean getFontOption(BitField field)
{
int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS);
return field.isSet(options);
}
/**
* set the font to be italics or not
*
* @param italics - whether the font is italics or not
* @see #setAttributes(short)
*/
public void setItalic(boolean italic)
{
setFontOption(italic, posture);
}
/**
* get whether the font is to be italics or not
*
* @return italics - whether the font is italics or not
* @see #getAttributes()
*/
public boolean isItalic()
{
return getFontOption(posture);
}
public void setOutline(boolean on)
{
setFontOption(on, outline);
}
public boolean isOutlineOn()
{
return getFontOption(outline);
}
public void setShadow(boolean on)
{
setFontOption(on, shadow);
}
public boolean isShadowOn()
{
return getFontOption(shadow);
}
public void setCondense(boolean on)
{
setFontOption(on, condense);
}
public boolean isCondenseOn()
{
return getFontOption(condense);
}
/**
* set the font to be stricken out or not
*
* @param strike - whether the font is stricken out or not
*/
public void setStrikeout(boolean strike)
{
setFontOption(strike, cancellation);
}
/**
* get whether the font is to be stricken out or not
*
* @return strike - whether the font is stricken out or not
* @see #getAttributes()
*/
public boolean isStruckout()
{
return getFontOption(cancellation);
}
/**
* set the font weight (100-1000dec or 0x64-0x3e8). Default is
* 0x190 for normal and 0x2bc for bold
*
* @param bw - a number between 100-1000 for the fonts "boldness"
*/
private void setFontWeight(short bw)
{
if( bw<100) { bw=100; }
if( bw>1000){ bw=1000; }
LittleEndian.putShort(record,OFFSET_FONT_WEIGHT, bw);
}
/**
* set the font weight to bold (weight=700) or to normal(weight=400) boldness.
*
* @param bold - set font weight to bold if true; to normal otherwise
*/
public void setBold(boolean bold)
{
setFontWeight(bold?FONT_WEIGHT_BOLD:FONT_WEIGHT_NORMAL);
}
/**
* get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is
* 0x190 for normal and 0x2bc for bold
*
* @return bw - a number between 100-1000 for the fonts "boldness"
*/
public short getFontWeight()
{
return LittleEndian.getShort(record,OFFSET_FONT_WEIGHT);
}
/**
* get whether the font weight is set to bold or not
*
* @return bold - whether the font is bold or not
*/
public boolean isBold()
{
return getFontWeight()==FONT_WEIGHT_BOLD;
}
/**
* get the type of super or subscript for the font
*
* @return super or subscript option
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB
*/
public short getEscapementType()
{
return LittleEndian.getShort(record,OFFSET_ESCAPEMENT_TYPE);
}
/**
* set the escapement type for the font
*
* @param escapementType super or subscript option
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB
*/
public void setEscapementType( short escapementType)
{
LittleEndian.putShort(record,OFFSET_ESCAPEMENT_TYPE, escapementType);
}
/**
* get the type of underlining for the font
*
* @return font underlining type
*
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING
*/
public short getUnderlineType()
{
return LittleEndian.getShort(record,OFFSET_UNDERLINE_TYPE);
}
/**
* set the type of underlining type for the font
*
* @param u super or subscript option
*
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING
*/
public void setUnderlineType( short underlineType)
{
LittleEndian.putShort(record,OFFSET_UNDERLINE_TYPE, underlineType);
}
public short getFontColorIndex()
{
return (short)LittleEndian.getInt(record,OFFSET_FONT_COLOR_INDEX);
}
public void setFontColorIndex(short fci )
{
LittleEndian.putInt(record,OFFSET_FONT_COLOR_INDEX,fci);
}
private boolean getOptionFlag(BitField field)
{
int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS);
int value = field.getValue(optionFlags);
return value==0? true : false ;
}
private void setOptionFlag(boolean modified, BitField field)
{
int value = modified? 0 : 1;
int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS);
optionFlags = field.setValue(optionFlags, value);
LittleEndian.putInt(record,OFFSET_OPTION_FLAGS, optionFlags);
}
public boolean isFontStyleModified()
{
return getOptionFlag(styleModified);
}
public void setFontStyleModified(boolean modified)
{
setOptionFlag(modified, styleModified);
}
public boolean isFontOutlineModified()
{
return getOptionFlag(outlineModified);
}
public void setFontOutlineModified(boolean modified)
{
setOptionFlag(modified, outlineModified);
}
public boolean isFontShadowModified()
{
return getOptionFlag(shadowModified);
}
public void setFontShadowModified(boolean modified)
{
setOptionFlag(modified, shadowModified);
}
public boolean isFontCondenseModified()
{
return getOptionFlag(condenseModified);
}
public void setFontCondenseModified(boolean modified)
{
setOptionFlag(modified, condenseModified);
}
public void setFontCancellationModified(boolean modified)
{
setOptionFlag(modified, cancellationModified);
}
public boolean isFontCancellationModified()
{
return getOptionFlag(cancellationModified);
}
public void setEscapementTypeModified(boolean modified)
{
int value = modified? 0 : 1;
LittleEndian.putInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED, value);
}
public boolean isEscapementTypeModified()
{
int escapementModified = LittleEndian.getInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED);
return escapementModified == 0;
}
public void setUnderlineTypeModified(boolean modified)
{
int value = modified? 0 : 1;
LittleEndian.putInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED, value);
}
public boolean isUnderlineTypeModified()
{
int underlineModified = LittleEndian.getInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED);
return underlineModified == 0;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append(" [Font Formatting]\n");
buffer.append(" .font height = ").append(getFontHeight()).append(" twips\n");
if( isFontStyleModified() )
{
buffer.append(" .font posture = ").append(isItalic()?"Italic":"Normal").append("\n");
}
else
{
buffer.append(" .font posture = ]not modified]").append("\n");
}
if( isFontOutlineModified() )
{
buffer.append(" .font outline = ").append(isOutlineOn()).append("\n");
}
else
{
buffer.append(" .font outline is not modified\n");
}
if( isFontShadowModified() )
{
buffer.append(" .font shadow = ").append(isShadowOn()).append("\n");
}
else
{
buffer.append(" .font shadow is not modified\n");
}
if( isFontCondenseModified() )
{
buffer.append(" .font condense = ").append(isCondenseOn()).append("\n");
}
else
{
buffer.append(" .font condense is not modified\n");
}
if( isFontCancellationModified() )
{
buffer.append(" .font strikeout = ").append(isStruckout()).append("\n");
}
else
{
buffer.append(" .font strikeout is not modified\n");
}
if( isFontStyleModified() )
{
buffer.append(" .font weight = ").
append(getFontWeight()).
append(
getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)"
: getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" : "0x"+Integer.toHexString(getFontWeight())).
append("\n");
}
else
{
buffer.append(" .font weight = ]not modified]").append("\n");
}
if( isEscapementTypeModified() )
{
buffer.append(" .escapement type = ").append(getEscapementType()).append("\n");
}
else
{
buffer.append(" .escapement type is not modified\n");
}
if( isUnderlineTypeModified() )
{
buffer.append(" .underline type = ").append(getUnderlineType()).append("\n");
}
else
{
buffer.append(" .underline type is not modified\n");
}
buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n");
buffer.append(" [/Font Formatting]\n");
return buffer.toString();
}
public Object clone()
{
FontFormatting rec = new FontFormatting();
if( record != null)
{
byte[] clone = new byte[record.length];
System.arraycopy(record, 0, clone, 0, record.length);
rec.record = clone;
}
return rec;
}
}

View File

@ -0,0 +1,206 @@
/* ====================================================================
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.
==================================================================== */
/*
* FontFormatting.java
*
* Created on January 22, 2008, 10:05 PM
*/
package org.apache.poi.hssf.record.cf;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
* Pattern Formatting Block of the Conditional Formatting Rule Record.
*
* @author Dmitriy Kumshayev
*/
public class PatternFormatting implements Cloneable
{
/** No background */
public final static short NO_FILL = 0 ;
/** Solidly filled */
public final static short SOLID_FOREGROUND = 1 ;
/** Small fine dots */
public final static short FINE_DOTS = 2 ;
/** Wide dots */
public final static short ALT_BARS = 3 ;
/** Sparse dots */
public final static short SPARSE_DOTS = 4 ;
/** Thick horizontal bands */
public final static short THICK_HORZ_BANDS = 5 ;
/** Thick vertical bands */
public final static short THICK_VERT_BANDS = 6 ;
/** Thick backward facing diagonals */
public final static short THICK_BACKWARD_DIAG = 7 ;
/** Thick forward facing diagonals */
public final static short THICK_FORWARD_DIAG = 8 ;
/** Large spots */
public final static short BIG_SPOTS = 9 ;
/** Brick-like layout */
public final static short BRICKS = 10 ;
/** Thin horizontal bands */
public final static short THIN_HORZ_BANDS = 11 ;
/** Thin vertical bands */
public final static short THIN_VERT_BANDS = 12 ;
/** Thin backward diagonal */
public final static short THIN_BACKWARD_DIAG = 13 ;
/** Thin forward diagonal */
public final static short THIN_FORWARD_DIAG = 14 ;
/** Squares */
public final static short SQUARES = 15 ;
/** Diamonds */
public final static short DIAMONDS = 16 ;
/** Less Dots */
public final static short LESS_DOTS = 17 ;
/** Least Dots */
public final static short LEAST_DOTS = 18 ;
public PatternFormatting()
{
field_15_pattern_style = (short)0;
field_16_pattern_color_indexes = (short)0;
}
/** Creates new FontFormatting */
public PatternFormatting(RecordInputStream in)
{
field_15_pattern_style = in.readShort();
field_16_pattern_color_indexes = in.readShort();
}
// PATTERN FORMATING BLOCK
// For Pattern Styles see constants at HSSFCellStyle (from NO_FILL to LEAST_DOTS)
private short field_15_pattern_style;
private static final BitField fillPatternStyle = BitFieldFactory.getInstance(0xFC00);
private short field_16_pattern_color_indexes;
private static final BitField patternColorIndex = BitFieldFactory.getInstance(0x007F);
private static final BitField patternBackgroundColorIndex = BitFieldFactory.getInstance(0x3F80);
/**
* setting fill pattern
*
* @see #NO_FILL
* @see #SOLID_FOREGROUND
* @see #FINE_DOTS
* @see #ALT_BARS
* @see #SPARSE_DOTS
* @see #THICK_HORZ_BANDS
* @see #THICK_VERT_BANDS
* @see #THICK_BACKWARD_DIAG
* @see #THICK_FORWARD_DIAG
* @see #BIG_SPOTS
* @see #BRICKS
* @see #THIN_HORZ_BANDS
* @see #THIN_VERT_BANDS
* @see #THIN_BACKWARD_DIAG
* @see #THIN_FORWARD_DIAG
* @see #SQUARES
* @see #DIAMONDS
*
* @param fp fill pattern
*/
public void setFillPattern(short fp)
{
field_15_pattern_style = fillPatternStyle.setShortValue(field_15_pattern_style, fp);
}
/**
* get the fill pattern
* @return fill pattern
*/
public short getFillPattern()
{
return fillPatternStyle.getShortValue(field_15_pattern_style);
}
/**
* set the background fill color.
*
* @param bg color
*/
public void setFillBackgroundColor(short bg)
{
field_16_pattern_color_indexes = patternBackgroundColorIndex.setShortValue(field_16_pattern_color_indexes,bg);
}
/**
* get the background fill color
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color
*/
public short getFillBackgroundColor()
{
return patternBackgroundColorIndex.getShortValue(field_16_pattern_color_indexes);
}
/**
* set the foreground fill color
* @param bg color
*/
public void setFillForegroundColor(short fg)
{
field_16_pattern_color_indexes = patternColorIndex.setShortValue(field_16_pattern_color_indexes,fg);
}
/**
* get the foreground fill color
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color
*/
public short getFillForegroundColor()
{
return patternColorIndex.getShortValue(field_16_pattern_color_indexes);
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append(" [Pattern Formatting]\n");
buffer.append(" .fillpattern= ").append(Integer.toHexString(getFillPattern())).append("\n");
buffer.append(" .fgcoloridx= ").append(Integer.toHexString(getFillForegroundColor())).append("\n");
buffer.append(" .bgcoloridx= ").append(Integer.toHexString(getFillBackgroundColor())).append("\n");
buffer.append(" [/Pattern Formatting]\n");
return buffer.toString();
}
public Object clone()
{
PatternFormatting rec = new PatternFormatting();
rec.field_15_pattern_style = field_15_pattern_style;
rec.field_16_pattern_color_indexes = field_16_pattern_color_indexes;
return rec;
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, offset, field_15_pattern_style);
offset += 2;
LittleEndian.putShort(data, offset, field_16_pattern_color_indexes);
offset += 2;
return 4;
}
}

View File

@ -0,0 +1,128 @@
/* ====================================================================
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 org.apache.poi.hssf.record.cf.BorderFormatting;
/**
* High level representation for Border Formatting component
* of Conditional Formatting settings
*
* @author Dmitriy Kumshayev
*
*/
public class HSSFBorderFormatting
{
/**
* 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;
private BorderFormatting borderFormatting;
public HSSFBorderFormatting()
{
borderFormatting = new BorderFormatting();
}
protected BorderFormatting getBorderFormattingBlock()
{
return borderFormatting;
}
}

View File

@ -0,0 +1,201 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.Region;
public class HSSFConditionalFormatting
{
HSSFSheet sheet;
CFRecordsAggregate cfAggregate;
protected HSSFConditionalFormatting(HSSFSheet sheet)
{
this.sheet = sheet;
this.cfAggregate = new CFRecordsAggregate();
}
protected HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
{
this.sheet = sheet;
this.cfAggregate = cfAggregate;
}
public void setFormattingRegions(Region[] regions)
{
if( regions != null)
{
CFHeaderRecord header = cfAggregate.getHeader();
header.setCellRanges(mergeCellRanges(toCellRangeList(regions)));
}
}
public Region[] getFormattingRegions()
{
CFHeaderRecord cfh = cfAggregate.getHeader();
List cellRanges = cfh.getCellRanges();
if (cellRanges != null)
{
return toRegionArray(cellRanges);
}
return null;
}
public void setConditionalFormat(int idx, HSSFConditionalFormattingRule cfRule)
{
cfAggregate.getRules().set(idx, cfRule);
}
public void addConditionalFormat(HSSFConditionalFormattingRule cfRule)
{
cfAggregate.getRules().add(cfRule);
}
public HSSFConditionalFormattingRule getConditionalFormat(int idx)
{
CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx);
return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord);
}
/**
* Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
* <li>if two cells have a shared border, merge them into one bigger cell range
* @param cellRangeList
* @return updated List of cell ranges
*/
private static List mergeCellRanges(List cellRangeList)
{
boolean merged = false;
do
{
merged = false;
if( cellRangeList.size()>1 )
{
for( int i=0; i<cellRangeList.size(); i++)
{
CellRange range1 = (CellRange)cellRangeList.get(i);
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRange range2 = (CellRange)cellRangeList.get(j);
switch(range1.intersect(range2))
{
case CellRange.NO_INTERSECTION:
{
if( range1.hasSharedBorder(range2))
{
cellRangeList.set(i, range1.createEnclosingCellRange(range2));
cellRangeList.remove(j--);
merged = true;
}
else
{
// No intersection and no shared border: do nothing
}
break;
}
case CellRange.OVERLAP:
{
// TODO split and re-merge the intersected area
break;
}
case CellRange.INSIDE:
{
// Remove range2, since it is completely inside of range1
cellRangeList.remove(j--);
merged = true;
break;
}
case CellRange.ENCLOSES:
{
// range2 encloses range1, so replace it with the enclosing one
cellRangeList.set(i, range2);
cellRangeList.remove(j--);
merged = true;
break;
}
}
}
}
}
}
while( merged );
return cellRangeList;
}
/**
* Convert a List of CellRange objects to an array of regions
*
* @param List of CellRange objects
* @return regions
*/
private static Region[] toRegionArray(List cellRanges)
{
int size = cellRanges.size();
Region[] regions = new Region[size];
for (int i = 0; i != size; i++)
{
CellRange cr = (CellRange) cellRanges.get(i);
regions[i] = new Region(cr.getFirstRow(), cr.getFirstColumn(),
cr.getLastRow(), cr.getLastColumn());
}
return regions;
}
/**
* Convert array of regions to a List of CellRange objects
*
* @param regions
* @return List of CellRange objects
*/
private static List toCellRangeList(Region[] regions)
{
List cellRangeList = new ArrayList();
for( int i=0; i<regions.length; i++)
{
Region r = regions[i];
CellRange cr = new CellRange(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r
.getColumnTo());
cellRangeList.add(cr);
}
return cellRangeList;
}
public String toString()
{
if(cfAggregate!=null)
{
return cfAggregate.toString();
}
return null;
}
}

View File

@ -0,0 +1,248 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import java.util.List;
import java.util.Stack;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.formula.Ptg;
/**
*
* High level representation of Conditional Format
*
* @author Dmitriy Kumshayev
*/
public class HSSFConditionalFormattingRule
{
public static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
public static final byte FORMULA = CFRuleRecord.CONDITION_TYPE_FORMULA;
public static final byte COMPARISON_OPERATOR_NO_COMPARISON = CFRuleRecord.COMPARISON_OPERATOR_NO_COMPARISON;
public static final byte COMPARISON_OPERATOR_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_BETWEEN;
public static final byte COMPARISON_OPERATOR_NOT_BETWEEN = CFRuleRecord.COMPARISON_OPERATOR_NOT_BETWEEN;
public static final byte COMPARISON_OPERATOR_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_EQUAL;
public static final byte COMPARISON_OPERATOR_NOT_EQUAL = CFRuleRecord.COMPARISON_OPERATOR_NOT_EQUAL;
public static final byte COMPARISON_OPERATOR_GT = CFRuleRecord.COMPARISON_OPERATOR_GT;
public static final byte COMPARISON_OPERATOR_LT = CFRuleRecord.COMPARISON_OPERATOR_LT;
public static final byte COMPARISON_OPERATOR_GE = CFRuleRecord.COMPARISON_OPERATOR_GE;
public static final byte COMPARISON_OPERATOR_LE = CFRuleRecord.COMPARISON_OPERATOR_LE;
private 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;
}
/**
* 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();
}
/**
* Keep Pattern Formatting unchanged for this Conditional Formatting Rule
*/
public void setPatternFormattingUnchanged()
{
cfRuleRecord.setPatternFormattingUnchanged();
}
public void setFontFormatting(HSSFFontFormatting fontFormatting)
{
if( fontFormatting!=null )
{
cfRuleRecord.setFontFormatting(fontFormatting.getFontFormattingBlock());
}
else
{
setFontFormattingUnchanged();
}
}
public void setBorderFormatting(HSSFBorderFormatting borderFormatting)
{
if( borderFormatting != null )
{
cfRuleRecord.setBorderFormatting(borderFormatting.getBorderFormattingBlock());
}
else
{
setBorderFormattingUnchanged();
}
}
public void setPatternFormatting(HSSFPatternFormatting patternFormatting)
{
if( patternFormatting != null)
{
cfRuleRecord.setPatternFormatting(patternFormatting.getPatternFormattingBlock());
}
else
{
setPatternFormattingUnchanged();
}
}
public void setCellComparisonCondition(byte comparisonOperation, String formula1, String formula2)
{
cfRuleRecord.setConditionType(CELL_COMPARISON);
cfRuleRecord.setComparisonOperation(comparisonOperation);
// Formula 1
setFormula1(formula1);
// Formula 2
setFormula1(formula2);
}
public void setFormulaCondition(String formula)
{
cfRuleRecord.setConditionType(FORMULA);
// Formula 1
setFormula1(formula);
}
public void setFormula1(String formula)
{
// Formula 1
if( formula != null)
{
Stack parsedExpression = parseFormula(formula);
if( parsedExpression != null )
{
cfRuleRecord.setParsedExpression1(parsedExpression);
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
}
else
{
cfRuleRecord.setParsedExpression1(null);
}
}
public void setFormula2(String formula)
{
// Formula 2
if( formula != null)
{
Stack parsedExpression = parseFormula(formula);
if( parsedExpression != null )
{
cfRuleRecord.setParsedExpression2(parsedExpression);
}
else
{
cfRuleRecord.setParsedExpression2(null);
}
}
else
{
cfRuleRecord.setParsedExpression2(null);
}
}
public String getFormula1()
{
return toFormulaString(cfRuleRecord.getParsedExpression1());
}
public String getFormula2()
{
byte conditionType = cfRuleRecord.getConditionType();
switch(conditionType)
{
case CELL_COMPARISON:
{
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
switch(comparisonOperation)
{
case COMPARISON_OPERATOR_BETWEEN:
case COMPARISON_OPERATOR_NOT_BETWEEN:
return toFormulaString(cfRuleRecord.getParsedExpression2());
}
}
}
return null;
}
private String toFormulaString(List parsedExpression)
{
String formula = null;
if(parsedExpression!=null)
{
formula = FormulaParser.toFormulaString(workbook.getWorkbook(),parsedExpression);
}
return formula;
}
private Stack parseFormula(String formula2)
{
FormulaParser parser =
new FormulaParser(formula2, workbook.getWorkbook());
parser.parse();
Stack parsedExpression = convertToTokenStack(parser.getRPNPtg());
parsedExpression = convertToTokenStack(parser.getRPNPtg());
return parsedExpression;
}
private static Stack convertToTokenStack(Ptg[] ptgs)
{
if( ptgs != null)
{
Stack parsedExpression = new Stack();
// fill the Ptg Stack with Ptgs of new formula
for (int k = 0; k < ptgs.length; k++)
{
parsedExpression.push(ptgs[ k ]);
}
return parsedExpression;
}
else
{
return null;
}
}
}

View File

@ -0,0 +1,456 @@
/* ====================================================================
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 org.apache.poi.hssf.record.cf.FontFormatting;
/**
* High level representation for Font Formatting component
* of Conditional Formatting settings
*
* @author Dmitriy Kumshayev
*
*/
public class HSSFFontFormatting
{
/**
* Escapement type - None
*/
public final static short SS_NONE = FontFormatting.SS_NONE;
/**
* Escapement type - Superscript
*/
public final static short SS_SUPER = FontFormatting.SS_SUPER;
/**
* Escapement type - Subscript
*/
public final static short SS_SUB = FontFormatting.SS_SUB;
/**
* Underline type - None
*/
public final static byte U_NONE = FontFormatting.U_NONE;
/**
* Underline type - Single
*/
public final static byte U_SINGLE = FontFormatting.U_SINGLE;
/**
* Underline type - Double
*/
public final static byte U_DOUBLE = FontFormatting.U_DOUBLE;
/**
* Underline type - Single Accounting
*/
public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING;
/**
* Underline type - Double Accounting
*/
public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING;
private FontFormatting fontFormatting;
public HSSFFontFormatting()
{
fontFormatting = new FontFormatting();
}
protected FontFormatting getFontFormattingBlock()
{
return fontFormatting;
}
/**
* get the type of super or subscript for the font
*
* @return super or subscript option
* @see #SS_NONE
* @see #SS_SUPER
* @see #SS_SUB
*/
public short getEscapementType()
{
return fontFormatting.getEscapementType();
}
/**
* @return font color index
*/
public short getFontColorIndex()
{
return fontFormatting.getFontColorIndex();
}
/**
* gets the height of the font in 1/20th point units
*
* @return fontheight (in points/20); or -1 if not modified
*/
public short getFontHeight()
{
return fontFormatting.getFontHeight();
}
/**
* get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is
* 0x190 for normal and 0x2bc for bold
*
* @return bw - a number between 100-1000 for the fonts "boldness"
*/
public short getFontWeight()
{
return fontFormatting.getFontWeight();
}
/**
* @return
* @see org.apache.poi.hssf.record.cf.FontFormatting#getRawRecord()
*/
protected byte[] getRawRecord()
{
return fontFormatting.getRawRecord();
}
/**
* get the type of underlining for the font
*
* @return font underlining type
*
* @see #U_NONE
* @see #U_SINGLE
* @see #U_DOUBLE
* @see #U_SINGLE_ACCOUNTING
* @see #U_DOUBLE_ACCOUNTING
*/
public short getUnderlineType()
{
return fontFormatting.getUnderlineType();
}
/**
* get whether the font weight is set to bold or not
*
* @return bold - whether the font is bold or not
*/
public boolean isBold()
{
return fontFormatting.isBold();
}
/**
* @return whether the font is condense or not
*/
public boolean isCondenseOn()
{
return fontFormatting.isFontOutlineModified() && fontFormatting.isCondenseOn();
}
/**
* @return true if escapement type was modified from default
*/
public boolean isEscapementTypeModified()
{
return fontFormatting.isEscapementTypeModified();
}
/**
* @return true if font cancellation was modified from default
*/
public boolean isFontCancellationModified()
{
return fontFormatting.isFontCancellationModified();
}
/**
* @return true if font condense type was modified from default
*/
public boolean isFontCondenseModified()
{
return fontFormatting.isFontCondenseModified();
}
/**
* @return true if font outline type was modified from default
*/
public boolean isFontOutlineModified()
{
return fontFormatting.isFontOutlineModified();
}
/**
* @return true if font shadow type was modified from default
*/
public boolean isFontShadowModified()
{
return fontFormatting.isFontShadowModified();
}
/**
* @return true if font style was modified from default
*/
public boolean isFontStyleModified()
{
return fontFormatting.isFontStyleModified();
}
/**
* @return true if font style was set to <i>italic</i>
*/
public boolean isItalic()
{
return fontFormatting.isFontStyleModified() && fontFormatting.isItalic();
}
/**
* @return true if font outline is on
*/
public boolean isOutlineOn()
{
return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn();
}
/**
* @return true if font shadow is on
*/
public boolean isShadowOn()
{
return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn();
}
/**
* @return true if font strikeout is on
*/
public boolean isStruckout()
{
return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout();
}
/**
* @return true if font underline type was modified from default
*/
public boolean isUnderlineTypeModified()
{
return fontFormatting.isUnderlineTypeModified();
}
/**
* set font style options.
*
* @param italic - if true, set posture style to italic, otherwise to normal
* @param bold- if true, set font weight to bold, otherwise to normal
*/
public void setFontStyle(boolean italic, boolean bold)
{
boolean modified = italic || bold;
fontFormatting.setItalic(italic);
fontFormatting.setBold(bold);
fontFormatting.setFontStyleModified(modified);
}
/**
* set font style options to default values (non-italic, non-bold)
*/
public void resetFontStyle()
{
setFontStyle(false,false);
}
/**
* set the escapement type for the font
*
* @param escapementType super or subscript option
* @see #SS_NONE
* @see #SS_SUPER
* @see #SS_SUB
*/
public void setCondense(boolean on)
{
fontFormatting.setCondense(on);
fontFormatting.setFontCondenseModified(on);
}
/**
* set the escapement type for the font
*
* @param escapementType super or subscript option
* @see #SS_NONE
* @see #SS_SUPER
* @see #SS_SUB
*/
public void setEscapementType(short escapementType)
{
switch(escapementType)
{
case HSSFFontFormatting.SS_SUB:
case HSSFFontFormatting.SS_SUPER:
fontFormatting.setEscapementType(escapementType);
fontFormatting.setEscapementTypeModified(true);
break;
case HSSFFontFormatting.SS_NONE:
fontFormatting.setEscapementType(escapementType);
fontFormatting.setEscapementTypeModified(false);
break;
default:
}
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean)
*/
public void setEscapementTypeModified(boolean modified)
{
fontFormatting.setEscapementTypeModified(modified);
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean)
*/
public void setFontCancellationModified(boolean modified)
{
fontFormatting.setFontCancellationModified(modified);
}
/**
* @param fci
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short)
*/
public void setFontColorIndex(short fci)
{
fontFormatting.setFontColorIndex(fci);
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCondenseModified(boolean)
*/
public void setFontCondenseModified(boolean modified)
{
fontFormatting.setFontCondenseModified(modified);
}
/**
* @param height
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(short)
*/
public void setFontHeight(short height)
{
fontFormatting.setFontHeight(height);
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean)
*/
public void setFontOutlineModified(boolean modified)
{
fontFormatting.setFontOutlineModified(modified);
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean)
*/
public void setFontShadowModified(boolean modified)
{
fontFormatting.setFontShadowModified(modified);
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean)
*/
public void setFontStyleModified(boolean modified)
{
fontFormatting.setFontStyleModified(modified);
}
/**
* @param on
* @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean)
*/
public void setOutline(boolean on)
{
fontFormatting.setOutline(on);
fontFormatting.setFontOutlineModified(on);
}
/**
* @param on
* @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean)
*/
public void setShadow(boolean on)
{
fontFormatting.setShadow(on);
fontFormatting.setFontShadowModified(on);
}
/**
* @param strike
* @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean)
*/
public void setStrikeout(boolean strike)
{
fontFormatting.setStrikeout(strike);
fontFormatting.setFontCancellationModified(strike);
}
/**
* set the type of underlining type for the font
*
* @param u super or subscript option
*
* @see #U_NONE
* @see #U_SINGLE
* @see #U_DOUBLE
* @see #U_SINGLE_ACCOUNTING
* @see #U_DOUBLE_ACCOUNTING
*/
public void setUnderlineType(short underlineType)
{
switch(underlineType)
{
case HSSFFontFormatting.U_SINGLE:
case HSSFFontFormatting.U_DOUBLE:
case HSSFFontFormatting.U_SINGLE_ACCOUNTING:
case HSSFFontFormatting.U_DOUBLE_ACCOUNTING:
fontFormatting.setUnderlineType(underlineType);
setUnderlineTypeModified(true);
break;
case HSSFFontFormatting.U_NONE:
fontFormatting.setUnderlineType(underlineType);
setUnderlineTypeModified(false);
break;
default:
}
}
/**
* @param modified
* @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean)
*/
public void setUnderlineTypeModified(boolean modified)
{
fontFormatting.setUnderlineTypeModified(modified);
}
}

View File

@ -0,0 +1,134 @@
/* ====================================================================
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 org.apache.poi.hssf.record.cf.PatternFormatting;
/**
* High level representation for Conditional Formatting settings
*
* @author Dmitriy Kumshayev
*
*/
public class HSSFPatternFormatting
{
/** No background */
public final static short NO_FILL = PatternFormatting.NO_FILL;
/** Solidly filled */
public final static short SOLID_FOREGROUND = PatternFormatting.SOLID_FOREGROUND;
/** Small fine dots */
public final static short FINE_DOTS = PatternFormatting.FINE_DOTS;
/** Wide dots */
public final static short ALT_BARS = PatternFormatting.ALT_BARS;
/** Sparse dots */
public final static short SPARSE_DOTS = PatternFormatting.SPARSE_DOTS;
/** Thick horizontal bands */
public final static short THICK_HORZ_BANDS = PatternFormatting.THICK_HORZ_BANDS;
/** Thick vertical bands */
public final static short THICK_VERT_BANDS = PatternFormatting.THICK_VERT_BANDS;
/** Thick backward facing diagonals */
public final static short THICK_BACKWARD_DIAG = PatternFormatting.THICK_BACKWARD_DIAG;
/** Thick forward facing diagonals */
public final static short THICK_FORWARD_DIAG = PatternFormatting.THICK_FORWARD_DIAG;
/** Large spots */
public final static short BIG_SPOTS = PatternFormatting.BIG_SPOTS;
/** Brick-like layout */
public final static short BRICKS = PatternFormatting.BRICKS;
/** Thin horizontal bands */
public final static short THIN_HORZ_BANDS = PatternFormatting.THIN_HORZ_BANDS;
/** Thin vertical bands */
public final static short THIN_VERT_BANDS = PatternFormatting.THIN_VERT_BANDS;
/** Thin backward diagonal */
public final static short THIN_BACKWARD_DIAG = PatternFormatting.THIN_BACKWARD_DIAG;
/** Thin forward diagonal */
public final static short THIN_FORWARD_DIAG = PatternFormatting.THIN_FORWARD_DIAG;
/** Squares */
public final static short SQUARES = PatternFormatting.SQUARES;
/** Diamonds */
public final static short DIAMONDS = PatternFormatting.DIAMONDS;
/** Less Dots */
public final static short LESS_DOTS = PatternFormatting.LESS_DOTS;
/** Least Dots */
public final static short LEAST_DOTS = PatternFormatting.LEAST_DOTS;
private PatternFormatting patternFormatting;
public HSSFPatternFormatting()
{
patternFormatting = new PatternFormatting();
}
protected PatternFormatting getPatternFormattingBlock()
{
return patternFormatting;
}
/**
* @return
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillBackgroundColor()
*/
public short getFillBackgroundColor()
{
return patternFormatting.getFillBackgroundColor();
}
/**
* @return
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillForegroundColor()
*/
public short getFillForegroundColor()
{
return patternFormatting.getFillForegroundColor();
}
/**
* @return
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillPattern()
*/
public short getFillPattern()
{
return patternFormatting.getFillPattern();
}
/**
* @param bg
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillBackgroundColor(short)
*/
public void setFillBackgroundColor(short bg)
{
patternFormatting.setFillBackgroundColor(bg);
}
/**
* @param fg
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillForegroundColor(short)
*/
public void setFillForegroundColor(short fg)
{
patternFormatting.setFillForegroundColor(fg);
}
/**
* @param fp
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillPattern(short)
*/
public void setFillPattern(short fp)
{
patternFormatting.setFillPattern(fp);
}
}

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.ReferencePtg;
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
@ -1830,4 +1831,161 @@ public class HSSFSheet
return null;
}
/**
* A factory method allowing to create a conditional formatting rule
* 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>
* </p>
* @param formula1 - formula for the valued, compared with the cell
* @param formula2 - second formula (only used with
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
* {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
* @param fontFmt - font formatting rules
* @param bordFmt - border formatting rules
* @param patternFmt - pattern formatting rules
* @return
*
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation,
String formula1,
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;
}
/**
* A factory method allowing to create a conditional formatting rule with a formula
* and formatting rules such as font format, border format and pattern format. <br>
*
* 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
*
*/
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;
}
/**
* Adds a copy of HSSFConditionalFormatting object to the sheet
* <p>This method could be used to copy HSSFConditionalFormatting object
* from one sheet to another. For example:
* <pre>
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
* newSheet.addConditionalFormatting(cf);
* </pre>
*
* @param cf HSSFConditionalFormatting object
* @return index of the new Conditional Formatting object
*/
public int addConditionalFormatting( HSSFConditionalFormatting cf )
{
HSSFConditionalFormatting cfClone = new HSSFConditionalFormatting(this,cf.cfAggregate.cloneCFAggregate());
cfClone.sheet=this;
return sheet.addConditionalFormatting(cfClone.cfAggregate);
}
/**
* 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
*
* @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.addConditionalFormat(cfRules[i]);
}
}
return sheet.addConditionalFormatting(cf.cfAggregate);
}
/**
* gets Conditional Formatting object at a particular index
* @param index of the Conditional Formatting object to fetch
* @return Conditional Formatting object
*/
public HSSFConditionalFormatting getConditionalFormattingAt(int index)
{
CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
if( cf != null )
{
return new HSSFConditionalFormatting(this,cf);
}
return null;
}
/**
* @return number of Conditional Formatting objects of the sheet
*/
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)
{
sheet.removeConditionalFormatting(index);
}
}

View File

@ -0,0 +1,145 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.cf.CellRange;
/**
* Tests the serialization and deserialization of the TestCFHeaderRecord
* class works correctly.
*
* @author Dmitriy Kumshayev
*/
public class TestCFHeaderRecord
extends TestCase
{
public TestCFHeaderRecord(String name)
{
super(name);
}
public void testCreateCFHeaderRecord ()
{
CFHeaderRecord record = new CFHeaderRecord();
List ranges = new ArrayList();
ranges.add(new CellRange(0,-1,(short)5,(short)5));
ranges.add(new CellRange(0,-1,(short)6,(short)6));
ranges.add(new CellRange(0,1,(short)0,(short)1));
ranges.add(new CellRange(0,1,(short)2,(short)3));
ranges.add(new CellRange(2,3,(short)0,(short)1));
ranges.add(new CellRange(2,3,(short)2,(short)3));
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)
{
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class);
}
}

View File

@ -0,0 +1,296 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import junit.framework.TestCase;
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;
/**
* Tests the serialization and deserialization of the TestCFRuleRecord
* class works correctly.
*
* @author Dmitriy Kumshayev
*/
public 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
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());
}
private void testPatternFormattingAccessors(PatternFormatting patternFormatting)
{
patternFormatting.setFillBackgroundColor(HSSFColor.GREEN.index);
assertEquals(HSSFColor.GREEN.index,patternFormatting.getFillBackgroundColor());
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)
{
borderFormatting.setBackwardDiagonalOn(false);
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.setBorderRight(BorderFormatting.BORDER_MEDIUM_DASHED);
assertEquals(BorderFormatting.BORDER_MEDIUM_DASHED, borderFormatting.getBorderRight());
borderFormatting.setBorderTop(BorderFormatting.BORDER_HAIR);
assertEquals(BorderFormatting.BORDER_HAIR, borderFormatting.getBorderTop());
borderFormatting.setBottomBorderColor(HSSFColor.AQUA.index);
assertEquals(HSSFColor.AQUA.index, borderFormatting.getBottomBorderColor());
borderFormatting.setDiagonalBorderColor(HSSFColor.RED.index);
assertEquals(HSSFColor.RED.index, borderFormatting.getDiagonalBorderColor());
assertFalse(borderFormatting.isForwardDiagonalOn());
borderFormatting.setForwardDiagonalOn(true);
assertTrue(borderFormatting.isForwardDiagonalOn());
borderFormatting.setLeftBorderColor(HSSFColor.BLACK.index);
assertEquals(HSSFColor.BLACK.index, borderFormatting.getLeftBorderColor());
borderFormatting.setRightBorderColor(HSSFColor.BLUE.index);
assertEquals(HSSFColor.BLUE.index, borderFormatting.getRightBorderColor());
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());
}
public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord");
junit.textui.TestRunner.run(TestCFRuleRecord.class);
}
}

View File

@ -0,0 +1,111 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.aggregates;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
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.cf.CellRange;
/**
* Tests the serialization and deserialization of the CFRecordsAggregate
* class works correctly.
*
* @author Dmitriy Kumshayev
*/
public 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)
{
System.out.println("Testing org.apache.poi.hssf.record.aggregates.CFRecordsAggregate");
junit.textui.TestRunner.run(TestCFRecordsAggregate.class);
}
}

View File

@ -0,0 +1,139 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.cf;
import junit.framework.TestCase;
/**
* Tests CellRange operations.
*/
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);
boolean [][] contanis = new boolean[][]
{
// biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell
/*biggest */ new boolean[]{true, true , true , true , true , true , true},
/*tenthColumn*/ new boolean[]{false, true , false, false, false, false, true},
/*tenthRow */ new boolean[]{false, false, true , false, false, false, true},
/*box10x10 */ new boolean[]{false, false, false, true , true , false, true},
/*box9x9 */ new boolean[]{false, false, false, false, true , false, false},
/*box10to20c */ new boolean[]{false, false, false, false, false, true , true},
/*oneCell */ new boolean[]{false, false, false, false, false, false, true},
} ;
public void testContainsMethod()
{
CellRange [] ranges = new CellRange[]{biggest,tenthColumn,tenthRow,box10x10,box9x9,box10to20c,oneCell};
testContainsMethod(contanis,ranges);
}
private void testContainsMethod(boolean[][]contains,CellRange[] ranges)
{
for(int i=0; i!=ranges.length;i++)
{
for(int j=0; j!=ranges.length;j++)
{
assertEquals("("+i+","+j+"): ",contains[i][j],ranges[i].contains(ranges[j]));
}
}
}
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);
public void testHasSharedBorderMethod()
{
assertFalse(col1.hasSharedBorder(col1));
assertFalse(col2.hasSharedBorder(col2));
assertTrue(col1.hasSharedBorder(col2));
assertTrue(col2.hasSharedBorder(col1));
assertFalse(row1.hasSharedBorder(row1));
assertFalse(row2.hasSharedBorder(row2));
assertTrue(row1.hasSharedBorder(row2));
assertTrue(row2.hasSharedBorder(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(box1.hasSharedBorder(box1));
assertTrue(box1.hasSharedBorder(box2));
assertTrue(box1.hasSharedBorder(box3));
assertFalse(box1.hasSharedBorder(box4));
assertTrue(box2.hasSharedBorder(box1));
assertFalse(box2.hasSharedBorder(box2));
assertFalse(box2.hasSharedBorder(box3));
assertTrue(box2.hasSharedBorder(box4));
assertTrue(box3.hasSharedBorder(box1));
assertFalse(box3.hasSharedBorder(box2));
assertFalse(box3.hasSharedBorder(box3));
assertTrue(box3.hasSharedBorder(box4));
assertFalse(box4.hasSharedBorder(box1));
assertTrue(box4.hasSharedBorder(box2));
assertTrue(box4.hasSharedBorder(box3));
assertFalse(box4.hasSharedBorder(box4));
}
public void testIntersectMethod()
{
assertEquals( CellRange.OVERLAP,box0.intersect(box5));
assertEquals( CellRange.OVERLAP,box5.intersect(box0));
assertEquals(CellRange.NO_INTERSECTION,box1.intersect(box4));
assertEquals(CellRange.NO_INTERSECTION,box4.intersect(box1));
assertEquals(CellRange.NO_INTERSECTION,box2.intersect(box3));
assertEquals(CellRange.NO_INTERSECTION,box3.intersect(box2));
assertEquals(CellRange.INSIDE,box0.intersect(box1));
assertEquals(CellRange.INSIDE,box0.intersect(box0));
assertEquals(CellRange.ENCLOSES,box1.intersect(box0));
assertEquals(CellRange.INSIDE,tenthColumn.intersect(oneCell));
assertEquals(CellRange.ENCLOSES,oneCell.intersect(tenthColumn));
assertEquals(CellRange.OVERLAP,tenthColumn.intersect(tenthRow));
assertEquals(CellRange.OVERLAP,tenthRow.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
}
}