merge down trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hssf_cryptoapi@1755463 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2016-08-08 01:14:36 +00:00
parent 0bfefdfc04
commit 680683cf77
51 changed files with 1967 additions and 1249 deletions

View File

@ -17,7 +17,6 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
This build was tested with ant 1.9.4 although it will probably work with
other versions, however at least 1.8.0 is required.
@ -133,6 +132,7 @@ under the License.
<property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
<property name="ooxml.lite.output.dir" location="build/ooxml-lite-classes"/>
<property name="ooxml.lite.testokfile" location="build/ooxml-lite-testokfile.txt"/>
<!-- XSSF/SXSSF subset of OOXML: -->
<property name="ooxml.ss.testokfile" location="build/ooxml-ss-testokfile.txt"/>
@ -169,6 +169,9 @@ under the License.
<property name="main.ant.url" value="${repository.m2}/maven2/org/apache/ant/ant/1.9.4/ant-1.9.4.jar"/>
<property name="main.antlauncher.jar" location="${main.lib}/ant-launcher-1.9.4.jar"/>
<property name="main.antlauncher.url" value="${repository.m2}/maven2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar"/>
<property name="main.commons-collections4.jar" location="${main.lib}/commons-collections4-4.1.jar"/>
<property name="main.commons-collections4.url"
value="${repository.m2}/maven2/org/apache/commons/commons-collections4/4.1/commons-collections4-4.1.jar"/>
<!-- xml signature libs -->
<property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.0.6.jar"/>
@ -192,8 +195,8 @@ under the License.
value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.6.0/xmlbeans-2.6.0.jar"/>
<!-- coverage libs -->
<property name="jacoco.zip" location="${main.lib}/jacoco-0.7.6.201602180812.zip"/>
<property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.7.6.201602180812/jacoco-0.7.6.201602180812.zip"/>
<property name="jacoco.zip" location="${main.lib}/jacoco-0.7.7.201606060606.zip"/>
<property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.7.7.201606060606/jacoco-0.7.7.201606060606.zip"/>
<property name="asm.jar" location="${main.lib}/asm-all-5.0.3.jar"/>
<property name="asm.url" value="${repository.m2}/maven2/org/ow2/asm/asm-all/5.0.3/asm-all-5.0.3.jar"/>
@ -285,6 +288,7 @@ under the License.
</condition>
<property name="findbugs.version" value="2.0.3" if:set="findbugs.jdk6"/>
<property name="findbugs.version" value="3.0.1" unless:set="findbugs.jdk6"/>
<echo message="Findbugs-Version: ${findbugs.version} for Java ${ant.java.version}"/>
<property name="findbugs.url" value="http://prdownloads.sourceforge.net/findbugs/findbugs-noUpdateChecks-${findbugs.version}.zip?download"/>
<property name="findbugs.jar" location="${main.lib}/findbugs-noUpdateChecks-${findbugs.version}.zip"/>
@ -303,6 +307,8 @@ under the License.
<!-- this can be overwriten to empty when running with Java 9 -->
<property name="maxpermsize" value="-XX:MaxPermSize=256m"/>
<property name="java9addmods" value="-Dthis.is.a.dummy=true"/>
<property name="java9addmodsvalue" value="-Dthis.is.a.dummy=true"/>
<path id="main.classpath">
<pathelement location="${main.commons-logging.jar}"/>
@ -310,6 +316,7 @@ under the License.
<pathelement location="${main.log4j.jar}"/>
<pathelement location="${main.junit.jar}"/>
<pathelement location="${main.hamcrest.jar}"/>
<pathelement location="${main.commons-collections4.jar}"/>
</path>
<path id="scratchpad.classpath">
@ -498,9 +505,7 @@ under the License.
<attribute name="src"/>
<attribute name="dest"/>
<sequential>
<local name="exists"/>
<available file="@{dest}" property="exists"/>
<!--fail unless:true="${exists}"
<!--fail
message="Java version might be uncapable to download https URLs - see https://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception">
<condition>
<and>
@ -509,7 +514,7 @@ under the License.
</and>
</condition>
</fail-->
<get src="@{src}" dest="@{dest}" unless:true="${exists}"/>
<get src="@{src}" dest="@{dest}" skipexisting="true"/>
</sequential>
</macrodef>
@ -531,12 +536,14 @@ under the License.
<include name="jacoco-0.7.2*"/>
<include name="jacoco-0.7.3*"/>
<include name="jacoco-0.7.4*"/>
<include name="jacoco-0.7.6*"/>
<include name="log4j-1.2.13*"/>
<include name="org.jacoco.*-0.6.*"/>
<include name="org.jacoco.*-0.7.1*"/>
<include name="org.jacoco.*-0.7.2*"/>
<include name="org.jacoco.*-0.7.3*"/>
<include name="org.jacoco.*-0.7.4*"/>
<include name="org.jacoco.*-0.7.6*"/>
<include name="dom4j*"/>
<include name="apache-rat-0.10*"/>
<include name="xercesImpl-*.jar"/>
@ -587,6 +594,7 @@ under the License.
<available file="${dsig.bouncycastle-pkix.jar}"/>
<available file="${dsig.xmlsec.jar}"/>
<available file="${dsig.sl4j-api.jar}"/>
<available file="${main.commons-collections4.jar}"/>
</and>
<isset property="disconnected"/>
</or>
@ -605,6 +613,7 @@ under the License.
<downloadfile src="${main.antlauncher.url}" dest="${main.antlauncher.jar}"/>
<downloadfile src="${asm.url}" dest="${asm.jar}"/>
<downloadfile src="${jacoco.url}" dest="${jacoco.zip}"/>
<downloadfile src="${main.commons-collections4.url}" dest="${main.commons-collections4.jar}"/>
<unzip src="${jacoco.zip}" dest=".">
<patternset>
<include name="lib/*.jar"/>
@ -1161,6 +1170,8 @@ under the License.
<group name="Main">
<classfiles>
<fileset dir="${main.output.dir}">
<!-- exclude some generated classes -->
<exclude name="org/apache/poi/sl/draw/binding/*.class"/>
<!-- exclude large test-class -->
<exclude name="org/apache/poi/hssf/usermodel/DummyGraphics2d.class"/>
</fileset>
@ -1242,6 +1253,8 @@ under the License.
<jvmarg value="-ea"/>
<jvmarg value="-Xmx256m"/>
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${main.reports.test}">
@ -1258,6 +1271,16 @@ under the License.
<antcall target="-test-main-write-testfile"/>
</target>
<target name="test-report" depends="init">
<mkdir dir="build/report"/>
<junitreport todir="build/report">
<fileset dir="build">
<include name="*results/**/TEST-*.xml"/>
</fileset>
<report format="frames" todir="build/report"/>
</junitreport>
</target>
<target name="-test-property-check" unless="testcase">
<echo message="Please use -Dtestcase=org.your.testcase to run a single test"/>
<fail/>
@ -1288,6 +1311,8 @@ under the License.
<jvmarg value="-ea"/>
<jvmarg value="-Xmx256m"/>
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${main.reports.test}">
@ -1335,6 +1360,8 @@ under the License.
and on Windows with jdk-1.5.22
-->
<jvmarg value="-Xmx256M"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${scratchpad.reports.test}">
@ -1373,6 +1400,8 @@ under the License.
<jvmarg value="${maxpermsize}"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<formatter type="plain"/>
<formatter type="xml"/>
@ -1396,6 +1425,8 @@ under the License.
<syspropertyset refid="junit.properties"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${ooxml.reports.test}">
@ -1439,6 +1470,8 @@ under the License.
<jvmarg value="${maxpermsize}"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<formatter type="plain"/>
<formatter type="xml"/>
@ -1485,6 +1518,8 @@ under the License.
<syspropertyset refid="junit.properties"/>
<jvmarg value="-ea"/>
<jvmarg value="-Xmx1512M"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${integration.reports.test}">
@ -1503,7 +1538,20 @@ under the License.
</target>
<!-- Section: test-ooxml-lite -->
<target name="compile-ooxml-lite" depends="compile-ooxml">
<target name="-compile-ooxml-lite-check">
<uptodate property="ooxml.lite.test.notRequired" targetfile="${ooxml.lite.testokfile}">
<srcfiles dir="${ooxml.src}"/>
<srcfiles dir="${ooxml.src.test}"/>
<srcfiles file="${ooxml.xsds.jar}"/>
<srcfiles file="${ooxml.security.jar}"/>
</uptodate>
</target>
<target name="compile-ooxml-lite" depends="-compile-ooxml-lite-check,compile-ooxml"
unless="ooxml.lite.test.notRequired">
<delete file="${ooxml.lite.testokfile}"/>
<echo message="Running ooxml-lite generator"/>
<property name="ooxml.lite-merged.dir" location="build/ooxml-lite-merged"/>
<mkdir dir="${ooxml.lite-merged.dir}"/>
@ -1522,6 +1570,8 @@ under the License.
<syspropertyset refid="junit.properties"/>
<jvmarg value="${maxpermsize}"/>
<jvmarg value="-Xmx512m"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<arg value="-ooxml"/>
<arg value="${ooxml.lite-merged.dir}/ooxml-lite-merged.jar"/>
<arg value="-test"/>
@ -1529,6 +1579,8 @@ under the License.
<arg value="-dest"/>
<arg value="${ooxml.lite.output.dir}"/>
</java>
<echo file="${ooxml.lite.testokfile}" append="false" message="testok"/>
</target>
<target name="test-ooxml-lite" depends="jacocotask,compile-ooxml-xsds,compile-ooxml-lite">
@ -1557,6 +1609,8 @@ under the License.
<classpath refid="test.excelant.classpath"/>
<syspropertyset refid="junit.properties"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${excelant.reports.test}">
@ -1868,6 +1922,7 @@ under the License.
<fileset dir="${main.lib}">
<include name="commons-codec-*.jar"/>
<include name="commons-logging-*.jar"/>
<include name="commons-collections4-*.jar"/>
<include name="junit-*.jar"/>
<include name="log4j-*.jar"/>
</fileset>
@ -2083,7 +2138,7 @@ under the License.
</forbiddenapis>
</target>
<target name="findbugs" depends="assemble">
<target name="findbugs" depends="jar">
<downloadfile src="${findbugs.url}" dest="${findbugs.jar}"/>
<property name="findbugs.home" value="build/findbugs" />
@ -2103,11 +2158,13 @@ under the License.
output="xml:withMessages"
outputFile="build/findbugs.xml"
effort="max"
failOnError="true"
excludeFilter="src/resources/devtools/findbugs-filters.xml">
<fileset dir="${dist.dir}/maven">
<include name="poi/poi-${version.id}.jar"/>
<include name="poi-scratchpad/poi-scratchpad-${version.id}.jar"/>
<include name="poi-ooxml/poi-ooxml-${version.id}.jar"/>
<include name="poi-excelant/poi-excelant-${version.id}.jar"/>
</fileset>
<auxClasspath path="${dsig.bouncycastle-pkix.jar}" />
<auxClasspath path="${dsig.bouncycastle-prov.jar}" />
@ -2117,9 +2174,11 @@ under the License.
<auxClasspath path="${ooxml.security.jar}" />
<auxClasspath path="${ooxml.curvesapi.jar}" />
<auxClasspath path="${ooxml.xmlbeans26.jar}" />
<auxClasspath path="${main.commons-collections4.jar}" />
<auxClasspath path="${main.commons-codec.jar}" />
<auxClasspath path="${main.commons-logging.jar}" />
<auxClasspath path="${main.junit.jar}" />
<auxClasspath path="${main.ant.jar}" />
<sourcePath path="src/java" />
<sourcePath path="src/ooxml/java" />
<sourcePath path="src/scratchpad/src" />

View File

@ -91,6 +91,11 @@
<scope>test</scope>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
</dependencies>
</project>

View File

@ -110,6 +110,11 @@
</build>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>

View File

@ -194,7 +194,7 @@ public final class RowRecordsAggregate extends RecordAggregate {
private int getStartRowNumberForBlock(int block) {
int startIndex = block * DBCellRecord.BLOCK_SIZE;
if(_rowRecordValues == null){
if (_rowRecordValues == null) {
_rowRecordValues = _rowRecords.values().toArray(new RowRecord[_rowRecords.size()]);
}
@ -211,7 +211,7 @@ public final class RowRecordsAggregate extends RecordAggregate {
if (endIndex >= _rowRecords.size())
endIndex = _rowRecords.size()-1;
if(_rowRecordValues == null){
if (_rowRecordValues == null){
_rowRecordValues = _rowRecords.values().toArray(new RowRecord[_rowRecords.size()]);
}

View File

@ -19,10 +19,10 @@ package org.apache.poi.hssf.usermodel;
import java.util.Map;
import org.apache.poi.ss.formula.BaseFormulaEvaluator;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
import org.apache.poi.ss.formula.IStabilityClassifier;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.WorkbookEvaluatorProvider;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumericValueEval;
@ -33,8 +33,6 @@ import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Internal;
@ -45,9 +43,7 @@ import org.apache.poi.util.Internal;
* cell values. Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between
* calls to evaluate~ methods on this class.
*/
public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider {
private final WorkbookEvaluator _bookEvaluator;
public class HSSFFormulaEvaluator extends BaseFormulaEvaluator {
private final HSSFWorkbook _book;
public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
@ -71,8 +67,8 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
* @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
*/
private HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
super(new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder));
_book = workbook;
_bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder);
}
/**
@ -95,11 +91,7 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
*/
public static void setupEnvironment(String[] workbookNames, HSSFFormulaEvaluator[] evaluators) {
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
for (int i = 0; i < wbEvals.length; i++) {
wbEvals[i] = evaluators[i]._bookEvaluator;
}
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
BaseFormulaEvaluator.setupEnvironment(workbookNames, evaluators);
}
@Override
@ -107,23 +99,6 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators);
}
@Override
public WorkbookEvaluator _getWorkbookEvaluator() {
return _bookEvaluator;
}
/**
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
* in the evaluated workbook. If performance is not critical, a single call to this method
* may be used instead of many specific calls to the notify~ methods.
*
* Failure to call this method after changing cell values will cause incorrect behaviour
* of the evaluate~ methods of this class
*/
@Override
public void clearAllCachedResultValues() {
_bookEvaluator.clearAllCachedResultValues();
}
/**
* Should be called to tell the cell value cache that the specified (value or formula) cell
* has changed.
@ -162,62 +137,6 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell));
}
/**
* If cell contains a formula, the formula is evaluated and returned,
* else the CellValue simply copies the appropriate cell value from
* the cell and also its cell type. This method should be preferred over
* evaluateInCell() when the call should not modify the contents of the
* original cell.
*
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
*/
@Override
public CellValue evaluate(Cell cell) {
if (cell == null) {
return null;
}
switch (cell.getCellTypeEnum()) {
case BOOLEAN:
return CellValue.valueOf(cell.getBooleanCellValue());
case ERROR:
return CellValue.getError(cell.getErrorCellValue());
case FORMULA:
return evaluateFormulaCellValue(cell);
case NUMERIC:
return new CellValue(cell.getNumericCellValue());
case STRING:
return new CellValue(cell.getRichStringCellValue().getString());
case BLANK:
return null;
default:
throw new IllegalStateException("Bad cell type (" + cell.getCellTypeEnum() + ")");
}
}
/**
* If cell contains formula, it evaluates the formula, and saves the result of the formula. The
* cell remains as a formula cell. If the cell does not contain formula, this method returns -1
* and leaves the cell unchanged.
*
* Note that the type of the <em>formula result</em> is returned, so you know what kind of
* cached formula result is also stored with the formula.
* <pre>
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
* </pre>
* Be aware that your cell will hold both the formula, and the result. If you want the cell
* replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
* @param cell The cell to evaluate
* @return -1 for non-formula cells, or the type of the <em>formula result</em>
*/
@Override
public int evaluateFormulaCell(Cell cell) {
return evaluateFormulaCellEnum(cell).getCode();
}
/**
* If cell contains formula, it evaluates the formula, and saves the result of the formula. The
* cell remains as a formula cell. If the cell does not contain formula, rather than throwing an
@ -275,24 +194,6 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
}
return result;
}
private static void setCellType(Cell cell, CellValue cv) {
CellType cellType = cv.getCellType();
switch (cellType) {
case BOOLEAN:
case ERROR:
case NUMERIC:
case STRING:
cell.setCellType(cellType);
return;
case BLANK:
// never happens - blanks eventually get translated to zero
case FORMULA:
// this will never happen, we have already evaluated the formula
default:
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
}
}
private static void setCellValue(Cell cell, CellValue cv) {
CellType cellType = cv.getCellType();
@ -345,21 +246,7 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
* cells, and calling evaluateFormulaCell on each one.
*/
public static void evaluateAllFormulaCells(Workbook wb) {
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluateAllFormulaCells(wb, evaluator);
}
private static void evaluateAllFormulaCells(Workbook wb, FormulaEvaluator evaluator) {
for(int i=0; i<wb.getNumberOfSheets(); i++) {
Sheet sheet = wb.getSheetAt(i);
for(Row r : sheet) {
for (Cell c : r) {
if (c.getCellTypeEnum() == CellType.FORMULA) {
evaluator.evaluateFormulaCellEnum(c);
}
}
}
}
BaseFormulaEvaluator.evaluateAllFormulaCells(wb);
}
/**
@ -374,7 +261,7 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
* cells, and calling evaluateFormulaCell on each one.
*/
@Override
public void evaluateAll() {
public void evaluateAll() {
evaluateAllFormulaCells(_book, this);
}
@ -382,7 +269,7 @@ public void evaluateAll() {
* Returns a CellValue wrapper around the supplied ValueEval instance.
* @param cell
*/
private CellValue evaluateFormulaCellValue(Cell cell) {
protected CellValue evaluateFormulaCellValue(Cell cell) {
ValueEval eval = _bookEvaluator.evaluate(new HSSFEvaluationCell((HSSFCell)cell));
if (eval instanceof BoolEval) {
BoolEval be = (BoolEval) eval;

View File

@ -92,6 +92,7 @@ import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
import org.apache.poi.ss.formula.udf.IndexedUDFFinder;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
@ -548,7 +549,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
* the 'active' sheet (which is the sheet with focus).
* Unselects sheets that are not in <code>indexes</code>.
*
* @param indexes
* @param indexes Array of sheets to select, the index is 0-based.
*/
public void setSelectedTabs(int[] indexes) {
Collection<Integer> list = new ArrayList<Integer>(indexes.length);
@ -563,7 +564,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
* the 'active' sheet (which is the sheet with focus).
* Unselects sheets that are not in <code>indexes</code>.
*
* @param indexes
* @param indexes Collection of sheets to select, the index is 0-based.
*/
public void setSelectedTabs(Collection<Integer> indexes) {
@ -893,8 +894,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
*/
@Override
public Iterator<Sheet> sheetIterator() {
Iterator<Sheet> result = new SheetIterator<Sheet>();
return result;
return new SheetIterator<Sheet>();
}
/**
@ -1280,9 +1280,9 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
/**
* Closes the underlying {@link NPOIFSFileSystem} from which
* the Workbook was read, if any. Has no effect on Workbooks
* opened from an InputStream, or newly created ones.
* <p>Once {@link #close()} has been called, no further
* the Workbook was read, if any.
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* Workbook.
*/
@ -1531,6 +1531,11 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
return names.get(nameIndex);
}
@Override
public List<HSSFName> getAllNames() {
return Collections.unmodifiableList(names);
}
public NameRecord getNameRecord(int nameIndex) {
return getWorkbook().getNameRecord(nameIndex);
}
@ -1702,8 +1707,9 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
*
* @param name the name to remove.
*/
void removeName(HSSFName name) {
int index = getNameIndex(name);
@Override
public void removeName(Name name) {
int index = getNameIndex((HSSFName) name);
removeName(index);
}

View File

@ -374,6 +374,7 @@ public class CryptoFunctions {
// SET Verifier TO 0x0000
short verifier = 0;
if (!"".equals(password)) {
// FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER
for (int i = arrByteChars.length-1; i >= 0; i--) {
// SET Verifier TO Intermediate3 BITWISE XOR PasswordByte
@ -388,6 +389,7 @@ public class CryptoFunctions {
// RETURN Verifier BITWISE XOR 0xCE4B
verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K')
}
return verifier & 0xFFFF;
}

View File

@ -0,0 +1,194 @@
/* ====================================================================
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;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
/**
* Common functionality across file formats for evaluating formula cells.<p/>
*/
public abstract class BaseFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider {
protected final WorkbookEvaluator _bookEvaluator;
protected BaseFormulaEvaluator(WorkbookEvaluator bookEvaluator) {
this._bookEvaluator = bookEvaluator;
}
/**
* Coordinates several formula evaluators together so that formulas that involve external
* references can be evaluated.
* @param workbookNames the simple file names used to identify the workbooks in formulas
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
*/
public static void setupEnvironment(String[] workbookNames, BaseFormulaEvaluator[] evaluators) {
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
for (int i = 0; i < wbEvals.length; i++) {
wbEvals[i] = evaluators[i]._bookEvaluator;
}
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
}
@Override
public void setupReferencedWorkbooks(Map<String, FormulaEvaluator> evaluators) {
CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators);
}
@Override
public WorkbookEvaluator _getWorkbookEvaluator() {
return _bookEvaluator;
}
/**
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
* in the evaluated workbook. If performance is not critical, a single call to this method
* may be used instead of many specific calls to the notify~ methods.
*
* Failure to call this method after changing cell values will cause incorrect behaviour
* of the evaluate~ methods of this class
*/
@Override
public void clearAllCachedResultValues() {
_bookEvaluator.clearAllCachedResultValues();
}
/**
* If cell contains a formula, the formula is evaluated and returned,
* else the CellValue simply copies the appropriate cell value from
* the cell and also its cell type. This method should be preferred over
* evaluateInCell() when the call should not modify the contents of the
* original cell.
*
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
*/
@Override
public CellValue evaluate(Cell cell) {
if (cell == null) {
return null;
}
switch (cell.getCellTypeEnum()) {
case BOOLEAN:
return CellValue.valueOf(cell.getBooleanCellValue());
case ERROR:
return CellValue.getError(cell.getErrorCellValue());
case FORMULA:
return evaluateFormulaCellValue(cell);
case NUMERIC:
return new CellValue(cell.getNumericCellValue());
case STRING:
return new CellValue(cell.getRichStringCellValue().getString());
case BLANK:
return null;
default:
throw new IllegalStateException("Bad cell type (" + cell.getCellTypeEnum() + ")");
}
}
protected abstract CellValue evaluateFormulaCellValue(Cell cell);
/**
* If cell contains formula, it evaluates the formula, and saves the result of the formula. The
* cell remains as a formula cell. If the cell does not contain formula, this method returns -1
* and leaves the cell unchanged.
*
* Note that the type of the <em>formula result</em> is returned, so you know what kind of
* cached formula result is also stored with the formula.
* <pre>
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
* </pre>
* Be aware that your cell will hold both the formula, and the result. If you want the cell
* replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
* @param cell The cell to evaluate
* @return -1 for non-formula cells, or the type of the <em>formula result</em>
*/
@Override
public int evaluateFormulaCell(Cell cell) {
return evaluateFormulaCellEnum(cell).getCode();
}
protected static void setCellType(Cell cell, CellValue cv) {
CellType cellType = cv.getCellType();
switch (cellType) {
case BOOLEAN:
case ERROR:
case NUMERIC:
case STRING:
cell.setCellType(cellType);
return;
case BLANK:
// never happens - blanks eventually get translated to zero
throw new IllegalArgumentException("This should never happen. Blanks eventually get translated to zero.");
case FORMULA:
// this will never happen, we have already evaluated the formula
throw new IllegalArgumentException("This should never happen. Formulas should have already been evaluated.");
default:
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
}
}
/**
* Loops over all cells in all sheets of the supplied
* workbook.
* For cells that contain formulas, their formulas are
* evaluated, and the results are saved. These cells
* remain as formula cells.
* For cells that do not contain formulas, no changes
* are made.
* This is a helpful wrapper around looping over all
* cells, and calling evaluateFormulaCell on each one.
*/
public static void evaluateAllFormulaCells(Workbook wb) {
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluateAllFormulaCells(wb, evaluator);
}
protected static void evaluateAllFormulaCells(Workbook wb, FormulaEvaluator evaluator) {
for(int i=0; i<wb.getNumberOfSheets(); i++) {
Sheet sheet = wb.getSheetAt(i);
for(Row r : sheet) {
for (Cell c : r) {
if (c.getCellTypeEnum() == CellType.FORMULA) {
evaluator.evaluateFormulaCellEnum(c);
}
}
}
}
}
/** {@inheritDoc} */
@Override
public void setIgnoreMissingWorkbooks(boolean ignore){
_bookEvaluator.setIgnoreMissingWorkbooks(ignore);
}
/** {@inheritDoc} */
@Override
public void setDebugEvaluationOutputForNextEval(boolean value){
_bookEvaluator.setDebugEvaluationOutputForNextEval(value);
}
}

View File

@ -27,7 +27,7 @@ import org.apache.poi.ss.util.CellReference;
/**
* Provides Lazy Evaluation to a 3D Reference
*/
final class LazyRefEval extends RefEvalBase {
public final class LazyRefEval extends RefEvalBase {
private final SheetRangeEvaluator _evaluator;
public LazyRefEval(int rowIndex, int columnIndex, SheetRangeEvaluator sre) {
@ -47,14 +47,17 @@ final class LazyRefEval extends RefEvalBase {
return new LazyAreaEval(area, _evaluator);
}
public boolean isSubTotal() {
SheetRefEvaluator sheetEvaluator = _evaluator.getSheetEvaluator(getFirstSheetIndex());
return sheetEvaluator.isSubTotal(getRow(), getColumn());
}
public String toString() {
CellReference cr = new CellReference(getRow(), getColumn());
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append("[");
sb.append(_evaluator.getSheetNameRange());
sb.append('!');
sb.append(cr.formatAsString());
sb.append("]");
return sb.toString();
return getClass().getName() + "[" +
_evaluator.getSheetNameRange() +
'!' +
cr.formatAsString() +
"]";
}
}

View File

@ -19,6 +19,7 @@ package org.apache.poi.ss.formula.functions;
import static org.apache.poi.ss.formula.functions.AggregateFunction.subtotalInstance;
import org.apache.poi.ss.formula.LazyRefEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NotImplementedException;
@ -26,6 +27,11 @@ import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Implementation for the Excel function SUBTOTAL<p>
*
@ -61,7 +67,6 @@ import org.apache.poi.ss.formula.eval.ValueEval;
public class Subtotal implements Function {
private static Function findFunction(int functionCode) throws EvaluationException {
Function func;
switch (functionCode) {
case 1: return subtotalInstance(AggregateFunction.AVERAGE);
case 2: return Count.subtotalInstance();
@ -87,7 +92,7 @@ public class Subtotal implements Function {
return ErrorEval.VALUE_INVALID;
}
Function innerFunc;
final Function innerFunc;
try {
ValueEval ve = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex);
int functionCode = OperandResolver.coerceValueToInt(ve);
@ -96,9 +101,24 @@ public class Subtotal implements Function {
return e.getErrorEval();
}
ValueEval[] innerArgs = new ValueEval[nInnerArgs];
System.arraycopy(args, 1, innerArgs, 0, nInnerArgs);
// ignore the first arg, this is the function-type, we check for the length above
final List<ValueEval> list = new ArrayList<ValueEval>(Arrays.asList(args).subList(1, args.length));
return innerFunc.evaluate(innerArgs, srcRowIndex, srcColumnIndex);
Iterator<ValueEval> it = list.iterator();
// See https://support.office.com/en-us/article/SUBTOTAL-function-7b027003-f060-4ade-9040-e478765b9939
// "If there are other subtotals within ref1, ref2,... (or nested subtotals), these nested subtotals are ignored to avoid double counting."
// For array references it is handled in other evaluation steps, but we need to handle this here for references to subtotal-functions
while(it.hasNext()) {
ValueEval eval = it.next();
if(eval instanceof LazyRefEval) {
LazyRefEval lazyRefEval = (LazyRefEval) eval;
if(lazyRefEval.isSubTotal()) {
it.remove();
}
}
}
return innerFunc.evaluate(list.toArray(new ValueEval[list.size()]), srcRowIndex, srcColumnIndex);
}
}

View File

@ -81,7 +81,7 @@ public interface CellStyle {
/**
* vertically justified vertical alignment
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#TOP} instead.
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#JUSTIFY} instead.
*/
static final short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode();

View File

@ -341,9 +341,11 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
/**
* Close the underlying input resource (File or Stream),
* from which the Workbook was read. After closing, the
* Workbook should no longer be used.
* <p>This will have no effect newly created Workbooks.
* from which the Workbook was read.
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* Workbook.
*/
@Override
void close() throws IOException;
@ -367,6 +369,13 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
*/
List<? extends Name> getNames(String name);
/**
* Returns all defined names.
*
* @return a list of the defined names. An empty list is returned if none is found.
*/
List<? extends Name> getAllNames();
/**
* @param nameIndex position of the named range (0-based)
* @return the defined name at the specified index
@ -405,6 +414,13 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
*/
void removeName(String name);
/**
* Remove a defined name
*
* @param name the name of the defined name
*/
void removeName(Name name);
/**
* Adds the linking required to allow formulas referencing
* the specified external workbook to be added to this one.

View File

@ -27,19 +27,13 @@ import org.apache.commons.logging.LogFactory;
* developers to write log calls, while simultaneously making those
* calls as cheap as possible by performing lazy evaluation of the log
* message.<p>
*
* @author Marc Johnson (mjohnson at apache dot org)
* @author Glen Stampoultzis (glens at apache.org)
* @author Nicola Ken Barozzi (nicolaken at apache.org)
*/
public class CommonsLogger extends POILogger
{
private static LogFactory _creator = LogFactory.getFactory();
private Log log = null;
@Override
public void initialize(final String cat)
{
this.log = _creator.getInstance(cat);
@ -51,6 +45,7 @@ public class CommonsLogger extends POILogger
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param obj1 The object to log.
*/
@Override
public void log(final int level, final Object obj1)
{
if(level==FATAL)
@ -104,6 +99,7 @@ public class CommonsLogger extends POILogger
* @param obj1 The object to log. This is converted to a string.
* @param exception An exception to be logged
*/
@Override
public void log(final int level, final Object obj1,
final Throwable exception)
{
@ -175,7 +171,7 @@ public class CommonsLogger extends POILogger
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
*/
@Override
public boolean check(final int level)
{
if(level==FATAL)

View File

@ -22,14 +22,10 @@ package org.apache.poi.util;
* developers to write log calls, while simultaneously making those
* calls as cheap as possible by performing lazy evaluation of the log
* message.<p>
*
* @author Marc Johnson (mjohnson at apache dot org)
* @author Glen Stampoultzis (glens at apache.org)
* @author Nicola Ken Barozzi (nicolaken at apache.org)
*/
public class NullLogger extends POILogger {
@Override
public void initialize(final String cat){
public void initialize(final String cat) {
// do nothing
}
@ -41,8 +37,7 @@ public class NullLogger extends POILogger {
*/
@Override
public void log(final int level, final Object obj1)
{
public void log(final int level, final Object obj1) {
// do nothing
}
@ -53,6 +48,7 @@ public class NullLogger extends POILogger {
* @param obj1 The object to log. This is converted to a string.
* @param exception An exception to be logged
*/
@Override
public void log(int level, Object obj1, final Throwable exception) {
// do nothing
}

View File

@ -24,15 +24,12 @@ package org.apache.poi.util;
* developers to write log calls, while simultaneously making those
* calls as cheap as possible by performing lazy evaluation of the log
* message.
*
* @author Marc Johnson (mjohnson at apache dot org)
* @author Glen Stampoultzis (glens at apache.org)
* @author Nicola Ken Barozzi (nicolaken at apache.org)
*/
public class SystemOutLogger extends POILogger
{
private String _cat;
@Override
public void initialize(final String cat)
{
this._cat=cat;
@ -44,7 +41,7 @@ public class SystemOutLogger extends POILogger
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param obj1 The object to log.
*/
@Override
public void log(final int level, final Object obj1)
{
log(level, obj1, null);
@ -57,6 +54,7 @@ public class SystemOutLogger extends POILogger
* @param obj1 The object to log. This is converted to a string.
* @param exception An exception to be logged
*/
@Override
@SuppressForbidden("uses printStackTrace")
public void log(final int level, final Object obj1,
final Throwable exception) {
@ -78,6 +76,7 @@ public class SystemOutLogger extends POILogger
* @see #ERROR
* @see #FATAL
*/
@Override
public boolean check(final int level)
{
int currentLevel;

View File

@ -194,6 +194,10 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart implements Close
* Closes the underlying {@link OPCPackage} from which this
* document was read, if there is one
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* document.
*
* @throws IOException for writable packages, if an IO exception occur during the saving process.
*/
@Override

View File

@ -382,8 +382,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
}
// Creates a new package
OPCPackage pkg = null;
pkg = new ZipPackage();
OPCPackage pkg = new ZipPackage();
pkg.originalPackagePath = file.getAbsolutePath();
configurePackage(pkg);
@ -391,8 +390,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
}
public static OPCPackage create(OutputStream output) {
OPCPackage pkg = null;
pkg = new ZipPackage();
OPCPackage pkg = new ZipPackage();
pkg.originalPackagePath = null;
pkg.output = output;
@ -542,7 +540,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
// Create the thumbnail part name
String contentType = ContentTypes
.getContentTypeFromFileExtension(filename);
PackagePartName thumbnailPartName = null;
PackagePartName thumbnailPartName;
try {
thumbnailPartName = PackagingURIHelper.createPartName("/docProps/"
+ filename);

View File

@ -29,10 +29,7 @@ import java.util.TreeMap;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.util.DocumentHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -54,7 +51,7 @@ public abstract class ContentTypeManager {
/**
* Content type namespace
*/
public static final String TYPES_NAMESPACE_URI = "http://schemas.openxmlformats.org/package/2006/content-types";
public static final String TYPES_NAMESPACE_URI = PackageNamespaces.CONTENT_TYPES;
/* Xml elements in content type part */

View File

@ -304,13 +304,13 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
@Override
public boolean getFlipHorizontal(){
CTGroupTransform2D xfrm = getXfrm();
return (xfrm == null || !xfrm.isSetFlipH()) ? false : xfrm.getFlipH();
return !(xfrm == null || !xfrm.isSetFlipH()) && xfrm.getFlipH();
}
@Override
public boolean getFlipVertical(){
CTGroupTransform2D xfrm = getXfrm();
return (xfrm == null || !xfrm.isSetFlipV()) ? false : xfrm.getFlipV();
return !(xfrm == null || !xfrm.isSetFlipV()) && xfrm.getFlipV();
}
@Override
@ -333,7 +333,7 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
// recursively update each shape
for(XSLFShape shape : gr.getShapes()) {
XSLFShape newShape = null;
XSLFShape newShape;
if (shape instanceof XSLFTextBox) {
newShape = createTextBox();
} else if (shape instanceof XSLFAutoShape) {

View File

@ -41,7 +41,6 @@ import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.DocumentHelper;
@ -55,7 +54,6 @@ import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@ -118,7 +116,6 @@ public class XSSFExportToXml implements Comparator<String>{
* @throws SAXException
* @throws ParserConfigurationException
* @throws TransformerException
* @throws InvalidFormatException
*/
public void exportToXML(OutputStream os, String encoding, boolean validate) throws SAXException, ParserConfigurationException, TransformerException{
List<XSSFSingleXmlCell> singleXMLCells = map.getRelatedSingleXMLCell();
@ -128,10 +125,10 @@ public class XSSFExportToXml implements Comparator<String>{
Document doc = DocumentHelper.createDocument();
Element root = null;
final Element root;
if (isNamespaceDeclared()) {
root=doc.createElementNS(getNamespace(),rootElement);
root = doc.createElementNS(getNamespace(),rootElement);
} else {
root = doc.createElementNS("", rootElement);
}
@ -152,7 +149,6 @@ public class XSSFExportToXml implements Comparator<String>{
tableMappings.put(commonXPath, table);
}
Collections.sort(xpaths,this);
for(String xpath : xpaths) {
@ -167,8 +163,7 @@ public class XSSFExportToXml implements Comparator<String>{
XSSFCell cell = simpleXmlCell.getReferencedCell();
if (cell!=null) {
Node currentNode = getNodeByXPath(xpath,doc.getFirstChild(),doc,false);
STXmlDataType.Enum dataType = simpleXmlCell.getXmlDataType();
mapCellOnNode(cell,currentNode,dataType);
mapCellOnNode(cell,currentNode);
//remove nodes which are empty in order to keep the output xml valid
if("".equals(currentNode.getTextContent()) && currentNode.getParentNode() != null) {
@ -202,22 +197,15 @@ public class XSSFExportToXml implements Comparator<String>{
XSSFXmlColumnPr pointer = tableColumns.get(j-startColumnIndex);
String localXPath = pointer.getLocalXPath();
Node currentNode = getNodeByXPath(localXPath,tableRootNode,doc,false);
STXmlDataType.Enum dataType = pointer.getXmlDataType();
mapCellOnNode(cell,currentNode,dataType);
mapCellOnNode(cell,currentNode);
}
}
}
}
} else {
} /*else {
// TODO: implement filtering management in xpath
}
}*/
}
boolean isValid = true;
@ -225,8 +213,6 @@ public class XSSFExportToXml implements Comparator<String>{
isValid =isValid(doc);
}
if (isValid) {
/////////////////
@ -275,7 +261,7 @@ public class XSSFExportToXml implements Comparator<String>{
}
private void mapCellOnNode(XSSFCell cell, Node node, STXmlDataType.Enum outputDataType) {
private void mapCellOnNode(XSSFCell cell, Node node) {
String value ="";
switch (cell.getCellTypeEnum()) {
@ -349,11 +335,7 @@ public class XSSFExportToXml implements Comparator<String>{
}
currentNode = selectedNode;
} else {
Node attribute = createAttribute(doc, currentNode, axisName);
currentNode = attribute;
currentNode = createAttribute(doc, currentNode, axisName);
}
}
return currentNode;
@ -421,12 +403,11 @@ public class XSSFExportToXml implements Comparator<String>{
for(int i =1;i <minLenght; i++) {
String leftElementName =leftTokens[i];
String leftElementName = leftTokens[i];
String rightElementName = rightTokens[i];
if (leftElementName.equals(rightElementName)) {
Node complexType = getComplexTypeForElement(leftElementName, xmlSchema,localComplexTypeRootNode);
localComplexTypeRootNode = complexType;
localComplexTypeRootNode = getComplexTypeForElement(leftElementName, xmlSchema, localComplexTypeRootNode);
} else {
int leftIndex = indexOfElementInComplexType(leftElementName,localComplexTypeRootNode);
int rightIndex = indexOfElementInComplexType(rightElementName,localComplexTypeRootNode);
@ -436,9 +417,9 @@ public class XSSFExportToXml implements Comparator<String>{
}if ( leftIndex > rightIndex) {
return 1;
}
} else {
} /*else {
// NOTE: the xpath doesn't match correctly in the schema
}
}*/
}
}
@ -483,7 +464,7 @@ public class XSSFExportToXml implements Comparator<String>{
// Note: we expect that all the complex types are defined at root level
Node complexTypeNode = null;
if (!"".equals(complexTypeName)) {
complexTypeNode = getComplexTypeNodeFromSchemaChildren(xmlSchema, complexTypeNode, complexTypeName);
complexTypeNode = getComplexTypeNodeFromSchemaChildren(xmlSchema, null, complexTypeName);
}
return complexTypeNode;

View File

@ -338,7 +338,11 @@ public class SXSSFCell implements Cell {
}
if(_value.getType()==CellType.FORMULA)
((StringFormulaValue)_value).setPreEvaluatedValue(value);
if(_value instanceof NumericFormulaValue) {
((NumericFormulaValue) _value).setPreEvaluatedValue(Double.parseDouble(value));
} else {
((StringFormulaValue) _value).setPreEvaluatedValue(value);
}
else
((PlainStringValue)_value).setValue(value);
} else {
@ -956,6 +960,7 @@ public class SXSSFCell implements Cell {
}
/*package*/ void setFormulaType(CellType type)
{
Value prevValue = _value;
switch(type)
{
case NUMERIC:
@ -983,7 +988,13 @@ public class SXSSFCell implements Cell {
throw new IllegalArgumentException("Illegal type " + type);
}
}
// if we had a Formula before, we should copy over the _value of the formula
if(prevValue instanceof FormulaValue) {
((FormulaValue)_value)._value = ((FormulaValue)prevValue)._value;
}
}
//TODO: implement this correctly
@NotImplemented
/*package*/ CellType computeTypeFromFormula(String formula)

View File

@ -893,8 +893,11 @@ public class SXSSFWorkbook implements Workbook {
/**
* Closes the underlying {@link XSSFWorkbook} and {@link OPCPackage}
* on which this Workbook is based, if any. Has no effect on Workbooks
* created from scratch.
* on which this Workbook is based, if any.
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* Workbook.
*/
@Override
public void close() throws IOException {
@ -1003,12 +1006,25 @@ public class SXSSFWorkbook implements Workbook {
return _wb.getNames(name);
}
/**
* Returns all defined names
*
* @return all defined names
*/
@Override
public List<? extends Name> getAllNames()
{
return _wb.getAllNames();
}
/**
* @param nameIndex position of the named range (0-based)
* @return the defined name at the specified index
* @throws IllegalArgumentException if the supplied index is invalid
* @deprecated 3.16. New projects should avoid accessing named ranges by index.
*/
@Override
@Deprecated
public Name getNameAt(int nameIndex)
{
return _wb.getNameAt(nameIndex);
@ -1033,8 +1049,12 @@ public class SXSSFWorkbook implements Workbook {
*
* @param name the name of the defined name
* @return zero based index of the defined name. <code>-1</code> if not found.
*
* @deprecated 3.16. New projects should avoid accessing named ranges by index.
* Use {@link #getName(String)} instead.
*/
@Override
@Deprecated
public int getNameIndex(String name)
{
return _wb.getNameIndex(name);
@ -1044,8 +1064,11 @@ public class SXSSFWorkbook implements Workbook {
* Remove the defined name at the specified index
*
* @param index named range index (0 based)
*
* @deprecated 3.16. New projects should use {@link #removeName(Name)}.
*/
@Override
@Deprecated
public void removeName(int index)
{
_wb.removeName(index);
@ -1055,9 +1078,23 @@ public class SXSSFWorkbook implements Workbook {
* Remove a defined name by name
*
* @param name the name of the defined name
*
* @deprecated 3.16. New projects should use {@link #removeName(Name)}.
*/
@Override
@Deprecated
public void removeName(String name)
{
_wb.removeName(name);
}
/**
* Remove the given defined name
*
* @param name the name to remove
*/
@Override
public void removeName(Name name)
{
_wb.removeName(name);
}

View File

@ -232,7 +232,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
// Otherwise, try it as a named range
if (sheet == null) {
if (_uBook.getNameIndex(name) > -1) {
if (!_uBook.getNames(name).isEmpty()) {
return new NameXPxg(null, name);
}
return null;

View File

@ -17,12 +17,9 @@
package org.apache.poi.xssf.usermodel;
import java.util.Map;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
import org.apache.poi.ss.formula.BaseFormulaEvaluator;
import org.apache.poi.ss.formula.EvaluationCell;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.WorkbookEvaluatorProvider;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval;
@ -31,28 +28,16 @@ import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.util.Internal;
/**
* Internal POI use only - parent of XSSF and SXSSF formula evaluators
*/
public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider {
private WorkbookEvaluator _bookEvaluator;
public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator {
protected BaseXSSFFormulaEvaluator(WorkbookEvaluator bookEvaluator) {
_bookEvaluator = bookEvaluator;
super(bookEvaluator);
}
/**
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
* in the evaluated workbook.
* Failure to call this method after changing cell values will cause incorrect behaviour
* of the evaluate~ methods of this class
*/
public void clearAllCachedResultValues() {
_bookEvaluator.clearAllCachedResultValues();
}
public void notifySetFormula(Cell cell) {
_bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell));
}
@ -63,60 +48,6 @@ public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, Work
_bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell));
}
/**
* If cell contains a formula, the formula is evaluated and returned,
* else the CellValue simply copies the appropriate cell value from
* the cell and also its cell type. This method should be preferred over
* evaluateInCell() when the call should not modify the contents of the
* original cell.
* @param cell
*/
public CellValue evaluate(Cell cell) {
if (cell == null) {
return null;
}
switch (cell.getCellTypeEnum()) {
case BOOLEAN:
return CellValue.valueOf(cell.getBooleanCellValue());
case ERROR:
return CellValue.getError(cell.getErrorCellValue());
case FORMULA:
return evaluateFormulaCellValue(cell);
case NUMERIC:
return new CellValue(cell.getNumericCellValue());
case STRING:
return new CellValue(cell.getRichStringCellValue().getString());
case BLANK:
return null;
default:
throw new IllegalStateException("Bad cell type (" + cell.getCellTypeEnum() + ")");
}
}
/**
* If cell contains formula, it evaluates the formula,
* and saves the result of the formula. The cell
* remains as a formula cell.
* Else if cell does not contain formula, this method leaves
* the cell unchanged.
* Note that the type of the formula result is returned,
* so you know what kind of value is also stored with
* the formula.
* <pre>
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
* </pre>
* Be aware that your cell will hold both the formula,
* and the result. If you want the cell replaced with
* the result of the formula, use {@link #evaluate(org.apache.poi.ss.usermodel.Cell)} }
* @param cell The cell to evaluate
* @return The type of the formula result (the cell's type remains as CellType.FORMULA however)
*/
public int evaluateFormulaCell(Cell cell) {
return evaluateFormulaCellEnum(cell).getCode();
}
/**
* If cell contains formula, it evaluates the formula,
* and saves the result of the formula. The cell
@ -164,27 +95,6 @@ public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, Work
setCellValue(cell, cv);
}
}
private static void setCellType(Cell cell, CellValue cv) {
CellType cellType = cv.getCellType();
switch (cellType) {
case BOOLEAN:
case ERROR:
case NUMERIC:
case STRING:
cell.setCellType(cellType);
return;
case BLANK:
// never happens - blanks eventually get translated to zero
throw new IllegalArgumentException("This should never happen. Blanks eventually get translated to zero.");
case FORMULA:
// this will never happen, we have already evaluated the formula
throw new IllegalArgumentException("This should never happen. Formulas should have already been evaluated.");
default:
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
}
}
private static void setCellValue(Cell cell, CellValue cv) {
CellType cellType = cv.getCellType();
@ -218,7 +128,7 @@ public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, Work
/**
* Returns a CellValue wrapper around the supplied ValueEval instance.
*/
private CellValue evaluateFormulaCellValue(Cell cell) {
protected CellValue evaluateFormulaCellValue(Cell cell) {
EvaluationCell evalCell = toEvaluationCell(cell);
ValueEval eval = _bookEvaluator.evaluate(evalCell);
if (eval instanceof NumberEval) {
@ -238,22 +148,4 @@ public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, Work
}
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
}
public void setupReferencedWorkbooks(Map<String, FormulaEvaluator> evaluators) {
CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators);
}
public WorkbookEvaluator _getWorkbookEvaluator() {
return _bookEvaluator;
}
/** {@inheritDoc} */
public void setIgnoreMissingWorkbooks(boolean ignore){
_bookEvaluator.setIgnoreMissingWorkbooks(ignore);
}
/** {@inheritDoc} */
public void setDebugEvaluationOutputForNextEval(boolean value){
_bookEvaluator.setDebugEvaluationOutputForNextEval(value);
}
}

View File

@ -17,7 +17,7 @@
package org.apache.poi.xssf.usermodel;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.ss.formula.BaseFormulaEvaluator;
import org.apache.poi.ss.formula.EvaluationCell;
import org.apache.poi.ss.formula.IStabilityClassifier;
import org.apache.poi.ss.formula.WorkbookEvaluator;
@ -88,7 +88,7 @@ public final class XSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator {
* cells, and calling evaluateFormulaCell on each one.
*/
public static void evaluateAllFormulaCells(XSSFWorkbook wb) {
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
BaseFormulaEvaluator.evaluateAllFormulaCells(wb);
}
/**
* Loops over all cells in all sheets of the supplied
@ -102,7 +102,7 @@ public final class XSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator {
* cells, and calling evaluateFormulaCell on each one.
*/
public void evaluateAll() {
HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
evaluateAllFormulaCells(_book, this);
}
/**

View File

@ -167,19 +167,18 @@ public final class XSSFName implements Name {
public void setNameName(String name) {
validateName(name);
String oldName = getNameName();
int sheetIndex = getSheetIndex();
int numberOfNames = _workbook.getNumberOfNames();
//Check to ensure no other names have the same case-insensitive name at the same scope
for (int i = 0; i < numberOfNames; i++) {
XSSFName nm = _workbook.getNameAt(i);
if ((nm != this)
&& name.equalsIgnoreCase(nm.getNameName())
&& (sheetIndex == nm.getSheetIndex())) {
for (XSSFName foundName : _workbook.getNames(name)) {
if (foundName.getSheetIndex() == sheetIndex && foundName != this) {
String msg = "The "+(sheetIndex == -1 ? "workbook" : "sheet")+" already contains this name: " + name;
throw new IllegalArgumentException(msg);
}
}
_ctName.setName(name);
//Need to update the name -> named ranges map
_workbook.updateName(this, oldName);
}
public String getRefersToFormula() {

View File

@ -18,8 +18,8 @@
package org.apache.poi.xssf.usermodel;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.setPassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.validatePassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword;
import java.io.IOException;
import java.io.InputStream;

View File

@ -18,8 +18,8 @@
package org.apache.poi.xssf.usermodel;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.setPassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.validatePassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword;
import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -29,16 +29,20 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.regex.Pattern;
import javax.xml.namespace.QName;
import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
@ -59,6 +63,7 @@ import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
import org.apache.poi.ss.formula.udf.IndexedUDFFinder;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
@ -140,6 +145,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
*/
private List<XSSFSheet> sheets;
/**
* this holds the XSSFName objects attached to this workbook, keyed by lower-case name
*/
private ListValuedMap<String, XSSFName> namedRangesByName;
/**
* this holds the XSSFName objects attached to this workbook
*/
@ -442,6 +452,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
stylesSource.setWorkbook(this);
namedRanges = new ArrayList<XSSFName>();
namedRangesByName = new ArrayListValuedHashMap<String, XSSFName>();
sheets = new ArrayList<XSSFSheet>();
pivotTables = new ArrayList<XSSFPivotTable>();
}
@ -733,8 +744,13 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
public XSSFName createName() {
CTDefinedName ctName = CTDefinedName.Factory.newInstance();
ctName.setName("");
return createAndStoreName(ctName);
}
private XSSFName createAndStoreName(CTDefinedName ctName) {
XSSFName name = new XSSFName(ctName, this);
namedRanges.add(name);
namedRangesByName.put(ctName.getName().toLowerCase(Locale.ENGLISH), name);
return name;
}
@ -938,28 +954,47 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
return stylesSource.getFontAt(idx);
}
/**
* Get the first named range with the given name.
*
* Note: names of named ranges are not unique as they are scoped by sheet.
* {@link #getNames(String name)} returns all named ranges with the given name.
*
* @param name named range name
* @return XSSFName with the given name. <code>null</code> is returned no named range could be found.
*/
@Override
public XSSFName getName(String name) {
int nameIndex = getNameIndex(name);
if (nameIndex < 0) {
Collection<XSSFName> list = getNames(name);
if (list.isEmpty()) {
return null;
}
return namedRanges.get(nameIndex);
return list.iterator().next();
}
/**
* Get the named ranges with the given name.
* <i>Note:</i>Excel named ranges are case-insensitive and
* this method performs a case-insensitive search.
*
* @param name named range name
* @return list of XSSFNames with the given name. An empty list if no named ranges could be found
*/
@Override
public List<XSSFName> getNames(String name) {
List<XSSFName> names = new ArrayList<XSSFName>();
for(XSSFName nr : namedRanges) {
if(nr.getNameName().equals(name)) {
names.add(nr);
}
}
return names;
return Collections.unmodifiableList(namedRangesByName.get(name.toLowerCase(Locale.ENGLISH)));
}
/**
* Get the named range at the given index.
*
* @param nameIndex the index of the named range
* @return the XSSFName at the given index
*
* @deprecated 3.16. New projects should avoid accessing named ranges by index.
*/
@Override
@Deprecated
public XSSFName getNameAt(int nameIndex) {
int nNames = namedRanges.size();
if (nNames < 1) {
@ -973,21 +1008,30 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
/**
* Gets the named range index by his name
* <i>Note:</i>Excel named ranges are case-insensitive and
* this method performs a case-insensitive search.
* Get a list of all the named ranges in the workbook.
*
* @param name named range name
* @return named range index
* @return list of XSSFNames in the workbook
*/
@Override
public int getNameIndex(String name) {
int i = 0;
for(XSSFName nr : namedRanges) {
if(nr.getNameName().equals(name)) {
return i;
public List<XSSFName> getAllNames() {
return Collections.unmodifiableList(namedRanges);
}
i++;
/**
* Gets the named range index by name.
*
* @param name named range name
* @return named range index. <code>-1</code> is returned if no named ranges could be found.
*
* @deprecated 3.16. New projects should avoid accessing named ranges by index.
* Use {@link #getName(String)} instead.
*/
@Override
@Deprecated
public int getNameIndex(String name) {
XSSFName nm = getName(name);
if (nm != null) {
return namedRanges.indexOf(nm);
}
return -1;
}
@ -1258,23 +1302,41 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
return getPackagePart().getContentType().equals(XSSFRelation.MACROS_WORKBOOK.getContentType());
}
/**
* Remove the named range at the given index.
*
* @param nameIndex the index of the named range name to remove
*
* @deprecated 3.16. New projects should use {@link #removeName(Name)}.
*/
@Override
@Deprecated
public void removeName(int nameIndex) {
namedRanges.remove(nameIndex);
removeName(getNameAt(nameIndex));
}
/**
* Remove the first named range found with the given name.
*
* Note: names of named ranges are not unique (name + sheet
* index is unique), so {@link #removeName(Name)} should
* be used if possible.
*
* @param name the named range name to remove
*
* @throws IllegalArgumentException if no named range could be found
*
* @deprecated 3.16. New projects should use {@link #removeName(Name)}.
*/
@Override
@Deprecated
public void removeName(String name) {
int idx = 0;
for (XSSFName nm : namedRanges) {
if(nm.getNameName().equalsIgnoreCase(name)) {
removeName(idx);
return;
}
idx++;
}
List<XSSFName> names = namedRangesByName.get(name.toLowerCase(Locale.ENGLISH));
if (names.isEmpty()) {
throw new IllegalArgumentException("Named range was not found: " + name);
}
removeName(names.get(0));
}
/**
@ -1282,13 +1344,24 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
* (name + sheet index is unique), this method is more accurate.
*
* @param name the name to remove.
*
* @throws IllegalArgumentException if the named range is not a part of this XSSFWorkbook
*/
void removeName(XSSFName name) {
if (!namedRanges.remove(name)) {
@Override
public void removeName(Name name) {
if (!namedRangesByName.removeMapping(name.getNameName().toLowerCase(Locale.ENGLISH), name)
|| !namedRanges.remove(name)) {
throw new IllegalArgumentException("Name was not found: " + name);
}
}
void updateName(XSSFName name, String oldName) {
if (!namedRangesByName.removeMapping(oldName.toLowerCase(Locale.ENGLISH), name)) {
throw new IllegalArgumentException("Name was not found: " + name);
}
namedRangesByName.put(name.getNameName().toLowerCase(Locale.ENGLISH), name);
}
/**
* Delete the printarea for the sheet specified
@ -1297,13 +1370,9 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
*/
@Override
public void removePrintArea(int sheetIndex) {
int cont = 0;
for (XSSFName name : namedRanges) {
if (name.getNameName().equals(XSSFName.BUILTIN_PRINT_AREA) && name.getSheetIndex() == sheetIndex) {
namedRanges.remove(cont);
break;
}
cont++;
XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex);
if (name != null) {
removeName(name);
}
}
@ -1369,17 +1438,20 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
//adjust indices of names ranges
for (Iterator<XSSFName> it = namedRanges.iterator(); it.hasNext();) {
XSSFName nm = it.next();
List<XSSFName> toRemove = new ArrayList<XSSFName>();
for (XSSFName nm : namedRanges) {
CTDefinedName ct = nm.getCTName();
if(!ct.isSetLocalSheetId()) continue;
if (ct.getLocalSheetId() == index) {
it.remove();
toRemove.add(nm);
} else if (ct.getLocalSheetId() > index){
// Bump down by one, so still points at the same sheet
ct.setLocalSheetId(ct.getLocalSheetId()-1);
}
}
for (XSSFName nm : toRemove) {
removeName(nm);
}
}
/**
@ -1514,8 +1586,8 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
XSSFName getBuiltInName(String builtInCode, int sheetNumber) {
for (XSSFName name : namedRanges) {
if (name.getNameName().equalsIgnoreCase(builtInCode) && name.getSheetIndex() == sheetNumber) {
for (XSSFName name : namedRangesByName.get(builtInCode.toLowerCase(Locale.ENGLISH))) {
if (name.getSheetIndex() == sheetNumber) {
return name;
}
}
@ -1537,15 +1609,12 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
nameRecord.setName(builtInName);
nameRecord.setLocalSheetId(sheetNumber);
XSSFName name = new XSSFName(nameRecord, this);
for (XSSFName nr : namedRanges) {
if (nr.equals(name))
if (getBuiltInName(builtInName, sheetNumber) != null) {
throw new POIXMLException("Builtin (" + builtInName
+ ") already exists for sheet (" + sheetNumber + ")");
}
namedRanges.add(name);
return name;
return createAndStoreName(nameRecord);
}
/**
@ -1665,10 +1734,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
private void reprocessNamedRanges() {
namedRangesByName = new ArrayListValuedHashMap<String, XSSFName>();
namedRanges = new ArrayList<XSSFName>();
if(workbook.isSetDefinedNames()) {
for(CTDefinedName ctName : workbook.getDefinedNames().getDefinedNameArray()) {
namedRanges.add(new XSSFName(ctName, this));
createAndStoreName(ctName);
}
}
}

View File

@ -65,9 +65,7 @@ public final class XSSFFormulaUtils {
*/
public void updateSheetName(final int sheetIndex, final String oldName, final String newName) {
// update named ranges
final int numberOfNames = _wb.getNumberOfNames();
for (int i = 0; i < numberOfNames; i++) {
XSSFName nm = _wb.getNameAt(i);
for (XSSFName nm : _wb.getAllNames()) {
if (nm.getSheetIndex() == -1 || nm.getSheetIndex() == sheetIndex) {
updateName(nm, oldName, newName);
}

View File

@ -0,0 +1,136 @@
/*
* ====================================================================
* 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.xssf.usermodel.helpers;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Locale;
import javax.xml.bind.DatatypeConverter;
import javax.xml.namespace.QName;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
@Internal(since="3.15 beta 3")
public final class XSSFPasswordHelper {
private XSSFPasswordHelper() {
// no instances of this static class
}
/**
* Sets the XORed or hashed password
*
* @param xobj the xmlbeans object which contains the password attributes
* @param password the password, if null, the password attributes will be removed
* @param hashAlgo the hash algorithm, if null the password will be XORed
* @param prefix the prefix of the password attributes, may be null
*/
public static void setPassword(XmlObject xobj, String password, HashAlgorithm hashAlgo, String prefix) {
XmlCursor cur = xobj.newCursor();
if (password == null) {
cur.removeAttribute(getAttrName(prefix, "password"));
cur.removeAttribute(getAttrName(prefix, "algorithmName"));
cur.removeAttribute(getAttrName(prefix, "hashValue"));
cur.removeAttribute(getAttrName(prefix, "saltValue"));
cur.removeAttribute(getAttrName(prefix, "spinCount"));
return;
}
cur.toFirstContentToken();
if (hashAlgo == null) {
int hash = CryptoFunctions.createXorVerifier1(password);
cur.insertAttributeWithValue(getAttrName(prefix, "password"),
String.format(Locale.ROOT, "%04X", hash).toUpperCase(Locale.ROOT));
} else {
SecureRandom random = new SecureRandom();
byte salt[] = random.generateSeed(16);
// Iterations specifies the number of times the hashing function shall be iteratively run (using each
// iteration's result as the input for the next iteration).
int spinCount = 100000;
// Implementation Notes List:
// --> In this third stage, the reversed byte order legacy hash from the second stage shall
// be converted to Unicode hex string representation
byte hash[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCount, false);
cur.insertAttributeWithValue(getAttrName(prefix, "algorithmName"), hashAlgo.jceId);
cur.insertAttributeWithValue(getAttrName(prefix, "hashValue"), DatatypeConverter.printBase64Binary(hash));
cur.insertAttributeWithValue(getAttrName(prefix, "saltValue"), DatatypeConverter.printBase64Binary(salt));
cur.insertAttributeWithValue(getAttrName(prefix, "spinCount"), ""+spinCount);
}
cur.dispose();
}
/**
* Validates the password, i.e.
* calculates the hash of the given password and compares it against the stored hash
*
* @param xobj the xmlbeans object which contains the password attributes
* @param password the password, if null the method will always return false,
* even if there's no password set
* @param prefix the prefix of the password attributes, may be null
*
* @return true, if the hashes match
*/
public static boolean validatePassword(XmlObject xobj, String password, String prefix) {
// TODO: is "velvetSweatshop" the default password?
if (password == null) return false;
XmlCursor cur = xobj.newCursor();
String xorHashVal = cur.getAttributeText(getAttrName(prefix, "password"));
String algoName = cur.getAttributeText(getAttrName(prefix, "algorithmName"));
String hashVal = cur.getAttributeText(getAttrName(prefix, "hashValue"));
String saltVal = cur.getAttributeText(getAttrName(prefix, "saltValue"));
String spinCount = cur.getAttributeText(getAttrName(prefix, "spinCount"));
cur.dispose();
if (xorHashVal != null) {
int hash1 = Integer.parseInt(xorHashVal, 16);
int hash2 = CryptoFunctions.createXorVerifier1(password);
return hash1 == hash2;
} else {
if (hashVal == null || algoName == null || saltVal == null || spinCount == null) {
return false;
}
byte hash1[] = DatatypeConverter.parseBase64Binary(hashVal);
HashAlgorithm hashAlgo = HashAlgorithm.fromString(algoName);
byte salt[] = DatatypeConverter.parseBase64Binary(saltVal);
int spinCnt = Integer.parseInt(spinCount);
byte hash2[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false);
return Arrays.equals(hash1, hash2);
}
}
private static QName getAttrName(String prefix, String name) {
if (prefix == null || "".equals(prefix)) {
return new QName(name);
} else {
return new QName(prefix+Character.toUpperCase(name.charAt(0))+name.substring(1));
}
}
}

View File

@ -19,18 +19,17 @@
package org.apache.poi.xssf.usermodel.helpers;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Locale;
import javax.xml.bind.DatatypeConverter;
import javax.xml.namespace.QName;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.xmlbeans.XmlCursor;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Removal;
import org.apache.xmlbeans.XmlObject;
/**
* @deprecated POI 3.15 beta 3. Use {@link XSSFPasswordHelper} instead.
*/
@Internal(since="3.15 beta 3")
@Deprecated
@Removal(version="3.17")
public class XSSFPaswordHelper {
/**
* Sets the XORed or hashed password
@ -41,41 +40,7 @@ public class XSSFPaswordHelper {
* @param prefix the prefix of the password attributes, may be null
*/
public static void setPassword(XmlObject xobj, String password, HashAlgorithm hashAlgo, String prefix) {
XmlCursor cur = xobj.newCursor();
if (password == null) {
cur.removeAttribute(getAttrName(prefix, "password"));
cur.removeAttribute(getAttrName(prefix, "algorithmName"));
cur.removeAttribute(getAttrName(prefix, "hashValue"));
cur.removeAttribute(getAttrName(prefix, "saltValue"));
cur.removeAttribute(getAttrName(prefix, "spinCount"));
return;
}
cur.toFirstContentToken();
if (hashAlgo == null) {
int hash = CryptoFunctions.createXorVerifier1(password);
cur.insertAttributeWithValue(getAttrName(prefix, "password"),
Integer.toHexString(hash).toUpperCase(Locale.ROOT));
} else {
SecureRandom random = new SecureRandom();
byte salt[] = random.generateSeed(16);
// Iterations specifies the number of times the hashing function shall be iteratively run (using each
// iteration's result as the input for the next iteration).
int spinCount = 100000;
// Implementation Notes List:
// --> In this third stage, the reversed byte order legacy hash from the second stage shall
// be converted to Unicode hex string representation
byte hash[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCount, false);
cur.insertAttributeWithValue(getAttrName(prefix, "algorithmName"), hashAlgo.jceId);
cur.insertAttributeWithValue(getAttrName(prefix, "hashValue"), DatatypeConverter.printBase64Binary(hash));
cur.insertAttributeWithValue(getAttrName(prefix, "saltValue"), DatatypeConverter.printBase64Binary(salt));
cur.insertAttributeWithValue(getAttrName(prefix, "spinCount"), ""+spinCount);
}
cur.dispose();
XSSFPasswordHelper.setPassword(xobj, password, hashAlgo, prefix);
}
/**
@ -90,41 +55,6 @@ public class XSSFPaswordHelper {
* @return true, if the hashes match
*/
public static boolean validatePassword(XmlObject xobj, String password, String prefix) {
// TODO: is "velvetSweatshop" the default password?
if (password == null) return false;
XmlCursor cur = xobj.newCursor();
String xorHashVal = cur.getAttributeText(getAttrName(prefix, "password"));
String algoName = cur.getAttributeText(getAttrName(prefix, "algorithmName"));
String hashVal = cur.getAttributeText(getAttrName(prefix, "hashValue"));
String saltVal = cur.getAttributeText(getAttrName(prefix, "saltValue"));
String spinCount = cur.getAttributeText(getAttrName(prefix, "spinCount"));
cur.dispose();
if (xorHashVal != null) {
int hash1 = Integer.parseInt(xorHashVal, 16);
int hash2 = CryptoFunctions.createXorVerifier1(password);
return hash1 == hash2;
} else {
if (hashVal == null || algoName == null || saltVal == null || spinCount == null) {
return false;
}
byte hash1[] = DatatypeConverter.parseBase64Binary(hashVal);
HashAlgorithm hashAlgo = HashAlgorithm.fromString(algoName);
byte salt[] = DatatypeConverter.parseBase64Binary(saltVal);
int spinCnt = Integer.parseInt(spinCount);
byte hash2[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false);
return Arrays.equals(hash1, hash2);
}
}
private static QName getAttrName(String prefix, String name) {
if (prefix == null || "".equals(prefix)) {
return new QName(name);
} else {
return new QName(prefix+Character.toUpperCase(name.charAt(0))+name.substring(1));
}
return XSSFPasswordHelper.validatePassword(xobj, password, prefix);
}
}

View File

@ -83,9 +83,7 @@ public final class XSSFRowShifter extends RowShifter {
public void updateNamedRanges(FormulaShifter shifter) {
Workbook wb = sheet.getWorkbook();
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
final int numberOfNames = wb.getNumberOfNames();
for (int i = 0; i < numberOfNames; i++) {
Name name = wb.getNameAt(i);
for (Name name : wb.getAllNames()) {
String formula = name.getRefersToFormula();
int sheetIndex = name.getSheetIndex();
final int rowIndex = -1; //don't care, named ranges are not allowed to include structured references

View File

@ -18,6 +18,7 @@
package org.apache.poi.openxml4j.opc.internal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@ -44,6 +45,7 @@ public final class TestContentTypeManager {
// Retrieves core properties part
OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ);
try {
PackageRelationshipCollection rels = p.getRelationshipsByType(PackageRelationshipTypes.CORE_PROPERTIES);
PackageRelationship corePropertiesRelationship = rels.getRelationship(0);
PackagePart coreDocument = p.getPart(corePropertiesRelationship);
@ -54,6 +56,10 @@ public final class TestContentTypeManager {
assumeTrue("finish writing this test", false);
ContentTypeManager ctm = new ZipContentTypeManager(coreDocument.getInputStream(), p);
assertNotNull(ctm);
} finally {
p.close();
}
}
/**

View File

@ -115,25 +115,25 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
assertFalse(wb.isMacroEnabled());
assertEquals(3, wb.getNumberOfNames());
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId());
assertEquals("SheetA!$A$1", wb.getNameAt(0).getRefersToFormula());
assertEquals("SheetA", wb.getNameAt(0).getSheetName());
assertEquals(0, wb.getName("SheetAA1").getCTName().getLocalSheetId());
assertFalse(wb.getName("SheetAA1").getCTName().isSetLocalSheetId());
assertEquals("SheetA!$A$1", wb.getName("SheetAA1").getRefersToFormula());
assertEquals("SheetA", wb.getName("SheetAA1").getSheetName());
assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId());
assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId());
assertEquals("SheetB!$A$1", wb.getNameAt(1).getRefersToFormula());
assertEquals("SheetB", wb.getNameAt(1).getSheetName());
assertEquals(0, wb.getName("SheetBA1").getCTName().getLocalSheetId());
assertFalse(wb.getName("SheetBA1").getCTName().isSetLocalSheetId());
assertEquals("SheetB!$A$1", wb.getName("SheetBA1").getRefersToFormula());
assertEquals("SheetB", wb.getName("SheetBA1").getSheetName());
assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId());
assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId());
assertEquals("SheetC!$A$1", wb.getNameAt(2).getRefersToFormula());
assertEquals("SheetC", wb.getNameAt(2).getSheetName());
assertEquals(0, wb.getName("SheetCA1").getCTName().getLocalSheetId());
assertFalse(wb.getName("SheetCA1").getCTName().isSetLocalSheetId());
assertEquals("SheetC!$A$1", wb.getName("SheetCA1").getRefersToFormula());
assertEquals("SheetC", wb.getName("SheetCA1").getSheetName());
// Save and re-load, still there
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb);
assertEquals(3, nwb.getNumberOfNames());
assertEquals("SheetA!$A$1", nwb.getNameAt(0).getRefersToFormula());
assertEquals("SheetA!$A$1", nwb.getName("SheetAA1").getRefersToFormula());
nwb.close();
wb.close();

View File

@ -154,7 +154,9 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
evaluator.evaluate(cXSL_cell);
fail("Without a fix for #56752, shouldn't be able to evaluate a " +
"reference to a non-provided linked workbook");
} catch(Exception e) {}
} catch(Exception e) {
// expected here
}
// Setup the environment
Map<String,FormulaEvaluator> evaluators = new HashMap<String, FormulaEvaluator>();
@ -171,8 +173,19 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
evaluator.evaluate(c);
}
}
// And evaluate the other way too
evaluator.evaluateAll();
// Evaluate and check results
// Static evaluator won't work, as no references passed in
try {
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
fail("Static method lacks references, shouldn't work");
} catch(Exception e) {
// expected here
}
// Evaluate specific cells and check results
assertEquals("\"Hello!\"", evaluator.evaluate(cXSLX_cell).formatAsString());
assertEquals("\"Test A1\"", evaluator.evaluate(cXSLX_sNR).formatAsString());
assertEquals("142.0", evaluator.evaluate(cXSLX_gNR).formatAsString());
@ -196,7 +209,9 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
try {
cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1");
fail("New workbook not linked, shouldn't be able to add");
} catch (Exception e) {}
} catch (Exception e) {
// expected here
}
// Link and re-try
Workbook alt = new XSSFWorkbook();
@ -651,4 +666,20 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
private Cell getCell(Sheet sheet, int rowNo, int column) {
return sheet.getRow(rowNo).getCell(column);
}
@Test
public void test59736() {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("59736.xlsx");
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
Cell cell = wb.getSheetAt(0).getRow(0).getCell(0);
assertEquals(1, cell.getNumericCellValue(), 0.001);
cell = wb.getSheetAt(0).getRow(1).getCell(0);
CellValue value = evaluator.evaluate(cell);
assertEquals(1, value.getNumberValue(), 0.001);
cell = wb.getSheetAt(0).getRow(2).getCell(0);
value = evaluator.evaluate(cell);
assertEquals(1, value.getNumberValue(), 0.001);
}
}

View File

@ -53,9 +53,8 @@ public final class TestXSSFName extends BaseTestNamedRange {
//sheet.createFreezePane(0, 3);
}
assertEquals(1, wb.getNumberOfNames());
XSSFName nr1 = wb.getNameAt(0);
XSSFName nr1 = wb.getName(XSSFName.BUILTIN_PRINT_TITLE);
assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName());
assertEquals("'First Sheet'!$A:$A,'First Sheet'!$1:$4", nr1.getRefersToFormula());
//remove the columns part
@ -77,9 +76,8 @@ public final class TestXSSFName extends BaseTestNamedRange {
wb.close();
assertEquals(1, nwb.getNumberOfNames());
nr1 = nwb.getNameAt(0);
nr1 = nwb.getName(XSSFName.BUILTIN_PRINT_TITLE);
assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName());
assertEquals("'First Sheet'!$A:$A,'First Sheet'!$1:$4", nr1.getRefersToFormula());
// check that setting RR&C on a second sheet causes a new Print_Titles built-in
@ -89,7 +87,7 @@ public final class TestXSSFName extends BaseTestNamedRange {
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("B:C"));
assertEquals(2, nwb.getNumberOfNames());
XSSFName nr2 = nwb.getNameAt(1);
XSSFName nr2 = nwb.getNames(XSSFName.BUILTIN_PRINT_TITLE).get(1);
assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr2.getNameName());
assertEquals("SecondSheet!$B:$C,SecondSheet!$1:$1", nr2.getRefersToFormula());
@ -98,4 +96,38 @@ public final class TestXSSFName extends BaseTestNamedRange {
sheet2.setRepeatingColumns(null);
nwb.close();
}
@Test
public void testSetNameName() throws Exception {
// Test that renaming named ranges doesn't break our new named range map
XSSFWorkbook wb = new XSSFWorkbook();
wb.createSheet("First Sheet");
// Two named ranges called "name1", one scoped to sheet1 and one globally
XSSFName nameSheet1 = wb.createName();
nameSheet1.setNameName("name1");
nameSheet1.setRefersToFormula("'First Sheet'!$A$1");
nameSheet1.setSheetIndex(0);
XSSFName nameGlobal = wb.createName();
nameGlobal.setNameName("name1");
nameGlobal.setRefersToFormula("'First Sheet'!$B$1");
// Rename sheet-scoped name to "name2", check everything is updated properly
// and that the other name is unaffected
nameSheet1.setNameName("name2");
assertEquals(1, wb.getNames("name1").size());
assertEquals(1, wb.getNames("name2").size());
assertEquals(nameGlobal, wb.getName("name1"));
assertEquals(nameSheet1, wb.getName("name2"));
// Rename the other name to "name" and check everything again
nameGlobal.setNameName("name2");
assertEquals(0, wb.getNames("name1").size());
assertEquals(2, wb.getNames("name2").size());
assertTrue(wb.getNames("name2").contains(nameGlobal));
assertTrue(wb.getNames("name2").contains(nameSheet1));
wb.close();
}
}

View File

@ -80,6 +80,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex;
public final class TestXSSFSheet extends BaseTestXSheet {
@ -1099,6 +1100,30 @@ public final class TestXSSFSheet extends BaseTestXSheet {
wb.close();
}
@Test
public void protectSheet_emptyPassword() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet();
CTSheetProtection pr = sheet.getCTWorksheet().getSheetProtection();
assertNull("CTSheetProtection should be null by default", pr);
String password = "";
sheet.protectSheet(password);
pr = sheet.getCTWorksheet().getSheetProtection();
assertNotNull("CTSheetProtection should be not null", pr);
assertTrue("sheet protection should be on", pr.isSetSheet());
assertTrue("object protection should be on", pr.isSetObjects());
assertTrue("scenario protection should be on", pr.isSetScenarios());
int hashVal = CryptoFunctions.createXorVerifier1(password);
STUnsignedShortHex xpassword = pr.xgetPassword();
int actualVal = Integer.parseInt(xpassword.getStringValue(),16);
assertEquals("well known value for top secret hash should match", hashVal, actualVal);
sheet.protectSheet(null);
assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection());
wb.close();
}
@Test
public void protectSheet_lowlevel_2013() throws IOException {
String password = "test";

View File

@ -1140,4 +1140,44 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
wb.close();
}
@Test
public void testRemoveSheet() throws IOException {
// Test removing a sheet maintains the named ranges correctly
XSSFWorkbook wb = new XSSFWorkbook();
wb.createSheet("Sheet1");
wb.createSheet("Sheet2");
XSSFName sheet1Name = wb.createName();
sheet1Name.setNameName("name1");
sheet1Name.setSheetIndex(0);
sheet1Name.setRefersToFormula("Sheet1!$A$1");
XSSFName sheet2Name = wb.createName();
sheet2Name.setNameName("name1");
sheet2Name.setSheetIndex(1);
sheet2Name.setRefersToFormula("Sheet2!$A$1");
assertTrue(wb.getAllNames().contains(sheet1Name));
assertTrue(wb.getAllNames().contains(sheet2Name));
assertEquals(2, wb.getNames("name1").size());
assertEquals(sheet1Name, wb.getNames("name1").get(0));
assertEquals(sheet2Name, wb.getNames("name1").get(1));
// Remove sheet1, we should only have sheet2Name now
wb.removeSheetAt(0);
assertFalse(wb.getAllNames().contains(sheet1Name));
assertTrue(wb.getAllNames().contains(sheet2Name));
assertEquals(1, wb.getNames("name1").size());
assertEquals(sheet2Name, wb.getNames("name1").get(0));
// Check by index as well for sanity
assertEquals(1, wb.getNumberOfNames());
assertEquals(0, wb.getNameIndex("name1"));
assertEquals(sheet2Name, wb.getNameAt(0));
wb.close();
}
}

View File

@ -571,20 +571,39 @@ public final class HWPFDocument extends HWPFDocumentCore {
return _fields;
}
/**
* Warning - not currently implemented for HWPF!
*/
@Override
public void write() throws IOException {
throw new IllegalStateException("Coming soon!");
}
@Override
public void write(File newFile) throws IOException {
// TODO Implement
throw new IllegalStateException("Coming soon!");
}
/**
* Writes out the word file that is represented by an instance of this class.
*
* If {@code stream} is a {@link java.io.FileOutputStream} on a networked drive
* or has a high cost/latency associated with each written byte,
* If the {@link File} exists, it will be replaced, otherwise a new one
* will be created
*
* @param newFile The File to write to.
* @throws IOException If there is an unexpected IOException from writing
* to the File.
*
* @since 3.15 beta 3
*/
@Override
public void write(File newFile) throws IOException {
NPOIFSFileSystem pfs = POIFSFileSystem.create(newFile);
write(pfs, true);
pfs.writeFilesystem();
}
/**
* Writes out the word file that is represented by an instance of this class.
*
* For better performance when writing to files, use {@link #write(File)}.
* If {@code stream} has a high cost/latency associated with each written byte,
* consider wrapping the OutputStream in a {@link java.io.BufferedOutputStream}
* to improve write performance.
*
@ -592,9 +611,12 @@ public final class HWPFDocument extends HWPFDocumentCore {
* @throws IOException If there is an unexpected IOException from the passed
* in OutputStream.
*/
public void write(OutputStream out)
throws IOException
{
public void write(OutputStream out) throws IOException {
NPOIFSFileSystem pfs = new NPOIFSFileSystem();
write(pfs, true);
pfs.writeFilesystem( out );
}
private void write(NPOIFSFileSystem pfs, boolean copyOtherEntries) throws IOException {
// initialize our streams for writing.
HWPFFileSystem docSys = new HWPFFileSystem();
HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT);
@ -891,7 +913,8 @@ public final class HWPFDocument extends HWPFDocumentCore {
}
// create new document preserving order of entries
NPOIFSFileSystem pfs = new NPOIFSFileSystem();
// TODO Check "copyOtherEntries" and tweak behaviour based on that
// TODO That's needed for in-place write
boolean docWritten = false;
boolean dataWritten = false;
boolean objectPoolWritten = false;
@ -967,7 +990,6 @@ public final class HWPFDocument extends HWPFDocumentCore {
if ( !objectPoolWritten )
_objectPool.writeTo( pfs.getRoot() );
pfs.writeFilesystem( out );
this.directory = pfs.getRoot();
/*

View File

@ -0,0 +1,81 @@
/* ====================================================================
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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.HWPFTestCase;
import org.apache.poi.hwpf.HWPFTestDataSamples;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.TempFile;
/**
* Test various write situations
*/
public final class TestHWPFWrite extends HWPFTestCase {
/**
* Write to a stream
*/
public void testWriteStream() throws Exception {
HWPFDocument doc = HWPFTestDataSamples.openSampleFile("SampleDoc.doc");
Range r = doc.getRange();
assertEquals("I am a test document\r", r.getParagraph(0).text());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.write(baos);
doc.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
doc = new HWPFDocument(bais);
r = doc.getRange();
assertEquals("I am a test document\r", r.getParagraph(0).text());
doc.close();
}
/**
* Write to a new file
*/
public void testWriteNewFile() throws Exception {
HWPFDocument doc = HWPFTestDataSamples.openSampleFile("SampleDoc.doc");
Range r = doc.getRange();
assertEquals("I am a test document\r", r.getParagraph(0).text());
File file = TempFile.createTempFile("TestDocument", ".doc");
doc.write(file);
doc.close();
// Check reading from File and Stream
doc = new HWPFDocument(new FileInputStream(file));
r = doc.getRange();
assertEquals("I am a test document\r", r.getParagraph(0).text());
doc.close();
doc = new HWPFDocument(new POIFSFileSystem(file));
r = doc.getRange();
assertEquals("I am a test document\r", r.getParagraph(0).text());
doc.close();
}
// TODO In-place write positive and negative checks
}

View File

@ -50,15 +50,21 @@ public abstract class BaseTestSlideShow {
@Test
public void addPicture_Stream() throws IOException {
SlideShow<?,?> show = createSlideShow();
try {
InputStream stream = slTests.openResourceAsStream("clock.jpg");
try {
assertEquals(0, show.getPictureData().size());
PictureData picture = show.addPicture(stream, PictureType.JPEG);
assertEquals(1, show.getPictureData().size());
assertSame(picture, show.getPictureData().get(0));
} finally {
stream.close();
}
} finally {
show.close();
}
}
@Test
public void addPicture_ByteArray() throws IOException {

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
@ -105,6 +106,7 @@ public final class TestIndirect {
// non-error cases
confirm(feA, c, "INDIRECT(\"C2\")", 23);
confirm(feA, c, "INDIRECT(\"C2\", TRUE)", 23);
confirm(feA, c, "INDIRECT(\"$C2\")", 23);
confirm(feA, c, "INDIRECT(\"C$2\")", 23);
confirm(feA, c, "SUM(INDIRECT(\"Sheet2!B1:C3\"))", 351); // area ref
@ -203,4 +205,9 @@ public final class TestIndirect {
+ "' but got '" + cv.formatAsString() + "'.");
}
}
@Test
public void testInvalidInput() {
assertEquals(ErrorEval.VALUE_INVALID, Indirect.instance.evaluate(new ValueEval[] {}, null));
}
}

View File

@ -20,9 +20,8 @@ package org.apache.poi.ss.formula.functions;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.FormulaParseException;
import org.apache.poi.ss.formula.eval.*;
import junit.framework.TestCase;
import org.apache.poi.ss.usermodel.*;
@ -75,7 +74,6 @@ public final class TestSubtotal extends TestCase {
}
public void testAvg(){
Workbook wb = new HSSFWorkbook();
FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
@ -95,16 +93,18 @@ public final class TestSubtotal extends TestCase {
a6.setCellFormula("SUBTOTAL(1,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(1,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(1,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(2.0, a3.getNumericCellValue());
assertEquals(8.0, a6.getNumericCellValue());
assertEquals(3.0, a7.getNumericCellValue());
assertEquals(3.0, a8.getNumericCellValue());
}
public void testSum(){
Workbook wb = new HSSFWorkbook();
FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
@ -124,12 +124,15 @@ public final class TestSubtotal extends TestCase {
a6.setCellFormula("SUBTOTAL(9,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(9,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(9,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(4.0, a3.getNumericCellValue());
assertEquals(26.0, a6.getNumericCellValue());
assertEquals(12.0, a7.getNumericCellValue());
assertEquals(12.0, a8.getNumericCellValue());
}
public void testCount(){
@ -147,18 +150,21 @@ public final class TestSubtotal extends TestCase {
a3.setCellFormula("SUBTOTAL(2,B2:B3)");
Cell a4 = sh.createRow(4).createCell(1);
a4.setCellValue("POI"); // A4 is string and not counted
Cell a5 = sh.createRow(5).createCell(1); // A5 is blank and not counted
/*Cell a5 =*/ sh.createRow(5).createCell(1); // A5 is blank and not counted
Cell a6 = sh.createRow(6).createCell(1);
a6.setCellFormula("SUBTOTAL(2,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(2,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(2,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(2.0, a3.getNumericCellValue());
assertEquals(6.0, a6.getNumericCellValue());
assertEquals(2.0, a7.getNumericCellValue());
assertEquals(2.0, a8.getNumericCellValue());
}
public void testCounta(){
@ -176,18 +182,21 @@ public final class TestSubtotal extends TestCase {
a3.setCellFormula("SUBTOTAL(3,B2:B3)");
Cell a4 = sh.createRow(4).createCell(1);
a4.setCellValue("POI"); // A4 is string and not counted
Cell a5 = sh.createRow(5).createCell(1); // A5 is blank and not counted
/*Cell a5 =*/ sh.createRow(5).createCell(1); // A5 is blank and not counted
Cell a6 = sh.createRow(6).createCell(1);
a6.setCellFormula("SUBTOTAL(3,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(3,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(3,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(2.0, a3.getNumericCellValue());
assertEquals(8.0, a6.getNumericCellValue());
assertEquals(3.0, a7.getNumericCellValue());
assertEquals(3.0, a8.getNumericCellValue());
}
public void testMax(){
@ -211,12 +220,15 @@ public final class TestSubtotal extends TestCase {
a6.setCellFormula("SUBTOTAL(4,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(4,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(4,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(3.0, a3.getNumericCellValue());
assertEquals(16.0, a6.getNumericCellValue());
assertEquals(7.0, a7.getNumericCellValue());
assertEquals(7.0, a8.getNumericCellValue());
}
public void testMin(){
@ -240,12 +252,15 @@ public final class TestSubtotal extends TestCase {
a6.setCellFormula("SUBTOTAL(5,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(5,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(5,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(1.0, a3.getNumericCellValue());
assertEquals(4.0, a6.getNumericCellValue());
assertEquals(1.0, a7.getNumericCellValue());
assertEquals(1.0, a8.getNumericCellValue());
}
public void testStdev(){
@ -269,12 +284,15 @@ public final class TestSubtotal extends TestCase {
a6.setCellFormula("SUBTOTAL(7,B2:B6)*2 + 2");
Cell a7 = sh.createRow(7).createCell(1);
a7.setCellFormula("SUBTOTAL(7,B2:B7)");
Cell a8 = sh.createRow(8).createCell(1);
a8.setCellFormula("SUBTOTAL(7,B2,B3,B4,B5,B6,B7,B8)");
fe.evaluateAll();
assertEquals(1.41421, a3.getNumericCellValue(), 0.0001);
assertEquals(7.65685, a6.getNumericCellValue(), 0.0001);
assertEquals(2.82842, a7.getNumericCellValue(), 0.0001);
assertEquals(2.82842, a8.getNumericCellValue(), 0.0001);
}
public void test50209(){
@ -328,4 +346,69 @@ public final class TestSubtotal extends TestCase {
confirmExpectedResult(evaluator, "SUBTOTAL(COUNT;B2:B8,C2:C8)", cellC2, 3.0);
confirmExpectedResult(evaluator, "SUBTOTAL(COUNTA;B2:B8,C2:C8)", cellC3, 5.0);
}
public void testUnimplemented(){
Workbook wb = new HSSFWorkbook();
FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
Sheet sh = wb.createSheet();
Cell a3 = sh.createRow(3).createCell(1);
a3.setCellFormula("SUBTOTAL(8,B2:B3)");
try {
fe.evaluateAll();
fail("Should catch an NotImplementedFunctionException here, adjust these tests if it was actually implemented");
} catch (NotImplementedException e) {
// expected here
}
a3.setCellFormula("SUBTOTAL(10,B2:B3)");
try {
fe.evaluateAll();
fail("Should catch an NotImplementedFunctionException here, adjust these tests if it was actually implemented");
} catch (NotImplementedException e) {
// expected here
}
a3.setCellFormula("SUBTOTAL(11,B2:B3)");
try {
fe.evaluateAll();
fail("Should catch an NotImplementedFunctionException here, adjust these tests if it was actually implemented");
} catch (NotImplementedException e) {
// expected here
}
a3.setCellFormula("SUBTOTAL(107,B2:B3)");
try {
fe.evaluateAll();
fail("Should catch an NotImplementedFunctionException here, adjust these tests if it was actually implemented");
} catch (NotImplementedException e) {
// expected here
}
a3.setCellFormula("SUBTOTAL(0,B2:B3)");
fe.evaluateAll();
assertEquals(FormulaError.VALUE.getCode(), a3.getErrorCellValue());
try {
a3.setCellFormula("SUBTOTAL(9)");
fail("Should catch an exception here");
} catch (FormulaParseException e) {
// expected here
}
try {
a3.setCellFormula("SUBTOTAL()");
fail("Should catch an exception here");
} catch (FormulaParseException e) {
// expected here
}
Subtotal subtotal = new Subtotal();
assertEquals(ErrorEval.VALUE_INVALID, subtotal.evaluate(new ValueEval[] {}, 0, 0));
}
}

View File

@ -0,0 +1,66 @@
/* ====================================================================
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.functions;
import org.apache.poi.ss.formula.eval.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class TestWeekdayFunc {
@Test
public void testEvaluate() throws Exception {
assertEquals(2.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(2.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(1.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(1.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(2.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(0.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(3.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(1.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(11.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(7.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(12.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(6.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(13.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(5.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(14.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(4.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(15.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(3.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(16.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(2.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(17.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(3.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(3.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(1.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(2.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(2.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(1.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(3.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(2.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(11.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(1.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(12.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(7.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(13.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(6.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(14.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(5.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(15.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(4.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(16.0)}, 0, 0)).getNumberValue(), 0.001);
assertEquals(3.0, ((NumberEval)WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(39448.0), new NumberEval(17.0)}, 0, 0)).getNumberValue(), 0.001);
}
@Test
public void testEvaluateInvalid() throws Exception {
assertEquals(ErrorEval.VALUE_INVALID, WeekdayFunc.instance.evaluate(new ValueEval[]{}, 0, 0));
assertEquals(ErrorEval.VALUE_INVALID, WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(1.0), new NumberEval(1.0)}, 0, 0));
assertEquals(ErrorEval.NUM_ERROR, WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(-1.0)}, 0, 0));
assertEquals(ErrorEval.VALUE_INVALID, WeekdayFunc.instance.evaluate(new ValueEval[]{new StringEval("")}, 0, 0));
assertEquals(ErrorEval.VALUE_INVALID, WeekdayFunc.instance.evaluate(new ValueEval[]{new StringEval("1"), new StringEval("")}, 0, 0));
assertEquals(ErrorEval.NUM_ERROR, WeekdayFunc.instance.evaluate(new ValueEval[]{new StringEval("2"), BlankEval.instance}, 0, 0));
assertEquals(ErrorEval.NUM_ERROR, WeekdayFunc.instance.evaluate(new ValueEval[]{new StringEval("3"), MissingArgEval.instance}, 0, 0));
assertEquals(ErrorEval.NUM_ERROR, WeekdayFunc.instance.evaluate(new ValueEval[]{new NumberEval(1.0), new NumberEval(18.0)}, 0, 0));
}
}

View File

@ -33,9 +33,12 @@ import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
@ -1606,4 +1609,78 @@ public abstract class BaseTestBugzillaIssues {
assertNull("Sheet0 after write", wb2.getPrintArea(0)); // CURRENTLY FAILS with "Sheet0!$A$1:$C$6"
assertEquals("Sheet1 after write", "Sheet1!$A$1:$A$1", wb2.getPrintArea(1));
}
@Test
public void test55384() throws Exception {
Workbook wb = _testDataProvider.createWorkbook();
try {
Sheet sh = wb.createSheet();
for (int rownum = 0; rownum < 10; rownum++) {
org.apache.poi.ss.usermodel.Row row = sh.createRow(rownum);
for (int cellnum = 0; cellnum < 3; cellnum++) {
Cell cell = row.createCell(cellnum);
cell.setCellValue(rownum + cellnum);
}
}
Row row = sh.createRow(10);
// setting no precalculated value works just fine.
Cell cell1 = row.createCell(0);
cell1.setCellFormula("SUM(A1:A10)");
// but setting a precalculated STRING value fails totally in SXSSF
Cell cell2 = row.createCell(1);
cell2.setCellFormula("SUM(B1:B10)");
cell2.setCellValue("55");
// setting a precalculated int value works as expected
Cell cell3 = row.createCell(2);
cell3.setCellFormula("SUM(C1:C10)");
cell3.setCellValue(65);
assertEquals(CellType.FORMULA, cell1.getCellTypeEnum());
assertEquals(CellType.FORMULA, cell2.getCellTypeEnum());
assertEquals(CellType.FORMULA, cell3.getCellTypeEnum());
assertEquals("SUM(A1:A10)", cell1.getCellFormula());
assertEquals("SUM(B1:B10)", cell2.getCellFormula());
assertEquals("SUM(C1:C10)", cell3.getCellFormula());
/*String name = wb.getClass().getCanonicalName();
String ext = (wb instanceof HSSFWorkbook) ? ".xls" : ".xlsx";
OutputStream output = new FileOutputStream("/tmp" + name + ext);
try {
wb.write(output);
} finally {
output.close();
}*/
Workbook wbBack = _testDataProvider.writeOutAndReadBack(wb);
checkFormulaPreevaluatedString(wbBack);
wbBack.close();
} finally {
wb.close();
}
}
private void checkFormulaPreevaluatedString(Workbook readFile) {
Sheet sheet = readFile.getSheetAt(0);
Row row = sheet.getRow(sheet.getLastRowNum());
assertEquals(10, row.getRowNum());
for (Cell cell : row) {
String cellValue = null;
switch (cell.getCellTypeEnum()) {
case STRING:
cellValue = cell.getRichStringCellValue().getString();
break;
case FORMULA:
cellValue = cell.getCellFormula();
break;
}
assertNotNull(cellValue);
cellValue = cellValue.isEmpty() ? null : cellValue;
assertNotNull(cellValue);
}
}
}

View File

@ -201,11 +201,7 @@ public abstract class BaseTestNamedRange {
assertEquals("The sheet already contains this name: aaa", e.getMessage());
}
int cnt = 0;
for (int i = 0; i < wb.getNumberOfNames(); i++) {
if("aaa".equals(wb.getNameAt(i).getNameName())) cnt++;
}
assertEquals(3, cnt);
assertEquals(3, wb.getNames("aaa").size());
wb.close();
}
@ -250,11 +246,11 @@ public abstract class BaseTestNamedRange {
// Write the workbook to a file
// Read the Excel file and verify its content
Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
Name nm1 = wb2.getNameAt(wb2.getNameIndex("RangeTest1"));
Name nm1 = wb2.getName("RangeTest1");
assertTrue("Name is "+nm1.getNameName(),"RangeTest1".equals(nm1.getNameName()));
assertTrue("Reference is "+nm1.getRefersToFormula(),(wb2.getSheetName(0)+"!$A$1:$L$41").equals(nm1.getRefersToFormula()));
Name nm2 = wb2.getNameAt(wb2.getNameIndex("RangeTest2"));
Name nm2 = wb2.getName("RangeTest2");
assertTrue("Name is "+nm2.getNameName(),"RangeTest2".equals(nm2.getNameName()));
assertTrue("Reference is "+nm2.getRefersToFormula(),(wb2.getSheetName(1)+"!$A$1:$O$21").equals(nm2.getRefersToFormula()));
@ -466,11 +462,11 @@ public abstract class BaseTestNamedRange {
wb1.getNameAt(0);
Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
Name nm =wb2.getNameAt(wb2.getNameIndex("RangeTest"));
Name nm =wb2.getName("RangeTest");
assertTrue("Name is "+nm.getNameName(),"RangeTest".equals(nm.getNameName()));
assertTrue("Reference is "+nm.getRefersToFormula(),(wb2.getSheetName(0)+"!$D$4:$E$8").equals(nm.getRefersToFormula()));
nm = wb2.getNameAt(wb2.getNameIndex("AnotherTest"));
nm = wb2.getName("AnotherTest");
assertTrue("Name is "+nm.getNameName(),"AnotherTest".equals(nm.getNameName()));
assertTrue("Reference is "+nm.getRefersToFormula(),newNamedRange2.getRefersToFormula().equals(nm.getRefersToFormula()));
@ -499,8 +495,7 @@ public abstract class BaseTestNamedRange {
namedCell.setRefersToFormula(reference);
// retrieve the newly created named range
int namedCellIdx = wb.getNameIndex(cellName);
Name aNamedCell = wb.getNameAt(namedCellIdx);
Name aNamedCell = wb.getName(cellName);
assertNotNull(aNamedCell);
// retrieve the cell at the named range and test its contents
@ -540,8 +535,7 @@ public abstract class BaseTestNamedRange {
namedCell.setRefersToFormula(reference);
// retrieve the newly created named range
int namedCellIdx = wb.getNameIndex(cname);
Name aNamedCell = wb.getNameAt(namedCellIdx);
Name aNamedCell = wb.getName(cname);
assertNotNull(aNamedCell);
// retrieve the cell at the named range and test its contents

View File

@ -261,17 +261,17 @@ public abstract class BaseTestSheetShiftRows {
name4.setSheetIndex(1);
sheet1.shiftRows(0, 1, 2); //shift down the top row on Sheet1.
name1 = wb.getNameAt(0);
name1 = wb.getName("name1");
assertEquals("Sheet1!$A$3+Sheet1!$B$3", name1.getRefersToFormula());
name2 = wb.getNameAt(1);
name2 = wb.getName("name2");
assertEquals("Sheet1!$A$3", name2.getRefersToFormula());
//name3 and name4 refer to Sheet2 and should not be affected
name3 = wb.getNameAt(2);
name3 = wb.getName("name3");
assertEquals("Sheet2!$A$1", name3.getRefersToFormula());
name4 = wb.getNameAt(3);
name4 = wb.getName("name4");
assertEquals("A1", name4.getRefersToFormula());
wb.close();

View File

@ -78,15 +78,17 @@ public class BaseTestCellUtil {
@Test(expected=RuntimeException.class)
public void setCellStylePropertyWithInvalidValue() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
try {
Sheet s = wb.createSheet();
Row r = s.createRow(0);
Cell c = r.createCell(0);
// An invalid BorderStyle constant
CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, 42);
} finally {
wb.close();
}
}
@Test()
public void setCellStylePropertyBorderWithShortAndEnum() throws IOException {
@ -352,10 +354,8 @@ public class BaseTestCellUtil {
CellUtil.setFont(A1, font2);
fail("setFont not allowed if font belongs to a different workbook");
} catch (final IllegalArgumentException e) {
if (e.getMessage().startsWith("Font does not belong to this workbook")) {
// expected
}
else {
// one specific message is expected
if (!e.getMessage().startsWith("Font does not belong to this workbook")) {
throw e;
}
} finally {
@ -371,7 +371,7 @@ public class BaseTestCellUtil {
*/
// bug 55555
@Test
public void setFillForegroundColorBeforeFillBackgroundColor() {
public void setFillForegroundColorBeforeFillBackgroundColor() throws IOException {
Workbook wb1 = _testDataProvider.createWorkbook();
Cell A1 = wb1.createSheet().createRow(0).createCell(0);
Map<String, Object> properties = new HashMap<String, Object>();
@ -386,13 +386,14 @@ public class BaseTestCellUtil {
assertEquals("fill pattern", CellStyle.BRICKS, style.getFillPattern());
assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor()));
assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor()));
wb1.close();
}
/**
* bug 55555
* @since POI 3.15 beta 3
*/
@Test
public void setFillForegroundColorBeforeFillBackgroundColorEnum() {
public void setFillForegroundColorBeforeFillBackgroundColorEnum() throws IOException {
Workbook wb1 = _testDataProvider.createWorkbook();
Cell A1 = wb1.createSheet().createRow(0).createCell(0);
Map<String, Object> properties = new HashMap<String, Object>();
@ -407,5 +408,7 @@ public class BaseTestCellUtil {
assertEquals("fill pattern", FillPatternType.BRICKS, style.getFillPatternEnum());
assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor()));
assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor()));
wb1.close();
}
}

View File

@ -30,16 +30,20 @@ public class DummyPOILogger extends POILogger {
logged = new ArrayList<String>();
}
@Override
public boolean check(int level) {
return true;
}
@Override
public void initialize(String cat) {}
@Override
public void log(int level, Object obj1) {
logged.add(level + " - " + obj1);
}
@Override
public void log(int level, Object obj1, Throwable exception) {
logged.add(level + " - " + obj1 + " - " + exception);
}

View File

@ -26,10 +26,6 @@ import org.junit.Test;
/**
* Tests the log class.
*
* @author Glen Stampoultzis (glens at apache.org)
* @author Marc Johnson (mjohnson at apache dot org)
* @author Nicola Ken Barozzi (nicolaken at apache.org)
*/
public final class TestPOILogger extends POILogger {
private String lastLog = "";
@ -62,19 +58,25 @@ public final class TestPOILogger extends POILogger {
}
}
// ---------- POI Logger methods implemented for testing ----------
@Override
public void initialize(String cat) {
}
@Override
public void log(int level, Object obj1) {
lastLog = (obj1 == null) ? "" : obj1.toString();
lastEx = null;
}
@Override
public void log(int level, Object obj1, Throwable exception) {
lastLog = (obj1 == null) ? "" : obj1.toString();
lastEx = exception;
}
@Override
public boolean check(int level) {
return true;
}

Binary file not shown.