Fix for bug 45682 - allow cloning of sheets with conditional formatting

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@688655 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-08-25 08:30:54 +00:00
parent 02608ba18d
commit 57765829b9
7 changed files with 69 additions and 71 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.1.1-alpha1" date="2008-??-??"> <release version="3.1.1-alpha1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">45682 - Fix for cloning of CFRecordsAggregate</action>
<action dev="POI-DEVELOPERS" type="add">Initial support for evaluating external add-in functions like YEARFRAC</action> <action dev="POI-DEVELOPERS" type="add">Initial support for evaluating external add-in functions like YEARFRAC</action>
<action dev="POI-DEVELOPERS" type="fix">45672 - Fix for MissingRecordAwareHSSFListener to prevent multiple LastCellOfRowDummyRecords when shared formulas are present</action> <action dev="POI-DEVELOPERS" type="fix">45672 - Fix for MissingRecordAwareHSSFListener to prevent multiple LastCellOfRowDummyRecords when shared formulas are present</action>
<action dev="POI-DEVELOPERS" type="fix">45645 - Fix for HSSFSheet.autoSizeColumn() for widths exceeding Short.MAX_VALUE</action> <action dev="POI-DEVELOPERS" type="fix">45645 - Fix for HSSFSheet.autoSizeColumn() for widths exceeding Short.MAX_VALUE</action>

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.1.1-alpha1" date="2008-??-??"> <release version="3.1.1-alpha1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">45682 - Fix for cloning of CFRecordsAggregate</action>
<action dev="POI-DEVELOPERS" type="add">Initial support for evaluating external add-in functions like YEARFRAC</action> <action dev="POI-DEVELOPERS" type="add">Initial support for evaluating external add-in functions like YEARFRAC</action>
<action dev="POI-DEVELOPERS" type="fix">45672 - Fix for MissingRecordAwareHSSFListener to prevent multiple LastCellOfRowDummyRecords when shared formulas are present</action> <action dev="POI-DEVELOPERS" type="fix">45672 - Fix for MissingRecordAwareHSSFListener to prevent multiple LastCellOfRowDummyRecords when shared formulas are present</action>
<action dev="POI-DEVELOPERS" type="fix">45645 - Fix for HSSFSheet.autoSizeColumn() for widths exceeding Short.MAX_VALUE</action> <action dev="POI-DEVELOPERS" type="fix">45645 - Fix for HSSFSheet.autoSizeColumn() for widths exceeding Short.MAX_VALUE</action>

View File

@ -18,14 +18,12 @@
package org.apache.poi.hssf.record.aggregates; package org.apache.poi.hssf.record.aggregates;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.CellRangeAddress; import org.apache.poi.hssf.util.CellRangeAddress;
/** /**
@ -36,12 +34,10 @@ import org.apache.poi.hssf.util.CellRangeAddress;
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
* *
*/ */
public final class CFRecordsAggregate extends Record { public final class CFRecordsAggregate extends RecordAggregate {
/** Excel allows up to 3 conditional formating rules */ /** Excel allows up to 3 conditional formating rules */
private static final int MAX_CONDTIONAL_FORMAT_RULES = 3; private static final int MAX_CONDTIONAL_FORMAT_RULES = 3;
public final static short sid = -2008; // not a real BIFF record
private final CFHeaderRecord header; private final CFHeaderRecord header;
/** List of CFRuleRecord objects */ /** List of CFRuleRecord objects */
@ -107,45 +103,6 @@ public final class CFRecordsAggregate extends Record {
return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs); return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
} }
protected void fillFields(RecordInputStream in)
{
// You never fill an aggregate record
}
public short getSid()
{
return sid;
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize(int offset, byte[] data)
{
int nRules = rules.size();
header.setNumberOfConditionalFormats(nRules);
int pos = offset;
pos += header.serialize(pos, data);
for(int i=0; i< nRules; i++) {
pos += getRule(i).serialize(pos, data);
}
return pos - offset;
}
protected void validateSid(short id)
{
// do nothing here
}
/** /**
* @return the header. Never <code>null</code>. * @return the header. Never <code>null</code>.
*/ */
@ -165,10 +122,16 @@ public final class CFRecordsAggregate extends Record {
return (CFRuleRecord) rules.get(idx); return (CFRuleRecord) rules.get(idx);
} }
public void setRule(int idx, CFRuleRecord r) { public void setRule(int idx, CFRuleRecord r) {
if (r == null) {
throw new IllegalArgumentException("r must not be null");
}
checkRuleIndex(idx); checkRuleIndex(idx);
rules.set(idx, r); rules.set(idx, r);
} }
public void addRule(CFRuleRecord r) { public void addRule(CFRuleRecord r) {
if (r == null) {
throw new IllegalArgumentException("r must not be null");
}
if(rules.size() >= MAX_CONDTIONAL_FORMAT_RULES) { if(rules.size() >= MAX_CONDTIONAL_FORMAT_RULES) {
throw new IllegalStateException("Cannot have more than " throw new IllegalStateException("Cannot have more than "
+ MAX_CONDTIONAL_FORMAT_RULES + " conditional format rules"); + MAX_CONDTIONAL_FORMAT_RULES + " conditional format rules");
@ -180,26 +143,6 @@ public final class CFRecordsAggregate extends Record {
return rules.size(); return rules.size();
} }
/**
* @return sum of sizes of all aggregated records
*/
public int getRecordSize()
{
int size = 0;
if( header != null)
{
size += header.getRecordSize();
}
if( rules != null)
{
for(Iterator irecs = rules.iterator(); irecs.hasNext(); )
{
size += (( Record ) irecs.next()).getRecordSize();
}
}
return size;
}
/** /**
* String representation of CFRecordsAggregate * String representation of CFRecordsAggregate
*/ */
@ -215,12 +158,17 @@ public final class CFRecordsAggregate extends Record {
for(int i=0; i<rules.size(); i++) for(int i=0; i<rules.size(); i++)
{ {
CFRuleRecord cfRule = (CFRuleRecord)rules.get(i); CFRuleRecord cfRule = (CFRuleRecord)rules.get(i);
if(cfRule!=null) buffer.append(cfRule.toString());
{
buffer.append(cfRule.toString());
}
} }
buffer.append("[/CF]\n"); buffer.append("[/CF]\n");
return buffer.toString(); return buffer.toString();
} }
public void visitContainedRecords(RecordVisitor rv) {
rv.visitRecord(header);
for(int i=0; i<rules.size(); i++) {
CFRuleRecord rule = (CFRuleRecord)rules.get(i);
rv.visitRecord(rule);
}
}
} }

View File

@ -22,7 +22,6 @@ import java.util.List;
import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.Record;
/** /**
* Holds all the conditional formatting for a workbook sheet.<p/> * Holds all the conditional formatting for a workbook sheet.<p/>
@ -53,7 +52,8 @@ public final class ConditionalFormattingTable extends RecordAggregate {
public void visitContainedRecords(RecordVisitor rv) { public void visitContainedRecords(RecordVisitor rv) {
for (int i = 0; i < _cfHeaders.size(); i++) { for (int i = 0; i < _cfHeaders.size(); i++) {
rv.visitRecord((Record) _cfHeaders.get(i)); CFRecordsAggregate subAgg = (CFRecordsAggregate) _cfHeaders.get(i);
subAgg.visitContainedRecords(rv);
} }
} }

View File

@ -41,6 +41,12 @@ public final class HSSFConditionalFormattingRule
private final HSSFWorkbook workbook; private final HSSFWorkbook workbook;
HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) { HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) {
if (pWorkbook == null) {
throw new IllegalArgumentException("pWorkbook must not be null");
}
if (pRuleRecord == null) {
throw new IllegalArgumentException("pRuleRecord must not be null");
}
workbook = pWorkbook; workbook = pWorkbook;
cfRuleRecord = pRuleRecord; cfRuleRecord = pRuleRecord;
} }

View File

@ -63,7 +63,8 @@ public final class TestCFRecordsAggregate extends TestCase
record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0));
// Serialize // Serialize
byte [] serializedRecord = record.serialize(); byte [] serializedRecord = new byte[record.getRecordSize()];
record.serialize(0, serializedRecord);
InputStream in = new ByteArrayInputStream(serializedRecord); InputStream in = new ByteArrayInputStream(serializedRecord);
//Parse //Parse

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
@ -107,4 +108,44 @@ public final class TestHSSFConditionalFormatting extends TestCase
assertEquals("2",rule2.getFormula2()); assertEquals("2",rule2.getFormula2());
assertEquals("1",rule2.getFormula1()); assertEquals("1",rule2.getFormula1());
} }
public void testClone() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
String formula = "7";
HSSFSheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
HSSFConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula);
HSSFFontFormatting fontFmt = rule1.createFontFormatting();
fontFmt.setFontStyle(true, false);
HSSFPatternFormatting patternFmt = rule1.createPatternFormatting();
patternFmt.setFillBackgroundColor(HSSFColor.YELLOW.index);
HSSFConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2");
HSSFConditionalFormattingRule [] cfRules =
{
rule1, rule2
};
short col = 1;
CellRangeAddress [] regions = {
new CellRangeAddress(0, 65535, col, col)
};
sheetCF.addConditionalFormatting(regions, cfRules);
try {
wb.cloneSheet(0);
} catch (RuntimeException e) {
if (e.getMessage().indexOf("needs to define a clone method") > 0) {
throw new AssertionFailedError("Indentified bug 45682");
}
throw e;
}
assertEquals(2, wb.getNumberOfSheets());
}
} }