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:
parent
02608ba18d
commit
57765829b9
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user