git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690686 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_13_BETA1
@@ -154,11 +154,10 @@ public final class CFRule12Record extends CFRuleBase { | |||
public Object clone() { | |||
CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation()); | |||
super.copyTo(rec); | |||
// TODO The other fields | |||
rec.setFormula1(getFormula1().copy()); | |||
rec.setFormula2(getFormula2().copy()); | |||
rec.formulaScale = formulaScale.copy(); | |||
return rec; |
@@ -18,10 +18,15 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.hssf.model.HSSFFormulaParser; | |||
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.usermodel.HSSFSheet; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.FormulaType; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
/** | |||
* Conditional Formatting Rules. This can hold old-style rules | |||
@@ -85,6 +90,47 @@ public abstract class CFRuleBase extends StandardRecord { | |||
public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D; | |||
public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E; | |||
static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot | |||
static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified | |||
static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified | |||
static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified | |||
static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified | |||
static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified | |||
static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified | |||
static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified | |||
static final BitField notUsed1 = bf(0x00000080); // Always 1 | |||
static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified | |||
static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified | |||
static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified | |||
static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified | |||
static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified | |||
static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified | |||
static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified | |||
static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified | |||
static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified | |||
static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified | |||
static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified | |||
static final BitField notUsed2 = bf(0x00380000); // Always 111 | |||
static final BitField undocumented = bf(0x03C00000); // Undocumented bits | |||
static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot | |||
static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block | |||
static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block | |||
static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block | |||
static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block | |||
static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block | |||
static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified | |||
private static BitField bf(int i) { | |||
return BitFieldFactory.getInstance(i); | |||
} | |||
protected int field_5_options; // TODO Rename me | |||
protected short field_6_not_used; // TODO Rename me | |||
protected FontFormatting _fontFormatting; | |||
protected BorderFormatting _borderFormatting; | |||
protected PatternFormatting _patternFormatting; | |||
private Formula formula1; | |||
private Formula formula2; | |||
@@ -101,6 +147,30 @@ public abstract class CFRuleBase extends StandardRecord { | |||
this.formula2 = Formula.create(formula2); | |||
} | |||
protected CFRuleBase() {} | |||
protected int readFormatOptions(RecordInputStream in) { | |||
field_5_options = in.readInt(); | |||
field_6_not_used = in.readShort(); | |||
int len = 6; | |||
if (containsFontFormattingBlock()) { | |||
_fontFormatting = new FontFormatting(in); | |||
len += _fontFormatting.getDataLength(); | |||
} | |||
if (containsBorderFormattingBlock()) { | |||
_borderFormatting = new BorderFormatting(in); | |||
len += _borderFormatting.getDataLength(); | |||
} | |||
if (containsPatternFormattingBlock()) { | |||
_patternFormatting = new PatternFormatting(in); | |||
len += _patternFormatting.getDataLength(); | |||
} | |||
return len; | |||
} | |||
public byte getConditionType() { | |||
return condition_type; | |||
@@ -128,6 +198,150 @@ public abstract class CFRuleBase extends StandardRecord { | |||
return comparison_operator; | |||
} | |||
public boolean containsFontFormattingBlock() { | |||
return getOptionFlag(font); | |||
} | |||
public void setFontFormatting(FontFormatting fontFormatting) { | |||
_fontFormatting = fontFormatting; | |||
setOptionFlag(fontFormatting != null, font); | |||
} | |||
public FontFormatting getFontFormatting() { | |||
if( containsFontFormattingBlock()) { | |||
return _fontFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsAlignFormattingBlock() { | |||
return getOptionFlag(align); | |||
} | |||
public void setAlignFormattingUnchanged() { | |||
setOptionFlag(false,align); | |||
} | |||
public boolean containsBorderFormattingBlock() { | |||
return getOptionFlag(bord); | |||
} | |||
public void setBorderFormatting(BorderFormatting borderFormatting) { | |||
_borderFormatting = borderFormatting; | |||
setOptionFlag(borderFormatting != null, bord); | |||
} | |||
public BorderFormatting getBorderFormatting() { | |||
if( containsBorderFormattingBlock()) { | |||
return _borderFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsPatternFormattingBlock() { | |||
return getOptionFlag(patt); | |||
} | |||
public void setPatternFormatting(PatternFormatting patternFormatting) { | |||
_patternFormatting = patternFormatting; | |||
setOptionFlag(patternFormatting!=null, patt); | |||
} | |||
public PatternFormatting getPatternFormatting() { | |||
if( containsPatternFormattingBlock()) | |||
{ | |||
return _patternFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsProtectionFormattingBlock() { | |||
return getOptionFlag(prot); | |||
} | |||
public void setProtectionFormattingUnchanged() { | |||
setOptionFlag(false,prot); | |||
} | |||
/** | |||
* 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 | |||
* | |||
@@ -190,4 +404,24 @@ public abstract class CFRuleBase extends StandardRecord { | |||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); | |||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); | |||
} | |||
protected void copyTo(CFRuleBase rec) { | |||
rec.condition_type = condition_type; | |||
rec.comparison_operator = comparison_operator; | |||
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(); | |||
} | |||
rec.setFormula1(getFormula1().copy()); | |||
rec.setFormula2(getFormula2().copy()); | |||
} | |||
} |
@@ -19,14 +19,9 @@ package org.apache.poi.hssf.record; | |||
import java.util.Arrays; | |||
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.usermodel.HSSFSheet; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
@@ -39,51 +34,6 @@ import org.apache.poi.util.LittleEndianOutput; | |||
public final class CFRuleRecord extends CFRuleBase { | |||
public static final short sid = 0x01B1; | |||
private int field_5_options; | |||
private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot | |||
private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified | |||
private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified | |||
private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified | |||
private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified | |||
private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified | |||
private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified | |||
private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified | |||
private static final BitField notUsed1 = bf(0x00000080); // Always 1 | |||
private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified | |||
private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified | |||
private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified | |||
private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified | |||
private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified | |||
private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified | |||
private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified | |||
private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified | |||
private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified | |||
private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified | |||
private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified | |||
private static final BitField notUsed2 = bf(0x00380000); // Always 111 | |||
private static final BitField undocumented = bf(0x03C00000); // Undocumented bits | |||
private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot | |||
private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block | |||
private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block | |||
private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block | |||
private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block | |||
private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block | |||
private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified | |||
private static BitField bf(int i) { | |||
return BitFieldFactory.getInstance(i); | |||
} | |||
private short field_6_not_used; | |||
private FontFormatting _fontFormatting; | |||
private BorderFormatting _borderFormatting; | |||
private PatternFormatting _patternFormatting; | |||
/** Creates new CFRuleRecord */ | |||
private CFRuleRecord(byte conditionType, byte comparisonOperation) { | |||
super(conditionType, comparisonOperation); | |||
@@ -102,9 +52,9 @@ public final class CFRuleRecord extends CFRuleBase { | |||
field_5_options = undocumented.clear(field_5_options); | |||
field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads | |||
_fontFormatting=null; | |||
_borderFormatting=null; | |||
_patternFormatting=null; | |||
_fontFormatting = null; | |||
_borderFormatting = null; | |||
_patternFormatting = null; | |||
} | |||
/** | |||
@@ -130,170 +80,13 @@ public final class CFRuleRecord extends CFRuleBase { | |||
setComparisonOperation(in.readByte()); | |||
int field_3_formula1_len = in.readUShort(); | |||
int field_4_formula2_len = in.readUShort(); | |||
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); | |||
} | |||
readFormatOptions(in); | |||
// "You may not use unions, intersections or array constants in Conditional Formatting criteria" | |||
setFormula1(Formula.read(field_3_formula1_len, in)); | |||
setFormula2(Formula.read(field_4_formula2_len, in)); | |||
} | |||
public boolean containsFontFormattingBlock() { | |||
return getOptionFlag(font); | |||
} | |||
public void setFontFormatting(FontFormatting fontFormatting) { | |||
_fontFormatting = fontFormatting; | |||
setOptionFlag(fontFormatting != null, font); | |||
} | |||
public FontFormatting getFontFormatting() { | |||
if( containsFontFormattingBlock()) { | |||
return _fontFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsAlignFormattingBlock() { | |||
return getOptionFlag(align); | |||
} | |||
public void setAlignFormattingUnchanged() { | |||
setOptionFlag(false,align); | |||
} | |||
public boolean containsBorderFormattingBlock() { | |||
return getOptionFlag(bord); | |||
} | |||
public void setBorderFormatting(BorderFormatting borderFormatting) { | |||
_borderFormatting = borderFormatting; | |||
setOptionFlag(borderFormatting != null, bord); | |||
} | |||
public BorderFormatting getBorderFormatting() { | |||
if( containsBorderFormattingBlock()) { | |||
return _borderFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsPatternFormattingBlock() { | |||
return getOptionFlag(patt); | |||
} | |||
public void setPatternFormatting(PatternFormatting patternFormatting) { | |||
_patternFormatting = patternFormatting; | |||
setOptionFlag(patternFormatting!=null, patt); | |||
} | |||
public PatternFormatting getPatternFormatting() { | |||
if( containsPatternFormattingBlock()) | |||
{ | |||
return _patternFormatting; | |||
} | |||
return null; | |||
} | |||
public boolean containsProtectionFormattingBlock() { | |||
return getOptionFlag(prot); | |||
} | |||
public void setProtectionFormattingUnchanged() { | |||
setOptionFlag(false,prot); | |||
} | |||
/** | |||
* 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); | |||
} | |||
public short getSid() { | |||
return sid; | |||
} | |||
@@ -365,20 +158,7 @@ public final class CFRuleRecord extends CFRuleBase { | |||
public Object clone() { | |||
CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); | |||
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(); | |||
} | |||
rec.setFormula1(getFormula1().copy()); | |||
rec.setFormula2(getFormula2().copy()); | |||
super.copyTo(rec); | |||
return rec; | |||
} | |||
} |
@@ -38,7 +38,7 @@ import org.apache.poi.util.POILogger; | |||
* <p>Note that Excel versions before 2007 can only cope with a maximum of 3 | |||
* Conditional Formatting rules per sheet. Excel 2007 or newer can cope with | |||
* unlimited numbers, as can Apache OpenOffice. This is an Excel limitation, | |||
* not a file format one.</p> | |||
* not a file format one.</p> | |||
*/ | |||
public final class CFRecordsAggregate extends RecordAggregate { | |||
/** Excel 97-2003 allows up to 3 conditional formating rules */ |
@@ -89,6 +89,9 @@ public final class BorderFormatting { | |||
field_14_border_styles2 = in.readInt(); | |||
} | |||
public int getDataLength() { | |||
return 8; | |||
} | |||
/** | |||
* set the type of border to use for the left border of the cell |
@@ -149,6 +149,10 @@ public final class FontFormatting | |||
{ | |||
return _rawData; | |||
} | |||
public int getDataLength() { | |||
return RAW_DATA_SIZE; | |||
} | |||
/** | |||
* sets the height of the font in 1/20th point units |
@@ -89,6 +89,10 @@ public final class PatternFormatting implements Cloneable { | |||
field_16_pattern_color_indexes = in.readUShort(); | |||
} | |||
public int getDataLength() { | |||
return 4; | |||
} | |||
/** | |||
* setting fill pattern | |||
* |
@@ -78,6 +78,9 @@ public final class HSSFConditionalFormatting implements ConditionalFormatting | |||
private final HSSFWorkbook _workbook; | |||
private final CFRecordsAggregate cfAggregate; | |||
// TODO Should this be assigning unique IDs to the rules | |||
// as they get added to the file? | |||
HSSFConditionalFormatting(HSSFWorkbook workbook, CFRecordsAggregate cfAggregate) | |||
{ | |||
if(workbook == null) { |