Refactor some of the CFRuleRecord logic out to CFRuleBase, and begin work on CFRule12Record #58130
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690527 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2610a29c28
commit
a904047399
166
src/java/org/apache/poi/hssf/record/CFRule12Record.java
Normal file
166
src/java/org/apache/poi/hssf/record/CFRule12Record.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
165
src/java/org/apache/poi/hssf/record/CFRuleBase.java
Normal file
165
src/java/org/apache/poi/hssf/record/CFRuleBase.java
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -19,13 +19,11 @@ package org.apache.poi.hssf.record;
|
|||||||
|
|
||||||
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;
|
||||||
@ -38,27 +36,9 @@ import org.apache.poi.util.LittleEndianOutput;
|
|||||||
* 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
|
||||||
@ -104,15 +84,17 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
|
|
||||||
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)
|
private CFRuleRecord(byte conditionType, byte comparisonOperation) {
|
||||||
{
|
super(conditionType, comparisonOperation);
|
||||||
field_1_condition_type=conditionType;
|
setDefaults();
|
||||||
field_2_comparison_operator=comparisonOperation;
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
@ -123,14 +105,6 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,8 +126,8 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CFRuleRecord(RecordInputStream in) {
|
public CFRuleRecord(RecordInputStream in) {
|
||||||
field_1_condition_type = in.readByte();
|
setConditionType(in.readByte());
|
||||||
field_2_comparison_operator = 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();
|
||||||
@ -172,12 +146,8 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "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);
|
setFormula1(Formula.read(field_3_formula1_len, in));
|
||||||
field_18_formula2 = Formula.read(field_4_formula2_len, in);
|
setFormula2(Formula.read(field_4_formula2_len, in));
|
||||||
}
|
|
||||||
|
|
||||||
public byte getConditionType() {
|
|
||||||
return field_1_condition_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsFontFormattingBlock() {
|
public boolean containsFontFormattingBlock() {
|
||||||
@ -237,13 +207,6 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
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
|
||||||
*
|
*
|
||||||
@ -331,45 +294,10 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
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
|
||||||
@ -378,11 +306,11 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
* @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 formula1Len=getFormulaSize(getFormula1());
|
||||||
int formula2Len=getFormulaSize(field_18_formula2);
|
int formula2Len=getFormulaSize(getFormula2());
|
||||||
|
|
||||||
out.writeByte(field_1_condition_type);
|
out.writeByte(getConditionType());
|
||||||
out.writeByte(field_2_comparison_operator);
|
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);
|
||||||
@ -401,8 +329,8 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
_patternFormatting.serialize(out);
|
_patternFormatting.serialize(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
field_17_formula1.serializeTokens(out);
|
getFormula1().serializeTokens(out);
|
||||||
field_18_formula2.serializeTokens(out);
|
getFormula2().serializeTokens(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
@ -410,15 +338,15 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
(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(getFormula1())+
|
||||||
getFormulaSize(field_18_formula2);
|
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");
|
||||||
@ -429,14 +357,14 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
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 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n");
|
||||||
buffer.append(" Formula 2 =").append(Arrays.toString(field_18_formula2.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()) {
|
||||||
@ -448,25 +376,9 @@ public final class CFRuleRecord extends StandardRecord {
|
|||||||
if (containsPatternFormattingBlock()) {
|
if (containsPatternFormattingBlock()) {
|
||||||
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone();
|
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone();
|
||||||
}
|
}
|
||||||
rec.field_17_formula1 = field_17_formula1.copy();
|
rec.setFormula1(getFormula1().copy());
|
||||||
rec.field_18_formula2 = field_18_formula2.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
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;
|
||||||
|
@ -21,7 +21,7 @@ import static org.junit.Assert.assertArrayEquals;
|
|||||||
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;
|
||||||
@ -36,8 +36,7 @@ import org.apache.poi.util.LittleEndian;
|
|||||||
/**
|
/**
|
||||||
* Tests the serialization and deserialization of the TestCFRuleRecord
|
* Tests the serialization and deserialization of the TestCFRuleRecord
|
||||||
* class works correctly.
|
* class works correctly.
|
||||||
*
|
* TODO Add {@link CFRule12Record} tests
|
||||||
* @author Dmitriy Kumshayev
|
|
||||||
*/
|
*/
|
||||||
public final class TestCFRuleRecord extends TestCase {
|
public final class TestCFRuleRecord extends TestCase {
|
||||||
public void testConstructors () {
|
public void testConstructors () {
|
||||||
|
@ -27,11 +27,11 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user