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
This commit is contained in:
parent
fb38bcb821
commit
695b85049d
@ -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:
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
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 (containsFontFormattingBlock()) {
|
||||
fontFormatting = new FontFormatting(in);
|
||||
}
|
||||
|
||||
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()
|
||||
@ -323,24 +288,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
|
||||
*
|
||||
@ -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.
|
||||
@ -519,6 +456,17 @@ public final class CFRuleRecord extends Record
|
||||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
private final int field_1_index_extern_sheet;
|
||||
private final int unused1;
|
||||
private final int unused2;
|
||||
|
||||
/** Creates new DeletedArea3DPtg */
|
||||
public DeletedArea3DPtg( String arearef, short externIdx )
|
||||
{
|
||||
super(arearef, externIdx);
|
||||
}
|
||||
|
||||
public DeletedArea3DPtg( RecordInputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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 final class DeletedRef3DPtg extends OperandPtg {
|
||||
public final static byte sid = 0x3c;
|
||||
private final int field_1_index_extern_sheet;
|
||||
private final int unused1;
|
||||
|
||||
public class DeletedRef3DPtg extends Ref3DPtg {
|
||||
public final static byte sid = 0x3c;
|
||||
/** Creates new DeletedRef3DPtg */
|
||||
public DeletedRef3DPtg(RecordInputStream in) {
|
||||
field_1_index_extern_sheet = in.readUShort();
|
||||
unused1 = in.readInt();
|
||||
}
|
||||
|
||||
/** Creates new DeletedRef3DPtg */
|
||||
public DeletedRef3DPtg(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public DeletedRef3DPtg(String cellref, short externIdx ) {
|
||||
super(cellref, externIdx);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
}
|
||||
|
@ -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) {
|
||||
|
82
src/java/org/apache/poi/ss/usermodel/ErrorConstants.java
Normal file
82
src/java/org/apache/poi/ss/usermodel/ErrorConstants.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
* @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>)
|
||||
*/
|
||||
protected void replaceText(String pPlaceHolder, String pValue,
|
||||
int pStartOffset, int pPlaceHolderIndex, HWPFDocument pDocument) {
|
||||
int absPlaceHolderIndex = pStartOffset + pPlaceHolderIndex;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.ppt
Executable file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/text-margins.ppt
Executable file
Binary file not shown.
@ -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);
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -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);
|
||||
}
|
||||
}
|
BIN
src/testcases/org/apache/poi/hssf/data/30978-alt.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/30978-alt.xls
Normal file
Binary file not shown.
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user