Further CFRule12 parsing
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690742 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
363a2723c3
commit
c723be5dad
@ -24,6 +24,7 @@ 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.ptg.Ptg;
|
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||||
import org.apache.poi.util.LittleEndianOutput;
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conditional Formatting v12 Rule Record (0x087A).
|
* Conditional Formatting v12 Rule Record (0x087A).
|
||||||
@ -39,20 +40,46 @@ public final class CFRule12Record extends CFRuleBase {
|
|||||||
public static final short sid = 0x087A;
|
public static final short sid = 0x087A;
|
||||||
|
|
||||||
private FtrHeader futureHeader;
|
private FtrHeader futureHeader;
|
||||||
private Formula formulaScale;
|
private int ext_formatting_length;
|
||||||
|
private byte[] ext_formatting_data;
|
||||||
|
private Formula formula_scale;
|
||||||
|
private byte ext_opts;
|
||||||
|
private int priority;
|
||||||
|
private int template_type;
|
||||||
|
private byte template_param_length;
|
||||||
|
private byte[] template_params;
|
||||||
|
|
||||||
|
// TODO Parse these
|
||||||
|
private byte[] gradient_data;
|
||||||
|
private byte[] databar_data;
|
||||||
|
private byte[] filter_data;
|
||||||
|
private byte[] multistate_data;
|
||||||
|
|
||||||
/** Creates new CFRuleRecord */
|
/** Creates new CFRuleRecord */
|
||||||
private CFRule12Record(byte conditionType, byte comparisonOperation) {
|
private CFRule12Record(byte conditionType, byte comparisonOperation) {
|
||||||
super(conditionType, comparisonOperation);
|
super(conditionType, comparisonOperation);
|
||||||
futureHeader = new FtrHeader();
|
setDefaults();
|
||||||
futureHeader.setRecordType(sid);
|
|
||||||
// TODO Remaining fields
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CFRule12Record(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2, Ptg[] formulaScale) {
|
private CFRule12Record(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2, Ptg[] formulaScale) {
|
||||||
super(conditionType, comparisonOperation, formula1, formula2);
|
super(conditionType, comparisonOperation, formula1, formula2);
|
||||||
this.formulaScale = Formula.create(formulaScale);
|
setDefaults();
|
||||||
// TODO Remaining fields
|
this.formula_scale = Formula.create(formulaScale);
|
||||||
|
}
|
||||||
|
private void setDefaults() {
|
||||||
|
futureHeader = new FtrHeader();
|
||||||
|
futureHeader.setRecordType(sid);
|
||||||
|
|
||||||
|
ext_formatting_length = 0;
|
||||||
|
ext_formatting_data = new byte[4];
|
||||||
|
|
||||||
|
formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||||
|
|
||||||
|
ext_opts = 0;
|
||||||
|
priority = 0;
|
||||||
|
template_type = getConditionType();
|
||||||
|
template_param_length = 16;
|
||||||
|
template_params = new byte[template_param_length];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +119,47 @@ public final class CFRule12Record extends CFRuleBase {
|
|||||||
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();
|
||||||
|
|
||||||
// TODO Handle the remainder
|
ext_formatting_length = in.readInt();
|
||||||
|
ext_formatting_data = new byte[0];
|
||||||
|
if (ext_formatting_length == 0) {
|
||||||
|
// 2 bytes reserved
|
||||||
|
in.readUShort();
|
||||||
|
} else {
|
||||||
|
int len = readFormatOptions(in);
|
||||||
|
if (len < ext_formatting_length) {
|
||||||
|
ext_formatting_data = new byte[ext_formatting_length-len];
|
||||||
|
in.readFully(ext_formatting_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setFormula1(Formula.read(field_3_formula1_len, in));
|
||||||
|
setFormula2(Formula.read(field_4_formula2_len, in));
|
||||||
|
|
||||||
|
int formula_scale_len = in.readUShort();
|
||||||
|
formula_scale = Formula.read(formula_scale_len, in);
|
||||||
|
|
||||||
|
ext_opts = in.readByte();
|
||||||
|
priority = in.readUShort();
|
||||||
|
template_type = in.readUShort();
|
||||||
|
template_param_length = in.readByte();
|
||||||
|
if (template_param_length == 0 || template_param_length == 16) {
|
||||||
|
template_params = new byte[template_param_length];
|
||||||
|
in.readFully(template_params);
|
||||||
|
} else {
|
||||||
|
logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length);
|
||||||
|
in.readRemainder();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte type = getConditionType();
|
||||||
|
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||||
|
gradient_data = in.readRemainder();
|
||||||
|
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||||
|
databar_data = in.readRemainder();
|
||||||
|
} else if (type == CONDITION_TYPE_FILTER) {
|
||||||
|
filter_data = in.readRemainder();
|
||||||
|
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||||
|
multistate_data = in.readRemainder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,10 +171,10 @@ public final class CFRule12Record extends CFRuleBase {
|
|||||||
* callers should check for null!
|
* callers should check for null!
|
||||||
*/
|
*/
|
||||||
public Ptg[] getParsedExpressionScale() {
|
public Ptg[] getParsedExpressionScale() {
|
||||||
return formulaScale.getTokens();
|
return formula_scale.getTokens();
|
||||||
}
|
}
|
||||||
public void setParsedExpressionScale(Ptg[] ptgs) {
|
public void setParsedExpressionScale(Ptg[] ptgs) {
|
||||||
formulaScale = Formula.create(ptgs);
|
formula_scale = Formula.create(ptgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getSid() {
|
public short getSid() {
|
||||||
@ -132,22 +199,71 @@ public final class CFRule12Record extends CFRuleBase {
|
|||||||
out.writeShort(formula1Len);
|
out.writeShort(formula1Len);
|
||||||
out.writeShort(formula2Len);
|
out.writeShort(formula2Len);
|
||||||
|
|
||||||
// TODO Output the rest
|
// TODO Update ext_formatting_length
|
||||||
|
if (ext_formatting_length == 0) {
|
||||||
|
out.writeInt(0);
|
||||||
|
out.writeShort(0);
|
||||||
|
} else {
|
||||||
|
out.writeInt(ext_formatting_length);
|
||||||
|
serializeFormattingBlock(out);
|
||||||
|
out.write(ext_formatting_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormula1().serializeTokens(out);
|
||||||
|
getFormula2().serializeTokens(out);
|
||||||
|
formula_scale.serializeTokens(out);
|
||||||
|
|
||||||
|
out.writeByte(ext_opts);
|
||||||
|
out.writeShort(priority);
|
||||||
|
out.writeShort(template_type);
|
||||||
|
out.writeByte(template_param_length);
|
||||||
|
out.write(template_params);
|
||||||
|
|
||||||
|
byte type = getConditionType();
|
||||||
|
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||||
|
out.write(gradient_data);
|
||||||
|
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||||
|
out.write(databar_data);
|
||||||
|
} else if (type == CONDITION_TYPE_FILTER) {
|
||||||
|
out.write(filter_data);
|
||||||
|
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||||
|
out.write(multistate_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
// TODO Calculate
|
int len = FtrHeader.getDataSize() + 6;
|
||||||
return 0;
|
if (ext_formatting_length == 0) {
|
||||||
|
len += 6;
|
||||||
|
} else {
|
||||||
|
len += 4 + getFormattingBlockSize() + ext_formatting_data.length;
|
||||||
|
}
|
||||||
|
len += getFormulaSize(getFormula1());
|
||||||
|
len += getFormulaSize(getFormula2());
|
||||||
|
len += 4 + getFormulaSize(formula_scale);
|
||||||
|
len += 6 + template_params.length;
|
||||||
|
|
||||||
|
byte type = getConditionType();
|
||||||
|
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||||
|
len += gradient_data.length;
|
||||||
|
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||||
|
len += databar_data.length;
|
||||||
|
} else if (type == CONDITION_TYPE_FILTER) {
|
||||||
|
len += filter_data.length;
|
||||||
|
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||||
|
len += multistate_data.length;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append("[CFRULE12]\n");
|
buffer.append("[CFRULE12]\n");
|
||||||
buffer.append(" .condition_type =").append(getConditionType()).append("\n");
|
buffer.append(" .condition_type =").append(getConditionType()).append("\n");
|
||||||
buffer.append(" TODO The rest!\n");
|
buffer.append(" TODO The rest!\n"); // TODO The Rest
|
||||||
buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().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(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n");
|
||||||
buffer.append(" Formula S =").append(Arrays.toString(formulaScale.getTokens())).append("\n");
|
buffer.append(" Formula S =").append(Arrays.toString(formula_scale.getTokens())).append("\n");
|
||||||
buffer.append("[/CFRULE12]\n");
|
buffer.append("[/CFRULE12]\n");
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
@ -158,7 +274,7 @@ public final class CFRule12Record extends CFRuleBase {
|
|||||||
|
|
||||||
// TODO The other fields
|
// TODO The other fields
|
||||||
|
|
||||||
rec.formulaScale = formulaScale.copy();
|
rec.formula_scale = formula_scale.copy();
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@ 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;
|
||||||
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conditional Formatting Rules. This can hold old-style rules
|
* Conditional Formatting Rules. This can hold old-style rules
|
||||||
@ -49,6 +52,7 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
public static final byte LE = 8;
|
public static final byte LE = 8;
|
||||||
private static final byte max_operator = 8;
|
private static final byte max_operator = 8;
|
||||||
}
|
}
|
||||||
|
protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class);
|
||||||
|
|
||||||
private byte condition_type;
|
private byte condition_type;
|
||||||
// The only kinds that CFRuleRecord handles
|
// The only kinds that CFRuleRecord handles
|
||||||
@ -98,7 +102,7 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag 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 alignIndent = bf(0x00000020); // 0 = Indentation modified
|
||||||
static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
|
static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
|
||||||
static final BitField notUsed1 = bf(0x00000080); // Always 1
|
static final BitField mergeCell = bf(0x00000080); // Normally 1, 0 = Merge Cell flag modified
|
||||||
static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
|
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 protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
|
||||||
static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
|
static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
|
||||||
@ -110,7 +114,7 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
|
static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
|
||||||
static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour 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 pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
|
||||||
static final BitField notUsed2 = bf(0x00380000); // Always 111
|
static final BitField notUsed2 = bf(0x00380000); // Always 111 (ifmt / ifnt / 1)
|
||||||
static final BitField undocumented = bf(0x03C00000); // Undocumented bits
|
static final BitField undocumented = bf(0x03C00000); // Undocumented bits
|
||||||
static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
|
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 font = bf(0x04000000); // 1 = Record contains font formatting block
|
||||||
@ -124,8 +128,8 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
return BitFieldFactory.getInstance(i);
|
return BitFieldFactory.getInstance(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int field_5_options; // TODO Rename me
|
protected int formatting_options;
|
||||||
protected short field_6_not_used; // TODO Rename me
|
protected short formatting_not_used; // TODO Decode this properly
|
||||||
|
|
||||||
protected FontFormatting _fontFormatting;
|
protected FontFormatting _fontFormatting;
|
||||||
protected BorderFormatting _borderFormatting;
|
protected BorderFormatting _borderFormatting;
|
||||||
@ -149,8 +153,8 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
protected CFRuleBase() {}
|
protected CFRuleBase() {}
|
||||||
|
|
||||||
protected int readFormatOptions(RecordInputStream in) {
|
protected int readFormatOptions(RecordInputStream in) {
|
||||||
field_5_options = in.readInt();
|
formatting_options = in.readInt();
|
||||||
field_6_not_used = in.readShort();
|
formatting_not_used = in.readShort();
|
||||||
|
|
||||||
int len = 6;
|
int len = 6;
|
||||||
|
|
||||||
@ -261,14 +265,14 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
* @return bit mask
|
* @return bit mask
|
||||||
*/
|
*/
|
||||||
public int getOptions() {
|
public int getOptions() {
|
||||||
return field_5_options;
|
return formatting_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isModified(BitField field) {
|
private boolean isModified(BitField field) {
|
||||||
return !field.isSet(field_5_options);
|
return !field.isSet(formatting_options);
|
||||||
}
|
}
|
||||||
private void setModified(boolean modified, BitField field) {
|
private void setModified(boolean modified, BitField field) {
|
||||||
field_5_options = field.setBoolean(field_5_options, !modified);
|
formatting_options = field.setBoolean(formatting_options, !modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLeftBorderModified() {
|
public boolean isLeftBorderModified() {
|
||||||
@ -336,10 +340,34 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getOptionFlag(BitField field) {
|
private boolean getOptionFlag(BitField field) {
|
||||||
return field.isSet(field_5_options);
|
return field.isSet(formatting_options);
|
||||||
}
|
}
|
||||||
private void setOptionFlag(boolean flag, BitField field) {
|
private void setOptionFlag(boolean flag, BitField field) {
|
||||||
field_5_options = field.setBoolean(field_5_options, flag);
|
formatting_options = field.setBoolean(formatting_options, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getFormattingBlockSize() {
|
||||||
|
return
|
||||||
|
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
|
||||||
|
(containsBorderFormattingBlock()?8:0)+
|
||||||
|
(containsPatternFormattingBlock()?4:0);
|
||||||
|
}
|
||||||
|
protected void serializeFormattingBlock(LittleEndianOutput out) {
|
||||||
|
out.writeInt(formatting_options);
|
||||||
|
out.writeShort(formatting_not_used);
|
||||||
|
|
||||||
|
if (containsFontFormattingBlock()) {
|
||||||
|
byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord();
|
||||||
|
out.write(fontFormattingRawRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsBorderFormattingBlock()) {
|
||||||
|
_borderFormatting.serialize(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsPatternFormattingBlock()) {
|
||||||
|
_patternFormatting.serialize(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -409,8 +437,8 @@ public abstract class CFRuleBase extends StandardRecord {
|
|||||||
rec.condition_type = condition_type;
|
rec.condition_type = condition_type;
|
||||||
rec.comparison_operator = comparison_operator;
|
rec.comparison_operator = comparison_operator;
|
||||||
|
|
||||||
rec.field_5_options = field_5_options;
|
rec.formatting_options = formatting_options;
|
||||||
rec.field_6_not_used = field_6_not_used;
|
rec.formatting_not_used = formatting_not_used;
|
||||||
if (containsFontFormattingBlock()) {
|
if (containsFontFormattingBlock()) {
|
||||||
rec._fontFormatting = (FontFormatting) _fontFormatting.clone();
|
rec._fontFormatting = (FontFormatting) _fontFormatting.clone();
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,12 @@ public final class CFRuleRecord extends CFRuleBase {
|
|||||||
}
|
}
|
||||||
private void 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);
|
formatting_options = modificationBits.setValue(formatting_options, -1);
|
||||||
// Set formatting block flags to 0 (no formatting blocks)
|
// Set formatting block flags to 0 (no formatting blocks)
|
||||||
field_5_options = fmtBlockBits.setValue(field_5_options, 0);
|
formatting_options = fmtBlockBits.setValue(formatting_options, 0);
|
||||||
field_5_options = undocumented.clear(field_5_options);
|
formatting_options = undocumented.clear(formatting_options);
|
||||||
|
|
||||||
field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
|
formatting_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
|
||||||
_fontFormatting = null;
|
_fontFormatting = null;
|
||||||
_borderFormatting = null;
|
_borderFormatting = null;
|
||||||
_patternFormatting = null;
|
_patternFormatting = null;
|
||||||
@ -106,34 +106,17 @@ public final class CFRuleRecord extends CFRuleBase {
|
|||||||
out.writeByte(getComparisonOperation());
|
out.writeByte(getComparisonOperation());
|
||||||
out.writeShort(formula1Len);
|
out.writeShort(formula1Len);
|
||||||
out.writeShort(formula2Len);
|
out.writeShort(formula2Len);
|
||||||
out.writeInt(field_5_options);
|
|
||||||
out.writeShort(field_6_not_used);
|
|
||||||
|
|
||||||
if (containsFontFormattingBlock()) {
|
serializeFormattingBlock(out);
|
||||||
byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord();
|
|
||||||
out.write(fontFormattingRawRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (containsBorderFormattingBlock()) {
|
|
||||||
_borderFormatting.serialize(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (containsPatternFormattingBlock()) {
|
|
||||||
_patternFormatting.serialize(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFormula1().serializeTokens(out);
|
getFormula1().serializeTokens(out);
|
||||||
getFormula2().serializeTokens(out);
|
getFormula2().serializeTokens(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
int i = 12 +
|
return 12 + getFormattingBlockSize() +
|
||||||
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
|
|
||||||
(containsBorderFormattingBlock()?8:0)+
|
|
||||||
(containsPatternFormattingBlock()?4:0)+
|
|
||||||
getFormulaSize(getFormula1())+
|
getFormulaSize(getFormula1())+
|
||||||
getFormulaSize(getFormula2());
|
getFormulaSize(getFormula2());
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
Loading…
Reference in New Issue
Block a user