Browse Source

Start to add XSSF specific handling for NameX (named ranges or functions from another file) #56737

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611958 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_11_BETA1
Nick Burch 10 years ago
parent
commit
13628c0b8c

+ 1
- 1
src/java/org/apache/poi/ss/formula/FormulaParser.java View File

@@ -399,7 +399,7 @@ public final class FormulaParser {
throw new FormulaParseException("Cell reference or Named Range "
+ "expected after sheet name at index " + _pointer + ".");
}
NameXPtg nameXPtg = _book.getNameXPtg(name, sheetIden);
Ptg nameXPtg = _book.getNameXPtg(name, sheetIden);
if (nameXPtg == null) {
throw new FormulaParseException("Specified name '" + name +
"' for sheet " + sheetIden.asFormulaString() + " not found");

+ 1
- 2
src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java View File

@@ -18,7 +18,6 @@
package org.apache.poi.ss.formula;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.ptg.NameXPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
@@ -36,7 +35,7 @@ public interface FormulaParsingWorkbook {
*/
EvaluationName getName(String name, int sheetIndex);

NameXPtg getNameXPtg(String name, SheetIdentifier sheet);
Ptg getNameXPtg(String name, SheetIdentifier sheet);
/**
* Produce the appropriate Ptg for a 3d cell reference

+ 53
- 35
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java View File

@@ -30,6 +30,7 @@ import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.formula.ptg.Area3DPxg;
import org.apache.poi.ss.formula.ptg.NameXPtg;
import org.apache.poi.ss.formula.ptg.NameXPxg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPtg;
import org.apache.poi.ss.formula.ptg.Ref3DPxg;
@@ -297,41 +298,58 @@ public final class OperationEvaluationContext {
aptg.getLastRow(), aptg.getLastColumn(), sre);
}
public ValueEval getNameXEval(NameXPtg nameXPtg) {
// TODO Need HSSF and XSSF versions of these
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPtg.getSheetRefIndex());
if(externSheet == null)
return new NameXEval(nameXPtg);
String workbookName = externSheet.getWorkbookName();
ExternalName externName = _workbook.getExternalName(
nameXPtg.getSheetRefIndex(),
nameXPtg.getNameIndex()
);
try{
WorkbookEvaluator refWorkbookEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(),externName.getIx()-1);
if(evaluationName != null && evaluationName.hasFormula()){
if (evaluationName.getNameDefinition().length > 1) {
throw new RuntimeException("Complex name formulas not supported yet");
}
Ptg ptg = evaluationName.getNameDefinition()[0];
if(ptg instanceof Ref3DPtg){
Ref3DPtg ref3D = (Ref3DPtg)ptg;
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(ref3D.getExternSheetIndex());
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
return new LazyRefEval(ref3D.getRow(), ref3D.getColumn(), sre);
}else if(ptg instanceof Area3DPtg){
Area3DPtg area3D = (Area3DPtg)ptg;
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(area3D.getExternSheetIndex());
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
return new LazyAreaEval(area3D.getFirstRow(), area3D.getFirstColumn(), area3D.getLastRow(), area3D.getLastColumn(), sre);
public ValueEval getNameXEval(NameXPtg nameXPtg) {
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPtg.getSheetRefIndex());
if(externSheet == null || externSheet.getWorkbookName() == null) {
// External reference to our own workbook's name
return new NameXEval(nameXPtg);
}
String workbookName = externSheet.getWorkbookName();
ExternalName externName = _workbook.getExternalName(
nameXPtg.getSheetRefIndex(),
nameXPtg.getNameIndex()
);
return getNameXEval(externName, workbookName);
}
public ValueEval getNameXEval(NameXPxg nameXPxg) {
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPxg.getSheetName(), nameXPxg.getExternalWorkbookNumber());
if(externSheet == null || externSheet.getWorkbookName() == null) {
// External reference to our own workbook's name
// TODO How to do this?
return new NameXEval(null);
}
// TODO
return null;
// return getNameXEval(nameXPxg.getNameName(), externSheet.getWorkbookName());
}
private ValueEval getNameXEval(ExternalName externName, String workbookName) {
try {
WorkbookEvaluator refWorkbookEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(),externName.getIx()-1);
if (evaluationName != null && evaluationName.hasFormula()){
if (evaluationName.getNameDefinition().length > 1) {
throw new RuntimeException("Complex name formulas not supported yet");
}
Ptg ptg = evaluationName.getNameDefinition()[0];
if (ptg instanceof Ref3DPtg){
Ref3DPtg ref3D = (Ref3DPtg)ptg;
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(ref3D.getExternSheetIndex());
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
return new LazyRefEval(ref3D.getRow(), ref3D.getColumn(), sre);
} else if(ptg instanceof Area3DPtg){
Area3DPtg area3D = (Area3DPtg)ptg;
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(area3D.getExternSheetIndex());
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
return new LazyAreaEval(area3D.getFirstRow(), area3D.getFirstColumn(), area3D.getLastRow(), area3D.getLastColumn(), sre);
}
}
}
return ErrorEval.REF_INVALID;
}catch(WorkbookNotFoundException wnfe){
return ErrorEval.REF_INVALID;
}
return ErrorEval.REF_INVALID;
} catch(WorkbookNotFoundException wnfe){
return ErrorEval.REF_INVALID;
}
}
}

+ 1
- 1
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java View File

@@ -637,7 +637,7 @@ public final class WorkbookEvaluator {
EvaluationName nameRecord = _workbook.getName(namePtg);
return getEvalForNameRecord(nameRecord, ec);
}
if (ptg instanceof NameXPtg) {
if (ptg instanceof NameXPtg) { // TODO Generalise for NameXPxg
// Externally defined named ranges or macro functions
NameXPtg nameXPtg = (NameXPtg)ptg;
ValueEval eval = ec.getNameXEval(nameXPtg);

+ 99
- 0
src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java View File

@@ -0,0 +1,99 @@
/* ====================================================================
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.formula.ptg;

import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.util.LittleEndianOutput;

/**
* <p>Title: XSSF Area 3D Reference (Sheet + Area)<P>
* <p>Description: Defined an area in an external or different sheet. <P>
* <p>REFERENCE: </p>
*
* <p>This is XSSF only, as it stores the sheet / book references
* in String form. The HSSF equivalent using indexes is {@link Area3DPtg}</p>
*/
public final class Area3DPxg extends AreaPtgBase {
private int externalWorkbookNumber = -1;
private String sheetName;

public Area3DPxg(int externalWorkbookNumber, String sheetName, String arearef) {
this(externalWorkbookNumber, sheetName, new AreaReference(arearef));
}
public Area3DPxg(int externalWorkbookNumber, String sheetName, AreaReference arearef) {
super(arearef);
this.externalWorkbookNumber = externalWorkbookNumber;
this.sheetName = sheetName;
}

public Area3DPxg(String sheetName, String arearef) {
this(sheetName, new AreaReference(arearef));
}
public Area3DPxg(String sheetName, AreaReference arearef) {
this(-1, sheetName, arearef);
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append(" [");
if (externalWorkbookNumber >= 0) {
sb.append(" [");
sb.append("workbook=").append(getExternalWorkbookNumber());
sb.append("] ");
}
sb.append("sheet=").append(getSheetName());
sb.append(" ! ");
sb.append(formatReferenceAsString());
sb.append("]");
return sb.toString();
}
public int getExternalWorkbookNumber() {
return externalWorkbookNumber;
}
public String getSheetName() {
return sheetName;
}

public String format2DRefAsString() {
return formatReferenceAsString();
}
public String toFormulaString() {
StringBuffer sb = new StringBuffer();
if (externalWorkbookNumber >= 0) {
sb.append('[');
sb.append(externalWorkbookNumber);
sb.append(']');
}
sb.append(sheetName);
sb.append('!');
sb.append(formatReferenceAsString());
return sb.toString();
}

public int getSize() {
return 1;
}
public void write(LittleEndianOutput out) {
throw new IllegalStateException("XSSF-only Ptg, should not be serialised");
}

}

+ 6
- 2
src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java View File

@@ -23,8 +23,12 @@ import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;

/**
*
* @author aviks
* A Name, be that a Named Range or a Function / User Defined
* Function, addressed in the HSSF External Sheet style.
*
* <p>This is HSSF only, as it matches the HSSF file format way of
* referring to the sheet by an extern index. The XSSF equivalent
* is {@link NameXPxg}
*/
public final class NameXPtg extends OperandPtg implements WorkbookDependentFormula {
public final static short sid = 0x39;

+ 93
- 0
src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java View File

@@ -0,0 +1,93 @@
/* ====================================================================
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.formula.ptg;

import org.apache.poi.util.LittleEndianOutput;

/**
* A Name, be that a Named Range or a Function / User Defined
* Function, addressed in the HSSF External Sheet style.
*
* <p>This is XSSF only, as it stores the sheet / book references
* in String form. The HSSF equivalent using indexes is {@link NameXPtg}</p>
*/
public final class NameXPxg extends OperandPtg {
private int externalWorkbookNumber = -1;
private String sheetName;
private String nameName;

public NameXPxg(int externalWorkbookNumber, String sheetName, String nameName) {
this.externalWorkbookNumber = externalWorkbookNumber;
this.sheetName = sheetName;
this.nameName = nameName;
}
public NameXPxg(String sheetName, String nameName) {
this(-1, sheetName, nameName);
}

public String toString(){
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append(" [");
if (externalWorkbookNumber >= 0) {
sb.append(" [");
sb.append("workbook=").append(getExternalWorkbookNumber());
sb.append("] ");
}
sb.append("sheet=").append(getSheetName());
sb.append(" ! ");
sb.append("name=");
sb.append(nameName);
sb.append("]");
return sb.toString();
}

public int getExternalWorkbookNumber() {
return externalWorkbookNumber;
}
public String getSheetName() {
return sheetName;
}
public String getNameName() {
return nameName;
}

public String toFormulaString() {
StringBuffer sb = new StringBuffer();
if (externalWorkbookNumber >= 0) {
sb.append('[');
sb.append(externalWorkbookNumber);
sb.append(']');
}
sb.append(sheetName);
sb.append('!');
sb.append(nameName);
return sb.toString();
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}

public int getSize() {
return 1;
}
public void write(LittleEndianOutput out) {
throw new IllegalStateException("XSSF-only Ptg, should not be serialised");
}
}

+ 9
- 10
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java View File

@@ -31,6 +31,7 @@ import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.ptg.Area3DPxg;
import org.apache.poi.ss.formula.ptg.NamePtg;
import org.apache.poi.ss.formula.ptg.NameXPtg;
import org.apache.poi.ss.formula.ptg.NameXPxg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPxg;
import org.apache.poi.ss.formula.udf.IndexedUDFFinder;
@@ -42,11 +43,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;

/**
* Internal POI use only
*
* @author Josh Micich
*/
public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {

private final XSSFWorkbook _uBook;

public static XSSFEvaluationWorkbook create(XSSFWorkbook book) {
@@ -122,21 +120,22 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
throw new RuntimeException("Not implemented yet");
}

public NameXPtg getNameXPtg(String name, SheetIdentifier sheet) {
public NameXPxg getNameXPtg(String name, SheetIdentifier sheet) {
// First, try to find it as a User Defined Function
IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder();
FreeRefFunction func = udfFinder.findFunction(name);
if (func != null) {
return new NameXPtg(0, udfFinder.getFunctionIndex(name));
return new NameXPxg(null, name);
}
// Otherwise, try it as a named range
XSSFName xname = _uBook.getName(name);
if (xname != null) {
int nameAt = _uBook.getNameIndex(name);
return new NameXPtg(xname.getSheetIndex(), nameAt);
String sheetName = sheet._sheetIdentifier.getName();
if (sheet._bookName != null) {
int bookIndex = resolveBookIndex(sheet._bookName);
return new NameXPxg(bookIndex, sheetName, name);
} else {
return null;
return new NameXPxg(sheetName, name);
}
}
public Ptg get3DReferencePtg(CellReference cell, SheetIdentifier sheet) {

Loading…
Cancel
Save