aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Burch <nick@apache.org>2008-07-06 12:11:37 +0000
committerNick Burch <nick@apache.org>2008-07-06 12:11:37 +0000
commit510130f5631bc1f5247994eb916da0e09ff74b96 (patch)
treeece56f198ecb5086f3967d0d47d218161cc871bd
parent35c912df0c76fc520ded7c18a2c3838967978977 (diff)
downloadpoi-510130f5631bc1f5247994eb916da0e09ff74b96.tar.gz
poi-510130f5631bc1f5247994eb916da0e09ff74b96.zip
Merged revisions 668156-671000 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r668257 | yegor | 2008-06-16 19:38:59 +0100 (Mon, 16 Jun 2008) | 1 line TextShape.getMarginLeft() returned incorrect value. Added a unit test for text margins. ........ r668259 | yegor | 2008-06-16 19:40:51 +0100 (Mon, 16 Jun 2008) | 1 line patch from bug #45177: Remove GPL reference in NOTICE ........ r669140 | nick | 2008-06-18 12:35:04 +0100 (Wed, 18 Jun 2008) | 1 line A partial fix for bug #30978, but something still remains, which seems to be related to changing the ptg ........ r669456 | nick | 2008-06-19 12:47:48 +0100 (Thu, 19 Jun 2008) | 1 line Improved HWPF Range.replaceText, from N. Hira in bug #45001 ........ r669658 | josh | 2008-06-19 20:07:20 +0100 (Thu, 19 Jun 2008) | 1 line Fix for bug 45234 - Removed incorrect shared formula conversion in CFRuleRecord ........ r669809 | josh | 2008-06-20 08:10:03 +0100 (Fri, 20 Jun 2008) | 1 line Fix for bug 30978 - small re-arrangement of class Ptg hierarchy for DeletedRef3DPtg and DeletedArea3DPtg. Similar to c664220 ........ r670190 | yegor | 2008-06-21 13:41:34 +0100 (Sat, 21 Jun 2008) | 1 line started a new section for poi-3.2 family, updated release date of 3.2-FINAL ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@674287 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--legal/NOTICE8
-rw-r--r--src/documentation/content/xdocs/changes.xml8
-rw-r--r--src/documentation/content/xdocs/status.xml8
-rw-r--r--src/java/org/apache/poi/hssf/model/Workbook.java24
-rw-r--r--src/java/org/apache/poi/hssf/record/CFRuleRecord.java191
-rw-r--r--src/java/org/apache/poi/hssf/record/NameRecord.java54
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java2
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java42
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java41
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java2
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java59
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java7
-rw-r--r--src/java/org/apache/poi/ss/usermodel/ErrorConstants.java82
-rwxr-xr-xsrc/scratchpad/src/org/apache/poi/hslf/model/TextShape.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java34
-rwxr-xr-xsrc/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.pptbin0 -> 44032 bytes
-rwxr-xr-xsrc/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java43
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.docbin0 -> 104448 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java119
-rw-r--r--src/testcases/org/apache/poi/hssf/data/30978-alt.xlsbin0 -> 14848 bytes
-rw-r--r--src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java54
-rw-r--r--src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java62
22 files changed, 539 insertions, 303 deletions
diff --git a/legal/NOTICE b/legal/NOTICE
index d5d7883b35..848c767bc3 100644
--- a/legal/NOTICE
+++ b/legal/NOTICE
@@ -10,14 +10,6 @@ Common Public License Version 1.0:
http://www.opensource.org/licenses/cpl.php
See http://www.junit.org/
-A single data file of the POI component HDGF is based on VSDump,
- and is under the GNU General Public Licence version 3 (GPL v3):
- http://gplv3.fsf.org/
-Since this is a data file, and has no compiled version (the original
- file is distributed in both source and binary versions), there should
- be little difference in licencing requirements compared to the ASL.
-See http://www.gnome.ru/projects/vsdump_en.html
-
The Office Open XML experimental support had additional dependencies,
with their own licensing:
diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index 43b373d04d..561ab0d4d2 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -45,7 +45,13 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
- <release version="3.1-final" date="2008-06-??">
+ <release version="3.2-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="add"><!-- to keep forrest dtd quiet--></action>
+ </release>
+ <release version="3.1-final" date="2008-06-29">
+ <action dev="POI-DEVELOPERS" type="fix">30978 - Fixed re-serialization of tRefErr3d and tAreaErr3d</action>
+ <action dev="POI-DEVELOPERS" type="fix">45234 - Removed incorrect shared formula conversion in CFRuleRecord</action>
+ <action dev="POI-DEVELOPERS" type="fix">45001 - Improved HWPF Range.replaceText()</action>
<action dev="POI-DEVELOPERS" type="fix">44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size</action>
<action dev="POI-DEVELOPERS" type="add">Support custom image renderers in HSLF</action>
<action dev="POI-DEVELOPERS" type="fix">Correctly increment the reference count of a blip when a picture is inserted</action>
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index 3ad07a2162..ca47e0f209 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -42,7 +42,13 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
- <release version="3.1-final" date="2008-06-??">
+ <release version="3.2-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="add"><!-- to keep forrest dtd quiet--></action>
+ </release>
+ <release version="3.1-final" date="2008-06-29">
+ <action dev="POI-DEVELOPERS" type="fix">30978 - Fixed re-serialization of tRefErr3d and tAreaErr3d</action>
+ <action dev="POI-DEVELOPERS" type="fix">45234 - Removed incorrect shared formula conversion in CFRuleRecord</action>
+ <action dev="POI-DEVELOPERS" type="fix">45001 - Improved HWPF Range.replaceText()</action>
<action dev="POI-DEVELOPERS" type="fix">44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size</action>
<action dev="POI-DEVELOPERS" type="add">Support custom image renderers in HSLF</action>
<action dev="POI-DEVELOPERS" type="fix">Correctly increment the reference count of a blip when a picture is inserted</action>
diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java
index 5b38935f4c..fa22cfb688 100644
--- a/src/java/org/apache/poi/hssf/model/Workbook.java
+++ b/src/java/org/apache/poi/hssf/model/Workbook.java
@@ -604,8 +604,28 @@ public class Workbook implements Model
fixTabIdRecord();
}
- // If we decide that we need to fix up
- // NameRecords, do it here
+ // Within NameRecords, it's ok to have the formula
+ // part point at deleted sheets. It's also ok to
+ // have the ExternSheetNumber point at deleted
+ // sheets.
+ // However, the sheet index must be adjusted, or
+ // excel will break. (Sheet index is either 0 for
+ // global, or 1 based index to sheet)
+ int sheetNum1Based = sheetnum + 1;
+ for(int i=0; i<getNumNames(); i++) {
+ NameRecord nr = getNameRecord(i);
+
+ if(nr.getIndexToSheet() == sheetNum1Based) {
+ // Excel re-writes these to point to no sheet
+ nr.setEqualsToIndexToSheet((short)0);
+ } else if(nr.getIndexToSheet() > sheetNum1Based) {
+ // Bump down by one, so still points
+ // at the same sheet
+ nr.setEqualsToIndexToSheet((short)(
+ nr.getEqualsToIndexToSheet()-1
+ ));
+ }
+ }
}
/**
diff --git a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java
index 2b1705abe2..d000b5311d 100644
--- a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java
+++ b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java
@@ -14,14 +14,10 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record;
-import java.util.Stack;
-
import org.apache.poi.hssf.model.FormulaParser;
-import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
@@ -30,7 +26,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
/**
* Conditional Formatting Rule Record.
@@ -59,9 +54,6 @@ public final class CFRuleRecord extends Record
private byte field_2_comparison_operator;
- private short field_3_formula1_len;
- private short field_4_formula2_len;
-
private int field_5_options;
private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
@@ -121,8 +113,6 @@ public final class CFRuleRecord extends Record
{
field_1_condition_type=conditionType;
field_2_comparison_operator=comparisonOperation;
- field_3_formula1_len = (short)0;
- field_4_formula2_len = (short)0;
// Set modification flags to 1: by default options are not modified
field_5_options = modificationBits.setValue(field_5_options, -1);
@@ -147,8 +137,8 @@ public final class CFRuleRecord extends Record
this(conditionType, comparisonOperation);
field_1_condition_type = CONDITION_TYPE_CELL_VALUE_IS;
field_2_comparison_operator = comparisonOperation;
- setParsedExpression1(formula1);
- setParsedExpression2(formula2);
+ field_17_formula1 = formula1;
+ field_18_formula2 = formula2;
}
/**
@@ -167,63 +157,38 @@ public final class CFRuleRecord extends Record
Ptg[] formula1 = parseFormula(formulaText1, workbook);
Ptg[] formula2 = parseFormula(formulaText2, workbook);
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
-
}
- /**
- * Constructs a Formula record and sets its fields appropriately.
- * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
- * "explanation of this bug in the documentation) or an exception
- * will be throw upon validation
- *
- * @param in the RecordInputstream to read the record from
- */
-
- public CFRuleRecord(RecordInputStream in)
- {
+ public CFRuleRecord(RecordInputStream in) {
super(in);
}
+ protected void fillFields(RecordInputStream in) {
+ field_1_condition_type = in.readByte();
+ field_2_comparison_operator = in.readByte();
+ int field_3_formula1_len = in.readUShort();
+ int field_4_formula2_len = in.readUShort();
+ field_5_options = in.readInt();
+ field_6_not_used = in.readShort();
+ if (containsFontFormattingBlock()) {
+ fontFormatting = new FontFormatting(in);
+ }
- protected void fillFields(RecordInputStream in) {
- try {
- field_1_condition_type = in.readByte();
- field_2_comparison_operator = in.readByte();
- field_3_formula1_len = in.readShort();
- field_4_formula2_len = in.readShort();
- field_5_options = in.readInt();
- field_6_not_used = in.readShort();
-
- if (containsFontFormattingBlock()) {
- fontFormatting = new FontFormatting(in);
- }
-
- if (containsBorderFormattingBlock()) {
- borderFormatting = new BorderFormatting(in);
- }
-
- if (containsPatternFormattingBlock()) {
- patternFormatting = new PatternFormatting(in);
- }
-
- if (field_3_formula1_len > 0) {
- Stack ptgs = Ptg.createParsedExpressionTokens(field_3_formula1_len, in);
- // Now convert any fields as required
- ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
- field_17_formula1 = toArray(ptgs);
- }
- if (field_4_formula2_len > 0) {
- Stack ptgs = Ptg.createParsedExpressionTokens(field_4_formula2_len, in);
-
- // Now convert any fields as required
- ptgs = SharedFormulaRecord.convertSharedFormulas(ptgs, 0, 0);
- field_18_formula2 = toArray(ptgs);
- }
- } catch (java.lang.UnsupportedOperationException uoe) {
- throw new RecordFormatException(uoe);
+ if (containsBorderFormattingBlock()) {
+ borderFormatting = new BorderFormatting(in);
+ }
+
+ if (containsPatternFormattingBlock()) {
+ patternFormatting = new PatternFormatting(in);
}
+ if (field_3_formula1_len > 0) {
+ field_17_formula1 = Ptg.readTokens(field_3_formula1_len, in);
+ }
+ if (field_4_formula2_len > 0) {
+ field_18_formula2 = Ptg.readTokens(field_4_formula2_len, in);
+ }
}
public byte getConditionType()
@@ -324,24 +289,6 @@ public final class CFRuleRecord extends Record
/**
- * get the length (in number of tokens) of the expression 1
- * @return expression length
- */
- private short getExpression1Length()
- {
- return field_3_formula1_len;
- }
-
-
- /**
- * get the length (in number of tokens) of the expression 2
- * @return expression length
- */
- private short getExpression2Length()
- {
- return field_4_formula2_len;
- }
- /**
* get the option flags
*
* @return bit mask
@@ -489,16 +436,6 @@ public final class CFRuleRecord extends Record
return field_18_formula2;
}
- private void setParsedExpression1(Ptg[] ptgs) {
- short len = getTotalPtgSize(field_17_formula1 = ptgs);
- field_3_formula1_len = len;
- }
-
- private void setParsedExpression2(Ptg[] ptgs) {
- short len = getTotalPtgSize(field_18_formula2 = ptgs);
- field_4_formula2_len = len;
- }
-
/**
* called by constructor, should throw runtime exception in the event of a
* record passed with a differing ID.
@@ -520,6 +457,17 @@ public final class CFRuleRecord extends Record
}
/**
+ * @param ptgs may be <code>null</code>
+ * @return encoded size of the formula
+ */
+ private static int getFormulaSize(Ptg[] ptgs) {
+ if (ptgs == null) {
+ return 0;
+ }
+ return Ptg.getEncodedSize(ptgs);
+ }
+
+ /**
* 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.
@@ -528,18 +476,20 @@ public final class CFRuleRecord extends Record
* @param data byte array containing instance data
* @return number of bytes written
*/
-
public int serialize(int pOffset, byte [] data)
{
+ int formula1Len=getFormulaSize(field_17_formula1);
+ int formula2Len=getFormulaSize(field_18_formula2);
+
int offset = pOffset;
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.putUShort(data, 6 + offset, formula1Len);
+ LittleEndian.putUShort(data, 8 + offset, formula2Len);
LittleEndian.putInt(data, 10 + offset, field_5_options);
LittleEndian.putShort(data,14 + offset, field_6_not_used);
@@ -562,16 +512,12 @@ public final class CFRuleRecord extends Record
offset += patternFormatting.serialize(offset, data);
}
- if (getExpression1Length()>0)
- {
- Ptg.serializePtgStack(convertToTokenStack(field_17_formula1), data, offset);
- offset += getExpression1Length();
+ if (field_17_formula1 != null) {
+ offset += Ptg.serializePtgs(field_17_formula1, data, offset);
}
- if (getExpression2Length()>0)
- {
- Ptg.serializePtgStack(convertToTokenStack(field_18_formula2), data, offset);
- offset += getExpression2Length();
+ if (field_18_formula2 != null) {
+ offset += Ptg.serializePtgs(field_18_formula2, data, offset);
}
if(offset - pOffset != recordsize) {
throw new IllegalStateException("write mismatch (" + (offset - pOffset) + "!=" + recordsize + ")");
@@ -586,24 +532,12 @@ public final class CFRuleRecord extends Record
(containsFontFormattingBlock()?fontFormatting.getRawRecord().length:0)+
(containsBorderFormattingBlock()?8:0)+
(containsPatternFormattingBlock()?4:0)+
- getExpression1Length()+
- getExpression2Length()
+ getFormulaSize(field_17_formula1)+
+ getFormulaSize(field_18_formula2)
;
return retval;
}
- private short getTotalPtgSize(Ptg[] ptgs)
- {
- if( ptgs == null) {
- return 0;
- }
- short retval = 0;
- for (int i = 0; i < ptgs.length; i++)
- {
- retval += ptgs[i].getSize();
- }
- return retval;
- }
public String toString()
{
@@ -629,8 +563,6 @@ public final class CFRuleRecord extends Record
public Object clone() {
CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, 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()) {
@@ -642,10 +574,10 @@ public final class CFRuleRecord extends Record
if (containsPatternFormattingBlock()) {
rec.patternFormatting = (PatternFormatting) patternFormatting.clone();
}
- if (field_3_formula1_len > 0) {
+ if (field_17_formula1 != null) {
rec.field_17_formula1 = (Ptg[]) field_17_formula1.clone();
}
- if (field_4_formula2_len > 0) {
+ if (field_18_formula2 != null) {
rec.field_18_formula2 = (Ptg[]) field_18_formula2.clone();
}
@@ -653,30 +585,17 @@ public final class CFRuleRecord extends Record
}
/**
+ * TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
+ * this call will produce the wrong results if the formula contains any cell references
+ * One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
+ * Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects.
+ *
* @return <code>null</code> if <tt>formula</tt> was null.
*/
- private static Ptg[] parseFormula(String formula, HSSFWorkbook workbook)
- {
+ private static Ptg[] parseFormula(String formula, HSSFWorkbook workbook) {
if(formula == null) {
return null;
}
return FormulaParser.parse(formula, workbook);
}
-
- // TODO - treat formulas as token arrays instead of Stacks throughout the rest of POI
- private static Stack convertToTokenStack(Ptg[] ptgs)
- {
- Stack parsedExpression = new Stack();
- // fill the Ptg Stack with Ptgs of new formula
- for (int k = 0; k < ptgs.length; k++)
- {
- parsedExpression.push(ptgs[ k ]);
- }
- return parsedExpression;
- }
- private static Ptg[] toArray(Stack ptgs) {
- Ptg[] result = new Ptg[ptgs.size()];
- ptgs.toArray(result);
- return result;
- }
}
diff --git a/src/java/org/apache/poi/hssf/record/NameRecord.java b/src/java/org/apache/poi/hssf/record/NameRecord.java
index 786c0b3d6b..dbd796991c 100644
--- a/src/java/org/apache/poi/hssf/record/NameRecord.java
+++ b/src/java/org/apache/poi/hssf/record/NameRecord.java
@@ -14,7 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record;
@@ -22,9 +21,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Stack;
+import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.formula.Area3DPtg;
-import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
-import org.apache.poi.hssf.record.formula.DeletedRef3DPtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.record.formula.UnionPtg;
@@ -44,8 +42,7 @@ import org.apache.poi.util.StringUtil;
* @author Glen Stampoultzis (glens at apache.org)
* @version 1.0-pre
*/
-
-public class NameRecord extends Record {
+public final class NameRecord extends Record {
/**
*/
public final static short sid = 0x18; //Docs says that it is 0x218
@@ -650,50 +647,9 @@ public class NameRecord extends Record {
/** gets the reference , the area only (range)
* @return area reference
*/
- public String getAreaReference(HSSFWorkbook book){
- if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return "Error";
- Ptg ptg = (Ptg) field_13_name_definition.peek();
- String result = "";
-
- // If it's a union, descend in and process
- if (ptg.getClass() == UnionPtg.class) {
- Iterator it =field_13_name_definition.iterator();
- while( it.hasNext() ) {
- Ptg p = (Ptg)it.next();
-
- String thisRes = getAreaRefString(p, book);
- if(thisRes.length() > 0) {
- // Add a comma to the end if needed
- if(result.length() > 0 && !result.endsWith(",")) {
- result += ",";
- }
- // And add the string it corresponds to
- result += thisRes;
- }
- }
- } else {
- // Otherwise just get the string
- result = getAreaRefString(ptg, book);
- }
-
- return result;
- }
-
- /**
- * Turn the given ptg into a string, or
- * return an empty string if nothing is possible
- * for it.
- */
- private String getAreaRefString(Ptg ptg,HSSFWorkbook book) {
- if (ptg.getClass() == Area3DPtg.class){
- return ptg.toFormulaString(book);
- } else if (ptg.getClass() == Ref3DPtg.class){
- return ptg.toFormulaString(book);
- } else if (ptg.getClass() == DeletedArea3DPtg.class || ptg.getClass() == DeletedRef3DPtg.class) {
- return "#REF!";
- }
- return "";
- }
+ public String getAreaReference(HSSFWorkbook book){
+ return FormulaParser.toFormulaString(book, field_13_name_definition);
+ }
/** sets the reference , the area only (range)
* @param ref area reference
diff --git a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
index 2804e37c3d..8deaa919f1 100644
--- a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
@@ -35,7 +35,7 @@ import org.apache.poi.util.LittleEndian;
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-public class Area3DPtg extends OperandPtg implements AreaI {
+public final class Area3DPtg extends OperandPtg implements AreaI {
public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg
private short field_1_index_extern_sheet;
diff --git a/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
index 36d7e16860..a1c5b3db59 100644
--- a/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
@@ -18,6 +18,9 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.ss.usermodel.ErrorConstants;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.util.LittleEndian;
/**
* Title: Deleted Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
@@ -26,19 +29,30 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Patrick Luby
* @version 1.0-pre
*/
-
-public class DeletedArea3DPtg extends Area3DPtg
-{
+public final class DeletedArea3DPtg extends OperandPtg {
public final static byte sid = 0x3d;
-
- /** Creates new DeletedArea3DPtg */
- public DeletedArea3DPtg( String arearef, short externIdx )
- {
- super(arearef, externIdx);
- }
-
- public DeletedArea3DPtg( RecordInputStream in)
- {
- super(in);
- }
+ private final int field_1_index_extern_sheet;
+ private final int unused1;
+ private final int unused2;
+
+ public DeletedArea3DPtg( RecordInputStream in) {
+ field_1_index_extern_sheet = in.readUShort();
+ unused1 = in.readInt();
+ unused2 = in.readInt();
+ }
+ public String toFormulaString(Workbook book) {
+ return ErrorConstants.getText(ErrorConstants.ERROR_REF);
+ }
+ public byte getDefaultOperandClass() {
+ return Ptg.CLASS_REF;
+ }
+ public int getSize() {
+ return 11;
+ }
+ public void writeBytes(byte[] data, int offset) {
+ LittleEndian.putByte(data, 0 + offset, sid + getPtgClass());
+ LittleEndian.putUShort(data, 1 + offset, field_1_index_extern_sheet);
+ LittleEndian.putInt(data, 3 + offset, unused1);
+ LittleEndian.putInt(data, 7 + offset, unused2);
+ }
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
index a3c7809655..9312b2d766 100644
--- a/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
@@ -15,11 +15,13 @@
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.ss.usermodel.ErrorConstants;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.util.LittleEndian;
/**
* Title: Deleted Reference 3D Ptg <P>
@@ -28,16 +30,29 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Patrick Luby
* @version 1.0-pre
*/
-
-public class DeletedRef3DPtg extends Ref3DPtg {
- public final static byte sid = 0x3c;
-
- /** Creates new DeletedRef3DPtg */
- public DeletedRef3DPtg(RecordInputStream in) {
- super(in);
- }
-
- public DeletedRef3DPtg(String cellref, short externIdx ) {
- super(cellref, externIdx);
- }
+public final class DeletedRef3DPtg extends OperandPtg {
+ public final static byte sid = 0x3c;
+ private final int field_1_index_extern_sheet;
+ private final int unused1;
+
+ /** Creates new DeletedRef3DPtg */
+ public DeletedRef3DPtg(RecordInputStream in) {
+ field_1_index_extern_sheet = in.readUShort();
+ unused1 = in.readInt();
+ }
+
+ public String toFormulaString(Workbook book) {
+ return ErrorConstants.getText(ErrorConstants.ERROR_REF);
+ }
+ public byte getDefaultOperandClass() {
+ return Ptg.CLASS_REF;
+ }
+ public int getSize() {
+ return 7;
+ }
+ public void writeBytes(byte[] data, int offset) {
+ LittleEndian.putByte(data, 0 + offset, sid + getPtgClass());
+ LittleEndian.putUShort(data, 1 + offset, field_1_index_extern_sheet);
+ LittleEndian.putInt(data, 3 + offset, unused1);
+ }
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
index 0ec0645815..52a5518e40 100644
--- a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
@@ -34,7 +34,7 @@ import org.apache.poi.util.LittleEndian;
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-public class Ref3DPtg extends OperandPtg {
+public final class Ref3DPtg extends OperandPtg {
public final static byte sid = 0x3a;
private final static int SIZE = 7; // 6 + 1 for Ptg
private short field_1_index_extern_sheet;
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java b/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java
index 89c25d1e87..f82ee721d0 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFErrorConstants.java
@@ -16,67 +16,12 @@
==================================================================== */
package org.apache.poi.hssf.usermodel;
+import org.apache.poi.ss.usermodel.ErrorConstants;
/**
* Contains raw Excel error codes (as defined in OOO's excelfileformat.pdf (2.5.6)
*
* @author Michael Harhen
*/
-public final class HSSFErrorConstants {
- private HSSFErrorConstants() {
- // no instances of this class
- }
-
- /** <b>#NULL!</b> - Intersection of two cell ranges is empty */
- public static final int ERROR_NULL = 0x00;
- /** <b>#DIV/0!</b> - Division by zero */
- public static final int ERROR_DIV_0 = 0x07;
- /** <b>#VALUE!</b> - Wrong type of operand */
- public static final int ERROR_VALUE = 0x0F;
- /** <b>#REF!</b> - Illegal or deleted cell reference */
- public static final int ERROR_REF = 0x17;
- /** <b>#NAME?</b> - Wrong function or range name */
- public static final int ERROR_NAME = 0x1D;
- /** <b>#NUM!</b> - Value range overflow */
- public static final int ERROR_NUM = 0x24;
- /** <b>#N/A</b> - Argument or function not available */
- public static final int ERROR_NA = 0x2A;
-
-
- /**
- * @return Standard Excel error literal for the specified error code.
- * @throws IllegalArgumentException if the specified error code is not one of the 7
- * standard error codes
- */
- public static final String getText(int errorCode) {
- switch(errorCode) {
- case ERROR_NULL: return "#NULL!";
- case ERROR_DIV_0: return "#DIV/0!";
- case ERROR_VALUE: return "#VALUE!";
- case ERROR_REF: return "#REF!";
- case ERROR_NAME: return "#NAME?";
- case ERROR_NUM: return "#NUM!";
- case ERROR_NA: return "#N/A";
- }
- throw new IllegalArgumentException("Bad error code (" + errorCode + ")");
- }
-
- /**
- * @return <code>true</code> if the specified error code is a standard Excel error code.
- */
- public static final boolean isValidCode(int errorCode) {
- // This method exists because it would be bad to force clients to catch
- // IllegalArgumentException if there were potential for passing an invalid error code.
- switch(errorCode) {
- case ERROR_NULL:
- case ERROR_DIV_0:
- case ERROR_VALUE:
- case ERROR_REF:
- case ERROR_NAME:
- case ERROR_NUM:
- case ERROR_NA:
- return true;
- }
- return false;
- }
+public final class HSSFErrorConstants extends ErrorConstants {
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java
index c042456a4f..8e8cf40a1b 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java
@@ -39,7 +39,8 @@ public final class HSSFSheetConditionalFormatting {
/**
* A factory method allowing to create a conditional formatting rule
- * with a cell comparison operator
+ * with a cell comparison operator<p/>
+ * TODO - formulas containing cell references are currently not parsed properly
*
* @param comparisonOperation - a constant value from
* <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
@@ -72,8 +73,8 @@ public final class HSSFSheetConditionalFormatting {
/**
* A factory method allowing to create a conditional formatting rule with a formula.<br>
*
- * The formatting rules are applied by Excel when the value of the formula not equal to 0.
- *
+ * The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
+ * TODO - formulas containing cell references are currently not parsed properly
* @param formula - formula for the valued, compared with the cell
*/
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
diff --git a/src/java/org/apache/poi/ss/usermodel/ErrorConstants.java b/src/java/org/apache/poi/ss/usermodel/ErrorConstants.java
new file mode 100644
index 0000000000..1bfa184523
--- /dev/null
+++ b/src/java/org/apache/poi/ss/usermodel/ErrorConstants.java
@@ -0,0 +1,82 @@
+/* ====================================================================
+ 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.ss.usermodel;
+
+/**
+ * Contains raw Excel error codes (as defined in OOO's excelfileformat.pdf (2.5.6)
+ *
+ * @author Michael Harhen
+ */
+public class ErrorConstants {
+ protected ErrorConstants() {
+ // no instances of this class
+ }
+
+ /** <b>#NULL!</b> - Intersection of two cell ranges is empty */
+ public static final int ERROR_NULL = 0x00;
+ /** <b>#DIV/0!</b> - Division by zero */
+ public static final int ERROR_DIV_0 = 0x07;
+ /** <b>#VALUE!</b> - Wrong type of operand */
+ public static final int ERROR_VALUE = 0x0F;
+ /** <b>#REF!</b> - Illegal or deleted cell reference */
+ public static final int ERROR_REF = 0x17;
+ /** <b>#NAME?</b> - Wrong function or range name */
+ public static final int ERROR_NAME = 0x1D;
+ /** <b>#NUM!</b> - Value range overflow */
+ public static final int ERROR_NUM = 0x24;
+ /** <b>#N/A</b> - Argument or function not available */
+ public static final int ERROR_NA = 0x2A;
+
+
+ /**
+ * @return Standard Excel error literal for the specified error code.
+ * @throws IllegalArgumentException if the specified error code is not one of the 7
+ * standard error codes
+ */
+ public static final String getText(int errorCode) {
+ switch(errorCode) {
+ case ERROR_NULL: return "#NULL!";
+ case ERROR_DIV_0: return "#DIV/0!";
+ case ERROR_VALUE: return "#VALUE!";
+ case ERROR_REF: return "#REF!";
+ case ERROR_NAME: return "#NAME?";
+ case ERROR_NUM: return "#NUM!";
+ case ERROR_NA: return "#N/A";
+ }
+ throw new IllegalArgumentException("Bad error code (" + errorCode + ")");
+ }
+
+ /**
+ * @return <code>true</code> if the specified error code is a standard Excel error code.
+ */
+ public static final boolean isValidCode(int errorCode) {
+ // This method exists because it would be bad to force clients to catch
+ // IllegalArgumentException if there were potential for passing an invalid error code.
+ switch(errorCode) {
+ case ERROR_NULL:
+ case ERROR_DIV_0:
+ case ERROR_VALUE:
+ case ERROR_REF:
+ case ERROR_NAME:
+ case ERROR_NUM:
+ case ERROR_NA:
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
index d1a84a5e44..44cb2b2412 100755
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
@@ -355,7 +355,7 @@ public abstract class TextShape extends SimpleShape {
*/
public float getMarginLeft(){
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT);
int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
return (float)val/EMU_PER_POINT;
}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
index 6324cd86a2..80e9b7526c 100644
--- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
+++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
@@ -635,27 +635,24 @@ public class Range
/**
* Replace (one instance of) a piece of text with another...
*
- * @param pPlaceHolder The text to be replaced (e.g., "${company}")
- * @param pValue The replacement text (e.g., "Cognocys, Inc.")
- * @param pDocument The <code>HWPFDocument</code> in which the placeholder was found
- * @param pStartOffset The offset or index where the <code>CharacterRun</code> begins
- * @param pPlaceHolderIndex The offset or index of the placeholder,
- * relative to the <code>CharacterRun</code> where
- * <code>pPlaceHolder</code> was found
- */
- protected void replaceText(String pPlaceHolder, String pValue,
- int pStartOffset, int pPlaceHolderIndex, HWPFDocument pDocument) {
- int absPlaceHolderIndex = pStartOffset + pPlaceHolderIndex;
+ * @param pPlaceHolder The text to be replaced (e.g., "${organization}")
+ * @param pValue The replacement text (e.g., "Apache Software Foundation")
+ * @param pOffset The offset or index where the text to be replaced begins
+ * (relative to/within this <code>Range</code>)
+ */
+ public void replaceText(String pPlaceHolder, String pValue, int pOffset)
+ {
+ int absPlaceHolderIndex = getStartOffset() + pOffset;
Range subRange = new Range(
absPlaceHolderIndex,
- (absPlaceHolderIndex + pPlaceHolder.length()), pDocument
+ (absPlaceHolderIndex + pPlaceHolder.length()), getDocument()
);
if (subRange.usesUnicode()) {
- absPlaceHolderIndex = pStartOffset + (pPlaceHolderIndex * 2);
+ absPlaceHolderIndex = getStartOffset() + (pOffset * 2);
subRange = new Range(
absPlaceHolderIndex,
(absPlaceHolderIndex + (pPlaceHolder.length() * 2)),
- pDocument
+ getDocument()
);
}
@@ -665,13 +662,13 @@ public class Range
subRange = new Range(
(absPlaceHolderIndex + pValue.length()),
(absPlaceHolderIndex + pPlaceHolder.length() + pValue.length()),
- pDocument
+ getDocument()
);
if (subRange.usesUnicode())
subRange = new Range(
(absPlaceHolderIndex + (pValue.length() * 2)),
(absPlaceHolderIndex + (pPlaceHolder.length() * 2) +
- (pValue.length() * 2)), pDocument
+ (pValue.length() * 2)), getDocument()
);
subRange.delete();
@@ -942,4 +939,9 @@ public class Range
return _end;
}
+
+ protected HWPFDocument getDocument() {
+
+ return _doc;
+ }
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.ppt
new file mode 100755
index 0000000000..cf539aea74
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.ppt
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
index 25a8db9187..7fc8787567 100755
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
@@ -23,6 +23,7 @@ import junit.framework.TestCase;
import java.io.*;
import java.util.ArrayList;
+import java.util.HashMap;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hslf.record.TextHeaderAtom;
@@ -157,4 +158,46 @@ public class TestTextShape extends TestCase {
assertEquals("Testing TextShape", shape1.getTextRun().getText());
}
+ public void testMargins() throws IOException {
+ FileInputStream is = new FileInputStream(new File(cwd, "text-margins.ppt"));
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ Slide slide = ppt.getSlides()[0];
+
+ HashMap map = new HashMap();
+ Shape[] shape = slide.getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ if(shape[i] instanceof TextShape){
+ TextShape tx = (TextShape)shape[i];
+ map.put(tx.getText(), tx);
+ }
+ }
+
+ TextShape tx;
+
+ tx = (TextShape)map.get("TEST1");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST2");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST3");
+ assertEquals(0.39, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST4");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ }
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc
new file mode 100644
index 0000000000..949980d4e1
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java
new file mode 100644
index 0000000000..4b2b9ce370
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java
@@ -0,0 +1,119 @@
+
+/* ====================================================================
+ 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.hwpf.usermodel;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.util.List;
+
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.model.PicturesTable;
+import org.apache.poi.hwpf.usermodel.Picture;
+
+import junit.framework.TestCase;
+
+/**
+ * Test to see if Range.replaceText() works even if the Range contains a
+ * CharacterRun that uses Unicode characters.
+ */
+public class TestRangeReplacement extends TestCase {
+
+ // u201c and u201d are "smart-quotes"
+ private String originalText =
+ "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r";
+ private String searchText = "${organization}";
+ private String replacementText = "Apache Software Foundation";
+ private String expectedText =
+ "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the Apache Software Foundation and all the POI contributors for their assistance in this matter.\r";
+
+ private String illustrativeDocFile;
+
+ protected void setUp() throws Exception {
+
+ String dirname = System.getProperty("HWPF.testdata.path");
+
+ illustrativeDocFile = dirname + "/testRangeReplacement.doc";
+ }
+
+ /**
+ * Test just opening the files
+ */
+ public void testOpen() throws Exception {
+
+ HWPFDocument docA = new HWPFDocument(new FileInputStream(illustrativeDocFile));
+ }
+
+ /**
+ * Test (more "confirm" than test) that we have the general structure that we expect to have.
+ */
+ public void testDocStructure() throws Exception {
+
+ HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile));
+
+ Range range = daDoc.getRange();
+
+ assertEquals(1, range.numSections());
+ Section section = range.getSection(0);
+
+ assertEquals(5, section.numParagraphs());
+ Paragraph para = section.getParagraph(2);
+
+ assertEquals(5, para.numCharacterRuns());
+ String text = para.getCharacterRun(0).text() + para.getCharacterRun(1).text() +
+ para.getCharacterRun(2).text() + para.getCharacterRun(3).text() + para.getCharacterRun(4).text();
+
+ assertEquals(originalText, text);
+ }
+
+ /**
+ * Test that we can replace text in our Range with Unicode text.
+ */
+ public void testRangeReplacement() throws Exception {
+
+ HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile));
+
+ Range range = daDoc.getRange();
+ assertEquals(1, range.numSections());
+
+ Section section = range.getSection(0);
+ assertEquals(5, section.numParagraphs());
+
+ Paragraph para = section.getParagraph(2);
+
+ String text = para.text();
+ assertEquals(originalText, text);
+
+ int offset = text.indexOf(searchText);
+ assertEquals(181, offset);
+
+ para.replaceText(searchText, replacementText, offset);
+
+ // we need to let the model re-calculate the Range before we evaluate it
+ range = daDoc.getRange();
+
+ assertEquals(1, range.numSections());
+ section = range.getSection(0);
+
+ assertEquals(5, section.numParagraphs());
+ para = section.getParagraph(2);
+
+ text = para.text();
+ assertEquals(expectedText, text);
+ }
+}
diff --git a/src/testcases/org/apache/poi/hssf/data/30978-alt.xls b/src/testcases/org/apache/poi/hssf/data/30978-alt.xls
new file mode 100644
index 0000000000..c591582885
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/data/30978-alt.xls
Binary files differ
diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
index afc44e7043..1eb052bec7 100644
--- a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
+++ b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
@@ -17,12 +17,16 @@
package org.apache.poi.hssf.record;
+import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
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.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.RefNPtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.LittleEndian;
@@ -296,7 +300,57 @@ public final class TestCFRuleRecord extends TestCase
// check all remaining flag bits (some are not well understood yet)
assertEquals(0x203FFFFF, flags);
}
+
+ private static final byte[] DATA_REFN = {
+ // formula extracted from bugzilla 45234 att 22141
+ 1, 3,
+ 9, // formula 1 length
+ 0, 0, 0, -1, -1, 63, 32, 2, -128, 0, 0, 0, 5,
+ // formula 1: "=B3=1" (formula is relative to B4)
+ 76, -1, -1, 0, -64, // tRefN(B1)
+ 30, 1, 0,
+ 11,
+ };
+
+ /**
+ * tRefN and tAreaN tokens must be preserved when re-serializing conditional format formulas
+ */
+ public void testReserializeRefNTokens() {
+
+ RecordInputStream is = new TestcaseRecordInputStream(CFRuleRecord.sid, DATA_REFN);
+ CFRuleRecord rr = new CFRuleRecord(is);
+ Ptg[] ptgs = rr.getParsedExpression1();
+ assertEquals(3, ptgs.length);
+ if (ptgs[0] instanceof RefPtg) {
+ throw new AssertionFailedError("Identified bug 45234");
+ }
+ assertEquals(RefNPtg.class, ptgs[0].getClass());
+ RefNPtg refNPtg = (RefNPtg) ptgs[0];
+ assertTrue(refNPtg.isColRelative());
+ assertTrue(refNPtg.isRowRelative());
+
+ byte[] data = rr.serialize();
+
+ if (!compareArrays(DATA_REFN, 0, data, 4, DATA_REFN.length)) {
+ fail("Did not re-serialize correctly");
+ }
+ }
+ private static boolean compareArrays(byte[] arrayA, int offsetA, byte[] arrayB, int offsetB, int length) {
+
+ if (offsetA + length > arrayA.length) {
+ return false;
+ }
+ if (offsetB + length > arrayB.length) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (arrayA[i+offsetA] != arrayB[i+offsetB]) {
+ return false;
+ }
+ }
+ return true;
+ }
public static void main(String[] ignored_args)
{
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
index 419bc33bb4..79ef47be38 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
@@ -30,7 +30,10 @@ import junit.framework.TestCase;
import org.apache.poi.ss.util.Region;
import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
+import org.apache.poi.hssf.record.NameRecord;
+import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
import org.apache.poi.util.TempFile;
/**
@@ -990,4 +993,63 @@ public final class TestBugs extends TestCase {
fail();
} catch(FileNotFoundException e) {}
}
+
+ /**
+ * Test that we can delete sheets without
+ * breaking the build in named ranges
+ * used for printing stuff.
+ * Currently broken, as we change the Ptg
+ */
+ public void test30978() throws Exception {
+ HSSFWorkbook wb = openSample("30978-alt.xls");
+ assertEquals(1, wb.getNumberOfNames());
+ assertEquals(3, wb.getNumberOfSheets());
+
+ // Check all names fit within range, and use
+ // DeletedArea3DPtg
+ Workbook w = wb.getWorkbook();
+ for(int i=0; i<w.getNumNames(); i++) {
+ NameRecord r = w.getNameRecord(i);
+ assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+
+ List nd = r.getNameDefinition();
+ assertEquals(1, nd.size());
+ assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+ }
+
+
+ // Delete the 2nd sheet
+ wb.removeSheetAt(1);
+
+
+ // Re-check
+ assertEquals(1, wb.getNumberOfNames());
+ assertEquals(2, wb.getNumberOfSheets());
+
+ for(int i=0; i<w.getNumNames(); i++) {
+ NameRecord r = w.getNameRecord(i);
+ assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+
+ List nd = r.getNameDefinition();
+ assertEquals(1, nd.size());
+ assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+ }
+
+
+ // Save and re-load
+ wb = writeOutAndReadBack(wb);
+ w = wb.getWorkbook();
+
+ assertEquals(1, wb.getNumberOfNames());
+ assertEquals(2, wb.getNumberOfSheets());
+
+ for(int i=0; i<w.getNumNames(); i++) {
+ NameRecord r = w.getNameRecord(i);
+ assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+
+ List nd = r.getNameDefinition();
+ assertEquals(1, nd.size());
+ assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+ }
+ }
}