git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690527 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_13_BETA1
/* ==================================================================== | |||||
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.Arrays; | |||||
import org.apache.poi.hssf.record.common.FtrHeader; | |||||
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.LittleEndianOutput; | |||||
/** | |||||
* Conditional Formatting v12 Rule Record (0x087A). | |||||
* | |||||
* <p>This is for newer-style Excel conditional formattings, | |||||
* from Excel 2007 onwards. | |||||
* | |||||
* <p>{@link CFRuleRecord} is used where the condition type is | |||||
* {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA}, | |||||
* this is only used for the other types | |||||
*/ | |||||
public final class CFRule12Record extends CFRuleBase { | |||||
public static final short sid = 0x087A; | |||||
private FtrHeader futureHeader; | |||||
private Formula formulaScale; | |||||
/** Creates new CFRuleRecord */ | |||||
private CFRule12Record(byte conditionType, byte comparisonOperation) { | |||||
super(conditionType, comparisonOperation); | |||||
futureHeader = new FtrHeader(); | |||||
futureHeader.setRecordType(sid); | |||||
// TODO Remaining fields | |||||
} | |||||
private CFRule12Record(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2, Ptg[] formulaScale) { | |||||
super(conditionType, comparisonOperation, formula1, formula2); | |||||
this.formulaScale = Formula.create(formulaScale); | |||||
// TODO Remaining fields | |||||
} | |||||
/** | |||||
* Creates a new comparison operation rule | |||||
*/ | |||||
public static CFRule12Record create(HSSFSheet sheet, String formulaText) { | |||||
Ptg[] formula1 = parseFormula(formulaText, sheet); | |||||
return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, | |||||
formula1, null, null); | |||||
} | |||||
/** | |||||
* Creates a new comparison operation rule | |||||
*/ | |||||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, | |||||
String formulaText1, String formulaText2) { | |||||
Ptg[] formula1 = parseFormula(formulaText1, sheet); | |||||
Ptg[] formula2 = parseFormula(formulaText2, sheet); | |||||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||||
formula1, formula2, null); | |||||
} | |||||
/** | |||||
* Creates a new comparison operation rule | |||||
*/ | |||||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, | |||||
String formulaText1, String formulaText2, String formulaTextScale) { | |||||
Ptg[] formula1 = parseFormula(formulaText1, sheet); | |||||
Ptg[] formula2 = parseFormula(formulaText2, sheet); | |||||
Ptg[] formula3 = parseFormula(formulaTextScale, sheet); | |||||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||||
formula1, formula2, formula3); | |||||
} | |||||
public CFRule12Record(RecordInputStream in) { | |||||
futureHeader = new FtrHeader(in); | |||||
setConditionType(in.readByte()); | |||||
setComparisonOperation(in.readByte()); | |||||
int field_3_formula1_len = in.readUShort(); | |||||
int field_4_formula2_len = in.readUShort(); | |||||
// TODO Handle the remainder | |||||
} | |||||
/** | |||||
* get the stack of the scale expression as a list | |||||
* | |||||
* @return list of tokens (casts stack to a list and returns it!) | |||||
* this method can return null is we are unable to create Ptgs from | |||||
* existing excel file | |||||
* callers should check for null! | |||||
*/ | |||||
public Ptg[] getParsedExpressionScale() { | |||||
return formulaScale.getTokens(); | |||||
} | |||||
public void setParsedExpressionScale(Ptg[] ptgs) { | |||||
formulaScale = Formula.create(ptgs); | |||||
} | |||||
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 out the stream to write to | |||||
*/ | |||||
public void serialize(LittleEndianOutput out) { | |||||
futureHeader.serialize(out); | |||||
int formula1Len=getFormulaSize(getFormula1()); | |||||
int formula2Len=getFormulaSize(getFormula2()); | |||||
out.writeByte(getConditionType()); | |||||
out.writeByte(getComparisonOperation()); | |||||
out.writeShort(formula1Len); | |||||
out.writeShort(formula2Len); | |||||
// TODO Output the rest | |||||
} | |||||
protected int getDataSize() { | |||||
// TODO Calculate | |||||
return 0; | |||||
} | |||||
public String toString() { | |||||
StringBuffer buffer = new StringBuffer(); | |||||
buffer.append("[CFRULE12]\n"); | |||||
buffer.append(" .condition_type =").append(getConditionType()).append("\n"); | |||||
buffer.append(" TODO The rest!\n"); | |||||
buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n"); | |||||
buffer.append(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n"); | |||||
buffer.append(" Formula S =").append(Arrays.toString(formulaScale.getTokens())).append("\n"); | |||||
buffer.append("[/CFRULE12]\n"); | |||||
return buffer.toString(); | |||||
} | |||||
public Object clone() { | |||||
CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation()); | |||||
// TODO The other fields | |||||
rec.setFormula1(getFormula1().copy()); | |||||
rec.setFormula2(getFormula2().copy()); | |||||
rec.formulaScale = formulaScale.copy(); | |||||
return rec; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 org.apache.poi.hssf.model.HSSFFormulaParser; | |||||
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; | |||||
/** | |||||
* Conditional Formatting Rules. This can hold old-style rules | |||||
* | |||||
* | |||||
* <p>This is for the older-style Excel conditional formattings, | |||||
* new-style (Excel 2007+) also make use of {@link CFRule12Record} | |||||
* and {@link CFExRuleRecord} for their rules. | |||||
*/ | |||||
public abstract class CFRuleBase extends StandardRecord { | |||||
public static final class ComparisonOperator { | |||||
public static final byte NO_COMPARISON = 0; | |||||
public static final byte BETWEEN = 1; | |||||
public static final byte NOT_BETWEEN = 2; | |||||
public static final byte EQUAL = 3; | |||||
public static final byte NOT_EQUAL = 4; | |||||
public static final byte GT = 5; | |||||
public static final byte LT = 6; | |||||
public static final byte GE = 7; | |||||
public static final byte LE = 8; | |||||
private static final byte max_operator = 8; | |||||
} | |||||
private byte condition_type; | |||||
// The only kinds that CFRuleRecord handles | |||||
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; | |||||
public static final byte CONDITION_TYPE_FORMULA = 2; | |||||
// These are CFRule12Rule only | |||||
public static final byte CONDITION_TYPE_COLOR_SCALE = 3; | |||||
public static final byte CONDITION_TYPE_DATA_BAR = 4; | |||||
public static final byte CONDITION_TYPE_FILTER = 5; | |||||
public static final byte CONDITION_TYPE_ICON_SET = 6; | |||||
private byte comparison_operator; | |||||
private Formula formula1; | |||||
private Formula formula2; | |||||
/** Creates new CFRuleRecord */ | |||||
protected CFRuleBase(byte conditionType, byte comparisonOperation) { | |||||
setConditionType(conditionType); | |||||
setComparisonOperation(comparisonOperation); | |||||
formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||||
formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||||
} | |||||
protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { | |||||
this(conditionType, comparisonOperation); | |||||
this.formula1 = Formula.create(formula1); | |||||
this.formula2 = Formula.create(formula2); | |||||
} | |||||
protected CFRuleBase() {} | |||||
public byte getConditionType() { | |||||
return condition_type; | |||||
} | |||||
protected void setConditionType(byte condition_type) { | |||||
if ((this instanceof CFRuleRecord)) { | |||||
if (condition_type == CONDITION_TYPE_CELL_VALUE_IS || | |||||
condition_type == CONDITION_TYPE_FORMULA) { | |||||
// Good, valid combination | |||||
} else { | |||||
throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types"); | |||||
} | |||||
} | |||||
this.condition_type = condition_type; | |||||
} | |||||
public void setComparisonOperation(byte operation) { | |||||
if (operation < 0 || operation > ComparisonOperator.max_operator) | |||||
throw new IllegalArgumentException( | |||||
"Valid operators are only in the range 0 to " +ComparisonOperator.max_operator); | |||||
this.comparison_operator = operation; | |||||
} | |||||
public byte getComparisonOperation() { | |||||
return comparison_operator; | |||||
} | |||||
/** | |||||
* get the stack of the 1st expression as a list | |||||
* | |||||
* @return list of tokens (casts stack to a list and returns it!) | |||||
* this method can return null is we are unable to create Ptgs from | |||||
* existing excel file | |||||
* callers should check for null! | |||||
*/ | |||||
public Ptg[] getParsedExpression1() { | |||||
return formula1.getTokens(); | |||||
} | |||||
public void setParsedExpression1(Ptg[] ptgs) { | |||||
formula1 = Formula.create(ptgs); | |||||
} | |||||
protected Formula getFormula1() { | |||||
return formula1; | |||||
} | |||||
protected void setFormula1(Formula formula1) { | |||||
this.formula1 = formula1; | |||||
} | |||||
/** | |||||
* get the stack of the 2nd expression as a list | |||||
* | |||||
* @return array of {@link Ptg}s, possibly <code>null</code> | |||||
*/ | |||||
public Ptg[] getParsedExpression2() { | |||||
return Formula.getTokens(formula2); | |||||
} | |||||
public void setParsedExpression2(Ptg[] ptgs) { | |||||
formula2 = Formula.create(ptgs); | |||||
} | |||||
protected Formula getFormula2() { | |||||
return formula2; | |||||
} | |||||
protected void setFormula2(Formula formula2) { | |||||
this.formula2 = formula2; | |||||
} | |||||
/** | |||||
* @param ptgs must not be <code>null</code> | |||||
* @return encoded size of the formula tokens (does not include 2 bytes for ushort length) | |||||
*/ | |||||
protected static int getFormulaSize(Formula formula) { | |||||
return formula.getEncodedTokenSize(); | |||||
} | |||||
/** | |||||
* TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea | |||||
* this call will produce the wrong results if the formula contains any cell references | |||||
* One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int) | |||||
* Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects. | |||||
* | |||||
* @return <code>null</code> if <tt>formula</tt> was null. | |||||
*/ | |||||
protected static Ptg[] parseFormula(String formula, HSSFSheet sheet) { | |||||
if(formula == null) { | |||||
return null; | |||||
} | |||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); | |||||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); | |||||
} | |||||
} |
import java.util.Arrays; | import java.util.Arrays; | ||||
import org.apache.poi.hssf.model.HSSFFormulaParser; | |||||
import org.apache.poi.hssf.record.cf.BorderFormatting; | import org.apache.poi.hssf.record.cf.BorderFormatting; | ||||
import org.apache.poi.hssf.record.cf.FontFormatting; | import org.apache.poi.hssf.record.cf.FontFormatting; | ||||
import org.apache.poi.hssf.record.cf.PatternFormatting; | import org.apache.poi.hssf.record.cf.PatternFormatting; | ||||
import org.apache.poi.hssf.usermodel.HSSFSheet; | import org.apache.poi.hssf.usermodel.HSSFSheet; | ||||
import org.apache.poi.ss.formula.Formula; | 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.ss.formula.ptg.Ptg; | ||||
import org.apache.poi.util.BitField; | import org.apache.poi.util.BitField; | ||||
import org.apache.poi.util.BitFieldFactory; | import org.apache.poi.util.BitFieldFactory; | ||||
* new-style (Excel 2007+) also make use of {@link CFRule12Record} | * new-style (Excel 2007+) also make use of {@link CFRule12Record} | ||||
* and {@link CFExRuleRecord} for their rules. | * and {@link CFExRuleRecord} for their rules. | ||||
*/ | */ | ||||
public final class CFRuleRecord extends StandardRecord { | |||||
public final class CFRuleRecord extends CFRuleBase { | |||||
public static final short sid = 0x01B1; | public static final short sid = 0x01B1; | ||||
public static final class ComparisonOperator { | |||||
public static final byte NO_COMPARISON = 0; | |||||
public static final byte BETWEEN = 1; | |||||
public static final byte NOT_BETWEEN = 2; | |||||
public static final byte EQUAL = 3; | |||||
public static final byte NOT_EQUAL = 4; | |||||
public static final byte GT = 5; | |||||
public static final byte LT = 6; | |||||
public static final byte GE = 7; | |||||
public static final byte LE = 8; | |||||
} | |||||
private byte field_1_condition_type; | |||||
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; | |||||
public static final byte CONDITION_TYPE_FORMULA = 2; | |||||
private byte field_2_comparison_operator; | |||||
private int field_5_options; | |||||
private int field_5_options; | |||||
private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot | 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 alignHor = bf(0x00000001); // 0 = Horizontal alignment modified | ||||
private PatternFormatting _patternFormatting; | private PatternFormatting _patternFormatting; | ||||
private Formula field_17_formula1; | |||||
private Formula field_18_formula2; | |||||
/** Creates new CFRuleRecord */ | /** Creates new CFRuleRecord */ | ||||
private CFRuleRecord(byte conditionType, byte comparisonOperation) | |||||
{ | |||||
field_1_condition_type=conditionType; | |||||
field_2_comparison_operator=comparisonOperation; | |||||
private CFRuleRecord(byte conditionType, byte comparisonOperation) { | |||||
super(conditionType, comparisonOperation); | |||||
setDefaults(); | |||||
} | |||||
private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { | |||||
super(conditionType, comparisonOperation, formula1, formula2); | |||||
setDefaults(); | |||||
} | |||||
private void setDefaults() { | |||||
// Set modification flags to 1: by default options are not modified | // Set modification flags to 1: by default options are not modified | ||||
field_5_options = modificationBits.setValue(field_5_options, -1); | field_5_options = modificationBits.setValue(field_5_options, -1); | ||||
// Set formatting block flags to 0 (no formatting blocks) | // Set formatting block flags to 0 (no formatting blocks) | ||||
_fontFormatting=null; | _fontFormatting=null; | ||||
_borderFormatting=null; | _borderFormatting=null; | ||||
_patternFormatting=null; | _patternFormatting=null; | ||||
field_17_formula1=Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||||
field_18_formula2=Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||||
} | |||||
private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { | |||||
this(conditionType, comparisonOperation); | |||||
field_17_formula1 = Formula.create(formula1); | |||||
field_18_formula2 = Formula.create(formula2); | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
public CFRuleRecord(RecordInputStream in) { | public CFRuleRecord(RecordInputStream in) { | ||||
field_1_condition_type = in.readByte(); | |||||
field_2_comparison_operator = in.readByte(); | |||||
setConditionType(in.readByte()); | |||||
setComparisonOperation(in.readByte()); | |||||
int field_3_formula1_len = in.readUShort(); | int field_3_formula1_len = in.readUShort(); | ||||
int field_4_formula2_len = in.readUShort(); | int field_4_formula2_len = in.readUShort(); | ||||
field_5_options = in.readInt(); | field_5_options = in.readInt(); | ||||
} | } | ||||
// "You may not use unions, intersections or array constants in Conditional Formatting criteria" | // "You may not use unions, intersections or array constants in Conditional Formatting criteria" | ||||
field_17_formula1 = Formula.read(field_3_formula1_len, in); | |||||
field_18_formula2 = Formula.read(field_4_formula2_len, in); | |||||
} | |||||
public byte getConditionType() { | |||||
return field_1_condition_type; | |||||
setFormula1(Formula.read(field_3_formula1_len, in)); | |||||
setFormula2(Formula.read(field_4_formula2_len, in)); | |||||
} | } | ||||
public boolean containsFontFormattingBlock() { | public boolean containsFontFormattingBlock() { | ||||
setOptionFlag(false,prot); | setOptionFlag(false,prot); | ||||
} | } | ||||
public void setComparisonOperation(byte operation) { | |||||
field_2_comparison_operator = operation; | |||||
} | |||||
public byte getComparisonOperation() { | |||||
return field_2_comparison_operator; | |||||
} | |||||
/** | /** | ||||
* get the option flags | * get the option flags | ||||
* | * | ||||
field_5_options = field.setBoolean(field_5_options, flag); | 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 Ptg[] getParsedExpression1() { | |||||
return field_17_formula1.getTokens(); | |||||
} | |||||
public void setParsedExpression1(Ptg[] ptgs) { | |||||
field_17_formula1 = Formula.create(ptgs); | |||||
} | |||||
/** | |||||
* get the stack of the 2nd expression as a list | |||||
* | |||||
* @return array of {@link Ptg}s, possibly <code>null</code> | |||||
*/ | |||||
public Ptg[] getParsedExpression2() { | |||||
return Formula.getTokens(field_18_formula2); | |||||
} | |||||
public void setParsedExpression2(Ptg[] ptgs) { | |||||
field_18_formula2 = Formula.create(ptgs); | |||||
} | |||||
public short getSid() { | public short getSid() { | ||||
return sid; | return sid; | ||||
} | } | ||||
/** | |||||
* @param ptgs must not be <code>null</code> | |||||
* @return encoded size of the formula tokens (does not include 2 bytes for ushort length) | |||||
*/ | |||||
private static int getFormulaSize(Formula formula) { | |||||
return formula.getEncodedTokenSize(); | |||||
} | |||||
/** | /** | ||||
* called by the class that is responsible for writing this sucker. | * called by the class that is responsible for writing this sucker. | ||||
* Subclasses should implement this so that their data is passed back in a | * Subclasses should implement this so that their data is passed back in a | ||||
* @param out the stream to write to | * @param out the stream to write to | ||||
*/ | */ | ||||
public void serialize(LittleEndianOutput out) { | public void serialize(LittleEndianOutput out) { | ||||
int formula1Len=getFormulaSize(field_17_formula1); | |||||
int formula2Len=getFormulaSize(field_18_formula2); | |||||
int formula1Len=getFormulaSize(getFormula1()); | |||||
int formula2Len=getFormulaSize(getFormula2()); | |||||
out.writeByte(field_1_condition_type); | |||||
out.writeByte(field_2_comparison_operator); | |||||
out.writeByte(getConditionType()); | |||||
out.writeByte(getComparisonOperation()); | |||||
out.writeShort(formula1Len); | out.writeShort(formula1Len); | ||||
out.writeShort(formula2Len); | out.writeShort(formula2Len); | ||||
out.writeInt(field_5_options); | out.writeInt(field_5_options); | ||||
_patternFormatting.serialize(out); | _patternFormatting.serialize(out); | ||||
} | } | ||||
field_17_formula1.serializeTokens(out); | |||||
field_18_formula2.serializeTokens(out); | |||||
getFormula1().serializeTokens(out); | |||||
getFormula2().serializeTokens(out); | |||||
} | } | ||||
protected int getDataSize() { | protected int getDataSize() { | ||||
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ | (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ | ||||
(containsBorderFormattingBlock()?8:0)+ | (containsBorderFormattingBlock()?8:0)+ | ||||
(containsPatternFormattingBlock()?4:0)+ | (containsPatternFormattingBlock()?4:0)+ | ||||
getFormulaSize(field_17_formula1)+ | |||||
getFormulaSize(field_18_formula2); | |||||
getFormulaSize(getFormula1())+ | |||||
getFormulaSize(getFormula2()); | |||||
return i; | return i; | ||||
} | } | ||||
public String toString() { | public String toString() { | ||||
StringBuffer buffer = new StringBuffer(); | StringBuffer buffer = new StringBuffer(); | ||||
buffer.append("[CFRULE]\n"); | buffer.append("[CFRULE]\n"); | ||||
buffer.append(" .condition_type =").append(field_1_condition_type).append("\n"); | |||||
buffer.append(" .condition_type =").append(getConditionType()).append("\n"); | |||||
buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n"); | buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n"); | ||||
if (containsFontFormattingBlock()) { | if (containsFontFormattingBlock()) { | ||||
buffer.append(_fontFormatting.toString()).append("\n"); | buffer.append(_fontFormatting.toString()).append("\n"); | ||||
if (containsPatternFormattingBlock()) { | if (containsPatternFormattingBlock()) { | ||||
buffer.append(_patternFormatting.toString()).append("\n"); | buffer.append(_patternFormatting.toString()).append("\n"); | ||||
} | } | ||||
buffer.append(" Formula 1 =").append(Arrays.toString(field_17_formula1.getTokens())).append("\n"); | |||||
buffer.append(" Formula 2 =").append(Arrays.toString(field_18_formula2.getTokens())).append("\n"); | |||||
buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n"); | |||||
buffer.append(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n"); | |||||
buffer.append("[/CFRULE]\n"); | buffer.append("[/CFRULE]\n"); | ||||
return buffer.toString(); | return buffer.toString(); | ||||
} | } | ||||
public Object clone() { | public Object clone() { | ||||
CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator); | |||||
CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); | |||||
rec.field_5_options = field_5_options; | rec.field_5_options = field_5_options; | ||||
rec.field_6_not_used = field_6_not_used; | rec.field_6_not_used = field_6_not_used; | ||||
if (containsFontFormattingBlock()) { | if (containsFontFormattingBlock()) { | ||||
if (containsPatternFormattingBlock()) { | if (containsPatternFormattingBlock()) { | ||||
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); | rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); | ||||
} | } | ||||
rec.field_17_formula1 = field_17_formula1.copy(); | |||||
rec.field_18_formula2 = field_18_formula2.copy(); | |||||
rec.setFormula1(getFormula1().copy()); | |||||
rec.setFormula2(getFormula2().copy()); | |||||
return rec; | return rec; | ||||
} | } | ||||
/** | |||||
* TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea | |||||
* this call will produce the wrong results if the formula contains any cell references | |||||
* One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int) | |||||
* Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects. | |||||
* | |||||
* @return <code>null</code> if <tt>formula</tt> was null. | |||||
*/ | |||||
private static Ptg[] parseFormula(String formula, HSSFSheet sheet) { | |||||
if(formula == null) { | |||||
return null; | |||||
} | |||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); | |||||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); | |||||
} | |||||
} | } |
package org.apache.poi.hssf.usermodel; | package org.apache.poi.hssf.usermodel; | ||||
import org.apache.poi.hssf.model.HSSFFormulaParser; | import org.apache.poi.hssf.model.HSSFFormulaParser; | ||||
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; | |||||
import org.apache.poi.hssf.record.CFRuleRecord; | import org.apache.poi.hssf.record.CFRuleRecord; | ||||
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; | |||||
import org.apache.poi.hssf.record.cf.BorderFormatting; | import org.apache.poi.hssf.record.cf.BorderFormatting; | ||||
import org.apache.poi.hssf.record.cf.FontFormatting; | import org.apache.poi.hssf.record.cf.FontFormatting; | ||||
import org.apache.poi.hssf.record.cf.PatternFormatting; | import org.apache.poi.hssf.record.cf.PatternFormatting; |
import junit.framework.AssertionFailedError; | import junit.framework.AssertionFailedError; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; | |||||
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; | |||||
import org.apache.poi.hssf.record.cf.BorderFormatting; | import org.apache.poi.hssf.record.cf.BorderFormatting; | ||||
import org.apache.poi.hssf.record.cf.FontFormatting; | import org.apache.poi.hssf.record.cf.FontFormatting; | ||||
import org.apache.poi.hssf.record.cf.PatternFormatting; | import org.apache.poi.hssf.record.cf.PatternFormatting; | ||||
/** | /** | ||||
* Tests the serialization and deserialization of the TestCFRuleRecord | * Tests the serialization and deserialization of the TestCFRuleRecord | ||||
* class works correctly. | * class works correctly. | ||||
* | |||||
* @author Dmitriy Kumshayev | |||||
* TODO Add {@link CFRule12Record} tests | |||||
*/ | */ | ||||
public final class TestCFRuleRecord extends TestCase { | public final class TestCFRuleRecord extends TestCase { | ||||
public void testConstructors () { | public void testConstructors () { |
import org.apache.poi.hssf.model.RecordStream; | import org.apache.poi.hssf.model.RecordStream; | ||||
import org.apache.poi.hssf.record.CFHeaderRecord; | import org.apache.poi.hssf.record.CFHeaderRecord; | ||||
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; | |||||
import org.apache.poi.hssf.record.CFRuleRecord; | import org.apache.poi.hssf.record.CFRuleRecord; | ||||
import org.apache.poi.hssf.record.RecordFactory; | import org.apache.poi.hssf.record.RecordFactory; | ||||
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; | |||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||||
import org.apache.poi.hssf.usermodel.HSSFSheet; | import org.apache.poi.hssf.usermodel.HSSFSheet; | ||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||||
import org.apache.poi.ss.util.CellRangeAddress; | import org.apache.poi.ss.util.CellRangeAddress; | ||||
import org.apache.poi.util.LittleEndian; | import org.apache.poi.util.LittleEndian; | ||||