52122: Excel does not handle conditional formatting based on formula correctly unless recalculation is forced

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753199 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2016-07-18 10:32:55 +00:00
parent 35173d9e30
commit abc3072df2
3 changed files with 124 additions and 13 deletions

View File

@ -83,10 +83,18 @@ public final class CFRecordsAggregate extends RecordAggregate {
this(createHeader(regions, rules), rules); this(createHeader(regions, rules), rules);
} }
private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) { private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) {
final CFHeaderBase header;
if (rules.length == 0 || rules[0] instanceof CFRuleRecord) { if (rules.length == 0 || rules[0] instanceof CFRuleRecord) {
return new CFHeaderRecord(regions, rules.length); header = new CFHeaderRecord(regions, rules.length);
} else {
header = new CFHeader12Record(regions, rules.length);
} }
return new CFHeader12Record(regions, rules.length);
// set the "needs recalculate" by default to avoid Excel handling conditional formatting incorrectly
// see bug 52122 for details
header.setNeedRecalculation(true);
return header;
} }
/** /**

View File

@ -64,8 +64,7 @@ public final class TestCFRecordsAggregate extends TestCase {
recs.add(rule1); recs.add(rule1);
recs.add(rule2); recs.add(rule2);
recs.add(rule3); recs.add(rule3);
CFRecordsAggregate record; CFRecordsAggregate record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0));
record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0));
// Serialize // Serialize
byte [] serializedRecord = new byte[record.getRecordSize()]; byte [] serializedRecord = new byte[record.getRecordSize()];
@ -81,12 +80,16 @@ public final class TestCFRecordsAggregate extends TestCase {
header = (CFHeaderRecord)recs.get(0); header = (CFHeaderRecord)recs.get(0);
rule1 = (CFRuleRecord)recs.get(1); rule1 = (CFRuleRecord)recs.get(1);
assertNotNull(rule1);
rule2 = (CFRuleRecord)recs.get(2); rule2 = (CFRuleRecord)recs.get(2);
assertNotNull(rule2);
rule3 = (CFRuleRecord)recs.get(3); rule3 = (CFRuleRecord)recs.get(3);
assertNotNull(rule3);
cellRanges = header.getCellRanges(); cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.length); assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats()); assertEquals(3, header.getNumberOfConditionalFormats());
assertFalse(header.getNeedRecalculation());
record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0));
@ -97,12 +100,16 @@ public final class TestCFRecordsAggregate extends TestCase {
header = record.getHeader(); header = record.getHeader();
rule1 = record.getRule(0); rule1 = record.getRule(0);
assertNotNull(rule1);
rule2 = record.getRule(1); rule2 = record.getRule(1);
assertNotNull(rule2);
rule3 = record.getRule(2); rule3 = record.getRule(2);
assertNotNull(rule3);
cellRanges = header.getCellRanges(); cellRanges = header.getCellRanges();
assertEquals(2, cellRanges.length); assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats()); assertEquals(3, header.getNumberOfConditionalFormats());
assertFalse(header.getNeedRecalculation());
} }
/** /**
@ -144,15 +151,20 @@ public final class TestCFRecordsAggregate extends TestCase {
try { try {
new CFRecordsAggregate(cellRanges, rules); new CFRecordsAggregate(cellRanges, rules);
fail("Shouldn't be able to mix between types"); fail("Shouldn't be able to mix between types");
} catch (IllegalArgumentException e) {} } catch (IllegalArgumentException e) {
// expected here
}
rules = new CFRuleBase[] { CFRuleRecord.create(sheet, "7") }; rules = new CFRuleBase[] { CFRuleRecord.create(sheet, "7") };
CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules); CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules);
assertTrue(agg.getHeader().getNeedRecalculation());
try { try {
agg.addRule(CFRule12Record.create(sheet, "7")); agg.addRule(CFRule12Record.create(sheet, "7"));
fail("Shouldn't be able to mix between types"); fail("Shouldn't be able to mix between types");
} catch (IllegalArgumentException e) {} } catch (IllegalArgumentException e) {
// expected here
}
} }
} }

View File

@ -19,16 +19,14 @@ package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BaseTestConditionalFormatting; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Color; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Test; import org.junit.Test;
/** /**
@ -116,10 +114,103 @@ public final class TestHSSFConditionalFormatting extends BaseTestConditionalForm
} }
} }
private void writeTemp53691(Workbook wb, String suffix) throws FileNotFoundException, IOException { private void writeTemp53691(Workbook wb, @SuppressWarnings("UnusedParameters") String suffix) throws IOException {
// assert that we can write/read it in memory // assert that we can write/read it in memory
Workbook wbBack = HSSFITestDataProvider.instance.writeOutAndReadBack(wb); Workbook wbBack = HSSFITestDataProvider.instance.writeOutAndReadBack(wb);
assertNotNull(wbBack); assertNotNull(wbBack);
wbBack.close(); wbBack.close();
} }
@SuppressWarnings("deprecation")
@Test
public void test52122() throws Exception {
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("Conditional Formatting Test");
sheet.setColumnWidth(0, 256 * 10);
sheet.setColumnWidth(1, 256 * 10);
sheet.setColumnWidth(2, 256 * 10);
// Create some content.
// row 0
Row row = sheet.createRow(0);
Cell cell0 = row.createCell(0);
cell0.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell0.setCellValue(100);
Cell cell1 = row.createCell(1);
cell1.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell1.setCellValue(120);
Cell cell2 = row.createCell(2);
cell2.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell2.setCellValue(130);
// row 1
row = sheet.createRow(1);
cell0 = row.createCell(0);
cell0.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell0.setCellValue(200);
cell1 = row.createCell(1);
cell1.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell1.setCellValue(220);
cell2 = row.createCell(2);
cell2.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell2.setCellValue(230);
// row 2
row = sheet.createRow(2);
cell0 = row.createCell(0);
cell0.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell0.setCellValue(300);
cell1 = row.createCell(1);
cell1.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell1.setCellValue(320);
cell2 = row.createCell(2);
cell2.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC);
cell2.setCellValue(330);
// Create conditional formatting, CELL1 should be yellow if CELL0 is not blank.
SheetConditionalFormatting formatting = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule = formatting.createConditionalFormattingRule("$A$1>75");
PatternFormatting pattern = rule.createPatternFormatting();
pattern.setFillBackgroundColor(IndexedColors.BLUE.index);
pattern.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
CellRangeAddress[] range = {CellRangeAddress.valueOf("B2:C2")};
CellRangeAddress[] range2 = {CellRangeAddress.valueOf("B1:C1")};
formatting.addConditionalFormatting(range, rule);
formatting.addConditionalFormatting(range2, rule);
// Write file.
/*FileOutputStream fos = new FileOutputStream("c:\\temp\\52122_conditional-sheet.xls");
try {
workbook.write(fos);
} finally {
fos.close();
}*/
Workbook wbBack = HSSFTestDataSamples.writeOutAndReadBack((HSSFWorkbook)workbook);
Sheet sheetBack = wbBack.getSheetAt(0);
final SheetConditionalFormatting sheetConditionalFormattingBack = sheetBack.getSheetConditionalFormatting();
assertNotNull(sheetConditionalFormattingBack);
final ConditionalFormatting formattingBack = sheetConditionalFormattingBack.getConditionalFormattingAt(0);
assertNotNull(formattingBack);
final ConditionalFormattingRule ruleBack = formattingBack.getRule(0);
assertNotNull(ruleBack);
final PatternFormatting patternFormattingBack1 = ruleBack.getPatternFormatting();
assertNotNull(patternFormattingBack1);
assertEquals(IndexedColors.BLUE.index, patternFormattingBack1.getFillBackgroundColor());
assertEquals(PatternFormatting.SOLID_FOREGROUND, patternFormattingBack1.getFillPattern());
}
} }