-1

I am trying to create a XSSFConditionalFormattingRule with a 3-scale coloring. Therefore I need to set the thresholds as well. Yet upon debugging I found that each XSSFConditionalFormattingThreshold throws an com.sun.jdi.InvocationException occurred invoking method. on their CTCfvo property, but only after calling rule.getColorScaleFormatting().setNumControlPoints(3);

My complete code is this:

CellRangeAddress[] regions = { CellRangeAddress.valueOf("Z2:Z" + (sheet.getLastRowNum() + 1)) };

XSSFConditionalFormattingRule rule = sheet.getSheetConditionalFormatting()
        .createConditionalFormattingColorScaleRule();

XSSFConditionalFormattingThreshold thresh5 = rule.getColorScaleFormatting().createThreshold();
thresh5.setRangeType(RangeType.NUMBER);
thresh5.setValue(0.05);
XSSFConditionalFormattingThreshold thresh10 = rule.getColorScaleFormatting().createThreshold();
thresh10.setRangeType(RangeType.NUMBER);
thresh10.setValue(0.10);
XSSFConditionalFormattingThreshold thresh15 = rule.getColorScaleFormatting().createThreshold();
thresh15.setRangeType(RangeType.NUMBER);
thresh15.setValue(0.15);

rule.getColorScaleFormatting().setNumControlPoints(3);
rule.getColorScaleFormatting()
        .setThresholds(new ConditionalFormattingThreshold[] { thresh5, thresh10, thresh15 });
XSSFColor colorGreen = new XSSFColor(IndexedColors.GREEN, colorMap);
XSSFColor colorYellow = new XSSFColor(IndexedColors.YELLOW, colorMap);
XSSFColor colorRed = new XSSFColor(IndexedColors.RED, colorMap);

rule.getColorScaleFormatting().setColors(new Color[] { colorGreen, colorYellow, colorRed });

sheet.getSheetConditionalFormatting().addConditionalFormatting(regions, rule);

And this the shortened stacktrace I get when execting the code above:

org.apache.xmlbeans.impl.values.XmlValueDisconnectedException at org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1258) at org.apache.xmlbeans.impl.values.XmlObjectBase.newCursor(XmlObjectBase.java:286) at org.apache.xmlbeans.impl.values.XmlComplexContentImpl.arraySetterHelper(XmlComplexContentImpl.java:1124) at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTColorScaleImpl.setCfvoArray(Unknown Source) at org.apache.poi.xssf.usermodel.XSSFColorScaleFormatting.setThresholds(XSSFColorScaleFormatting.java:85)

What causes the error I am seeing here? Is it a mistake when I create the XSSFConditionalFormattingThreshold? Or something entirely else?


I am using apache poi v4.0.0.

XtremeBaumer
  • 6,275
  • 3
  • 19
  • 65

1 Answers1

1

As stated in the question, the only occurences of this error was attributed to writing the workbook twice (SO question, bugzilla). So that got me wondering what I am doing wrong. I had no real idea where to start, as everything associated with the error has nothing to do with my problem.

My first look went to the documentation of void org.apache.poi.xssf.usermodel.XSSFColorScaleFormatting.setNumControlPoints(int num), which states the following:

Sets the number of control points to use to map the colours. Should normally be 2 or 3.

After updating, you need to ensure that the Threshold count and Color count match

The second part caught my eye. I thought something along the lines:

I create the thresholds directly on the ColorScaleFormatting with getColorScaleFormatting().createThreshold(). So what if setNumControlPoints() actually resets all the thresholds which have been previously created?

And that was the point where I simply moved rule.getColorScaleFormatting().setNumControlPoints(3); in before the creation of all the XSSFConditionalFormattingThreshold and there it was, my code working just fine.

Having a look at the setNumControlPoints method we can see this:

public void setNumControlPoints(int num) {
    while (num < _scale.sizeOfCfvoArray()) {
        _scale.removeCfvo(_scale.sizeOfCfvoArray()-1);
        _scale.removeColor(_scale.sizeOfColorArray()-1);
    }
    while (num > _scale.sizeOfCfvoArray()) {
        _scale.addNewCfvo();
        _scale.addNewColor();
    }
}

This clearly suggests that some things might get removed when calling this method, though I couldn't quite get what the initial size of _scale.sizeOfCfvoArray() is (I'd assume 0). And because of that I couldn't quite see how stuff gets removed, because I created 3 thresholds (_scale.sizeOfCfvoArray() should be 3) and then I call setNumControlPoints(3), so we would have num == _scale.sizeOfCfvoArray() and I couldn't find anything for what happens in that case (looks like complete removal of everything though).

To conclude, setNumControlPoints(int num) should always be called as first thing after creating the rule and before creating any thresholds.


If anyone can point out why everything gets reset if num == _scale.sizeOfCfvoArray(), feel free to comment or edit.

XtremeBaumer
  • 6,275
  • 3
  • 19
  • 65