FormatConditionCollection addArea, Conditional Formatting of color to be applied on specific cell is not corresponding the condition

Hi team,

Recently I upgraded Aspose Cell version from 19.10 to 23.10. We have a code is not working on 23.10 version but is working well in 19.10 version.

We have a code where looping to set up the cell area background color (green, red, blue, grey) using the FormatConditionCollection to add the condition, then added it for the cell area. The weired issue is, when the condition cell value is “Passed” is equal “Passed”, it should add the “156,231,140” color. But when I exported excel, the background it setted up to another color (red color in this case).

So I cant find any issue in the code, can you help me to identify the issue and to see if any changes in in the version 23.10 ?

       int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL,"Passed", null);
        Color color = Color.fromArgb("156,231,140");
    
        FormatCondition fc = fcs.get(ii);
        Style ss = fc.getStyle();
        ss.setBackgroundColor(color);
        fc.setStyle(ss);

       fcs.addArea(cellArea);

Regards,

@jguo
By testing with the latest version v23.12, we can obtain the correct results. Please refer to the attachment (6.9 KB).

The sample code as follows:

Workbook workbook =  new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
Cells cells = sheet.getCells();
cells.get("B3").putValue("Passed");
cells.get("B4").putValue("Passed222");
cells.get("B5").putValue("Passed");

cells.get("C3").putValue("Passedccccc");
cells.get("C4").putValue("Passed");
cells.get("C5").putValue("Passeddddd");
	
ConditionalFormattingCollection cfs =sheet.getConditionalFormattings();
int index = cfs.add();
FormatConditionCollection fcs = cfs.get(index);
   
int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL,"Passed", null);
Color color = Color.fromArgb(156231140);

FormatCondition fc = fcs.get(ii);
Style ss = fc.getStyle();
ss.setBackgroundColor(color);
fc.setStyle(ss);
CellArea cellArea = CellArea.createCellArea("B3", "C5");
fcs.addArea(cellArea);

Cell a1 = cells.get("A1");		
a1.putValue("test test");
Style a1Style = a1.getStyle();
a1Style.setForegroundColor(color);
a1Style.setPattern(BackgroundType.SOLID);
a1.setStyle(a1Style);

workbook.save(filePath + "out_java.xlsx");

If you still have any questions or confusion, please provide your sample file and executable console project, and we will check it soon.

Hi @John.He

We upgraded to v23.12 and still have the same issue. In our webpage we have the correct colors (see the picture), but when exporting it to Excel the colors are incorrect.

It is working on v19.10, were there any updates between these versions related format conditional to setup the background color and apply the the cell area?

I attach a picture, the left is our expected result and the right is the wrong result.

The colors Hex that we used are:

Status Name            Hex        RGB              Byte returned
---------------------------------------------------------------
Passed                 9CE78C     156,231,140      -6494324
In Progress            9CE0E1     156,224,225      -6496031
Failed                 E39191     227,145,145      -1863279
Blocked                F8B275     248,178,117      -478603
Not applicable         C3C3C3     195,195,195      -3947581
public static Color hex2Color(String colorStr) { // colorStr = "9CE78C"
        if (isColorStringNotEmpty(colorStr)) {
            if (!colorStr.startsWith("#")) {
                colorStr = "#" + colorStr;
            }
            return Color.fromArgb(Integer.valueOf(colorStr.substring(1, 3), 16), Integer.valueOf(colorStr.substring(3, 5), 16), Integer.valueOf(colorStr.substring(5, 7), 16));
        }
        return null;
    }
private void setConditionalFormattingConditionForColor(FormatConditionCollection fcs, String formula, String hexColorString) {
        Color color = AsposeCellsUtil.hex2Color(hexColorString); // hexColorString = "9CE78C"
        if (color != null) {
            int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL, formula, null);
            FormatCondition fc = fcs.get(ii);
            Style ss = fc.getStyle();
            ss.setBackgroundColor(color);
            fc.setStyle(ss);
        }
    }

Regards,

image.png (51.5 KB)

@jguo
Based on the detailed information you provided for testing, we found some differences in the results obtained using RGB values and hex values. The hex color value can obtain the correct result. This may be due to some deviation in the conversion from RGB values to colors. If possible, please use the hex color values for testing. Please refer to the attachment (14.2 KB).

The sample code as follows:

Workbook workbook =  new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
Cells cells = sheet.getCells();
cells.get("B3").putValue("Passed");
cells.get("B4").putValue("Passed1111");
cells.get("B5").putValue("Passed");

cells.get("C3").putValue("In Progress");
cells.get("C4").putValue("In Progress1111");
cells.get("C5").putValue("In Progress");

cells.get("D3").putValue("Failed");
cells.get("D4").putValue("Failed2222");
cells.get("D5").putValue("Failed");

cells.get("E3").putValue("Blocked");
cells.get("E4").putValue("Blocked3333");
cells.get("E5").putValue("Blocked");


cells.get("F3").putValue("Not applicable");
cells.get("F4").putValue("Not applicable5555");
cells.get("F5").putValue("Not applicable");
	
ConditionalFormattingCollection cfs =sheet.getConditionalFormattings();
Color color = hex2Color("9CE78C");//Color.fromArgb(156231140);
String compareStr = "Passed";
CellArea cellArea = CellArea.createCellArea("B3", "B5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell b10 = cells.get("B10");		
b10.putValue("test test");
Style b10Style = b10.getStyle();
b10Style.setForegroundColor(color);
b10Style.setPattern(BackgroundType.SOLID);
b10.setStyle(b10Style);

color = hex2Color("9CE0E1");//Color.fromArgb(156224225);
compareStr = "In Progress";
cellArea = CellArea.createCellArea("C3", "C5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell c10 = cells.get("C10");		
c10.putValue("test test");
Style c10Style = c10.getStyle();
c10Style.setForegroundColor(color);
c10Style.setPattern(BackgroundType.SOLID);
c10.setStyle(c10Style);

color = hex2Color("E39191");//Color.fromArgb(227145145);
compareStr = "Failed";
cellArea = CellArea.createCellArea("D3", "D5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell d10 = cells.get("D10");		
d10.putValue("test test");
Style d10Style = d10.getStyle();
d10Style.setForegroundColor(color);
d10Style.setPattern(BackgroundType.SOLID);
d10.setStyle(d10Style);

color = hex2Color("F8B275");//Color.fromArgb(248178117);
compareStr = "Blocked";
cellArea = CellArea.createCellArea("E3", "E5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell e10 = cells.get("E10");		
e10.putValue("test test");
Style e10Style = e10.getStyle();
e10Style.setForegroundColor(color);
e10Style.setPattern(BackgroundType.SOLID);
e10.setStyle(e10Style);

color = hex2Color("C3C3C3");//Color.fromArgb(195195195);
compareStr = "Not applicable";
cellArea = CellArea.createCellArea("F3", "F5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);		

Cell f10 = cells.get("F10");		
f10.putValue("test test");
Style f10Style = f10.getStyle();
f10Style.setForegroundColor(color);
f10Style.setPattern(BackgroundType.SOLID);
f10.setStyle(f10Style);

workbook.save(filePath + "out_java_hexcolor.xlsx");

private static void AddConfitionalFormat(ConditionalFormattingCollection cfs, String str, Color color, CellArea cellArea)
{
	int index = cfs.add();
	FormatConditionCollection fcs = cfs.get(index);
	   
	int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL, str, null);		

	FormatCondition fc = fcs.get(ii);
	Style ss = fc.getStyle();
	ss.setBackgroundColor(color);
	fc.setStyle(ss);
	
	fcs.addArea(cellArea);
}

Hope helps a bit.

@John.He
We have been using hex color values, we didn’t use RGB color values. Our code is very close to your example and we still can’t find the reason. But another weird behavior that we discovered is, we have an enum class where defined the status names and color.

In section “Version A” class we defined the Hex color value that we expect for each status name, this is the original values that we have.

If you look at the section “Version B” class, we shift the Hex colors values that we already have in the class to some status name and the colors is working when we exported the Excel.

That mean for example, for the status “Passed”, we shift “E1E5E7” color instead “9CE78C” color in TestRunStatus class and when we export the excel it came out with green color that we want.

Also for status “Failed” and “In Progress”.
“Failed”, shift “9CE78C” color instead “E39191”, came out with red color that we expect when export.
“In Progress”, shift “E39191” color instead “9CE0E1”, came out with light blue color that we expect.

There is no logic with this replacement and we just trying everything and we noticed this behavior.
Although it has been temporarily solved, it is only a partial solution. Because we have some that are saved in the database. Shifting in color we run the risk of this issue occurring again and it is confusing.

I uploaded more detail about the code

Version A

public enum TestRunStatus implements EnumWithId {

    PASSED(1, "Passed", "9CE78C"),

    NOT_RUN(2, "Not Run", null),

    INPROGRESS(3, "In Progress", "9CE0E1"),

    FAILED(4, "Failed", "E39191"),

    BLOCKED(5, "Blocked", "F8B275"),

    NOT_APPLICABLE(6, "Not applicable", "C3C3C3");
}

Version B

public enum TestRunStatus implements EnumWithId {

    PASSED(1, "Passed", "9CE0E1"),

    NOT_RUN(2, "Not Run", null),

    INPROGRESS(3, "In Progress", "E39191"),

    FAILED(4, "Failed", "9CE78C"),

    BLOCKED(5, "Blocked", "F8B275"),

    NOT_APPLICABLE(6, "Not applicable", "C3C3C3");
private void setCellAreaBackgroundColorsForLookups(CellArea cellArea, String rangeName, Collection<?> options) {
        if (AsposeCellsUtil.optionsHaveAtLeastOneColor(options)) { // options = [{name="Passed", color="9CE0E1"}]
            FormatConditionCollection fcs = validationAndFormatting.getConditionalFormattingForRange(rangeName, options);
            fcs.addArea(cellArea);
        }
    }
FormatConditionCollection getConditionalFormattingForRange(String rangeName, Collection<?> options) {
        ConditionalFormattingCollection cf = worksheet.getConditionalFormattings();
        Integer cfIndex = rangeNameToConditionalFormattingIndexMap.get(rangeName);
        if (cfIndex == null) {
            cfIndex = cf.add();
            FormatConditionCollection fcs = cf.get(cfIndex);
            createConditionalFormatting(fcs, options);
            rangeNameToConditionalFormattingIndexMap.put(rangeName, cfIndex);
        }
        return worksheet.getConditionalFormattings().get(cfIndex);
    }
private void createConditionalFormatting(FormatConditionCollection fcs, Collection<?> options) {
        for (Object option : options) {
            Pair<String, String> nameAndColor = createNameAndColorLookupPropertyDTO(option);
            String color = nameAndColor.getRight(); // color = "9CE0E1"
            String equals = nameAndColor.getLeft(); // equals = "Passed"
            setConditionalFormattingConditionForColor(fcs, equals, color);
        }
    }
private static Pair<String, String> createNameAndColorLookupPropertyDTO(Object valueObject) {
        if (valueObject != null) {
            if (valueObject instanceof TestRunStatus) {
                return new Pair<>(((TestRunStatus) valueObject).getName(), ((TestRunStatus) valueObject).getColor());
            }
        }
        return null;
    }
private void setConditionalFormattingConditionForColor(FormatConditionCollection fcs, String formula, String hexColorString) {
        Color color = AsposeCellsUtil.hex2Color(hexColorString);
        if (color != null) {
            int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL, formula, null);
            FormatCondition fc = fcs.get(ii);
            Style ss = fc.getStyle();
            ss.setBackgroundColor(color);
            fc.setStyle(ss);
        }
    }

@jguo
Thanks for further details. Let us investigate and analyze your issue in details.Once we have an update on it, we will let you know.

@jguo
By running the sample code replied earlier, the conditional style color can be correctly set, indicating the conditional style function of Cells is normal.

By analyzing your sample code, there is no problem with the logic of changing colors, and it can be set correctly. We found that the setCellAreaBackgroundColorsForLookups function for adding conditional formatting regions was not called in the sample code. Please check if your business logic is complete.

Would you like to share a runnable console program and sample file to reproduce the issue? We will check it soon.

@John.He

We were checking our code these days and we found the reason. We currently exporte the Excel file with .xls extension, with .xls we got the wrong cell background color but if we change it to .xlsx, the background color displayed as expected.

Can you provide an example code export the Excel file with .xls extension and with the same color that I provided?

@jguo
By using the following sample code for testing in the latest version v24.1, we can obtain the correct results. Please refer to the attachment. result.zip (9.4 KB)

The sample code as follows:

Workbook workbook =  new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
Cells cells = sheet.getCells();
cells.get("B3").putValue("Passed");
cells.get("B4").putValue("Passed1111");
cells.get("B5").putValue("Passed");

cells.get("C3").putValue("In Progress");
cells.get("C4").putValue("In Progress1111");
cells.get("C5").putValue("In Progress");

cells.get("D3").putValue("Failed");
cells.get("D4").putValue("Failed2222");
cells.get("D5").putValue("Failed");

cells.get("E3").putValue("Blocked");
cells.get("E4").putValue("Blocked3333");
cells.get("E5").putValue("Blocked");


cells.get("F3").putValue("Not applicable");
cells.get("F4").putValue("Not applicable5555");
cells.get("F5").putValue("Not applicable");
	
ConditionalFormattingCollection cfs =sheet.getConditionalFormattings();
Color color = hex2Color("9CE78C");//Color.fromArgb(156231140);
String compareStr = "Passed";
CellArea cellArea = CellArea.createCellArea("B3", "B5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell b10 = cells.get("B10");		
b10.putValue("test test");
Style b10Style = b10.getStyle();
b10Style.setForegroundColor(color);
b10Style.setPattern(BackgroundType.SOLID);
b10.setStyle(b10Style);

color = hex2Color("9CE0E1");//Color.fromArgb(156224225);
compareStr = "In Progress";
cellArea = CellArea.createCellArea("C3", "C5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell c10 = cells.get("C10");		
c10.putValue("test test");
Style c10Style = c10.getStyle();
c10Style.setForegroundColor(color);
c10Style.setPattern(BackgroundType.SOLID);
c10.setStyle(c10Style);

color = hex2Color("E39191");//Color.fromArgb(227145145);
compareStr = "Failed";
cellArea = CellArea.createCellArea("D3", "D5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell d10 = cells.get("D10");		
d10.putValue("test test");
Style d10Style = d10.getStyle();
d10Style.setForegroundColor(color);
d10Style.setPattern(BackgroundType.SOLID);
d10.setStyle(d10Style);

color = hex2Color("F8B275");//Color.fromArgb(248178117);
compareStr = "Blocked";
cellArea = CellArea.createCellArea("E3", "E5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);

Cell e10 = cells.get("E10");		
e10.putValue("test test");
Style e10Style = e10.getStyle();
e10Style.setForegroundColor(color);
e10Style.setPattern(BackgroundType.SOLID);
e10.setStyle(e10Style);

color = hex2Color("C3C3C3");//Color.fromArgb(195195195);
compareStr = "Not applicable";
cellArea = CellArea.createCellArea("F3", "F5");
AddConfitionalFormat(cfs, compareStr, color, cellArea);		

Cell f10 = cells.get("F10");		
f10.putValue("test test");
Style f10Style = f10.getStyle();
f10Style.setForegroundColor(color);
f10Style.setPattern(BackgroundType.SOLID);
f10.setStyle(f10Style);

workbook.save(filePath + "out_java_hexcolor.xls");
workbook.save(filePath + "out_java_hexcolor.xlsx");


private static void AddConfitionalFormat(ConditionalFormattingCollection cfs, String str, Color color, CellArea cellArea)
{
	int index = cfs.add();
	FormatConditionCollection fcs = cfs.get(index);
	   
	int ii = fcs.addCondition(FormatConditionType.CELL_VALUE, OperatorType.EQUAL, str, null);		

	FormatCondition fc = fcs.get(ii);
	Style ss = fc.getStyle();
	ss.setBackgroundColor(color);
	fc.setStyle(ss);
	
	fcs.addArea(cellArea);
}

If you still have any questions or confusion, please provide your sample code and we will check it soon.

@John.He

After analyzed the sampe code that you provided and we did some POC. We was able to fixed the issue. I’m going to share the solution here. Thank you

Before

 public void setValidationForFieldAndColumn(Integer rowIndex, Integer columnIndex, DocumentTypeFieldDTO typeField) {
        setValidationForFieldAndColumn(rowIndex, columnIndex, new FieldData(typeField));
    }

After

 public void setValidationForFieldAndColumn(Integer rowIndex, Integer columnIndex, DocumentTypeFieldDTO typeField, Worksheet worksheet) { // Now we are passing the argument worksheet here
        setValidationForFieldAndColumn(rowIndex, columnIndex, new FieldData(typeField), worksheet);
    }

Before

private void setValidationForFieldAndColumn(Integer rowIndex, Integer columnIndex, FieldData typeField) {
    CellArea area = setValidationForRangeNameAndColumn(rowIndex, columnIndex, rangeName, typeField.readOnly);
    Collection<?> options = ensureLookupTypeValuesExist(typeField);
    setCellAreaBackgroundColorsForLookups(area, rangeName, options); // deleted this method that I shared previous comment
}

After

private void setValidationForFieldAndColumn(Integer rowIndex, Integer columnIndex, FieldData typeField, Worksheet worksheet) { // Now we are passing the argument worksheet here
    CellArea area = setValidationForRangeNameAndColumn(rowIndex, columnIndex, rangeName, typeField.readOnly);
    Collection<?> options = ensureLookupTypeValuesExist(typeField);

    ConditionalFormattingCollection fcs = worksheet.getConditionalFormattings();
    validationAndFormatting.createConditionalFormatting(fcs, options, area);
}

Deleted getConditionalFormattingForRange method
Refactor the method createConditionalFormatting

Before

private void createConditionalFormatting(FormatConditionCollection fcs, Collection<?> options) {
    for (Object option : options) {
        Pair<String, String> nameAndColor = createNameAndColorLookupPropertyDTO(option);
        String color = nameAndColor.getRight();
        String equals = nameAndColor.getLeft();
        setConditionalFormattingConditionForColor(fcs, equals, color);
    }
}

After
Deleted setConditionalFormattingConditionForColor

protected void createConditionalFormatting(ConditionalFormattingCollection fcs, Collection<?> options, CellArea cellArea)
{
    if (AsposeCellsUtil.optionsHaveAtLeastOneColor(options)) {
        for (Object option : options) {
            Pair<String, String> nameAndColor = createNameAndColorLookupPropertyDTO(option);
            String hexColorString = nameAndColor.getRight();
            Color color =  AsposeCellsUtil.hex2Color(hexColorString);
            String statusName = nameAndColor.getLeft();
            addConditionalFormatForColor(fcs, statusName, color, cellArea);
        }
    }
 }

Before

public ExcelExportContent runExcelTemplateReport(ExcelExportContext context,
                                                     Map<String, String> specifiedReportParameters,
                                                     Map<String, Object> officeTemplateModel,
                                                     SimpleDateFormat dateFmt,
                                                     Report report,
                                                     QuickReportDTO quickReportDto
    ) throws Exception {
    
    Worksheet worksheet = workbook.getWorksheets().get(0);
    for(int i = 0; i < rowsList.size(); i++) { // Loop Row
        for(DocumentTypeField field : documentTypeFieldList) { // Loop each column for current row

           comboCreator.setValidationForFieldAndColumn(nextRow.getIndex(), context.getCurIndex() - 1, field);

        }
    }

}

After

public ExcelExportContent runExcelTemplateReport(ExcelExportContext context,
                                                     Map<String, String> specifiedReportParameters,
                                                     Map<String, Object> officeTemplateModel,
                                                     SimpleDateFormat dateFmt,
                                                     Report report,
                                                     QuickReportDTO quickReportDto
    ) throws Exception {
    
    Worksheet worksheet = workbook.getWorksheets().get(0);
    for(int i = 0; i < rowsList.size(); i++) { // Loop Row
        for(DocumentTypeField field : documentTypeFieldList) { // Loop each column for current row

           comboCreator.setValidationForFieldAndColumn(nextRow.getIndex(), context.getCurIndex() - 1, field, worksheet); // Now we are passing the argument worksheet here

        }
     }
 }

@jguo
Thank you for your feedback. I’m glad your issue has been resolved. You are welcome. If you have any questions, please feel free to contact us.