Browse Source

#58130 CF Threshold formats differ slightly between types

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691858 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_13_FINAL
Nick Burch 9 years ago
parent
commit
7ccb4ad2d8

+ 2
- 1
src/java/org/apache/poi/hssf/record/CFRule12Record.java View File

@@ -21,6 +21,7 @@ import java.util.Arrays;

import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
import org.apache.poi.hssf.record.cf.IconMultiStateThreshold;
import org.apache.poi.hssf.record.cf.Threshold;
import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.hssf.record.common.FutureRecord;
@@ -125,7 +126,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) {
Threshold[] ts = new Threshold[iconSet.num];
for (int i=0; i<ts.length; i++) {
ts[i] = new Threshold();
ts[i] = new IconMultiStateThreshold();
}
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE,

+ 56
- 23
src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java View File

@@ -17,6 +17,7 @@

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;
@@ -33,15 +34,16 @@ public final class ColorGradientFormatting implements Cloneable {
private static POILogger log = POILogFactory.getLogger(ColorGradientFormatting.class);

private byte options = 0;
private Threshold[] thresholds;
private byte[] colors; // TODO Decode
private ColorGradientThreshold[] thresholds;
private ExtendedColor[] colors;
private static BitField clamp = BitFieldFactory.getInstance(0x01);
private static BitField background = BitFieldFactory.getInstance(0x02);
public ColorGradientFormatting() {
options = 3;
thresholds = new Threshold[3];
thresholds = new ColorGradientThreshold[3];
colors = new ExtendedColor[3];
}
public ColorGradientFormatting(LittleEndianInput in) {
in.readShort(); // Ignored
@@ -53,15 +55,15 @@ public final class ColorGradientFormatting implements Cloneable {
}
options = in.readByte();
// TODO Are these correct?
thresholds = new Threshold[numI];
thresholds = new ColorGradientThreshold[numI];
for (int i=0; i<thresholds.length; i++) {
thresholds[i] = new Threshold(in);
in.readDouble(); // Rather pointless value...
thresholds[i] = new ColorGradientThreshold(in);
}
colors = new ExtendedColor[numG];
for (int i=0; i<colors.length; i++) {
in.readDouble(); // Slightly pointless step counter
colors[i] = new ExtendedColor(in);
}
// TODO Decode colors
colors = new byte[in.available()];
in.readFully(colors);
}
public int getNumControlPoints() {
@@ -69,19 +71,34 @@ public final class ColorGradientFormatting implements Cloneable {
}
public void setNumControlPoints(int num) {
if (num != thresholds.length) {
thresholds = new Threshold[num];
// TODO Colors
ColorGradientThreshold[] nt = new ColorGradientThreshold[num];
ExtendedColor[] nc = new ExtendedColor[num];
int copy = Math.min(thresholds.length, num);
System.arraycopy(thresholds, 0, nt, 0, copy);
System.arraycopy(colors, 0, nc, 0, copy);
this.thresholds = nt;
this.colors = nc;
updateThresholdPositions();
}
}
public Threshold[] getThresholds() {
public ColorGradientThreshold[] getThresholds() {
return thresholds;
}
public void setThresholds(Threshold[] thresholds) {
public void setThresholds(ColorGradientThreshold[] thresholds) {
this.thresholds = thresholds;
updateThresholdPositions();
}

// TODO Colors
public ExtendedColor[] getColors() {
return colors;
}
public void setColors(ExtendedColor[] colors) {
this.colors = colors;
}
public boolean isClampToCurve() {
return getOptionFlag(clamp);
@@ -93,6 +110,13 @@ public final class ColorGradientFormatting implements Cloneable {
int value = field.getValue(options);
return value==0 ? false : true;
}

private void updateThresholdPositions() {
double step = 1d / (thresholds.length-1);
for (int i=0; i<thresholds.length; i++) {
thresholds[i].setPosition(step*i);
}
}
public String toString() {
StringBuffer buffer = new StringBuffer();
@@ -102,6 +126,9 @@ public final class ColorGradientFormatting implements Cloneable {
for (Threshold t : thresholds) {
buffer.append(t.toString());
}
for (ExtendedColor c : colors) {
buffer.append(c.toString());
}
buffer.append(" [/Color Gradient Formatting]\n");
return buffer.toString();
}
@@ -109,9 +136,10 @@ public final class ColorGradientFormatting implements Cloneable {
public Object clone() {
ColorGradientFormatting rec = new ColorGradientFormatting();
rec.options = options;
rec.thresholds = new Threshold[thresholds.length];
rec.thresholds = new ColorGradientThreshold[thresholds.length];
rec.colors = new ExtendedColor[colors.length];
System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length);
// TODO Colors
System.arraycopy(colors, 0, rec.colors, 0, colors.length);
return rec;
}
@@ -119,9 +147,11 @@ public final class ColorGradientFormatting implements Cloneable {
int len = 6;
for (Threshold t : thresholds) {
len += t.getDataLength();
}
for (ExtendedColor c : colors) {
len += c.getDataLength();
len += 8;
}
len += colors.length;
return len;
}

@@ -132,13 +162,16 @@ public final class ColorGradientFormatting implements Cloneable {
out.writeByte(thresholds.length);
out.writeByte(options);
double step = 1d / (thresholds.length-1);
for (int i=0; i<thresholds.length; i++) {
Threshold t = thresholds[i];
for (ColorGradientThreshold t : thresholds) {
t.serialize(out);
out.writeDouble(step*i);
}
out.write(colors);
double step = 1d / (colors.length-1);
for (int i=0; i<colors.length; i++) {
out.writeDouble(i*step);
ExtendedColor c = colors[i];
c.serialize(out);
}
}
}

+ 63
- 0
src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java View File

@@ -0,0 +1,63 @@
/* ====================================================================
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;
import org.apache.poi.util.LittleEndianOutput;

/**
* Color Gradient / Color Scale specific Threshold / value (CFVO),
* for changes in Conditional Formatting
*/
public final class ColorGradientThreshold extends Threshold {
private double position;

public ColorGradientThreshold() {
super();
position = 0d;
}

/** Creates new Ico Multi-State Threshold */
public ColorGradientThreshold(LittleEndianInput in) {
super(in);
position = in.readDouble();
}

public double getPosition() {
return position;
}
public void setPosition(double position) {
this.position = position;
}

public int getDataLength() {
return super.getDataLength() + 8;
}

public Object clone() {
ColorGradientThreshold rec = new ColorGradientThreshold();
super.copyTo(rec);
rec.position = position;
return rec;
}

public void serialize(LittleEndianOutput out) {
super.serialize(out);
out.writeDouble(position);
}
}

+ 1
- 1
src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java View File

@@ -56,7 +56,7 @@ public final class IconMultiStateFormatting implements Cloneable {
thresholds = new Threshold[iconSet.num];
for (int i=0; i<thresholds.length; i++) {
thresholds[i] = new Threshold(in);
thresholds[i] = new IconMultiStateThreshold(in);
}
}

+ 75
- 0
src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java View File

@@ -0,0 +1,75 @@
/* ====================================================================
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;
import org.apache.poi.util.LittleEndianOutput;

/**
* Icon / Multi-State specific Threshold / value (CFVO),
* for changes in Conditional Formatting
*/
public final class IconMultiStateThreshold extends Threshold {
/**
* Cell values that are equal to the threshold value do not pass the threshold
*/
public static final byte EQUALS_EXCLUDE = 0;
/**
* Cell values that are equal to the threshold value pass the threshold.
*/
public static final byte EQUALS_INCLUDE = 1;
private byte equals;

public IconMultiStateThreshold() {
super();
equals = EQUALS_INCLUDE;
}

/** Creates new Ico Multi-State Threshold */
public IconMultiStateThreshold(LittleEndianInput in) {
super(in);
equals = in.readByte();
// Reserved, 4 bytes, all 0
in.readInt();
}

public byte getEquals() {
return equals;
}
public void setEquals(byte equals) {
this.equals = equals;
}

public int getDataLength() {
return super.getDataLength() + 5;
}

public Object clone() {
IconMultiStateThreshold rec = new IconMultiStateThreshold();
super.copyTo(rec);
rec.equals = equals;
return rec;
}

public void serialize(LittleEndianOutput out) {
super.serialize(out);
out.writeByte(equals);
out.writeInt(0); // Reserved
}
}

+ 6
- 32
src/java/org/apache/poi/hssf/record/cf/Threshold.java View File

@@ -26,31 +26,21 @@ import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;

/**
* Threshold / value for changes in Conditional Formatting
* Threshold / value (CFVO) for changes in Conditional Formatting
*/
public final class Threshold {
/**
* Cell values that are equal to the threshold value do not pass the threshold
*/
public static final byte EQUALS_EXCLUDE = 0;
/**
* Cell values that are equal to the threshold value pass the threshold.
*/
public static final byte EQUALS_INCLUDE = 1;
public abstract class Threshold {
private byte type;
private Formula formula;
private Double value;
private byte equals;

public Threshold() {
protected Threshold() {
type = (byte)RangeType.NUMBER.id;
formula = Formula.create(null);
value = 0d;
}

/** Creates new Threshold */
public Threshold(LittleEndianInput in) {
protected Threshold(LittleEndianInput in) {
type = in.readByte();
short formulaLen = in.readShort();
if (formulaLen > 0) {
@@ -63,9 +53,6 @@ public final class Threshold {
type != RangeType.MAX.id) {
value = in.readDouble();
}
equals = in.readByte();
// Reserved, 4 bytes, all 0
in.readInt();
}

public byte getType() {
@@ -74,7 +61,7 @@ public final class Threshold {
public void setType(byte type) {
this.type = type;

// Ensure the value presense / absense is consistent for the new type
// Ensure the value presence / absence is consistent for the new type
if (type == RangeType.MIN.id || type == RangeType.MAX.id ||
type == RangeType.FORMULA.id) {
this.value = null;
@@ -106,19 +93,11 @@ public final class Threshold {
this.value = value;
}
public byte getEquals() {
return equals;
}
public void setEquals(byte equals) {
this.equals = equals;
}

public int getDataLength() {
int len = 1 + formula.getEncodedSize();
if (value != null) {
len += 8;
}
len += 5;
return len;
}

@@ -132,13 +111,10 @@ public final class Threshold {
return buffer.toString();
}

public Object clone() {
Threshold rec = new Threshold();
public void copyTo(Threshold rec) {
rec.type = type;
rec.formula = formula;
rec.value = value;
rec.equals = equals;
return rec;
}

public void serialize(LittleEndianOutput out) {
@@ -151,7 +127,5 @@ public final class Threshold {
if (value != null) {
out.writeDouble(value);
}
out.writeByte(equals);
out.writeInt(0); // Reserved
}
}

+ 5
- 3
src/java/org/apache/poi/hssf/usermodel/HSSFColorScaleFormatting.java View File

@@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel;

import org.apache.poi.hssf.record.CFRule12Record;
import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
import org.apache.poi.hssf.record.cf.ColorGradientThreshold;
import org.apache.poi.hssf.record.cf.Threshold;
import org.apache.poi.ss.usermodel.Color;
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold;
@@ -62,14 +63,15 @@ public final class HSSFColorScaleFormatting implements org.apache.poi.ss.usermod
}

public void setThresholds(ConditionalFormattingThreshold[] thresholds) {
Threshold[] t = new Threshold[thresholds.length];
ColorGradientThreshold[] t = new ColorGradientThreshold[thresholds.length];
for (int i=0; i<t.length; i++) {
t[i] = ((HSSFConditionalFormattingThreshold)thresholds[i]).getThreshold();
HSSFConditionalFormattingThreshold hssfT = (HSSFConditionalFormattingThreshold)thresholds[i];
t[i] = (ColorGradientThreshold)hssfT.getThreshold();
}
colorFormatting.setThresholds(t);
}

public HSSFConditionalFormattingThreshold createThreshold() {
return new HSSFConditionalFormattingThreshold(new Threshold(), sheet);
return new HSSFConditionalFormattingThreshold(new ColorGradientThreshold(), sheet);
}
}

Loading…
Cancel
Save