#58130 Begin CF DataBar support

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691867 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2015-07-20 03:21:57 +00:00
parent 85da2c3069
commit 21a8a53496
6 changed files with 310 additions and 55 deletions

View File

@ -21,6 +21,8 @@ import java.util.Arrays;
import org.apache.poi.hssf.record.cf.ColorGradientFormatting; import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
import org.apache.poi.hssf.record.cf.ColorGradientThreshold; import org.apache.poi.hssf.record.cf.ColorGradientThreshold;
import org.apache.poi.hssf.record.cf.DataBarFormatting;
import org.apache.poi.hssf.record.cf.DataBarThreshold;
import org.apache.poi.hssf.record.cf.IconMultiStateFormatting; import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
import org.apache.poi.hssf.record.cf.IconMultiStateThreshold; import org.apache.poi.hssf.record.cf.IconMultiStateThreshold;
import org.apache.poi.hssf.record.cf.Threshold; import org.apache.poi.hssf.record.cf.Threshold;
@ -30,6 +32,7 @@ import org.apache.poi.hssf.record.common.FutureRecord;
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.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
@ -59,11 +62,10 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
private byte template_param_length; private byte template_param_length;
private byte[] template_params; private byte[] template_params;
private DataBarFormatting data_bar;
private IconMultiStateFormatting multistate; private IconMultiStateFormatting multistate;
private ColorGradientFormatting color_gradient; private ColorGradientFormatting color_gradient;
// TODO Parse this, see #58150
// TODO Parse these
private byte[] databar_data;
private byte[] filter_data; private byte[] filter_data;
/** Creates new CFRuleRecord */ /** Creates new CFRuleRecord */
@ -122,6 +124,27 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation,
formula1, formula2, formula3); formula1, formula2, formula3);
} }
/**
* Creates a new Data Bar formatting
*/
public static CFRule12Record create(HSSFSheet sheet, ExtendedColor color) {
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_DATA_BAR,
ComparisonOperator.NO_COMPARISON);
DataBarFormatting dbf = r.createDataBarFormatting();
dbf.setColor(color);
dbf.setPercentMin((byte)50);
dbf.setPercentMax((byte)50);
DataBarThreshold min = new DataBarThreshold();
min.setType(RangeType.MIN.id);
dbf.setThresholdMin(min);
DataBarThreshold max = new DataBarThreshold();
max.setType(RangeType.MAX.id);
dbf.setThresholdMax(max);
return r;
}
/** /**
* Creates a new Icon Set / Multi-State formatting * Creates a new Icon Set / Multi-State formatting
*/ */
@ -158,7 +181,6 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
cgf.setColors(colors); cgf.setColors(colors);
return r; return r;
} }
// TODO Static creators for Data Bars
public CFRule12Record(RecordInputStream in) { public CFRule12Record(RecordInputStream in) {
futureHeader = new FtrHeader(in); futureHeader = new FtrHeader(in);
@ -202,7 +224,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
color_gradient = new ColorGradientFormatting(in); color_gradient = new ColorGradientFormatting(in);
} else if (type == CONDITION_TYPE_DATA_BAR) { } else if (type == CONDITION_TYPE_DATA_BAR) {
databar_data = in.readRemainder(); data_bar = new DataBarFormatting(in);
} else if (type == CONDITION_TYPE_FILTER) { } else if (type == CONDITION_TYPE_FILTER) {
filter_data = in.readRemainder(); filter_data = in.readRemainder();
} else if (type == CONDITION_TYPE_ICON_SET) { } else if (type == CONDITION_TYPE_ICON_SET) {
@ -210,6 +232,21 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
} }
} }
public boolean containsDataBarBlock() {
return (data_bar != null);
}
public DataBarFormatting getDataBarFormatting() {
return data_bar;
}
public DataBarFormatting createDataBarFormatting() {
if (data_bar != null) return data_bar;
// Convert, setup and return
setConditionType(CONDITION_TYPE_DATA_BAR);
data_bar = new DataBarFormatting();
return data_bar;
}
public boolean containsMultiStateBlock() { public boolean containsMultiStateBlock() {
return (multistate != null); return (multistate != null);
} }
@ -302,7 +339,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
color_gradient.serialize(out); color_gradient.serialize(out);
} else if (type == CONDITION_TYPE_DATA_BAR) { } else if (type == CONDITION_TYPE_DATA_BAR) {
out.write(databar_data); data_bar.serialize(out);
} else if (type == CONDITION_TYPE_FILTER) { } else if (type == CONDITION_TYPE_FILTER) {
out.write(filter_data); out.write(filter_data);
} else if (type == CONDITION_TYPE_ICON_SET) { } else if (type == CONDITION_TYPE_ICON_SET) {
@ -326,7 +363,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
len += color_gradient.getDataLength(); len += color_gradient.getDataLength();
} else if (type == CONDITION_TYPE_DATA_BAR) { } else if (type == CONDITION_TYPE_DATA_BAR) {
len += databar_data.length; len += data_bar.getDataLength();
} else if (type == CONDITION_TYPE_FILTER) { } else if (type == CONDITION_TYPE_FILTER) {
len += filter_data.length; len += filter_data.length;
} else if (type == CONDITION_TYPE_ICON_SET) { } else if (type == CONDITION_TYPE_ICON_SET) {
@ -358,7 +395,6 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
buffer.append(" .priority =").append(priority).append("\n"); buffer.append(" .priority =").append(priority).append("\n");
buffer.append(" .template_type =").append(template_type).append("\n"); buffer.append(" .template_type =").append(template_type).append("\n");
buffer.append(" .template_params=").append(HexDump.toHex(template_params)).append("\n"); buffer.append(" .template_params=").append(HexDump.toHex(template_params)).append("\n");
buffer.append(" .databar_data =").append(HexDump.toHex(databar_data)).append("\n");
buffer.append(" .filter_data =").append(HexDump.toHex(filter_data)).append("\n"); buffer.append(" .filter_data =").append(HexDump.toHex(filter_data)).append("\n");
if (color_gradient != null) { if (color_gradient != null) {
buffer.append(color_gradient); buffer.append(color_gradient);
@ -366,6 +402,9 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
if (multistate != null) { if (multistate != null) {
buffer.append(multistate); buffer.append(multistate);
} }
if (data_bar != null) {
buffer.append(data_bar);
}
buffer.append("[/CFRULE12]\n"); buffer.append("[/CFRULE12]\n");
return buffer.toString(); return buffer.toString();
} }
@ -389,7 +428,19 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
rec.template_params = new byte[template_param_length]; rec.template_params = new byte[template_param_length];
System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length); System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length);
// TODO Clone the rgbCT data like Gradients, Databars etc if (color_gradient != null) {
rec.color_gradient = (ColorGradientFormatting)color_gradient.clone();
}
if (multistate != null) {
rec.multistate = (IconMultiStateFormatting)multistate.clone();
}
if (data_bar != null) {
rec.data_bar = (DataBarFormatting)data_bar.clone();
}
if (filter_data != null) {
rec.filter_data = new byte[filter_data.length];
System.arraycopy(filter_data, 0, rec.filter_data, 0, filter_data.length);
}
return rec; return rec;
} }

View File

@ -0,0 +1,160 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.cf;
import org.apache.poi.hssf.record.common.ExtendedColor;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/**
* Data Bar Conditional Formatting Rule Record.
*/
public final class DataBarFormatting implements Cloneable {
private static POILogger log = POILogFactory.getLogger(DataBarFormatting.class);
private byte options = 0;
private byte percentMin = 0;
private byte percentMax = 0;
private ExtendedColor color;
private DataBarThreshold thresholdMin;
private DataBarThreshold thresholdMax;
private static BitField iconOnly = BitFieldFactory.getInstance(0x01);
private static BitField reversed = BitFieldFactory.getInstance(0x04);
public DataBarFormatting() {
options = 2;
}
public DataBarFormatting(LittleEndianInput in) {
in.readShort(); // Ignored
in.readByte(); // Reserved
options = in.readByte();
percentMin = in.readByte();
percentMax = in.readByte();
if (percentMin < 0 || percentMin > 100)
log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
if (percentMax < 0 || percentMax > 100)
log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
color = new ExtendedColor(in);
thresholdMin = new DataBarThreshold(in);
thresholdMax = new DataBarThreshold(in);
}
public boolean isIconOnly() {
return getOptionFlag(iconOnly);
}
public void setIconOnly(boolean only) {
setOptionFlag(only, iconOnly);
}
public boolean isReversed() {
return getOptionFlag(reversed);
}
public void setReversed(boolean rev) {
setOptionFlag(rev, reversed);
}
private boolean getOptionFlag(BitField field) {
int value = field.getValue(options);
return value==0 ? false : true;
}
private void setOptionFlag(boolean option, BitField field) {
options = field.setByteBoolean(options, option);
}
public byte getPercentMin() {
return percentMin;
}
public void setPercentMin(byte percentMin) {
this.percentMin = percentMin;
}
public byte getPercentMax() {
return percentMax;
}
public void setPercentMax(byte percentMax) {
this.percentMax = percentMax;
}
public ExtendedColor getColor() {
return color;
}
public void setColor(ExtendedColor color) {
this.color = color;
}
public DataBarThreshold getThresholdMin() {
return thresholdMin;
}
public void setThresholdMin(DataBarThreshold thresholdMin) {
this.thresholdMin = thresholdMin;
}
public DataBarThreshold getThresholdMax() {
return thresholdMax;
}
public void setThresholdMax(DataBarThreshold thresholdMax) {
this.thresholdMax = thresholdMax;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(" [Data Bar Formatting]\n");
buffer.append(" .icon_only= ").append(isIconOnly()).append("\n");
buffer.append(" .reversed = ").append(isReversed()).append("\n");
buffer.append(color);
buffer.append(thresholdMin);
buffer.append(thresholdMax);
buffer.append(" [/Data Bar Formatting]\n");
return buffer.toString();
}
public Object clone() {
DataBarFormatting rec = new DataBarFormatting();
rec.options = options;
rec.percentMin = percentMin;
rec.percentMax = percentMax;
rec.color = (ExtendedColor)color.clone();
rec.thresholdMin = (DataBarThreshold)thresholdMin.clone();
rec.thresholdMax = (DataBarThreshold)thresholdMax.clone();
return rec;
}
public int getDataLength() {
return 6 + color.getDataLength() +
thresholdMin.getDataLength() +
thresholdMax.getDataLength();
}
public void serialize(LittleEndianOutput out) {
out.writeShort(0);
out.writeByte(0);
out.writeByte(options);
out.writeByte(percentMin);
out.writeByte(percentMax);
color.serialize(out);
thresholdMin.serialize(out);
thresholdMax.serialize(out);
}
}

View File

@ -0,0 +1,41 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.cf;
import org.apache.poi.util.LittleEndianInput;
/**
* Data Bar specific Threshold / value (CFVO),
* for changes in Conditional Formatting
*/
public final class DataBarThreshold extends Threshold {
public DataBarThreshold() {
super();
}
/** Creates new Data Bar Threshold */
public DataBarThreshold(LittleEndianInput in) {
super(in);
}
public Object clone() {
DataBarThreshold rec = new DataBarThreshold();
super.copyTo(rec);
return rec;
}
}

View File

@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormatting;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule; import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
import org.apache.poi.ss.usermodel.ExtendedColor;
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
@ -106,6 +107,24 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor
return new HSSFConditionalFormattingRule(_sheet, rr); return new HSSFConditionalFormattingRule(_sheet, rr);
} }
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link HSSFConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link HSSFDataBarFormatting#getMinThreshold()}
* and
* {@link HSSFDataBarFormatting#getMaxThreshold()}
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(HSSFExtendedColor color) {
CFRule12Record rr = CFRule12Record.create(_sheet, color.getExtendedColor());
return new HSSFConditionalFormattingRule(_sheet, rr);
}
public HSSFConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color) {
return createConditionalFormattingRule((HSSFExtendedColor)color);
}
/** /**
* Create a Color Scale / Color Gradient conditional formatting rule. * Create a Color Scale / Color Gradient conditional formatting rule.
* <p>The thresholds and colours for it will be created, but will be * <p>The thresholds and colours for it will be created, but will be
@ -121,22 +140,6 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor
return new HSSFConditionalFormattingRule(_sheet, rr); return new HSSFConditionalFormattingRule(_sheet, rr);
} }
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link HSSFConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link HSSFDataBarFormatting#getMinThreshold()}
* and
* {@link HSSFDataBarFormatting#getMaxThreshold()}
* and
* {@link HSSFDataBarFormatting#getColor()}
*/
public HSSFConditionalFormattingRule createConditionalFormattingDataBarRule() {
throw new IllegalStateException("Not Implemented Yet!"); // TODO Implement
}
/** /**
* Adds a copy of HSSFConditionalFormatting object to the sheet * Adds a copy of HSSFConditionalFormatting object to the sheet
* <p>This method could be used to copy HSSFConditionalFormatting object * <p>This method could be used to copy HSSFConditionalFormatting object

View File

@ -136,6 +136,18 @@ public interface SheetConditionalFormatting {
*/ */
ConditionalFormattingRule createConditionalFormattingRule(String formula); ConditionalFormattingRule createConditionalFormattingRule(String formula);
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link ConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link DataBarFormatting#getMinThreshold()}
* and
* {@link DataBarFormatting#getMaxThreshold()}
*/
ConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color);
/** /**
* Create an Icon Set / Multi-State conditional formatting rule. * Create an Icon Set / Multi-State conditional formatting rule.
* <p>The thresholds for it will be created, but will be empty * <p>The thresholds for it will be created, but will be empty
@ -158,20 +170,6 @@ public interface SheetConditionalFormatting {
*/ */
ConditionalFormattingRule createConditionalFormattingColorScaleRule(); ConditionalFormattingRule createConditionalFormattingColorScaleRule();
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link ConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link DataBarFormatting#getMinThreshold()}
* and
* {@link DataBarFormatting#getMaxThreshold()}
* and
* {@link DataBarFormatting#getColor()}
*/
ConditionalFormattingRule createConditionalFormattingDataBarRule();
/** /**
* Gets Conditional Formatting object at a particular index * Gets Conditional Formatting object at a particular index
* *

View File

@ -27,6 +27,7 @@ import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.ComparisonOperator; import org.apache.poi.ss.usermodel.ComparisonOperator;
import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormatting;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule; import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
import org.apache.poi.ss.usermodel.ExtendedColor;
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
@ -119,6 +120,23 @@ public class XSSFSheetConditionalFormatting implements SheetConditionalFormattin
return rule; return rule;
} }
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link XSSFConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link XSSFDataBarFormatting#getMinThreshold()}
* and
* {@link XSSFDataBarFormatting#getMaxThreshold()}
*/
public XSSFConditionalFormattingRule createConditionalFormattingRule(XSSFColor color) {
throw new IllegalStateException("Not Implemented Yet!"); // TODO Implement
}
public XSSFConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color) {
return createConditionalFormattingRule((XSSFColor)color);
}
/** /**
* A factory method allowing the creation of conditional formatting * A factory method allowing the creation of conditional formatting
* rules using an Icon Set / Multi-State formatting. * rules using an Icon Set / Multi-State formatting.
@ -158,22 +176,6 @@ public class XSSFSheetConditionalFormatting implements SheetConditionalFormattin
return rule; return rule;
} }
/**
* Create a Databar conditional formatting rule.
* <p>The thresholds and colour for it will be created, but will be
* empty and require configuring with
* {@link XSSFConditionalFormattingRule#getDataBarFormatting()}
* then
* {@link XSSFDataBarFormatting#getMinThreshold()}
* and
* {@link XSSFDataBarFormatting#getMaxThreshold()}
* and
* {@link XSSFDataBarFormatting#getColor()}
*/
public XSSFConditionalFormattingRule createConditionalFormattingDataBarRule() {
throw new IllegalStateException("Not Implemented Yet!"); // TODO Implement
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) {
if (regions == null) { if (regions == null) {