From 356410c13c4e794a9ef812ebfc774662a182729a Mon Sep 17 00:00:00 2001
From: Nick Burch
Date: Sat, 29 Mar 2008 17:00:47 +0000
Subject: [PATCH] Merged revisions
638001-638784,638786-639486,639488-639601,639603-639836 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk
........
r638803 | nick | 2008-03-19 11:57:38 +0000 (Wed, 19 Mar 2008) | 1 line
Added test to show that bug #41546 is already fixed. Also rename a test file to be more consistent
........
r638804 | nick | 2008-03-19 12:01:32 +0000 (Wed, 19 Mar 2008) | 1 line
Add test to show that bug #43251 is already fixed
........
r638812 | nick | 2008-03-19 12:28:56 +0000 (Wed, 19 Mar 2008) | 1 line
Patch from Dmitriy from bug #30311 - Support for conditional formatting records
........
r638815 | nick | 2008-03-19 12:49:35 +0000 (Wed, 19 Mar 2008) | 1 line
Fix bug #44627 - improve the thread safety of POILogFactory
........
r639231 | nick | 2008-03-20 10:06:59 +0000 (Thu, 20 Mar 2008) | 1 line
Test relating to bug #44636
........
r639232 | nick | 2008-03-20 10:16:15 +0000 (Thu, 20 Mar 2008) | 1 line
Simple patch from Josh from bug #44636 - fix for RefVPtg and edit-in-excel oddness
........
r639242 | nick | 2008-03-20 11:02:39 +0000 (Thu, 20 Mar 2008) | 1 line
Fix for readCompressedUnicode not moaning about length=0, from bug #44643
........
r639254 | nick | 2008-03-20 11:43:14 +0000 (Thu, 20 Mar 2008) | 1 line
Make junit happy
........
r639836 | nick | 2008-03-21 21:04:47 +0000 (Fri, 21 Mar 2008) | 1 line
Tweak how you get dataformat strings out of cell styles, to be more logical, and in keeping with how we'll want to do things for xssf too
........
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@642557 13f79535-47bb-0310-9956-ffa450edef68
---
src/documentation/content/xdocs/changes.xml | 3 +
src/documentation/content/xdocs/status.xml | 3 +
src/java/org/apache/poi/hssf/model/Sheet.java | 73 ++
.../poi/hssf/record/CFHeaderRecord.java | 223 ++++++
.../apache/poi/hssf/record/CFRuleRecord.java | 657 ++++++++++++++++++
.../apache/poi/hssf/record/RecordFactory.java | 2 +
.../poi/hssf/record/RecordInputStream.java | 5 +-
.../poi/hssf/record/SharedFormulaRecord.java | 42 +-
.../record/aggregates/CFRecordsAggregate.java | 224 ++++++
.../poi/hssf/record/cf/BorderFormatting.java | 560 +++++++++++++++
.../apache/poi/hssf/record/cf/CellRange.java | 259 +++++++
.../poi/hssf/record/cf/FontFormatting.java | 591 ++++++++++++++++
.../poi/hssf/record/cf/PatternFormatting.java | 206 ++++++
.../poi/hssf/record/formula/RefVPtg.java | 1 +
.../hssf/usermodel/HSSFBorderFormatting.java | 128 ++++
.../poi/hssf/usermodel/HSSFCellStyle.java | 12 +-
.../usermodel/HSSFConditionalFormatting.java | 201 ++++++
.../HSSFConditionalFormattingRule.java | 248 +++++++
.../hssf/usermodel/HSSFFontFormatting.java | 456 ++++++++++++
.../hssf/usermodel/HSSFPatternFormatting.java | 134 ++++
.../apache/poi/hssf/usermodel/HSSFSheet.java | 158 +++++
.../org/apache/poi/util/POILogFactory.java | 73 +-
.../hssf/usermodel/HSSFFormulaEvaluator.java | 30 +
.../usermodel/TestFormulaEvaluatorBugs.java | 88 +++
.../org/apache/poi/hssf/data/41546.xls | Bin 0 -> 18432 bytes
.../org/apache/poi/hssf/data/43251.xls | Bin 0 -> 166400 bytes
.../poi/hssf/data/{Bug44593.xls => 44593.xls} | Bin
.../org/apache/poi/hssf/data/44636.xls | Bin 0 -> 13824 bytes
.../org/apache/poi/hssf/data/44643.xls | Bin 0 -> 15872 bytes
.../poi/hssf/record/TestCFHeaderRecord.java | 145 ++++
.../poi/hssf/record/TestCFRuleRecord.java | 296 ++++++++
.../aggregates/TestCFRecordsAggregate.java | 111 +++
.../poi/hssf/record/cf/TestCellRange.java | 139 ++++
.../apache/poi/hssf/usermodel/TestBugs.java | 52 +-
.../poi/poifs/storage/TestRawDataBlock.java | 22 +-
.../poifs/storage/TestRawDataBlockList.java | 23 +-
36 files changed, 5104 insertions(+), 61 deletions(-)
create mode 100644 src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
create mode 100644 src/java/org/apache/poi/hssf/record/CFRuleRecord.java
create mode 100644 src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
create mode 100644 src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/record/cf/CellRange.java
create mode 100644 src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java
create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java
create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFPatternFormatting.java
create mode 100644 src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
create mode 100644 src/testcases/org/apache/poi/hssf/data/41546.xls
create mode 100644 src/testcases/org/apache/poi/hssf/data/43251.xls
rename src/testcases/org/apache/poi/hssf/data/{Bug44593.xls => 44593.xls} (100%)
create mode 100644 src/testcases/org/apache/poi/hssf/data/44636.xls
create mode 100644 src/testcases/org/apache/poi/hssf/data/44643.xls
create mode 100644 src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java
create mode 100644 src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
create mode 100644 src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
create mode 100644 src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java
diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index 4bfd32b0e..b1504a702 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -36,6 +36,9 @@
+ 44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits
+ 44627 - Improve the thread safety of POILogFactory
+ 30311 - Initial support for Conditional Formatting
44609 - Handle leading spaces in formulas, such as '= 4'
44608 - Support for PercentPtg in the formula evaluator
44606 - Support calculated string values for evaluated formulas
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index a6467d516..d29d57ff8 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -33,6 +33,9 @@
+ 44636 - Fix formula parsing of RefVPtg, which was causing #VALUE to be shown on subsequent edits
+ 44627 - Improve the thread safety of POILogFactory
+ 30311 - Initial support for Conditional Formatting
44609 - Handle leading spaces in formulas, such as '= 4'
44608 - Support for PercentPtg in the formula evaluator
44606 - Support calculated string values for evaluated formulas
diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java
index f3f7deba0..451cde757 100644
--- a/src/java/org/apache/poi/hssf/model/Sheet.java
+++ b/src/java/org/apache/poi/hssf/model/Sheet.java
@@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
+import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.util.PaneInformation;
@@ -96,6 +97,7 @@ public class Sheet implements Model
protected ObjectProtectRecord objprotect = null;
protected ScenarioProtectRecord scenprotect = null;
protected PasswordRecord password = null;
+ protected List condFormatting = new ArrayList();;
/** Add an UncalcedRecord if not true indicating formulas have not been calculated */
protected boolean uncalced = false;
@@ -184,6 +186,17 @@ public class Sheet implements Model
retval.merged = ( MergeCellsRecord ) rec;
retval.numMergedRegions += retval.merged.getNumAreas();
}
+ else if ( rec.getSid() == CFHeaderRecord.sid )
+ {
+ CFRecordsAggregate cfAgg = CFRecordsAggregate.createCFAggregate(recs, k);
+ retval.condFormatting.add(cfAgg);
+ rec = cfAgg;
+ }
+ else if ( rec.getSid() == CFRuleRecord.sid )
+ {
+ // Skip it since it is processed by CFRecordsAggregate
+ rec = null;
+ }
else if (rec.getSid() == ColumnInfoRecord.sid)
{
ColumnInfoRecord col = (ColumnInfoRecord)rec;
@@ -604,6 +617,66 @@ public class Sheet implements Model
{
return numMergedRegions;
}
+ // Find correct position to add new CF record
+ private int findConditionalFormattingPosition()
+ {
+ // This is default.
+ // If the algorithm does not find the right position,
+ // this one will be used (this is a position before EOF record)
+ int index = records.size()-2;
+
+ for( int i=index; i>=0; i-- )
+ {
+ Record rec = (Record)records.get(i);
+ short sid = rec.getSid();
+
+ // CFRecordsAggregate records already exist, just add to the end
+ if (rec instanceof CFRecordsAggregate) { return i+1; }
+
+ if( sid == (short)0x00ef ) { return i+1; }// PHONETICPR
+ if( sid == (short)0x015f ) { return i+1; }// LABELRANGES
+ if( sid == MergeCellsRecord.sid ) { return i+1; }
+ if( sid == (short)0x0099 ) { return i+1; }// STANDARDWIDTH
+ if( sid == SelectionRecord.sid ) { return i+1; }
+ if( sid == PaneRecord.sid ) { return i+1; }
+ if( sid == SCLRecord.sid ) { return i+1; }
+ if( sid == WindowTwoRecord.sid ) { return i+1; }
+ }
+
+ return index;
+ }
+
+ public int addConditionalFormatting(CFRecordsAggregate cfAggregate)
+ {
+ int index = findConditionalFormattingPosition();
+ records.add(index, cfAggregate);
+ condFormatting.add(cfAggregate);
+ return condFormatting.size()-1;
+ }
+
+ public void removeConditionalFormatting(int index)
+ {
+ if (index >= 0 && index <= condFormatting.size()-1 )
+ {
+ CFRecordsAggregate cfAggregate = getCFRecordsAggregateAt(index);
+ records.remove(cfAggregate);
+ condFormatting.remove(index);
+ }
+ }
+
+ public CFRecordsAggregate getCFRecordsAggregateAt(int index)
+ {
+ if (index >= 0 && index <= condFormatting.size()-1 )
+ {
+ return (CFRecordsAggregate) condFormatting.get(index);
+ }
+ return null;
+ }
+
+ public int getNumConditionalFormattings()
+ {
+ return condFormatting.size();
+ }
/**
* Returns the number of low level binary records in this sheet. This adjusts things for the so called
diff --git a/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java b/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
new file mode 100644
index 000000000..00a8646b4
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
@@ -0,0 +1,223 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+/*
+ * ConditionalFormattingHeaderRecord.java
+ *
+ * Created on January 17, 2008, 3:05 AM
+ */
+package org.apache.poi.hssf.record;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.hssf.record.cf.CellRange;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Conditional Formatting Header record (CFHEADER)
+ *
+ * @author Dmitriy Kumshayev
+ */
+public class CFHeaderRecord extends Record
+{
+ public static final short sid = 0x1B0;
+
+ private int field_1_numcf;
+ private int field_2_need_recalculation;
+ private CellRange field_3_enclosing_cell_range;
+ private List field_4_cell_ranges;
+
+ /** Creates new CFHeaderRecord */
+ public CFHeaderRecord()
+ {
+ field_4_cell_ranges = new ArrayList(5);
+ }
+
+ public CFHeaderRecord(RecordInputStream in)
+ {
+ super(in);
+ }
+
+ protected void fillFields(RecordInputStream in)
+ {
+ field_1_numcf = in.readShort();
+ field_2_need_recalculation = in.readShort();
+ field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
+ int numCellRanges = in.readShort();
+ field_4_cell_ranges = new ArrayList(5);
+ for( int i=0; i0)
+ {
+ buffer.append(" .cfranges=[");
+ for( int i=0; i0)
+ {
+ field_17_formula1 = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
+
+ // Now convert any fields as required
+ field_17_formula1 = SharedFormulaRecord.convertSharedFormulas(
+ field_17_formula1, 0, 0
+ );
+ }
+ if(field_4_formula2_len>0)
+ {
+ field_18_formula2 = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
+
+ // Now convert any fields as required
+ field_18_formula2 = SharedFormulaRecord.convertSharedFormulas(
+ field_18_formula2, 0, 0
+ );
+ }
+ } catch (java.lang.UnsupportedOperationException uoe) {
+ throw new RecordFormatException(uoe);
+ }
+
+ }
+
+ public void setConditionType(byte conditionType)
+ {
+ field_1_condition_type =
+ conditionType == CONDITION_TYPE_CELL_VALUE_IS ?
+ CONDITION_TYPE_CELL_VALUE_IS :
+ CONDITION_TYPE_FORMULA;
+ }
+
+ public byte getConditionType()
+ {
+ return field_1_condition_type;
+ }
+
+ /**
+ * set the option flags
+ *
+ * @param options bitmask
+ */
+
+ public void setOptions(int options)
+ {
+ field_5_options = options;
+ }
+
+ public boolean containsFontFormattingBlock()
+ {
+ return getOptionFlag(font);
+ }
+ public void setFontFormatting(FontFormatting fontFormatting)
+ {
+ this.fontFormatting = fontFormatting;
+ setOptionFlag(true,font);
+ }
+ public void setFontFormattingUnchanged()
+ {
+ setOptionFlag(false,font);
+ }
+
+ public boolean containsAlignFormattingBlock()
+ {
+ return getOptionFlag(align);
+ }
+ public void setAlignFormattingUnchanged()
+ {
+ setOptionFlag(false,align);
+ }
+
+ public boolean containsBorderFormattingBlock()
+ {
+ return getOptionFlag(bord);
+ }
+ public void setBorderFormatting(BorderFormatting borderFormatting)
+ {
+ this.borderFormatting = borderFormatting;
+ setOptionFlag(true,bord);
+ }
+ public void setBorderFormattingUnchanged()
+ {
+ setOptionFlag(false,bord);
+ }
+
+ public boolean containsPatternFormattingBlock()
+ {
+ return getOptionFlag(patt);
+ }
+ public void setPatternFormatting(PatternFormatting patternFormatting)
+ {
+ this.patternFormatting = patternFormatting;
+ setOptionFlag(true,patt);
+ }
+ public void setPatternFormattingUnchanged()
+ {
+ setOptionFlag(false,patt);
+ }
+
+ public boolean containsProtectionFormattingBlock()
+ {
+ return getOptionFlag(prot);
+ }
+ public void setProtectionFormattingUnchanged()
+ {
+ setOptionFlag(false,prot);
+ }
+
+ public void setComparisonOperation(byte operation)
+ {
+ field_2_comparison_operator = operation;
+ }
+
+ public byte getComparisonOperation()
+ {
+ return field_2_comparison_operator;
+ }
+
+ /**
+ * set the length (in number of tokens) of the expression 1
+ * @param len length
+ */
+
+ private void setExpression1Length(short len)
+ {
+ field_3_formula1_len = len;
+ }
+
+ /**
+ * get the length (in number of tokens) of the expression 1
+ * @return expression length
+ */
+
+ public short getExpression1Length()
+ {
+ return field_3_formula1_len;
+ }
+
+ /**
+ * set the length (in number of tokens) of the expression 2
+ * @param len length
+ */
+
+ private void setExpression2Length(short len)
+ {
+ field_4_formula2_len = len;
+ }
+
+ /**
+ * get the length (in number of tokens) of the expression 2
+ * @return expression length
+ */
+
+ public short getExpression2Length()
+ {
+ return field_4_formula2_len;
+ }
+ /**
+ * get the option flags
+ *
+ * @return bit mask
+ */
+ public int getOptions()
+ {
+ return field_5_options;
+ }
+
+ private boolean isModified(BitField field)
+ {
+ return !field.isSet(field_5_options);
+ }
+
+ private void setModified(boolean modified, BitField field)
+ {
+ field_5_options = field.setBoolean(field_5_options, !modified);
+ }
+
+ public boolean isLeftBorderModified()
+ {
+ return isModified(bordLeft);
+ }
+
+ public void setLeftBorderModified(boolean modified)
+ {
+ setModified(modified,bordLeft);
+ }
+
+ public boolean isRightBorderModified()
+ {
+ return isModified(bordRight);
+ }
+
+ public void setRightBorderModified(boolean modified)
+ {
+ setModified(modified,bordRight);
+ }
+
+ public boolean isTopBorderModified()
+ {
+ return isModified(bordTop);
+ }
+
+ public void setTopBorderModified(boolean modified)
+ {
+ setModified(modified,bordTop);
+ }
+
+ public boolean isBottomBorderModified()
+ {
+ return isModified(bordBot);
+ }
+
+ public void setBottomBorderModified(boolean modified)
+ {
+ setModified(modified,bordBot);
+ }
+
+ public boolean isTopLeftBottomRightBorderModified()
+ {
+ return isModified(bordTlBr);
+ }
+
+ public void setTopLeftBottomRightBorderModified(boolean modified)
+ {
+ setModified(modified,bordTlBr);
+ }
+
+ public boolean isBottomLeftTopRightBorderModified()
+ {
+ return isModified(bordBlTr);
+ }
+
+ public void setBottomLeftTopRightBorderModified(boolean modified)
+ {
+ setModified(modified,bordBlTr);
+ }
+
+ public boolean isPatternStyleModified()
+ {
+ return isModified(pattStyle);
+ }
+
+ public void setPatternStyleModified(boolean modified)
+ {
+ setModified(modified,pattStyle);
+ }
+
+ public boolean isPatternColorModified()
+ {
+ return isModified(pattCol);
+ }
+
+ public void setPatternColorModified(boolean modified)
+ {
+ setModified(modified,pattCol);
+ }
+
+ public boolean isPatternBackgroundColorModified()
+ {
+ return isModified(pattBgCol);
+ }
+
+ public void setPatternBackgroundColorModified(boolean modified)
+ {
+ setModified(modified,pattBgCol);
+ }
+
+ private boolean getOptionFlag(BitField field)
+ {
+ return field.isSet(field_5_options);
+ }
+
+ private void setOptionFlag(boolean flag, BitField field)
+ {
+ field_5_options = field.setBoolean(field_5_options, flag);
+ }
+
+ /**
+ * get the stack of the 1st expression as a list
+ *
+ * @return list of tokens (casts stack to a list and returns it!)
+ * this method can return null is we are unable to create Ptgs from
+ * existing excel file
+ * callers should check for null!
+ */
+
+ public List getParsedExpression1()
+ {
+ return field_17_formula1;
+ }
+
+ /**
+ * get the stack of the 2nd expression as a list
+ *
+ * @return list of tokens (casts stack to a list and returns it!)
+ * this method can return null is we are unable to create Ptgs from
+ * existing excel file
+ * callers should check for null!
+ */
+
+ public List getParsedExpression2()
+ {
+ return field_18_formula2;
+ }
+
+ public void setParsedExpression1(Stack ptgs) {
+ setExpression1Length(getTotalPtgSize(field_17_formula1 = ptgs));
+ }
+
+ public void setParsedExpression2(Stack ptgs) {
+ setExpression1Length(getTotalPtgSize(field_18_formula2 = ptgs));
+ }
+
+ /**
+ * called by constructor, should throw runtime exception in the event of a
+ * record passed with a differing ID.
+ *
+ * @param id alleged id for this record
+ */
+
+ protected void validateSid(short id)
+ {
+ if (id != sid)
+ {
+ throw new RecordFormatException("NOT A CFRULE 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 recordsize = getRecordSize();
+ LittleEndian.putShort(data, 0 + offset, sid);
+ LittleEndian.putShort(data, 2 + offset, (short)(recordsize-4));
+ data[4 + offset] = field_1_condition_type;
+ data[5 + offset] = field_2_comparison_operator;
+ LittleEndian.putShort(data, 6 + offset, field_3_formula1_len);
+ LittleEndian.putShort(data, 8 + offset, field_4_formula2_len);
+ LittleEndian.putInt(data, 10 + offset, field_5_options);
+ LittleEndian.putShort(data,14 + offset, field_6_not_used);
+
+ offset += 16;
+
+ if( containsFontFormattingBlock() )
+ {
+ byte[] fontFormattingRawRecord = fontFormatting.getRawRecord();
+ System.arraycopy(fontFormattingRawRecord, 0, data, offset, fontFormattingRawRecord.length);
+ offset += fontFormattingRawRecord.length;
+ }
+
+ if( containsBorderFormattingBlock())
+ {
+ offset += borderFormatting.serialize(offset, data);
+ }
+
+ if( containsPatternFormattingBlock() )
+ {
+ offset += patternFormatting.serialize(offset, data);
+ }
+
+ if (getExpression1Length()>0)
+ {
+ Ptg.serializePtgStack(this.field_17_formula1, data, offset);
+ offset += getExpression1Length();
+ }
+
+ if (getExpression2Length()>0)
+ {
+ Ptg.serializePtgStack(this.field_18_formula2, data, offset);
+ offset += getExpression2Length();
+ }
+ return recordsize;
+ }
+
+
+
+
+ public int getRecordSize()
+ {
+ int retval =16+
+ (containsFontFormattingBlock()?fontFormatting.getRawRecord().length:0)+
+ (containsBorderFormattingBlock()?8:0)+
+ (containsPatternFormattingBlock()?4:0)+
+ getExpression1Length()+
+ getExpression2Length()
+ ;
+ return retval;
+ }
+
+ private short getTotalPtgSize(List list)
+ {
+ short retval = 0;
+ if( list!=null)
+ {
+ for (int k = 0; k < list.size(); k++)
+ {
+ Ptg ptg = ( Ptg ) list.get(k);
+
+ retval += ptg.getSize();
+ }
+ }
+ return retval;
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[CFRULE]\n");
+ if( containsFontFormattingBlock())
+ {
+ buffer.append(fontFormatting.toString());
+ }
+ if( containsBorderFormattingBlock())
+ {
+ buffer.append(borderFormatting.toString());
+ }
+ if( containsPatternFormattingBlock())
+ {
+ buffer.append(patternFormatting.toString());
+ }
+ buffer.append("[/CFRULE]\n");
+ return buffer.toString();
+ }
+
+ public Object clone() {
+ CFRuleRecord rec = new CFRuleRecord();
+ rec.field_1_condition_type= field_1_condition_type;
+ rec.field_2_comparison_operator = field_2_comparison_operator;
+ rec.field_3_formula1_len = field_3_formula1_len;
+ rec.field_4_formula2_len = field_4_formula2_len;
+ rec.field_5_options = field_5_options;
+ rec.field_6_not_used = field_6_not_used;
+ if( containsFontFormattingBlock())
+ {
+ rec.fontFormatting = (FontFormatting)fontFormatting.clone();
+ }
+ if( containsBorderFormattingBlock())
+ {
+ rec.borderFormatting = (BorderFormatting)borderFormatting.clone();
+ }
+ if( containsPatternFormattingBlock())
+ {
+ rec.patternFormatting = (PatternFormatting)patternFormatting.clone();
+ }
+ if( field_3_formula1_len>0)
+ {
+ rec.field_17_formula1 = (Stack)field_17_formula1.clone();
+ }
+ if( field_4_formula2_len>0)
+ {
+ rec.field_18_formula2 = (Stack)field_18_formula2.clone();
+ }
+
+ return rec;
+ }
+
+ public FontFormatting getFontFormatting()
+ {
+ return fontFormatting;
+ }
+
+}
diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java
index f247a8d4b..1dada4450 100644
--- a/src/java/org/apache/poi/hssf/record/RecordFactory.java
+++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java
@@ -82,6 +82,8 @@ public class RecordFactory
SupBookRecord.class,
CRNCountRecord.class,
CRNRecord.class,
+ CFHeaderRecord.class,
+ CFRuleRecord.class,
};
}
private static Map recordsMap = recordsToMap(records);
diff --git a/src/java/org/apache/poi/hssf/record/RecordInputStream.java b/src/java/org/apache/poi/hssf/record/RecordInputStream.java
index 431558ccc..ba900b2a2 100755
--- a/src/java/org/apache/poi/hssf/record/RecordInputStream.java
+++ b/src/java/org/apache/poi/hssf/record/RecordInputStream.java
@@ -266,6 +266,9 @@ public class RecordInputStream extends InputStream
}
public String readCompressedUnicode(int length) {
+ if(length == 0) {
+ return "";
+ }
if ((length < 0) || ((remaining() < length) && !isContinueNext())) {
throw new IllegalArgumentException("Illegal length " + length);
}
@@ -273,7 +276,7 @@ public class RecordInputStream extends InputStream
StringBuffer buf = new StringBuffer(length);
for (int i=0;i= formulaRow) &&
(getFirstColumn() <= formulaColumn) && (getLastColumn() >= formulaColumn));
}
-
- /** Creates a non shared formula from the shared formula counter part*/
- public void convertSharedFormulaRecord(FormulaRecord formula) {
- //Sanity checks
- final int formulaRow = formula.getRow();
- final int formulaColumn = formula.getColumn();
- if (isFormulaInShared(formula)) {
- formula.setExpressionLength(getExpressionLength());
+
+ /**
+ * Creates a non shared formula from the shared formula
+ * counter part
+ */
+ protected static Stack convertSharedFormulas(Stack ptgs, int formulaRow, int formulaColumn) {
Stack newPtgStack = new Stack();
- if (field_7_parsed_expr != null)
- for (int k = 0; k < field_7_parsed_expr.size(); k++) {
- Ptg ptg = (Ptg) field_7_parsed_expr.get(k);
+ if (ptgs != null)
+ for (int k = 0; k < ptgs.size(); k++) {
+ Ptg ptg = (Ptg) ptgs.get(k);
if (ptg instanceof RefNPtg) {
RefNPtg refNPtg = (RefNPtg)ptg;
ptg = new ReferencePtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
@@ -243,7 +241,23 @@ public final class SharedFormulaRecord extends Record {
areaNAPtg.isLastColRelative());
}
newPtgStack.add(ptg);
- }
+ }
+ return newPtgStack;
+ }
+
+ /**
+ * Creates a non shared formula from the shared formula
+ * counter part
+ */
+ public void convertSharedFormulaRecord(FormulaRecord formula) {
+ //Sanity checks
+ final int formulaRow = formula.getRow();
+ final int formulaColumn = formula.getColumn();
+ if (isFormulaInShared(formula)) {
+ formula.setExpressionLength(getExpressionLength());
+
+ Stack newPtgStack =
+ convertSharedFormulas(field_7_parsed_expr, formulaRow, formulaColumn);
formula.setParsedExpression(newPtgStack);
//Now its not shared!
formula.setSharedFormula(false);
@@ -252,7 +266,7 @@ public final class SharedFormulaRecord extends Record {
}
}
- private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
+ private static int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at column 256 ("IV")
return (column + currentcolumn) & 0x00FF;
@@ -260,7 +274,7 @@ public final class SharedFormulaRecord extends Record {
return column;
}
- private int fixupRelativeRow(int currentrow, int row, boolean relative) {
+ private static int fixupRelativeRow(int currentrow, int row, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at row 65536
return (row+currentrow) & 0x00FFFF;
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
new file mode 100644
index 000000000..78d1ecbd3
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
@@ -0,0 +1,224 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.hssf.record.aggregates;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.hssf.record.CFHeaderRecord;
+import org.apache.poi.hssf.record.CFRuleRecord;
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * CFRecordsAggregate - aggregates Conditional Formatting records CFHeaderRecord
+ * and number of up to three CFRuleRecord records together to simplify
+ * access to them.
+ *
+ * @author Dmitriy Kumshayev
+ *
+ */
+public class CFRecordsAggregate extends Record
+{
+ public final static short sid = -2008;
+
+ private static POILogger log = POILogFactory.getLogger(CFRecordsAggregate.class);
+
+ private CFHeaderRecord header;
+
+ // List of CFRuleRecord objects
+ private List rules;
+
+ public CFRecordsAggregate()
+ {
+ header = null;
+ rules = new ArrayList(3);
+ }
+
+ /**
+ * Create CFRecordsAggregate from a list of CF Records
+ * @param recs - list of {@link Record} objects
+ * @param offset - position of {@link CFHeaderRecord} object in the list of Record objects
+ * @return CFRecordsAggregate object
+ */
+ public static CFRecordsAggregate createCFAggregate(List recs, int offset)
+ {
+ CFRecordsAggregate cfRecords = new CFRecordsAggregate();
+ ArrayList records = new ArrayList(4);
+
+ int count = 0;
+ Record rec = ( Record ) recs.get(offset++);
+
+ if (rec.getSid() == CFHeaderRecord.sid)
+ {
+ records.add(rec);
+ cfRecords.header = (CFHeaderRecord)rec;
+
+ int nRules = cfRecords.header.getNumberOfConditionalFormats();
+ int rulesCount = 0;
+ while( offset0 )
+ {
+ header.setNumberOfConditionalFormats(rules.size());
+
+ pos += (( Record ) header).serialize(pos, data);
+
+ for(Iterator itr = rules.iterator(); itr.hasNext();)
+ {
+ pos += (( Record ) itr.next()).serialize(pos, data);
+ }
+ }
+ return pos - offset;
+ }
+
+ protected void validateSid(short id)
+ {
+ // do nothing here
+ }
+
+ /**
+ * @return the header
+ */
+ public CFHeaderRecord getHeader()
+ {
+ return header;
+ }
+
+ /**
+ * @return the rules
+ */
+ public List getRules()
+ {
+ return rules;
+ }
+
+ /**
+ * @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
+ */
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[CF]\n");
+ if( header != null )
+ {
+ buffer.append(header.toString());
+ }
+ if( rules != null )
+ {
+ for(int i=0; i=0 && field_2_last_row=0 && field_4_last_column
+ * Possible return codes are:
+ * NO_INTERSECTION - the specified range is outside of this range;
+ * OVERLAP - both ranges partially overlap;
+ * INSIDE - the specified range is inside of this one
+ * ENCLOSES - the specified range encloses this range
+ */
+ public int intersect(CellRange another )
+ {
+ int firstRow = another.getFirstRow();
+ int lastRow = another.getLastRow();
+ short firstCol = another.getFirstColumn();
+ short lastCol = another.getLastColumn();
+
+ if
+ (
+ gt(this.getFirstRow(),lastRow) ||
+ lt(this.getLastRow(),firstRow) ||
+ gt(this.getFirstColumn(),lastCol) ||
+ lt(this.getLastColumn(),firstCol)
+ )
+ {
+ return NO_INTERSECTION;
+ }
+ else if( this.contains(another) )
+ {
+ return INSIDE;
+ }
+ else if( another.contains(this) )
+ {
+ return ENCLOSES;
+ }
+ else
+ {
+ return OVERLAP;
+ }
+
+ }
+
+ /**
+ * Check if the specified range is located inside of this cell range.
+ *
+ * @param range
+ * @return true if this cell range contains the argument range inside if it's area
+ */
+ public boolean contains(CellRange range)
+ {
+ int firstRow = range.getFirstRow();
+ int lastRow = range.getLastRow();
+ short firstCol = range.getFirstColumn();
+ short lastCol = range.getLastColumn();
+ return le(this.getFirstRow(), firstRow) && ge(this.getLastRow(), lastRow)
+ && le(this.getFirstColumn(), firstCol) && ge(this.getLastColumn(), lastCol);
+ }
+
+ public boolean contains(int row, short column)
+ {
+ return le(this.getFirstRow(), row) && ge(this.getLastRow(), row)
+ && le(this.getFirstColumn(), column) && ge(this.getLastColumn(), column);
+ }
+
+ /**
+ * Check if the specified cell range has a shared border with the current range.
+ *
+ * @return true if the ranges have a shared border.
+ */
+ public boolean hasSharedBorder(CellRange range)
+ {
+ int firstRow = range.getFirstRow();
+ int lastRow = range.getLastRow();
+ short firstCol = range.getFirstColumn();
+ short lastCol = range.getLastColumn();
+ return
+ (this.getFirstRow()>0 && this.getFirstRow() - 1 == lastRow || firstRow>0 &&this.getLastRow() == firstRow -1)&&
+ (this.getFirstColumn() == firstCol) &&
+ (this.getLastColumn() == lastCol) ||
+ (this.getFirstColumn()>0 && this.getFirstColumn() - 1 == lastCol || firstCol>0 && this.getLastColumn() == firstCol -1) &&
+ (this.getFirstRow() == firstRow) &&
+ (this.getLastRow() == lastRow)
+ ;
+ }
+
+ /**
+ * Create an enclosing CellRange for the two cell ranges.
+ *
+ * @return enclosing CellRange
+ */
+ public CellRange createEnclosingCellRange(CellRange range)
+ {
+ if( range == null)
+ {
+ return cloneCellRange();
+ }
+ else
+ {
+ CellRange cellRange =
+ new CellRange(
+ lt(range.getFirstRow(),getFirstRow())?range.getFirstRow():getFirstRow(),
+ gt(range.getLastRow(),getLastRow())?range.getLastRow():getLastRow(),
+ lt(range.getFirstColumn(),getFirstColumn())?range.getFirstColumn():getFirstColumn(),
+ gt(range.getLastColumn(),getLastColumn())?range.getLastColumn():getLastColumn()
+ );
+ return cellRange;
+ }
+ }
+
+ public CellRange cloneCellRange()
+ {
+ return new CellRange(getFirstRow(),getLastRow(),getFirstColumn(),getLastColumn());
+ }
+
+ /**
+ * Copy data from antother cell range to this cell range
+ * @param cr - another cell range
+ */
+ public void setCellRange(CellRange cr)
+ {
+ setFirstRow(cr.getFirstRow());
+ setLastRow(cr.getLastRow());
+ setFirstColumn(cr.getFirstColumn());
+ setLastColumn(cr.getLastColumn());
+ }
+
+ /**
+ * @return true if a < b
+ */
+ private static boolean lt(int a, int b)
+ {
+ return a == -1 ? false : (b == -1 ? true : a < b);
+ }
+
+ /**
+ * @return true if a <= b
+ */
+ private static boolean le(int a, int b)
+ {
+ return a == b || lt(a,b);
+ }
+
+ /**
+ * @return true if a > b
+ */
+ private static boolean gt(int a, int b)
+ {
+ return lt(b,a);
+ }
+
+ /**
+ * @return true if a >= b
+ */
+ private static boolean ge(int a, int b)
+ {
+ return !lt(a,b);
+ }
+
+ public String toString()
+ {
+ return "("+this.getFirstRow()+","+this.getLastRow()+","+this.getFirstColumn()+","+this.getLastColumn()+")";
+ }
+
+}
diff --git a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
new file mode 100644
index 000000000..1e6abee7c
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
@@ -0,0 +1,591 @@
+
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.cf;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Font Formatting Block of the Conditional Formatting Rule Record.
+ *
+ * Created on January 22, 2008, 10:05 PM
+ *
+ * @author Dmitriy Kumshayev
+ */
+
+public class FontFormatting
+{
+ private byte [] record;
+
+ private static final int OFFSET_FONT_NAME = 0;
+ private static final int OFFSET_FONT_HEIGHT = 64;
+ private static final int OFFSET_FONT_OPTIONS = 68;
+ private static final int OFFSET_FONT_WEIGHT = 72;
+ private static final int OFFSET_ESCAPEMENT_TYPE = 74;
+ private static final int OFFSET_UNDERLINE_TYPE = 76;
+ private static final int OFFSET_FONT_COLOR_INDEX = 80;
+ private static final int OFFSET_OPTION_FLAGS = 88;
+ private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92;
+ private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96;
+ private static final int OFFSET_NOT_USED1 = 100;
+ private static final int OFFSET_NOT_USED2 = 104;
+ private static final int OFFSET_FONT_FORMATING_END = 116;
+
+
+ public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF;
+
+ // FONT OPTIONS MASKS
+ private static final BitField posture = BitFieldFactory.getInstance(0x00000002);
+ private static final BitField outline = BitFieldFactory.getInstance(0x00000008);
+ private static final BitField shadow = BitFieldFactory.getInstance(0x00000010);
+ private static final BitField condense = BitFieldFactory.getInstance(0x00000020);
+ private static final BitField cancellation = BitFieldFactory.getInstance(0x00000080);
+
+ // OPTION FLAGS MASKS
+
+ private static final BitField styleModified = BitFieldFactory.getInstance(0x00000002);
+ private static final BitField outlineModified = BitFieldFactory.getInstance(0x00000008);
+ private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010);
+ private static final BitField condenseModified = BitFieldFactory.getInstance(0x00000020);
+ private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080);
+
+ /**
+ * Escapement type - None
+ */
+ public final static short SS_NONE = 0;
+
+ /**
+ * Escapement type - Superscript
+ */
+ public final static short SS_SUPER = 1;
+
+ /**
+ * Escapement type - Subscript
+ */
+ public final static short SS_SUB = 2;
+
+ /**
+ * Underline type - None
+ */
+ public final static byte U_NONE = 0;
+
+ /**
+ * Underline type - Single
+ */
+ public final static byte U_SINGLE = 1;
+
+ /**
+ * Underline type - Double
+ */
+ public final static byte U_DOUBLE = 2;
+
+ /**
+ * Underline type - Single Accounting
+ */
+ public final static byte U_SINGLE_ACCOUNTING = 0x21;
+
+ /**
+ * Underline type - Double Accounting
+ */
+ public final static byte U_DOUBLE_ACCOUNTING = 0x22;
+
+ /**
+ * Normal boldness (not bold)
+ */
+
+ protected final static short FONT_WEIGHT_NORMAL = 0x190;
+
+ /**
+ * Bold boldness (bold)
+ */
+
+ protected final static short FONT_WEIGHT_BOLD = 0x2bc;
+
+ public FontFormatting()
+ {
+ this(new byte[118]);
+
+ this.setFontHeight((short)-1);
+ this.setItalic(false);
+ this.setBold(false);
+ this.setOutline(false);
+ this.setShadow(false);
+ this.setCondense(false);
+ this.setStrikeout(false);
+ this.setEscapementType((short)0);
+ this.setUnderlineType((byte)0);
+ this.setFontColorIndex((short)-1);
+
+ this.setFontStyleModified(false);
+ this.setFontOutlineModified(false);
+ this.setFontShadowModified(false);
+ this.setFontCondenseModified(false);
+ this.setFontCancellationModified(false);
+
+ this.setEscapementTypeModified(false);
+ this.setUnderlineTypeModified(false);
+
+ LittleEndian.putShort(record, OFFSET_FONT_NAME, (short)0);
+ LittleEndian.putInt(record, OFFSET_NOT_USED1, 0x00000001);
+ LittleEndian.putInt(record, OFFSET_NOT_USED2, 0x00000001);
+ LittleEndian.putShort(record, OFFSET_FONT_FORMATING_END, (short)0x0001);
+ }
+
+ /** Creates new FontFormatting */
+ private FontFormatting(byte[] record)
+ {
+ this.record = record;
+ }
+
+ /** Creates new FontFormatting */
+ public FontFormatting(RecordInputStream in)
+ {
+ record = new byte[118];
+ for (int i = 0; i != record.length; i++)
+ {
+ record[i] = in.readByte();
+ }
+ }
+
+ public byte[] getRawRecord()
+ {
+ return record;
+ }
+
+ /**
+ * sets the height of the font in 1/20th point units
+ *
+ *
+ * @param height fontheight (in points/20); or -1 to preserve the cell font height
+ */
+
+ public void setFontHeight(short height)
+ {
+ LittleEndian.putInt(record, OFFSET_FONT_HEIGHT, height);
+ }
+
+ /**
+ * gets the height of the font in 1/20th point units
+ *
+ * @return fontheight (in points/20); or -1 if not modified
+ */
+ public short getFontHeight()
+ {
+ return (short) LittleEndian.getInt(record, OFFSET_FONT_HEIGHT);
+ }
+
+ private void setFontOption(boolean option, BitField field)
+ {
+ int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS);
+ options = field.setBoolean(options, option);
+ LittleEndian.putInt(record,OFFSET_FONT_OPTIONS, options);
+ }
+
+ private boolean getFontOption(BitField field)
+ {
+ int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS);
+ return field.isSet(options);
+ }
+
+ /**
+ * set the font to be italics or not
+ *
+ * @param italics - whether the font is italics or not
+ * @see #setAttributes(short)
+ */
+
+ public void setItalic(boolean italic)
+ {
+ setFontOption(italic, posture);
+ }
+
+ /**
+ * get whether the font is to be italics or not
+ *
+ * @return italics - whether the font is italics or not
+ * @see #getAttributes()
+ */
+
+ public boolean isItalic()
+ {
+ return getFontOption(posture);
+ }
+
+ public void setOutline(boolean on)
+ {
+ setFontOption(on, outline);
+ }
+
+ public boolean isOutlineOn()
+ {
+ return getFontOption(outline);
+ }
+
+ public void setShadow(boolean on)
+ {
+ setFontOption(on, shadow);
+ }
+
+ public boolean isShadowOn()
+ {
+ return getFontOption(shadow);
+ }
+
+ public void setCondense(boolean on)
+ {
+ setFontOption(on, condense);
+ }
+
+ public boolean isCondenseOn()
+ {
+ return getFontOption(condense);
+ }
+
+ /**
+ * set the font to be stricken out or not
+ *
+ * @param strike - whether the font is stricken out or not
+ */
+
+ public void setStrikeout(boolean strike)
+ {
+ setFontOption(strike, cancellation);
+ }
+
+ /**
+ * get whether the font is to be stricken out or not
+ *
+ * @return strike - whether the font is stricken out or not
+ * @see #getAttributes()
+ */
+
+ public boolean isStruckout()
+ {
+ return getFontOption(cancellation);
+ }
+
+ /**
+ * set the font weight (100-1000dec or 0x64-0x3e8). Default is
+ * 0x190 for normal and 0x2bc for bold
+ *
+ * @param bw - a number between 100-1000 for the fonts "boldness"
+ */
+
+ private void setFontWeight(short bw)
+ {
+ if( bw<100) { bw=100; }
+ if( bw>1000){ bw=1000; }
+ LittleEndian.putShort(record,OFFSET_FONT_WEIGHT, bw);
+ }
+
+ /**
+ * set the font weight to bold (weight=700) or to normal(weight=400) boldness.
+ *
+ * @param bold - set font weight to bold if true; to normal otherwise
+ */
+ public void setBold(boolean bold)
+ {
+ setFontWeight(bold?FONT_WEIGHT_BOLD:FONT_WEIGHT_NORMAL);
+ }
+
+ /**
+ * get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is
+ * 0x190 for normal and 0x2bc for bold
+ *
+ * @return bw - a number between 100-1000 for the fonts "boldness"
+ */
+
+ public short getFontWeight()
+ {
+ return LittleEndian.getShort(record,OFFSET_FONT_WEIGHT);
+ }
+
+ /**
+ * get whether the font weight is set to bold or not
+ *
+ * @return bold - whether the font is bold or not
+ */
+
+ public boolean isBold()
+ {
+ return getFontWeight()==FONT_WEIGHT_BOLD;
+ }
+
+ /**
+ * get the type of super or subscript for the font
+ *
+ * @return super or subscript option
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB
+ */
+ public short getEscapementType()
+ {
+ return LittleEndian.getShort(record,OFFSET_ESCAPEMENT_TYPE);
+ }
+
+ /**
+ * set the escapement type for the font
+ *
+ * @param escapementType super or subscript option
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB
+ */
+ public void setEscapementType( short escapementType)
+ {
+ LittleEndian.putShort(record,OFFSET_ESCAPEMENT_TYPE, escapementType);
+ }
+
+ /**
+ * get the type of underlining for the font
+ *
+ * @return font underlining type
+ *
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING
+ */
+
+ public short getUnderlineType()
+ {
+ return LittleEndian.getShort(record,OFFSET_UNDERLINE_TYPE);
+ }
+
+ /**
+ * set the type of underlining type for the font
+ *
+ * @param u super or subscript option
+ *
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING
+ * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING
+ */
+ public void setUnderlineType( short underlineType)
+ {
+ LittleEndian.putShort(record,OFFSET_UNDERLINE_TYPE, underlineType);
+ }
+
+
+ public short getFontColorIndex()
+ {
+ return (short)LittleEndian.getInt(record,OFFSET_FONT_COLOR_INDEX);
+ }
+
+ public void setFontColorIndex(short fci )
+ {
+ LittleEndian.putInt(record,OFFSET_FONT_COLOR_INDEX,fci);
+ }
+
+ private boolean getOptionFlag(BitField field)
+ {
+ int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS);
+ int value = field.getValue(optionFlags);
+ return value==0? true : false ;
+ }
+
+ private void setOptionFlag(boolean modified, BitField field)
+ {
+ int value = modified? 0 : 1;
+ int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS);
+ optionFlags = field.setValue(optionFlags, value);
+ LittleEndian.putInt(record,OFFSET_OPTION_FLAGS, optionFlags);
+ }
+
+
+ public boolean isFontStyleModified()
+ {
+ return getOptionFlag(styleModified);
+ }
+
+ public void setFontStyleModified(boolean modified)
+ {
+ setOptionFlag(modified, styleModified);
+ }
+
+ public boolean isFontOutlineModified()
+ {
+ return getOptionFlag(outlineModified);
+ }
+
+ public void setFontOutlineModified(boolean modified)
+ {
+ setOptionFlag(modified, outlineModified);
+ }
+
+ public boolean isFontShadowModified()
+ {
+ return getOptionFlag(shadowModified);
+ }
+
+ public void setFontShadowModified(boolean modified)
+ {
+ setOptionFlag(modified, shadowModified);
+ }
+ public boolean isFontCondenseModified()
+ {
+ return getOptionFlag(condenseModified);
+ }
+
+ public void setFontCondenseModified(boolean modified)
+ {
+ setOptionFlag(modified, condenseModified);
+ }
+
+ public void setFontCancellationModified(boolean modified)
+ {
+ setOptionFlag(modified, cancellationModified);
+ }
+
+ public boolean isFontCancellationModified()
+ {
+ return getOptionFlag(cancellationModified);
+ }
+
+ public void setEscapementTypeModified(boolean modified)
+ {
+ int value = modified? 0 : 1;
+ LittleEndian.putInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED, value);
+ }
+
+ public boolean isEscapementTypeModified()
+ {
+ int escapementModified = LittleEndian.getInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED);
+ return escapementModified == 0;
+ }
+
+ public void setUnderlineTypeModified(boolean modified)
+ {
+ int value = modified? 0 : 1;
+ LittleEndian.putInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED, value);
+ }
+
+ public boolean isUnderlineTypeModified()
+ {
+ int underlineModified = LittleEndian.getInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED);
+ return underlineModified == 0;
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(" [Font Formatting]\n");
+
+ buffer.append(" .font height = ").append(getFontHeight()).append(" twips\n");
+
+ if( isFontStyleModified() )
+ {
+ buffer.append(" .font posture = ").append(isItalic()?"Italic":"Normal").append("\n");
+ }
+ else
+ {
+ buffer.append(" .font posture = ]not modified]").append("\n");
+ }
+
+ if( isFontOutlineModified() )
+ {
+ buffer.append(" .font outline = ").append(isOutlineOn()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .font outline is not modified\n");
+ }
+
+ if( isFontShadowModified() )
+ {
+ buffer.append(" .font shadow = ").append(isShadowOn()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .font shadow is not modified\n");
+ }
+ if( isFontCondenseModified() )
+ {
+ buffer.append(" .font condense = ").append(isCondenseOn()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .font condense is not modified\n");
+ }
+
+ if( isFontCancellationModified() )
+ {
+ buffer.append(" .font strikeout = ").append(isStruckout()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .font strikeout is not modified\n");
+ }
+
+ if( isFontStyleModified() )
+ {
+ buffer.append(" .font weight = ").
+ append(getFontWeight()).
+ append(
+ getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)"
+ : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" : "0x"+Integer.toHexString(getFontWeight())).
+ append("\n");
+ }
+ else
+ {
+ buffer.append(" .font weight = ]not modified]").append("\n");
+ }
+
+ if( isEscapementTypeModified() )
+ {
+ buffer.append(" .escapement type = ").append(getEscapementType()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .escapement type is not modified\n");
+ }
+
+ if( isUnderlineTypeModified() )
+ {
+ buffer.append(" .underline type = ").append(getUnderlineType()).append("\n");
+ }
+ else
+ {
+ buffer.append(" .underline type is not modified\n");
+ }
+ buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n");
+
+
+ buffer.append(" [/Font Formatting]\n");
+ return buffer.toString();
+ }
+
+ public Object clone()
+ {
+ FontFormatting rec = new FontFormatting();
+ if( record != null)
+ {
+ byte[] clone = new byte[record.length];
+ System.arraycopy(record, 0, clone, 0, record.length);
+ rec.record = clone;
+ }
+ return rec;
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java b/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
new file mode 100644
index 000000000..3157bf46c
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
@@ -0,0 +1,206 @@
+
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+
+/*
+ * FontFormatting.java
+ *
+ * Created on January 22, 2008, 10:05 PM
+ */
+package org.apache.poi.hssf.record.cf;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Pattern Formatting Block of the Conditional Formatting Rule Record.
+ *
+ * @author Dmitriy Kumshayev
+ */
+
+public class PatternFormatting implements Cloneable
+{
+ /** No background */
+ public final static short NO_FILL = 0 ;
+ /** Solidly filled */
+ public final static short SOLID_FOREGROUND = 1 ;
+ /** Small fine dots */
+ public final static short FINE_DOTS = 2 ;
+ /** Wide dots */
+ public final static short ALT_BARS = 3 ;
+ /** Sparse dots */
+ public final static short SPARSE_DOTS = 4 ;
+ /** Thick horizontal bands */
+ public final static short THICK_HORZ_BANDS = 5 ;
+ /** Thick vertical bands */
+ public final static short THICK_VERT_BANDS = 6 ;
+ /** Thick backward facing diagonals */
+ public final static short THICK_BACKWARD_DIAG = 7 ;
+ /** Thick forward facing diagonals */
+ public final static short THICK_FORWARD_DIAG = 8 ;
+ /** Large spots */
+ public final static short BIG_SPOTS = 9 ;
+ /** Brick-like layout */
+ public final static short BRICKS = 10 ;
+ /** Thin horizontal bands */
+ public final static short THIN_HORZ_BANDS = 11 ;
+ /** Thin vertical bands */
+ public final static short THIN_VERT_BANDS = 12 ;
+ /** Thin backward diagonal */
+ public final static short THIN_BACKWARD_DIAG = 13 ;
+ /** Thin forward diagonal */
+ public final static short THIN_FORWARD_DIAG = 14 ;
+ /** Squares */
+ public final static short SQUARES = 15 ;
+ /** Diamonds */
+ public final static short DIAMONDS = 16 ;
+ /** Less Dots */
+ public final static short LESS_DOTS = 17 ;
+ /** Least Dots */
+ public final static short LEAST_DOTS = 18 ;
+
+ public PatternFormatting()
+ {
+ field_15_pattern_style = (short)0;
+ field_16_pattern_color_indexes = (short)0;
+ }
+
+ /** Creates new FontFormatting */
+ public PatternFormatting(RecordInputStream in)
+ {
+ field_15_pattern_style = in.readShort();
+ field_16_pattern_color_indexes = in.readShort();
+ }
+
+ // PATTERN FORMATING BLOCK
+ // For Pattern Styles see constants at HSSFCellStyle (from NO_FILL to LEAST_DOTS)
+ private short field_15_pattern_style;
+ private static final BitField fillPatternStyle = BitFieldFactory.getInstance(0xFC00);
+
+ private short field_16_pattern_color_indexes;
+ private static final BitField patternColorIndex = BitFieldFactory.getInstance(0x007F);
+ private static final BitField patternBackgroundColorIndex = BitFieldFactory.getInstance(0x3F80);
+
+ /**
+ * setting fill pattern
+ *
+ * @see #NO_FILL
+ * @see #SOLID_FOREGROUND
+ * @see #FINE_DOTS
+ * @see #ALT_BARS
+ * @see #SPARSE_DOTS
+ * @see #THICK_HORZ_BANDS
+ * @see #THICK_VERT_BANDS
+ * @see #THICK_BACKWARD_DIAG
+ * @see #THICK_FORWARD_DIAG
+ * @see #BIG_SPOTS
+ * @see #BRICKS
+ * @see #THIN_HORZ_BANDS
+ * @see #THIN_VERT_BANDS
+ * @see #THIN_BACKWARD_DIAG
+ * @see #THIN_FORWARD_DIAG
+ * @see #SQUARES
+ * @see #DIAMONDS
+ *
+ * @param fp fill pattern
+ */
+ public void setFillPattern(short fp)
+ {
+ field_15_pattern_style = fillPatternStyle.setShortValue(field_15_pattern_style, fp);
+ }
+
+ /**
+ * get the fill pattern
+ * @return fill pattern
+ */
+
+ public short getFillPattern()
+ {
+ return fillPatternStyle.getShortValue(field_15_pattern_style);
+ }
+
+ /**
+ * set the background fill color.
+ *
+ * @param bg color
+ */
+
+ public void setFillBackgroundColor(short bg)
+ {
+ field_16_pattern_color_indexes = patternBackgroundColorIndex.setShortValue(field_16_pattern_color_indexes,bg);
+ }
+
+ /**
+ * get the background fill color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @return fill color
+ */
+ public short getFillBackgroundColor()
+ {
+ return patternBackgroundColorIndex.getShortValue(field_16_pattern_color_indexes);
+ }
+
+ /**
+ * set the foreground fill color
+ * @param bg color
+ */
+ public void setFillForegroundColor(short fg)
+ {
+ field_16_pattern_color_indexes = patternColorIndex.setShortValue(field_16_pattern_color_indexes,fg);
+ }
+
+ /**
+ * get the foreground fill color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @return fill color
+ */
+ public short getFillForegroundColor()
+ {
+ return patternColorIndex.getShortValue(field_16_pattern_color_indexes);
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(" [Pattern Formatting]\n");
+ buffer.append(" .fillpattern= ").append(Integer.toHexString(getFillPattern())).append("\n");
+ buffer.append(" .fgcoloridx= ").append(Integer.toHexString(getFillForegroundColor())).append("\n");
+ buffer.append(" .bgcoloridx= ").append(Integer.toHexString(getFillBackgroundColor())).append("\n");
+ buffer.append(" [/Pattern Formatting]\n");
+ return buffer.toString();
+ }
+
+ public Object clone()
+ {
+ PatternFormatting rec = new PatternFormatting();
+ rec.field_15_pattern_style = field_15_pattern_style;
+ rec.field_16_pattern_color_indexes = field_16_pattern_color_indexes;
+ return rec;
+ }
+
+ public int serialize(int offset, byte [] data)
+ {
+ LittleEndian.putShort(data, offset, field_15_pattern_style);
+ offset += 2;
+ LittleEndian.putShort(data, offset, field_16_pattern_color_indexes);
+ offset += 2;
+ return 4;
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java
index 8a6b2c03b..75c634890 100644
--- a/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java
@@ -32,6 +32,7 @@ public final class RefVPtg extends ReferencePtg {
public RefVPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
super(row, column, isRowRelative, isColumnRelative);
+ setClass(CLASS_VALUE);
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java
new file mode 100644
index 000000000..622f3a674
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java
@@ -0,0 +1,128 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+
+import org.apache.poi.hssf.record.cf.BorderFormatting;
+
+/**
+ * High level representation for Border Formatting component
+ * of Conditional Formatting settings
+ *
+ * @author Dmitriy Kumshayev
+ *
+ */
+public class HSSFBorderFormatting
+{
+ /**
+ * No border
+ */
+
+ public final static short BORDER_NONE = BorderFormatting.BORDER_NONE;
+
+ /**
+ * Thin border
+ */
+
+ public final static short BORDER_THIN = BorderFormatting.BORDER_THIN;
+
+ /**
+ * Medium border
+ */
+
+ public final static short BORDER_MEDIUM = BorderFormatting.BORDER_MEDIUM;
+
+ /**
+ * dash border
+ */
+
+ public final static short BORDER_DASHED = BorderFormatting.BORDER_DASHED;
+
+ /**
+ * dot border
+ */
+
+ public final static short BORDER_HAIR = BorderFormatting.BORDER_HAIR;
+
+ /**
+ * Thick border
+ */
+
+ public final static short BORDER_THICK = BorderFormatting.BORDER_THICK;
+
+ /**
+ * double-line border
+ */
+
+ public final static short BORDER_DOUBLE = BorderFormatting.BORDER_DOUBLE;
+
+ /**
+ * hair-line border
+ */
+
+ public final static short BORDER_DOTTED = BorderFormatting.BORDER_DOTTED;
+
+ /**
+ * Medium dashed border
+ */
+
+ public final static short BORDER_MEDIUM_DASHED = BorderFormatting.BORDER_MEDIUM_DASHED;
+
+ /**
+ * dash-dot border
+ */
+
+ public final static short BORDER_DASH_DOT = BorderFormatting.BORDER_DASH_DOT;
+
+ /**
+ * medium dash-dot border
+ */
+
+ public final static short BORDER_MEDIUM_DASH_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT;
+
+ /**
+ * dash-dot-dot border
+ */
+
+ public final static short BORDER_DASH_DOT_DOT = BorderFormatting.BORDER_DASH_DOT_DOT;
+
+ /**
+ * medium dash-dot-dot border
+ */
+
+ public final static short BORDER_MEDIUM_DASH_DOT_DOT = BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT;
+
+ /**
+ * slanted dash-dot border
+ */
+
+ public final static short BORDER_SLANTED_DASH_DOT = BorderFormatting.BORDER_SLANTED_DASH_DOT;
+
+
+ private BorderFormatting borderFormatting;
+
+ public HSSFBorderFormatting()
+ {
+ borderFormatting = new BorderFormatting();
+ }
+
+ protected BorderFormatting getBorderFormattingBlock()
+ {
+ return borderFormatting;
+ }
+
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
index d0d29b5b7..11d14782b 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
@@ -277,7 +277,7 @@ public class HSSFCellStyle implements CellStyle
/**
* Get the contents of the format string, by looking up
- * the DataFormat against the supplied workbook
+ * the DataFormat against the bound workbook
* @see org.apache.poi.hssf.usermodel.HSSFDataFormat
*/
public String getDataFormatString() {
@@ -285,6 +285,16 @@ public class HSSFCellStyle implements CellStyle
return format.getFormat(getDataFormat());
}
+ /**
+ * Get the contents of the format string, by looking up
+ * the DataFormat against the supplied workbook
+ * @see org.apache.poi.hssf.usermodel.HSSFDataFormat
+ */
+ public String getDataFormatString(org.apache.poi.ss.usermodel.Workbook workbook) {
+ HSSFDataFormat format = new HSSFDataFormat( ((HSSFWorkbook)workbook).getWorkbook() );
+
+ return format.getFormat(getDataFormat());
+ }
/**
* set the font for this style
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java
new file mode 100644
index 000000000..e5fbb1d30
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java
@@ -0,0 +1,201 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.hssf.usermodel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hssf.record.CFHeaderRecord;
+import org.apache.poi.hssf.record.CFRuleRecord;
+import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
+import org.apache.poi.hssf.record.cf.CellRange;
+import org.apache.poi.hssf.util.Region;
+
+public class HSSFConditionalFormatting
+{
+ HSSFSheet sheet;
+ CFRecordsAggregate cfAggregate;
+
+ protected HSSFConditionalFormatting(HSSFSheet sheet)
+ {
+ this.sheet = sheet;
+ this.cfAggregate = new CFRecordsAggregate();
+ }
+
+ protected HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
+ {
+ this.sheet = sheet;
+ this.cfAggregate = cfAggregate;
+ }
+
+
+ public void setFormattingRegions(Region[] regions)
+ {
+ if( regions != null)
+ {
+ CFHeaderRecord header = cfAggregate.getHeader();
+ header.setCellRanges(mergeCellRanges(toCellRangeList(regions)));
+ }
+ }
+
+ public Region[] getFormattingRegions()
+ {
+ CFHeaderRecord cfh = cfAggregate.getHeader();
+
+ List cellRanges = cfh.getCellRanges();
+
+ if (cellRanges != null)
+ {
+ return toRegionArray(cellRanges);
+ }
+ return null;
+ }
+
+ public void setConditionalFormat(int idx, HSSFConditionalFormattingRule cfRule)
+ {
+ cfAggregate.getRules().set(idx, cfRule);
+ }
+
+ public void addConditionalFormat(HSSFConditionalFormattingRule cfRule)
+ {
+ cfAggregate.getRules().add(cfRule);
+ }
+
+ public HSSFConditionalFormattingRule getConditionalFormat(int idx)
+ {
+ CFRuleRecord ruleRecord = (CFRuleRecord)cfAggregate.getRules().get(idx);
+ return new HSSFConditionalFormattingRule(sheet.workbook, ruleRecord);
+ }
+
+ /**
+ * Do all possible cell merges between cells of the list so that:
+ * if a cell range is completely inside of another cell range, it gets removed from the list
+ * if two cells have a shared border, merge them into one bigger cell range
+ * @param cellRangeList
+ * @return updated List of cell ranges
+ */
+ private static List mergeCellRanges(List cellRangeList)
+ {
+ boolean merged = false;
+
+ do
+ {
+ merged = false;
+
+ if( cellRangeList.size()>1 )
+ {
+ for( int i=0; iitalic
+ */
+ public boolean isItalic()
+ {
+ return fontFormatting.isFontStyleModified() && fontFormatting.isItalic();
+ }
+
+ /**
+ * @return true if font outline is on
+ */
+ public boolean isOutlineOn()
+ {
+ return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn();
+ }
+
+ /**
+ * @return true if font shadow is on
+ */
+ public boolean isShadowOn()
+ {
+ return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn();
+ }
+
+ /**
+ * @return true if font strikeout is on
+ */
+ public boolean isStruckout()
+ {
+ return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout();
+ }
+
+ /**
+ * @return true if font underline type was modified from default
+ */
+ public boolean isUnderlineTypeModified()
+ {
+ return fontFormatting.isUnderlineTypeModified();
+ }
+
+ /**
+ * set font style options.
+ *
+ * @param italic - if true, set posture style to italic, otherwise to normal
+ * @param bold- if true, set font weight to bold, otherwise to normal
+ */
+
+ public void setFontStyle(boolean italic, boolean bold)
+ {
+ boolean modified = italic || bold;
+ fontFormatting.setItalic(italic);
+ fontFormatting.setBold(bold);
+ fontFormatting.setFontStyleModified(modified);
+ }
+
+ /**
+ * set font style options to default values (non-italic, non-bold)
+ */
+ public void resetFontStyle()
+ {
+ setFontStyle(false,false);
+ }
+
+ /**
+ * set the escapement type for the font
+ *
+ * @param escapementType super or subscript option
+ * @see #SS_NONE
+ * @see #SS_SUPER
+ * @see #SS_SUB
+ */
+ public void setCondense(boolean on)
+ {
+ fontFormatting.setCondense(on);
+ fontFormatting.setFontCondenseModified(on);
+ }
+
+ /**
+ * set the escapement type for the font
+ *
+ * @param escapementType super or subscript option
+ * @see #SS_NONE
+ * @see #SS_SUPER
+ * @see #SS_SUB
+ */
+ public void setEscapementType(short escapementType)
+ {
+ switch(escapementType)
+ {
+ case HSSFFontFormatting.SS_SUB:
+ case HSSFFontFormatting.SS_SUPER:
+ fontFormatting.setEscapementType(escapementType);
+ fontFormatting.setEscapementTypeModified(true);
+ break;
+ case HSSFFontFormatting.SS_NONE:
+ fontFormatting.setEscapementType(escapementType);
+ fontFormatting.setEscapementTypeModified(false);
+ break;
+ default:
+ }
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean)
+ */
+ public void setEscapementTypeModified(boolean modified)
+ {
+ fontFormatting.setEscapementTypeModified(modified);
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean)
+ */
+ public void setFontCancellationModified(boolean modified)
+ {
+ fontFormatting.setFontCancellationModified(modified);
+ }
+
+ /**
+ * @param fci
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short)
+ */
+ public void setFontColorIndex(short fci)
+ {
+ fontFormatting.setFontColorIndex(fci);
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCondenseModified(boolean)
+ */
+ public void setFontCondenseModified(boolean modified)
+ {
+ fontFormatting.setFontCondenseModified(modified);
+ }
+
+ /**
+ * @param height
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(short)
+ */
+ public void setFontHeight(short height)
+ {
+ fontFormatting.setFontHeight(height);
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean)
+ */
+ public void setFontOutlineModified(boolean modified)
+ {
+ fontFormatting.setFontOutlineModified(modified);
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean)
+ */
+ public void setFontShadowModified(boolean modified)
+ {
+ fontFormatting.setFontShadowModified(modified);
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean)
+ */
+ public void setFontStyleModified(boolean modified)
+ {
+ fontFormatting.setFontStyleModified(modified);
+ }
+
+ /**
+ * @param on
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean)
+ */
+ public void setOutline(boolean on)
+ {
+ fontFormatting.setOutline(on);
+ fontFormatting.setFontOutlineModified(on);
+ }
+
+ /**
+ * @param on
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean)
+ */
+ public void setShadow(boolean on)
+ {
+ fontFormatting.setShadow(on);
+ fontFormatting.setFontShadowModified(on);
+ }
+
+ /**
+ * @param strike
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean)
+ */
+ public void setStrikeout(boolean strike)
+ {
+ fontFormatting.setStrikeout(strike);
+ fontFormatting.setFontCancellationModified(strike);
+ }
+
+ /**
+ * set the type of underlining type for the font
+ *
+ * @param u super or subscript option
+ *
+ * @see #U_NONE
+ * @see #U_SINGLE
+ * @see #U_DOUBLE
+ * @see #U_SINGLE_ACCOUNTING
+ * @see #U_DOUBLE_ACCOUNTING
+ */
+ public void setUnderlineType(short underlineType)
+ {
+ switch(underlineType)
+ {
+ case HSSFFontFormatting.U_SINGLE:
+ case HSSFFontFormatting.U_DOUBLE:
+ case HSSFFontFormatting.U_SINGLE_ACCOUNTING:
+ case HSSFFontFormatting.U_DOUBLE_ACCOUNTING:
+ fontFormatting.setUnderlineType(underlineType);
+ setUnderlineTypeModified(true);
+ break;
+
+ case HSSFFontFormatting.U_NONE:
+ fontFormatting.setUnderlineType(underlineType);
+ setUnderlineTypeModified(false);
+ break;
+ default:
+ }
+ }
+
+ /**
+ * @param modified
+ * @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean)
+ */
+ public void setUnderlineTypeModified(boolean modified)
+ {
+ fontFormatting.setUnderlineTypeModified(modified);
+ }
+
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatternFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatternFormatting.java
new file mode 100644
index 000000000..352a5b487
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatternFormatting.java
@@ -0,0 +1,134 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+
+import org.apache.poi.hssf.record.cf.PatternFormatting;
+
+/**
+ * High level representation for Conditional Formatting settings
+ *
+ * @author Dmitriy Kumshayev
+ *
+ */
+public class HSSFPatternFormatting
+{
+ /** No background */
+ public final static short NO_FILL = PatternFormatting.NO_FILL;
+ /** Solidly filled */
+ public final static short SOLID_FOREGROUND = PatternFormatting.SOLID_FOREGROUND;
+ /** Small fine dots */
+ public final static short FINE_DOTS = PatternFormatting.FINE_DOTS;
+ /** Wide dots */
+ public final static short ALT_BARS = PatternFormatting.ALT_BARS;
+ /** Sparse dots */
+ public final static short SPARSE_DOTS = PatternFormatting.SPARSE_DOTS;
+ /** Thick horizontal bands */
+ public final static short THICK_HORZ_BANDS = PatternFormatting.THICK_HORZ_BANDS;
+ /** Thick vertical bands */
+ public final static short THICK_VERT_BANDS = PatternFormatting.THICK_VERT_BANDS;
+ /** Thick backward facing diagonals */
+ public final static short THICK_BACKWARD_DIAG = PatternFormatting.THICK_BACKWARD_DIAG;
+ /** Thick forward facing diagonals */
+ public final static short THICK_FORWARD_DIAG = PatternFormatting.THICK_FORWARD_DIAG;
+ /** Large spots */
+ public final static short BIG_SPOTS = PatternFormatting.BIG_SPOTS;
+ /** Brick-like layout */
+ public final static short BRICKS = PatternFormatting.BRICKS;
+ /** Thin horizontal bands */
+ public final static short THIN_HORZ_BANDS = PatternFormatting.THIN_HORZ_BANDS;
+ /** Thin vertical bands */
+ public final static short THIN_VERT_BANDS = PatternFormatting.THIN_VERT_BANDS;
+ /** Thin backward diagonal */
+ public final static short THIN_BACKWARD_DIAG = PatternFormatting.THIN_BACKWARD_DIAG;
+ /** Thin forward diagonal */
+ public final static short THIN_FORWARD_DIAG = PatternFormatting.THIN_FORWARD_DIAG;
+ /** Squares */
+ public final static short SQUARES = PatternFormatting.SQUARES;
+ /** Diamonds */
+ public final static short DIAMONDS = PatternFormatting.DIAMONDS;
+ /** Less Dots */
+ public final static short LESS_DOTS = PatternFormatting.LESS_DOTS;
+ /** Least Dots */
+ public final static short LEAST_DOTS = PatternFormatting.LEAST_DOTS;
+
+ private PatternFormatting patternFormatting;
+
+ public HSSFPatternFormatting()
+ {
+ patternFormatting = new PatternFormatting();
+ }
+
+ protected PatternFormatting getPatternFormattingBlock()
+ {
+ return patternFormatting;
+ }
+
+ /**
+ * @return
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillBackgroundColor()
+ */
+ public short getFillBackgroundColor()
+ {
+ return patternFormatting.getFillBackgroundColor();
+ }
+
+ /**
+ * @return
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillForegroundColor()
+ */
+ public short getFillForegroundColor()
+ {
+ return patternFormatting.getFillForegroundColor();
+ }
+
+ /**
+ * @return
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillPattern()
+ */
+ public short getFillPattern()
+ {
+ return patternFormatting.getFillPattern();
+ }
+
+ /**
+ * @param bg
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillBackgroundColor(short)
+ */
+ public void setFillBackgroundColor(short bg)
+ {
+ patternFormatting.setFillBackgroundColor(bg);
+ }
+
+ /**
+ * @param fg
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillForegroundColor(short)
+ */
+ public void setFillForegroundColor(short fg)
+ {
+ patternFormatting.setFillForegroundColor(fg);
+ }
+
+ /**
+ * @param fp
+ * @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillPattern(short)
+ */
+ public void setFillPattern(short fp)
+ {
+ patternFormatting.setFillPattern(fp);
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index 047d7fcb3..d553f7b0a 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -53,6 +53,7 @@ import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
+import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.ReferencePtg;
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
@@ -1844,4 +1845,161 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
return null;
}
+
+ /**
+ * A factory method allowing to create a conditional formatting rule
+ * with a cell comparison operator and
+ * formatting rules such as font format, border format and pattern format
+ *
+ * @param comparisonOperation - one of the following values:
+ *
{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}
+ *
+ * @param formula1 - formula for the valued, compared with the cell
+ * @param formula2 - second formula (only used with
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
+ * @param fontFmt - font formatting rules
+ * @param bordFmt - border formatting rules
+ * @param patternFmt - pattern formatting rules
+ * @return
+ *
+ */
+ public HSSFConditionalFormattingRule createConditionalFormattingRule(
+ byte comparisonOperation,
+ String formula1,
+ String formula2,
+ HSSFFontFormatting fontFmt,
+ HSSFBorderFormatting bordFmt,
+ HSSFPatternFormatting patternFmt)
+ {
+ HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
+ cf.setFontFormatting(fontFmt);
+ cf.setBorderFormatting(bordFmt);
+ cf.setPatternFormatting(patternFmt);
+ cf.setCellComparisonCondition(comparisonOperation, formula1, formula2);
+ return cf;
+ }
+
+ /**
+ * A factory method allowing to create a conditional formatting rule with a formula
+ * and formatting rules such as font format, border format and pattern format.
+ *
+ * The formatting rules are applied by Excel when the value of the formula not equal to 0.
+ *
+ * @param comparisonOperation - one of the following values:
+ *
{@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_EQUAL}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_EQUAL}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GT}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LT}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_GE}
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_LE}
+ *
+ * @param formula1 - formula for the valued, compared with the cell
+ * @param formula2 - second formula (only used with
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_BETWEEN}) and
+ * {@link HSSFConditionalFormattingRule#COMPARISON_OPERATOR_NOT_BETWEEN} operations)
+ * @param fontFmt - font formatting rules
+ * @param bordFmt - border formatting rules
+ * @param patternFmt - pattern formatting rules
+ * @return
+ *
+ */
+ public HSSFConditionalFormattingRule createConditionalFormattingRule(
+ String formula,
+ HSSFFontFormatting fontFmt,
+ HSSFBorderFormatting bordFmt,
+ HSSFPatternFormatting patternFmt)
+ {
+ HSSFConditionalFormattingRule cf = new HSSFConditionalFormattingRule(workbook);
+ cf.setFontFormatting(fontFmt);
+ cf.setBorderFormatting(bordFmt);
+ cf.setPatternFormatting(patternFmt);
+ cf.setFormulaCondition(formula);
+ return cf;
+ }
+
+ /**
+ * Adds a copy of HSSFConditionalFormatting object to the sheet
+ * This method could be used to copy HSSFConditionalFormatting object
+ * from one sheet to another. For example:
+ *
+ * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
+ * newSheet.addConditionalFormatting(cf);
+ *
+ *
+ * @param cf HSSFConditionalFormatting object
+ * @return index of the new Conditional Formatting object
+ */
+ public int addConditionalFormatting( HSSFConditionalFormatting cf )
+ {
+ HSSFConditionalFormatting cfClone = new HSSFConditionalFormatting(this,cf.cfAggregate.cloneCFAggregate());
+ cfClone.sheet=this;
+ return sheet.addConditionalFormatting(cfClone.cfAggregate);
+ }
+
+ /**
+ * Allows to add a new Conditional Formatting set to the sheet.
+ *
+ * @param regions - list of rectangular regions to apply conditional formatting rules
+ * @param cfRules - set of up to three conditional formatting rules
+ *
+ * @return index of the newly created Conditional Formatting object
+ */
+
+ public int addConditionalFormatting( Region [] regions, HSSFConditionalFormattingRule [] cfRules )
+ {
+ HSSFConditionalFormatting cf = new HSSFConditionalFormatting(this);
+ cf.setFormattingRegions(regions);
+ if( cfRules != null )
+ {
+ for( int i=0; i!= cfRules.length; i++ )
+ {
+ cf.addConditionalFormat(cfRules[i]);
+ }
+ }
+ return sheet.addConditionalFormatting(cf.cfAggregate);
+ }
+
+ /**
+ * gets Conditional Formatting object at a particular index
+ * @param index of the Conditional Formatting object to fetch
+ * @return Conditional Formatting object
+ */
+
+ public HSSFConditionalFormatting getConditionalFormattingAt(int index)
+ {
+ CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index);
+ if( cf != null )
+ {
+ return new HSSFConditionalFormatting(this,cf);
+ }
+ return null;
+ }
+
+ /**
+ * @return number of Conditional Formatting objects of the sheet
+ */
+ public int getNumConditionalFormattings()
+ {
+ return sheet.getNumConditionalFormattings();
+ }
+
+ /**
+ * removes a Conditional Formatting object by index
+ * @param index of a Conditional Formatting object to remove
+ */
+ public void removeConditionalFormatting(int index)
+ {
+ sheet.removeConditionalFormatting(index);
+ }
+
}
diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java
index 74ea822a5..a9ce66f36 100644
--- a/src/java/org/apache/poi/util/POILogFactory.java
+++ b/src/java/org/apache/poi/util/POILogFactory.java
@@ -33,14 +33,25 @@ import java.util.*;
public class POILogFactory
{
- // map of POILogger instances, with classes as keys
- private static Map _loggers = new HashMap();;
-
+ /**
+ * Map of POILogger instances, with classes as keys
+ */
+ private static Map _loggers = new HashMap();;
/**
- * construct a POILogFactory.
+ * A common instance of NullLogger, as it does nothing
+ * we only need the one
*/
+ private static POILogger _nullLogger = new NullLogger();
+ /**
+ * The name of the class to use. Initialised the
+ * first time we need it
+ */
+ private static String _loggerClassName = null;
+ /**
+ * Construct a POILogFactory.
+ */
private POILogFactory()
{
}
@@ -69,28 +80,48 @@ public class POILogFactory
public static POILogger getLogger(final String cat)
{
POILogger logger = null;
-
- if (_loggers.containsKey(cat))
- {
- logger = ( POILogger ) _loggers.get(cat);
+
+ // If we haven't found out what logger to use yet,
+ // then do so now
+ // Don't look it up until we're first asked, so
+ // that our users can set the system property
+ // between class loading and first use
+ if(_loggerClassName == null) {
+ try {
+ _loggerClassName = System.getProperty("org.apache.poi.util.POILogger");
+ } catch(Exception e) {}
+
+ // Use the default logger if none specified,
+ // or none could be fetched
+ if(_loggerClassName == null) {
+ _loggerClassName = _nullLogger.getClass().getName();
+ }
}
- else
- {
- try{
- String loggerClassName = System.getProperty("org.apache.poi.util.POILogger");
- Class loggerClass = Class.forName(loggerClassName);
+
+ // Short circuit for the null logger, which
+ // ignores all categories
+ if(_loggerClassName.equals(_nullLogger.getClass().getName())) {
+ return _nullLogger;
+ }
+
+
+ // Fetch the right logger for them, creating
+ // it if that's required
+ if (_loggers.containsKey(cat)) {
+ logger = ( POILogger ) _loggers.get(cat);
+ } else {
+ try {
+ Class loggerClass = Class.forName(_loggerClassName);
logger = ( POILogger ) loggerClass.newInstance();
- }
- catch(Exception e){
-
- logger = new NullLogger();
+ logger.initialize(cat);
+ } catch(Exception e) {
+ // Give up and use the null logger
+ logger = _nullLogger;
}
- logger.initialize(cat);
-
+ // Save for next time
_loggers.put(cat, logger);
}
return logger;
}
-
-} // end public class POILogFactory
+} // end public class POILogFactory
\ No newline at end of file
diff --git a/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
index 58ab5b47a..bb16fdfad 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel;
import java.lang.reflect.Constructor;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
@@ -251,6 +252,35 @@ public class HSSFFormulaEvaluator {
}
return cell;
}
+
+ /**
+ * Loops over all cells in all sheets of the supplied
+ * workbook.
+ * For cells that contain formulas, their formulas are
+ * evaluated, and the results are saved. These cells
+ * remain as formula cells.
+ * For cells that do not contain formulas, no changes
+ * are made.
+ * This is a helpful wrapper around looping over all
+ * cells, and calling evaluateFormulaCell on each one.
+ */
+ public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
+ for(int i=0; icRjA&{wCjQXGq(JniijPE%x_;-(%vJ5lbsjgTG64s13<2w$Bgx_277^B;BBP*rv#&vj~B@3>UIC
zjok}BoAgPM%@lALDeSfnump}U58wgVz^2Xj-0hsHbcJriIx7VWMILy|*{Z<{lupOF
zx@C=8&eZZvjsp9&T#iO;w64dt%U8B9qZG7od#X?Mp475c%jqmF?9(}4tE3wa4pP7L
z@H29#*SN@7ouypKL04%{*S@X~yWZ^bbS&!Z7nkGcq^ht}Q-z&sw#UX)$TnN!Y>!Rk
z#@E?4!Mu781>S1G`Q=3_P9)!!m##c{NmqD2
zds({;8DygxF)ONeDcW%nFzC>FyQA(0ogTmIZ%;+g+S#g|zCkBzFTo;yI5j-4-3d=>
zcOo--(SggN&bSd3^ZwL`j0SppD^4%LVswX`2D)Xx6+vv~9L&Zno`Cbcom|v2u+VQ0
zEXvyF5$`$SQ3Wfa;t=tcvWoZ#*h?yWc3F+g9AZU|E=R!Kdg|&
z+ws+}4AX(E{yT}QA5&Y3J?J8u;yhTz&K^~&bp26T$%W
zcX+MxBSlZ^3{kmuI6Se9}D7
zR36h$^LR*>?>T{dZ=!rsg5T{a8})9wBz1$E(Yn#C)q18|qxCuNB&}z;w$^Z=b(33H
zTFd*Og~xc0cqJoyS&KCrhlaLxKfycyDt_LuY>r#@Y--5yB9Ay;*^E}1U{8@!llAS;
zg4G|b?Y_N7?!CP7VLlF68D_v;X5mj>=7UtCwG1|7W-$jc$Td&Xk;$yQN0j==Bg&K%
zA6r7HzYdtDH}t72@5BskH?Rci>EO@Tj(u^%`kQ(ORo<@h#afQ2gtz*#wFQI__z{nA
zc;1rUBj8@`9JUeD85FK`QWX*D%n$1BB(R3rB4b9G-uh)H0Ge-rx_NfAqu(Z$?6@X;Yi+yB_{>C@luIM(CErR3>Do>TN0
zWd89{gVTu=WMh$n86)?NY;i_5=hx(K&9Bd|>?V~tDE`ZFf@FLqdzUe|H~uZAL
zMZ)>Z&VsoUG5(A&exL7q#71~x(eW;9W27*0HKgp9iDW`};(AFku^iVsTV=x8!?^f-
z{kO2p=jsvse4ZZB^ErA(17XrP5CSH4?NPJe>}fEzfuOP
zBj_z?Li3J+r(S*X(8xC>IV;R1H<+zBcmSD+xrKjwmF%5nwf9ODwx@V+wiS}!cRVv-_2L3k
zQd7BQUfTR0!~%ja$V4%LRXkC>n84^OGmnc29NZPe1j2+q`7vZgYO)_CkiANX4unnk
zdu}R&fI+|@U=T0}REfafym_bf9e8wt#qQW+Fa7lUjT`GQ`~7rgTo-@0KVGv7_=
z^QiRYrYz4Na{IlOc^dQ0%zR6XwaoJDxr=dazSdP;2_&$IK4y36q3<^Ier!n_?|rn#
zy6$7k4}pusB!hrKz#w1{FbEg~3<3rLgMdN6AYc$M2p9zZB?QLf|EVuO`|^b)E%n=<
zC;#vG{SD#!E_0aw%eVf7|I1seK4#(n5(kiYKtFT9|ATJ_26dJbB*q}`OuUdjrcxy8
z5-Jcg`KS4=WM%$VmUrn_<3!&igMdN6AYc$M2p9wm0tNwtfI+|@U=T0}7z9op0pZj_
zy5+sQ%`DtrzAGubT>h^Eze}gTJ`>(9oL-2z{Ge?Hvy3;eZe*7C{lQP=n%JJrEaUva
zxBNy~euRv<%=4Iq;Gf4V<9{)?`fWB%I>QL8#%6xD!ok(p#Ci)J;%Zc%_`QEC*kn0|
z>N9dQ0YxowjaPZ)=gx~i%Xd6v-2?d*>i^!Ld(!n}q{{wfJE}1t-&xUs6|39me+%x#
z`cvEv{uc^M&Y=JUF^LTav}W-;&Sd*
vyZ`FC?Efly*r3}mq({KXZO^h(z`t4c#P=`F(@g>P)$af4`isv$oBjU-GFsRw
literal 0
HcmV?d00001
diff --git a/src/testcases/org/apache/poi/hssf/data/43251.xls b/src/testcases/org/apache/poi/hssf/data/43251.xls
new file mode 100644
index 0000000000000000000000000000000000000000..abc476ab0f3af28d7964b055ef61e752c131584e
GIT binary patch
literal 166400
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
literal 0
HcmV?d00001
diff --git a/src/testcases/org/apache/poi/hssf/data/44643.xls b/src/testcases/org/apache/poi/hssf/data/44643.xls
new file mode 100644
index 0000000000000000000000000000000000000000..7ae5071864c70bab4eea790d286e5c1e327981c2
GIT binary patch
literal 15872
zcmeHOU2GIp6#k~&rCTV_779|JtlJveQksGYXag;X1Wb{pR;lSWWuaRkEv@NK0*S^|
z;l-fA_}~kPV*HH;H5z>}rX)Pn2O=RMLE=L(Bqls)G-xD2*6+L9p|k6>v=|J?J(F|K
zopbKbnQ!jgyXWrA>F)|gj(t{q0U5L&*|?U>#WauJVScfDo)6lSNu9cK5%W}8x`PnN
z4e>@!3*yX@Q#s!bF`ErsKo&j?oL~z4NRHwe<-`9awQ}TXya5}HH!(-v3{ka?xojMz
zb`};G9}7)7$E2T_a$lQt9SThgCm-!vwASPtv}Dzra<7;)V$xYm9eic#oHv>kD8?{r
zB%eQ$asokT1NyKRF?8eBTHm@szX9YyUdge4dKEyKueBtw2tmvTB4v@%s?yS$_KMnQ
zxqA|=C<)w4#Q6lfD%x9{;vH@2g(Aq&6yO%Bu1Rl)=W1#xLWpFR%4lu0=o(aFCD1Nc
zD#Na4qo>hwqli}2jw&L{BlN4iyuO{iRHK3it9t8IhP{<4!)Z0@P=$xmJ4;
zPnUIdW1X(XGT#5OPTl&~`*kauuDvyj@DBK_MV^ZHM`}mY$9f|rfnvOiA{v_e2II7h
zip{a^{y433@g8Q=y1j?CRMOc=eH-5A)i|xZ-yesU6T>z>r(u**S<0gZ)#Mtq6QWwQ
zq6u+ym@?%&o48JtbxHzd_y9|Q*0SZRY94IsAVsU9;eDiNIF&y@8o^wSL*Vyh*vM2e
z6qa5i)aWm}rit}>!u`sRr&p_f<^Rumhxd4lTs)VhaQM@;xcZ85^i|{ND}D7jZ1%EN
z`i%Ri-v)kq2f4oO$UEczh;pK#@atItxccF*
zXSVHXtZO&=N~2$9(ie>;;c@9cBEyvkFVJ#=(?QCemrUt{Cf$ZJGd-Q(WL7BsfXjKa
zlTJXeU7Fq->Y&WwnyK>^<3|JMkpUiYu7+WhV=d>I2RPY>v7fwxM?{nI6p43&J&dtm
z^(Jh^!`O~3>}LZyxfbsx_www1&U35iMHr1N(LlM{r-24qo9Q1HfV+YmUgc?yi&wc`
ze{oL=Tb-Yule&D3#XoX^i+L&AR6yxq;ot-nyitR<7~LS{FV!LG+T^Pxi-1MIBH)L>
zc=Lm+ccow5Or7Q~FKKlhkKA@M=Q`Ud_KqseZZ%oTh*^mS5{>aun1TLCXImKynl?5l*3g+
zv6sU*uO+KROA2YE&Xo?Hpe2OoxF<+*%5u5GN6itGP%6J|Z%=PuLp=8MV0>e&KfWv0
z-Q66I?PH-?w0dcMRw2GLlVrU|y_m5pCw!5dOx7X!3zw}R*6?g}Ws}j;or%CT?&}22
z9!k3Zy4fR#-u&_C5I@y%xf?Uht
zVn10y=RvZD@I_YA_*7ldc=>u6&jm}jJlW_dpBO&ZlKb+oqwzTUC@^QqB481)2v`Ix
z0u}*_fJML}U=gqgSOhEr7J(ZfFj4%Ub@tTRqty%ZUw?z~f7O-aivNen{L|RP|BaM<
zH3=5>wO6A!Yl57mOPKF_+R@0+C$L(z}sZM{Q$-HCzs4HZ81BpEMX_w
zhtM|E^|wBdN3B}bu7bST(c9P6zb76a=r|IF@wFmpednq8U2l#k?pKUoK-Pc$it}aH
zrxJ?wwI86jy%&&+$qUJ{|3#LxbbBDs#4jj%xlp)8#!)z=
zlwbCk6q{2bJ=OhpH9OdQAG)y1_|fI6CoTEy=k@;O$7CyR&>$rR@i^ZY-Nz$lu6-*}
z=rle_Ghn_j=}8s!P0QK8o*_LylkH!7U*_SV2x1d^+iiS^n>#Qyf7af__3IlVxBtHZ
DxvW$1
literal 0
HcmV?d00001
diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java
new file mode 100644
index 000000000..c3e568479
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java
@@ -0,0 +1,145 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.cf.CellRange;
+
+/**
+ * Tests the serialization and deserialization of the TestCFHeaderRecord
+ * class works correctly.
+ *
+ * @author Dmitriy Kumshayev
+ */
+public class TestCFHeaderRecord
+ extends TestCase
+{
+
+ public TestCFHeaderRecord(String name)
+ {
+ super(name);
+ }
+
+ public void testCreateCFHeaderRecord ()
+ {
+ CFHeaderRecord record = new CFHeaderRecord();
+ List ranges = new ArrayList();
+ ranges.add(new CellRange(0,-1,(short)5,(short)5));
+ ranges.add(new CellRange(0,-1,(short)6,(short)6));
+ ranges.add(new CellRange(0,1,(short)0,(short)1));
+ ranges.add(new CellRange(0,1,(short)2,(short)3));
+ ranges.add(new CellRange(2,3,(short)0,(short)1));
+ ranges.add(new CellRange(2,3,(short)2,(short)3));
+ record.setCellRanges(ranges);
+ ranges = record.getCellRanges();
+ assertEquals(6,ranges.size());
+ CellRange enclosingCellRange = record.getEnclosingCellRange();
+ assertEquals(0, enclosingCellRange.getFirstRow());
+ assertEquals(-1, enclosingCellRange.getLastRow());
+ assertEquals(0, enclosingCellRange.getFirstColumn());
+ assertEquals(6, enclosingCellRange.getLastColumn());
+ record.setNeedRecalculation(true);
+ assertTrue(record.getNeedRecalculation());
+ record.setNeedRecalculation(false);
+ assertFalse(record.getNeedRecalculation());
+ }
+
+ public void testSerialization() {
+ byte[] recordData = new byte[]
+ {
+ (byte)0x03, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+
+ (byte)0x04, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x00, (byte)0x00,
+ (byte)0x01, (byte)0x00,
+
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ (byte)0x02, (byte)0x00,
+ (byte)0x03, (byte)0x00,
+ };
+
+ CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
+
+ assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
+ assertTrue(record.getNeedRecalculation());
+ CellRange enclosingCellRange = record.getEnclosingCellRange();
+ assertEquals(0, enclosingCellRange.getFirstRow());
+ assertEquals(3, enclosingCellRange.getLastRow());
+ assertEquals(0, enclosingCellRange.getFirstColumn());
+ assertEquals(3, enclosingCellRange.getLastColumn());
+ List ranges = record.getCellRanges();
+ assertEquals(0, ((CellRange)ranges.get(0)).getFirstRow());
+ assertEquals(1, ((CellRange)ranges.get(0)).getLastRow());
+ assertEquals(0, ((CellRange)ranges.get(0)).getFirstColumn());
+ assertEquals(1, ((CellRange)ranges.get(0)).getLastColumn());
+ assertEquals(0, ((CellRange)ranges.get(1)).getFirstRow());
+ assertEquals(1, ((CellRange)ranges.get(1)).getLastRow());
+ assertEquals(2, ((CellRange)ranges.get(1)).getFirstColumn());
+ assertEquals(3, ((CellRange)ranges.get(1)).getLastColumn());
+ assertEquals(2, ((CellRange)ranges.get(2)).getFirstRow());
+ assertEquals(3, ((CellRange)ranges.get(2)).getLastRow());
+ assertEquals(0, ((CellRange)ranges.get(2)).getFirstColumn());
+ assertEquals(1, ((CellRange)ranges.get(2)).getLastColumn());
+ assertEquals(2, ((CellRange)ranges.get(3)).getFirstRow());
+ assertEquals(3, ((CellRange)ranges.get(3)).getLastRow());
+ assertEquals(2, ((CellRange)ranges.get(3)).getFirstColumn());
+ assertEquals(3, ((CellRange)ranges.get(3)).getLastColumn());
+ assertEquals(recordData.length+4, record.getRecordSize());
+
+ byte[] output = record.serialize();
+
+ assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
+
+ for (int i = 0; i < recordData.length;i++)
+ {
+ assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
+ }
+ }
+
+
+ public static void main(String[] ignored_args)
+ {
+ System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
+ junit.textui.TestRunner.run(TestCFHeaderRecord.class);
+ }
+
+}
diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
new file mode 100644
index 000000000..77731d781
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
@@ -0,0 +1,296 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.cf.BorderFormatting;
+import org.apache.poi.hssf.record.cf.FontFormatting;
+import org.apache.poi.hssf.record.cf.PatternFormatting;
+import org.apache.poi.hssf.util.HSSFColor;
+
+/**
+ * Tests the serialization and deserialization of the TestCFRuleRecord
+ * class works correctly.
+ *
+ * @author Dmitriy Kumshayev
+ */
+public class TestCFRuleRecord
+ extends TestCase
+{
+
+ public TestCFRuleRecord(String name)
+ {
+ super(name);
+ }
+
+ public void testCreateCFRuleRecord ()
+ {
+ CFRuleRecord record = new CFRuleRecord();
+ testCFRuleRecord(record);
+
+ // Serialize
+ byte [] serializedRecord = record.serialize();
+
+ // Strip header
+ byte [] recordData = new byte[serializedRecord.length-4];
+ System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);
+
+ // Deserialize
+ record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));
+
+ // Serialize again
+ byte[] output = record.serialize();
+
+ // Compare
+ assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
+
+ for (int i = 0; i < recordData.length;i++)
+ {
+ assertEquals("CFRuleRecord doesn't match", recordData[i], output[i+4]);
+ }
+ }
+
+ private void testCFRuleRecord(CFRuleRecord record)
+ {
+ FontFormatting fontFormatting = new FontFormatting();
+ testFontFormattingAccessors(fontFormatting);
+ assertFalse(record.containsFontFormattingBlock());
+ record.setFontFormatting(fontFormatting);
+ assertTrue(record.containsFontFormattingBlock());
+
+ BorderFormatting borderFormatting = new BorderFormatting();
+ testBorderFormattingAccessors(borderFormatting);
+ assertFalse(record.containsBorderFormattingBlock());
+ record.setBorderFormatting(borderFormatting);
+ assertTrue(record.containsBorderFormattingBlock());
+
+ assertFalse(record.isLeftBorderModified());
+ record.setLeftBorderModified(true);
+ assertTrue(record.isLeftBorderModified());
+
+ assertFalse(record.isRightBorderModified());
+ record.setRightBorderModified(true);
+ assertTrue(record.isRightBorderModified());
+
+ assertFalse(record.isTopBorderModified());
+ record.setTopBorderModified(true);
+ assertTrue(record.isTopBorderModified());
+
+ assertFalse(record.isBottomBorderModified());
+ record.setBottomBorderModified(true);
+ assertTrue(record.isBottomBorderModified());
+
+ assertFalse(record.isTopLeftBottomRightBorderModified());
+ record.setTopLeftBottomRightBorderModified(true);
+ assertTrue(record.isTopLeftBottomRightBorderModified());
+
+ assertFalse(record.isBottomLeftTopRightBorderModified());
+ record.setBottomLeftTopRightBorderModified(true);
+ assertTrue(record.isBottomLeftTopRightBorderModified());
+
+
+ PatternFormatting patternFormatting = new PatternFormatting();
+ testPatternFormattingAccessors(patternFormatting);
+ assertFalse(record.containsPatternFormattingBlock());
+ record.setPatternFormatting(patternFormatting);
+ assertTrue(record.containsPatternFormattingBlock());
+
+ assertFalse(record.isPatternBackgroundColorModified());
+ record.setPatternBackgroundColorModified(true);
+ assertTrue(record.isPatternBackgroundColorModified());
+
+ assertFalse(record.isPatternColorModified());
+ record.setPatternColorModified(true);
+ assertTrue(record.isPatternColorModified());
+
+ assertFalse(record.isPatternStyleModified());
+ record.setPatternStyleModified(true);
+ assertTrue(record.isPatternStyleModified());
+ }
+
+ private void testPatternFormattingAccessors(PatternFormatting patternFormatting)
+ {
+ patternFormatting.setFillBackgroundColor(HSSFColor.GREEN.index);
+ assertEquals(HSSFColor.GREEN.index,patternFormatting.getFillBackgroundColor());
+
+ patternFormatting.setFillForegroundColor(HSSFColor.INDIGO.index);
+ assertEquals(HSSFColor.INDIGO.index,patternFormatting.getFillForegroundColor());
+
+ patternFormatting.setFillPattern(PatternFormatting.DIAMONDS);
+ assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern());
+
+ }
+
+ private void testBorderFormattingAccessors(BorderFormatting borderFormatting)
+ {
+ borderFormatting.setBackwardDiagonalOn(false);
+ assertFalse(borderFormatting.isBackwardDiagonalOn());
+ borderFormatting.setBackwardDiagonalOn(true);
+ assertTrue(borderFormatting.isBackwardDiagonalOn());
+
+ borderFormatting.setBorderBottom(BorderFormatting.BORDER_DOTTED);
+ assertEquals(BorderFormatting.BORDER_DOTTED, borderFormatting.getBorderBottom());
+
+ borderFormatting.setBorderDiagonal(BorderFormatting.BORDER_MEDIUM);
+ assertEquals(BorderFormatting.BORDER_MEDIUM, borderFormatting.getBorderDiagonal());
+
+ borderFormatting.setBorderLeft(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT);
+ assertEquals(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT, borderFormatting.getBorderLeft());
+
+ borderFormatting.setBorderRight(BorderFormatting.BORDER_MEDIUM_DASHED);
+ assertEquals(BorderFormatting.BORDER_MEDIUM_DASHED, borderFormatting.getBorderRight());
+
+ borderFormatting.setBorderTop(BorderFormatting.BORDER_HAIR);
+ assertEquals(BorderFormatting.BORDER_HAIR, borderFormatting.getBorderTop());
+
+ borderFormatting.setBottomBorderColor(HSSFColor.AQUA.index);
+ assertEquals(HSSFColor.AQUA.index, borderFormatting.getBottomBorderColor());
+
+ borderFormatting.setDiagonalBorderColor(HSSFColor.RED.index);
+ assertEquals(HSSFColor.RED.index, borderFormatting.getDiagonalBorderColor());
+
+ assertFalse(borderFormatting.isForwardDiagonalOn());
+ borderFormatting.setForwardDiagonalOn(true);
+ assertTrue(borderFormatting.isForwardDiagonalOn());
+
+ borderFormatting.setLeftBorderColor(HSSFColor.BLACK.index);
+ assertEquals(HSSFColor.BLACK.index, borderFormatting.getLeftBorderColor());
+
+ borderFormatting.setRightBorderColor(HSSFColor.BLUE.index);
+ assertEquals(HSSFColor.BLUE.index, borderFormatting.getRightBorderColor());
+
+ borderFormatting.setTopBorderColor(HSSFColor.GOLD.index);
+ assertEquals(HSSFColor.GOLD.index, borderFormatting.getTopBorderColor());
+ }
+
+
+ private void testFontFormattingAccessors(FontFormatting fontFormatting)
+ {
+ // Check for defaults
+ assertFalse(fontFormatting.isEscapementTypeModified());
+ assertFalse(fontFormatting.isFontCancellationModified());
+ assertFalse(fontFormatting.isFontCondenseModified());
+ assertFalse(fontFormatting.isFontOutlineModified());
+ assertFalse(fontFormatting.isFontShadowModified());
+ assertFalse(fontFormatting.isFontStyleModified());
+ assertFalse(fontFormatting.isUnderlineTypeModified());
+
+ assertFalse(fontFormatting.isBold());
+ assertFalse(fontFormatting.isCondenseOn());
+ assertFalse(fontFormatting.isItalic());
+ assertFalse(fontFormatting.isOutlineOn());
+ assertFalse(fontFormatting.isShadowOn());
+ assertFalse(fontFormatting.isStruckout());
+
+ assertEquals(0, fontFormatting.getEscapementType());
+ assertEquals(-1, fontFormatting.getFontColorIndex());
+ assertEquals(-1, fontFormatting.getFontHeight());
+ assertEquals(400, fontFormatting.getFontWeight());
+ assertEquals(0, fontFormatting.getUnderlineType());
+
+ fontFormatting.setBold(true);
+ assertTrue(fontFormatting.isBold());
+ fontFormatting.setBold(false);
+ assertFalse(fontFormatting.isBold());
+
+ fontFormatting.setCondense(true);
+ assertTrue(fontFormatting.isCondenseOn());
+ fontFormatting.setCondense(false);
+ assertFalse(fontFormatting.isCondenseOn());
+
+ fontFormatting.setEscapementType(FontFormatting.SS_SUB);
+ assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType());
+ fontFormatting.setEscapementType(FontFormatting.SS_SUPER);
+ assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType());
+ fontFormatting.setEscapementType(FontFormatting.SS_NONE);
+ assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType());
+
+ fontFormatting.setEscapementTypeModified(false);
+ assertFalse(fontFormatting.isEscapementTypeModified());
+ fontFormatting.setEscapementTypeModified(true);
+ assertTrue(fontFormatting.isEscapementTypeModified());
+
+ fontFormatting.setFontCancellationModified(false);
+ assertFalse(fontFormatting.isFontCancellationModified());
+ fontFormatting.setFontCancellationModified(true);
+ assertTrue(fontFormatting.isFontCancellationModified());
+
+ fontFormatting.setFontColorIndex((short)10);
+ assertEquals(10,fontFormatting.getFontColorIndex());
+
+ fontFormatting.setFontCondenseModified(false);
+ assertFalse(fontFormatting.isFontCondenseModified());
+ fontFormatting.setFontCondenseModified(true);
+ assertTrue(fontFormatting.isFontCondenseModified());
+
+ fontFormatting.setFontHeight((short)100);
+ assertEquals(100,fontFormatting.getFontHeight());
+
+ fontFormatting.setFontOutlineModified(false);
+ assertFalse(fontFormatting.isFontOutlineModified());
+ fontFormatting.setFontOutlineModified(true);
+ assertTrue(fontFormatting.isFontOutlineModified());
+
+ fontFormatting.setFontShadowModified(false);
+ assertFalse(fontFormatting.isFontShadowModified());
+ fontFormatting.setFontShadowModified(true);
+ assertTrue(fontFormatting.isFontShadowModified());
+
+ fontFormatting.setFontStyleModified(false);
+ assertFalse(fontFormatting.isFontStyleModified());
+ fontFormatting.setFontStyleModified(true);
+ assertTrue(fontFormatting.isFontStyleModified());
+
+ fontFormatting.setItalic(false);
+ assertFalse(fontFormatting.isItalic());
+ fontFormatting.setItalic(true);
+ assertTrue(fontFormatting.isItalic());
+
+ fontFormatting.setOutline(false);
+ assertFalse(fontFormatting.isOutlineOn());
+ fontFormatting.setOutline(true);
+ assertTrue(fontFormatting.isOutlineOn());
+
+ fontFormatting.setShadow(false);
+ assertFalse(fontFormatting.isShadowOn());
+ fontFormatting.setShadow(true);
+ assertTrue(fontFormatting.isShadowOn());
+
+ fontFormatting.setStrikeout(false);
+ assertFalse(fontFormatting.isStruckout());
+ fontFormatting.setStrikeout(true);
+ assertTrue(fontFormatting.isStruckout());
+
+ fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING);
+ assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType());
+
+ fontFormatting.setUnderlineTypeModified(false);
+ assertFalse(fontFormatting.isUnderlineTypeModified());
+ fontFormatting.setUnderlineTypeModified(true);
+ assertTrue(fontFormatting.isUnderlineTypeModified());
+ }
+
+
+ public static void main(String[] ignored_args)
+ {
+ System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord");
+ junit.textui.TestRunner.run(TestCFRuleRecord.class);
+ }
+
+}
diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
new file mode 100644
index 000000000..332c99209
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
@@ -0,0 +1,111 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.aggregates;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.CFHeaderRecord;
+import org.apache.poi.hssf.record.CFRuleRecord;
+import org.apache.poi.hssf.record.RecordFactory;
+import org.apache.poi.hssf.record.cf.CellRange;
+
+/**
+ * Tests the serialization and deserialization of the CFRecordsAggregate
+ * class works correctly.
+ *
+ * @author Dmitriy Kumshayev
+ */
+public class TestCFRecordsAggregate
+ extends TestCase
+{
+
+ public TestCFRecordsAggregate(String name)
+ {
+ super(name);
+ }
+
+ public void testCFRecordsAggregate()
+ {
+ CFRecordsAggregate record = new CFRecordsAggregate();
+ List recs = new ArrayList();
+ CFHeaderRecord header = new CFHeaderRecord();
+ CFRuleRecord rule1 = new CFRuleRecord();
+ CFRuleRecord rule2 = new CFRuleRecord();
+ CFRuleRecord rule3 = new CFRuleRecord();
+ header.setNumberOfConditionalFormats(3);
+ CellRange range1 = new CellRange(0,1,(short)0,(short)0);
+ CellRange range2 = new CellRange(0,1,(short)2,(short)2);
+ List cellRanges = new ArrayList();
+ cellRanges.add(range1);
+ cellRanges.add(range2);
+ header.setCellRanges(cellRanges);
+ recs.add(header);
+ recs.add(rule1);
+ recs.add(rule2);
+ recs.add(rule3);
+ record = CFRecordsAggregate.createCFAggregate(recs, 0);
+
+ // Serialize
+ byte [] serializedRecord = record.serialize();
+ InputStream in = new ByteArrayInputStream(serializedRecord);
+
+ //Parse
+ recs = RecordFactory.createRecords(in);
+
+ // Verify
+ assertNotNull(recs);
+ assertEquals(4, recs.size());
+
+ header = (CFHeaderRecord)recs.get(0);
+ rule1 = (CFRuleRecord)recs.get(1);
+ rule2 = (CFRuleRecord)recs.get(2);
+ rule3 = (CFRuleRecord)recs.get(3);
+ cellRanges = header.getCellRanges();
+
+ assertEquals(2, cellRanges.size());
+ assertEquals(3, header.getNumberOfConditionalFormats());
+
+ record = CFRecordsAggregate.createCFAggregate(recs, 0);
+
+ record = record.cloneCFAggregate();
+
+ assertNotNull(record.getHeader());
+ assertEquals(3,record.getRules().size());
+
+ header = record.getHeader();
+ rule1 = (CFRuleRecord)record.getRules().get(0);
+ rule2 = (CFRuleRecord)record.getRules().get(1);
+ rule3 = (CFRuleRecord)record.getRules().get(2);
+ cellRanges = header.getCellRanges();
+
+ assertEquals(2, cellRanges.size());
+ assertEquals(3, header.getNumberOfConditionalFormats());
+ }
+
+ public static void main(String[] ignored_args)
+ {
+ System.out.println("Testing org.apache.poi.hssf.record.aggregates.CFRecordsAggregate");
+ junit.textui.TestRunner.run(TestCFRecordsAggregate.class);
+ }
+
+}
diff --git a/src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java b/src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java
new file mode 100644
index 000000000..f9857fb24
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java
@@ -0,0 +1,139 @@
+/* ====================================================================
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.cf;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests CellRange operations.
+ */
+public class TestCellRange extends TestCase
+{
+ private static final CellRange biggest = new CellRange(0, -1,(short) 0,(short)-1);
+ private static final CellRange tenthColumn = new CellRange(0, -1,(short)10,(short)10);
+ private static final CellRange tenthRow = new CellRange(10,10,(short) 0,(short)-1);
+ private static final CellRange box10x10 = new CellRange(0, 10,(short) 0,(short)10);
+ private static final CellRange box9x9 = new CellRange(0, 9,(short) 0,(short) 9);
+ private static final CellRange box10to20c = new CellRange(0, 10,(short)10,(short)20);
+ private static final CellRange oneCell = new CellRange(10,10,(short)10,(short)10);
+
+ boolean [][] contanis = new boolean[][]
+ {
+ // biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell
+ /*biggest */ new boolean[]{true, true , true , true , true , true , true},
+ /*tenthColumn*/ new boolean[]{false, true , false, false, false, false, true},
+ /*tenthRow */ new boolean[]{false, false, true , false, false, false, true},
+ /*box10x10 */ new boolean[]{false, false, false, true , true , false, true},
+ /*box9x9 */ new boolean[]{false, false, false, false, true , false, false},
+ /*box10to20c */ new boolean[]{false, false, false, false, false, true , true},
+ /*oneCell */ new boolean[]{false, false, false, false, false, false, true},
+ } ;
+
+
+ public void testContainsMethod()
+ {
+ CellRange [] ranges = new CellRange[]{biggest,tenthColumn,tenthRow,box10x10,box9x9,box10to20c,oneCell};
+ testContainsMethod(contanis,ranges);
+ }
+
+ private void testContainsMethod(boolean[][]contains,CellRange[] ranges)
+ {
+ for(int i=0; i!=ranges.length;i++)
+ {
+ for(int j=0; j!=ranges.length;j++)
+ {
+ assertEquals("("+i+","+j+"): ",contains[i][j],ranges[i].contains(ranges[j]));
+ }
+ }
+ }
+
+ private static final CellRange col1 = new CellRange(0, -1,(short) 1,(short)1);
+ private static final CellRange col2 = new CellRange(0, -1,(short) 2,(short)2);
+ private static final CellRange row1 = new CellRange(1, 1,(short) 0,(short)-1);
+ private static final CellRange row2 = new CellRange(2, 2,(short) 0,(short)-1);
+
+ private static final CellRange box0 = new CellRange( 0, 2,(short) 0,(short)2);
+ private static final CellRange box1 = new CellRange( 0, 1,(short) 0,(short)1);
+ private static final CellRange box2 = new CellRange( 0, 1,(short) 2,(short)3);
+ private static final CellRange box3 = new CellRange( 2, 3,(short) 0,(short)1);
+ private static final CellRange box4 = new CellRange( 2, 3,(short) 2,(short)3);
+ private static final CellRange box5 = new CellRange( 1, 3,(short) 1,(short)3);
+
+ public void testHasSharedBorderMethod()
+ {
+ assertFalse(col1.hasSharedBorder(col1));
+ assertFalse(col2.hasSharedBorder(col2));
+ assertTrue(col1.hasSharedBorder(col2));
+ assertTrue(col2.hasSharedBorder(col1));
+
+ assertFalse(row1.hasSharedBorder(row1));
+ assertFalse(row2.hasSharedBorder(row2));
+ assertTrue(row1.hasSharedBorder(row2));
+ assertTrue(row2.hasSharedBorder(row1));
+
+ assertFalse(row1.hasSharedBorder(col1));
+ assertFalse(row1.hasSharedBorder(col2));
+ assertFalse(col1.hasSharedBorder(row1));
+ assertFalse(col2.hasSharedBorder(row1));
+ assertFalse(row2.hasSharedBorder(col1));
+ assertFalse(row2.hasSharedBorder(col2));
+ assertFalse(col1.hasSharedBorder(row2));
+ assertFalse(col2.hasSharedBorder(row2));
+ assertTrue(col2.hasSharedBorder(col1));
+
+ assertFalse(box1.hasSharedBorder(box1));
+ assertTrue(box1.hasSharedBorder(box2));
+ assertTrue(box1.hasSharedBorder(box3));
+ assertFalse(box1.hasSharedBorder(box4));
+
+ assertTrue(box2.hasSharedBorder(box1));
+ assertFalse(box2.hasSharedBorder(box2));
+ assertFalse(box2.hasSharedBorder(box3));
+ assertTrue(box2.hasSharedBorder(box4));
+
+ assertTrue(box3.hasSharedBorder(box1));
+ assertFalse(box3.hasSharedBorder(box2));
+ assertFalse(box3.hasSharedBorder(box3));
+ assertTrue(box3.hasSharedBorder(box4));
+
+ assertFalse(box4.hasSharedBorder(box1));
+ assertTrue(box4.hasSharedBorder(box2));
+ assertTrue(box4.hasSharedBorder(box3));
+ assertFalse(box4.hasSharedBorder(box4));
+ }
+
+ public void testIntersectMethod()
+ {
+ assertEquals( CellRange.OVERLAP,box0.intersect(box5));
+ assertEquals( CellRange.OVERLAP,box5.intersect(box0));
+ assertEquals(CellRange.NO_INTERSECTION,box1.intersect(box4));
+ assertEquals(CellRange.NO_INTERSECTION,box4.intersect(box1));
+ assertEquals(CellRange.NO_INTERSECTION,box2.intersect(box3));
+ assertEquals(CellRange.NO_INTERSECTION,box3.intersect(box2));
+ assertEquals(CellRange.INSIDE,box0.intersect(box1));
+ assertEquals(CellRange.INSIDE,box0.intersect(box0));
+ assertEquals(CellRange.ENCLOSES,box1.intersect(box0));
+ assertEquals(CellRange.INSIDE,tenthColumn.intersect(oneCell));
+ assertEquals(CellRange.ENCLOSES,oneCell.intersect(tenthColumn));
+ assertEquals(CellRange.OVERLAP,tenthColumn.intersect(tenthRow));
+ assertEquals(CellRange.OVERLAP,tenthRow.intersect(tenthColumn));
+ assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
+ assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
+ }
+
+}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
index f06f591c4..05ba29d09 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
@@ -1034,6 +1034,28 @@ extends TestCase {
assertTrue("No Exceptions while reading file", true);
}
+ /**
+ * Bug 41546: Constructing HSSFWorkbook is failed,
+ * Unknown Ptg in Formula: 0x1a (26)
+ */
+ public void test41546() throws Exception {
+ FileInputStream in = new FileInputStream(new File(cwd, "41546.xls"));
+ HSSFWorkbook wb = new HSSFWorkbook(in);
+ in.close();
+
+ assertTrue("No Exceptions while reading file", true);
+ assertEquals(1, wb.getNumberOfSheets());
+
+ //serialize and read again
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ wb.write(out);
+ out.close();
+
+ wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
+ assertTrue("No Exceptions while reading file", true);
+ assertEquals(1, wb.getNumberOfSheets());
+ }
+
/**
* Bug 42564: Some files from Access were giving a RecordFormatException
* when reading the BOFRecord
@@ -1114,6 +1136,20 @@ extends TestCase {
//assertEquals("=CHOOSE(2,A2,A3,A4)", c2.getCellFormula());
}
+ /**
+ * Something up with the FileSharingRecord
+ */
+ public void test43251() throws Exception {
+ FileInputStream in = new FileInputStream(new File(cwd, "43251.xls"));
+
+ // Used to blow up with an IllegalArgumentException
+ // when creating a FileSharingRecord
+ HSSFWorkbook wb = new HSSFWorkbook(in);
+ in.close();
+
+ assertEquals(1, wb.getNumberOfSheets());
+ }
+
/**
* Crystal reports generates files with short
* StyleRecords, which is against the spec
@@ -1157,7 +1193,7 @@ extends TestCase {
* probably due to dropdowns
*/
public void test44593() throws Exception {
- FileInputStream in = new FileInputStream(new File(cwd, "Bug44593.xls"));
+ FileInputStream in = new FileInputStream(new File(cwd, "44593.xls"));
// Used to blow up with an IllegalArgumentException
// when creating a DVRecord
@@ -1168,6 +1204,20 @@ extends TestCase {
assertEquals(2, wb.getNumberOfSheets());
}
+
+ /**
+ * Used to give problems due to trying to read a zero
+ * length string, but that's now properly handled
+ */
+ public void test44643() throws Exception {
+ FileInputStream in = new FileInputStream(new File(cwd, "44643.xls"));
+
+ // Used to blow up with an IllegalArgumentException
+ HSSFWorkbook wb = new HSSFWorkbook(in);
+ in.close();
+
+ assertEquals(1, wb.getNumberOfSheets());
+ }
}
diff --git a/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlock.java b/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlock.java
index 4c84f04b7..73ddcad54 100644
--- a/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlock.java
+++ b/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlock.java
@@ -36,23 +36,23 @@ import junit.framework.*;
public class TestRawDataBlock
extends TestCase
{
-
- /**
- * Constructor TestRawDataBlock
- *
- * @param name
- */
-
- public TestRawDataBlock(String name)
- {
- super(name);
-
+ static {
// We always want to use our own
// logger
System.setProperty(
"org.apache.poi.util.POILogger",
"org.apache.poi.util.DummyPOILogger"
);
+ }
+
+ /**
+ * Constructor TestRawDataBlock
+ *
+ * @param name
+ */
+ public TestRawDataBlock(String name)
+ {
+ super(name);
}
/**
diff --git a/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java b/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java
index d15102976..0f65c0e8a 100644
--- a/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java
+++ b/src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java
@@ -36,23 +36,23 @@ import junit.framework.*;
public class TestRawDataBlockList
extends TestCase
{
-
- /**
- * Constructor TestRawDataBlockList
- *
- * @param name
- */
-
- public TestRawDataBlockList(String name)
- {
- super(name);
-
+ static {
// We always want to use our own
// logger
System.setProperty(
"org.apache.poi.util.POILogger",
"org.apache.poi.util.DummyPOILogger"
);
+ }
+
+ /**
+ * Constructor TestRawDataBlockList
+ *
+ * @param name
+ */
+ public TestRawDataBlockList(String name)
+ {
+ super(name);
}
/**
@@ -60,7 +60,6 @@ public class TestRawDataBlockList
*
* @exception IOException
*/
-
public void testNormalConstructor()
throws IOException
{