Bug 57007: Add initial implementations of DMIN and DGET functions
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1648166 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5c76ccba5b
commit
a0248ff4f0
@ -98,6 +98,8 @@ public final class FunctionEval {
|
||||
retval[38] = BooleanFunction.NOT;
|
||||
retval[39] = NumericFunction.MOD;
|
||||
|
||||
retval[43] = new DStarRunner(new DMin());
|
||||
|
||||
retval[46] = AggregateFunction.VAR;
|
||||
retval[48] = TextFunction.TEXT;
|
||||
|
||||
@ -188,6 +190,8 @@ public final class FunctionEval {
|
||||
retval[233] = NumericFunction.ACOSH;
|
||||
retval[234] = NumericFunction.ATANH;
|
||||
|
||||
retval[235] = new DStarRunner(new DGet());
|
||||
|
||||
retval[FunctionID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction
|
||||
|
||||
retval[261] = new Errortype();
|
||||
|
59
src/java/org/apache/poi/ss/formula/functions/DGet.java
Normal file
59
src/java/org/apache/poi/ss/formula/functions/DGet.java
Normal file
@ -0,0 +1,59 @@
|
||||
/* ====================================================================
|
||||
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.ErrorEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Implementation of the DGet function:
|
||||
* Finds the value of a column in an area with given conditions.
|
||||
*
|
||||
* TODO:
|
||||
* - wildcards ? and * in string conditions
|
||||
* - functions as conditions
|
||||
*/
|
||||
public final class DGet implements IDStarAlgorithm {
|
||||
private ValueEval result;
|
||||
|
||||
public void reset() {
|
||||
result = null;
|
||||
}
|
||||
|
||||
public boolean processMatch(ValueEval eval) {
|
||||
if(result == null) // First match, just set the value.
|
||||
{
|
||||
result = eval;
|
||||
}
|
||||
else // There was a previous match, since there is only exactly one allowed, bail out.
|
||||
{
|
||||
result = ErrorEval.NUM_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ValueEval getResult() {
|
||||
if(result == null) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
62
src/java/org/apache/poi/ss/formula/functions/DMin.java
Normal file
62
src/java/org/apache/poi/ss/formula/functions/DMin.java
Normal file
@ -0,0 +1,62 @@
|
||||
/* ====================================================================
|
||||
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.NumberEval;
|
||||
import org.apache.poi.ss.formula.eval.NumericValueEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Implementation of the DMin function:
|
||||
* Finds the minimum value of a column in an area with given conditions.
|
||||
*
|
||||
* TODO:
|
||||
* - wildcards ? and * in string conditions
|
||||
* - functions as conditions
|
||||
*/
|
||||
public final class DMin implements IDStarAlgorithm {
|
||||
private ValueEval minimumValue;
|
||||
|
||||
public void reset() {
|
||||
minimumValue = null;
|
||||
}
|
||||
|
||||
public boolean processMatch(ValueEval eval) {
|
||||
if(eval instanceof NumericValueEval) {
|
||||
if(minimumValue == null) { // First match, just set the value.
|
||||
minimumValue = eval;
|
||||
} else { // There was a previous match, find the new minimum.
|
||||
double currentValue = ((NumericValueEval)eval).getNumberValue();
|
||||
double oldValue = ((NumericValueEval)minimumValue).getNumberValue();
|
||||
if(currentValue < oldValue) {
|
||||
minimumValue = eval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ValueEval getResult() {
|
||||
if(minimumValue == null) {
|
||||
return NumberEval.ZERO;
|
||||
} else {
|
||||
return minimumValue;
|
||||
}
|
||||
}
|
||||
}
|
369
src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
Normal file
369
src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
Normal file
@ -0,0 +1,369 @@
|
||||
/* ====================================================================
|
||||
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.TwoDEval;
|
||||
import org.apache.poi.ss.formula.eval.BlankEval;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.formula.eval.EvaluationException;
|
||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||
import org.apache.poi.ss.formula.eval.NumericValueEval;
|
||||
import org.apache.poi.ss.formula.eval.RefEval;
|
||||
import org.apache.poi.ss.formula.eval.StringValueEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.util.NumberComparer;
|
||||
|
||||
/**
|
||||
* This class performs a D* calculation. It takes an {@link IDStarAlgorithm} object and
|
||||
* uses it for calculating the result value. Iterating a database and checking the
|
||||
* entries against the set of conditions is done here.
|
||||
*/
|
||||
public final class DStarRunner implements Function3Arg {
|
||||
private IDStarAlgorithm algorithm;
|
||||
|
||||
public DStarRunner(IDStarAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
||||
if(args.length == 3) {
|
||||
return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]);
|
||||
}
|
||||
else {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex,
|
||||
ValueEval database, ValueEval filterColumn, ValueEval conditionDatabase) {
|
||||
// Input processing and error checks.
|
||||
if(!(database instanceof TwoDEval) || !(conditionDatabase instanceof TwoDEval)) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
TwoDEval db = (TwoDEval)database;
|
||||
TwoDEval cdb = (TwoDEval)conditionDatabase;
|
||||
|
||||
int fc;
|
||||
try {
|
||||
fc = getColumnForName(filterColumn, db);
|
||||
}
|
||||
catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
if(fc == -1) { // column not found
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
// Reset algorithm.
|
||||
algorithm.reset();
|
||||
|
||||
// Iterate over all db entries.
|
||||
for(int row = 1; row < db.getHeight(); ++row) {
|
||||
boolean matches = true;
|
||||
try {
|
||||
matches = fullfillsConditions(db, row, cdb);
|
||||
}
|
||||
catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
// Filter each entry.
|
||||
if(matches) {
|
||||
try {
|
||||
ValueEval currentValueEval = solveReference(db.getValue(row, fc));
|
||||
// Pass the match to the algorithm and conditionally abort the search.
|
||||
boolean shouldContinue = algorithm.processMatch(currentValueEval);
|
||||
if(! shouldContinue) {
|
||||
break;
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the result of the algorithm.
|
||||
return algorithm.getResult();
|
||||
}
|
||||
|
||||
private enum operator {
|
||||
largerThan,
|
||||
largerEqualThan,
|
||||
smallerThan,
|
||||
smallerEqualThan,
|
||||
equal
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve reference(-chains) until we have a normal value.
|
||||
*
|
||||
* @param field a ValueEval which can be a RefEval.
|
||||
* @return a ValueEval which is guaranteed not to be a RefEval
|
||||
* @throws EvaluationException If a multi-sheet reference was found along the way.
|
||||
*/
|
||||
private static ValueEval solveReference(ValueEval field) throws EvaluationException {
|
||||
if (field instanceof RefEval) {
|
||||
RefEval refEval = (RefEval)field;
|
||||
if (refEval.getNumberOfSheets() > 1) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
return solveReference(refEval.getInnerValueEval(refEval.getFirstSheetIndex()));
|
||||
}
|
||||
else {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first column index that matches the given name. The name can either be
|
||||
* a string or an integer, when it's an integer, then the respective column
|
||||
* (1 based index) is returned.
|
||||
* @param nameValueEval
|
||||
* @param db
|
||||
* @return the first column index that matches the given name (or int)
|
||||
* @throws EvaluationException
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private static int getColumnForTag(ValueEval nameValueEval, TwoDEval db)
|
||||
throws EvaluationException {
|
||||
int resultColumn = -1;
|
||||
|
||||
// Numbers as column indicator are allowed, check that.
|
||||
if(nameValueEval instanceof NumericValueEval) {
|
||||
double doubleResultColumn = ((NumericValueEval)nameValueEval).getNumberValue();
|
||||
resultColumn = (int)doubleResultColumn;
|
||||
// Floating comparisions are usually not possible, but should work for 0.0.
|
||||
if(doubleResultColumn - resultColumn != 0.0)
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
resultColumn -= 1; // Numbers are 1-based not 0-based.
|
||||
} else {
|
||||
resultColumn = getColumnForName(nameValueEval, db);
|
||||
}
|
||||
return resultColumn;
|
||||
}
|
||||
|
||||
private static int getColumnForName(ValueEval nameValueEval, TwoDEval db)
|
||||
throws EvaluationException {
|
||||
String name = getStringFromValueEval(nameValueEval);
|
||||
return getColumnForString(db, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given database returns the column number for a column heading.
|
||||
*
|
||||
* @param db Database.
|
||||
* @param name Column heading.
|
||||
* @return Corresponding column number.
|
||||
* @throws EvaluationException If it's not possible to turn all headings into strings.
|
||||
*/
|
||||
private static int getColumnForString(TwoDEval db,String name)
|
||||
throws EvaluationException {
|
||||
int resultColumn = -1;
|
||||
for(int column = 0; column < db.getWidth(); ++column) {
|
||||
ValueEval columnNameValueEval = db.getValue(0, column);
|
||||
String columnName = getStringFromValueEval(columnNameValueEval);
|
||||
if(name.equals(columnName)) {
|
||||
resultColumn = column;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a row in a database against a condition database.
|
||||
*
|
||||
* @param db Database.
|
||||
* @param row The row in the database to check.
|
||||
* @param cdb The condition database to use for checking.
|
||||
* @return Whether the row matches the conditions.
|
||||
* @throws EvaluationException If references could not be resolved or comparison
|
||||
* operators and operands didn't match.
|
||||
*/
|
||||
private static boolean fullfillsConditions(TwoDEval db, int row, TwoDEval cdb)
|
||||
throws EvaluationException {
|
||||
// Only one row must match to accept the input, so rows are ORed.
|
||||
// Each row is made up of cells where each cell is a condition,
|
||||
// all have to match, so they are ANDed.
|
||||
for(int conditionRow = 1; conditionRow < cdb.getHeight(); ++conditionRow) {
|
||||
boolean matches = true;
|
||||
for(int column = 0; column < cdb.getWidth(); ++column) { // columns are ANDed
|
||||
// Whether the condition column matches a database column, if not it's a
|
||||
// special column that accepts formulas.
|
||||
boolean columnCondition = true;
|
||||
ValueEval condition = null;
|
||||
try {
|
||||
// The condition to apply.
|
||||
condition = solveReference(cdb.getValue(conditionRow, column));
|
||||
} catch (java.lang.RuntimeException e) {
|
||||
// It might be a special formula, then it is ok if it fails.
|
||||
columnCondition = false;
|
||||
}
|
||||
// If the condition is empty it matches.
|
||||
if(condition instanceof BlankEval)
|
||||
continue;
|
||||
// The column in the DB to apply the condition to.
|
||||
ValueEval targetHeader = solveReference(cdb.getValue(0, column));
|
||||
targetHeader = solveReference(targetHeader);
|
||||
|
||||
|
||||
if(!(targetHeader instanceof StringValueEval))
|
||||
columnCondition = false;
|
||||
else if (getColumnForName(targetHeader, db) == -1)
|
||||
// No column found, it's again a special column that accepts formulas.
|
||||
columnCondition = false;
|
||||
|
||||
if(columnCondition == true) { // normal column condition
|
||||
// Should not throw, checked above.
|
||||
ValueEval target = db.getValue(
|
||||
row, getColumnForName(targetHeader, db));
|
||||
// Must be a string.
|
||||
String conditionString = getStringFromValueEval(condition);
|
||||
if(!testNormalCondition(target, conditionString)) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
} else { // It's a special formula condition.
|
||||
throw new NotImplementedException(
|
||||
"D* function with formula conditions");
|
||||
}
|
||||
}
|
||||
if (matches == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a value against a simple (< > <= >= = starts-with) condition string.
|
||||
*
|
||||
* @param value The value to check.
|
||||
* @param condition The condition to check for.
|
||||
* @return Whether the condition holds.
|
||||
* @throws EvaluationException If comparison operator and operands don't match.
|
||||
*/
|
||||
private static boolean testNormalCondition(ValueEval value, String condition)
|
||||
throws EvaluationException {
|
||||
if(condition.startsWith("<")) { // It's a </<= condition.
|
||||
String number = condition.substring(1);
|
||||
if(number.startsWith("=")) {
|
||||
number = number.substring(1);
|
||||
return testNumericCondition(value, operator.smallerEqualThan, number);
|
||||
} else {
|
||||
return testNumericCondition(value, operator.smallerThan, number);
|
||||
}
|
||||
}
|
||||
else if(condition.startsWith(">")) { // It's a >/>= condition.
|
||||
String number = condition.substring(1);
|
||||
if(number.startsWith("=")) {
|
||||
number = number.substring(1);
|
||||
return testNumericCondition(value, operator.largerEqualThan, number);
|
||||
} else {
|
||||
return testNumericCondition(value, operator.largerThan, number);
|
||||
}
|
||||
}
|
||||
else if(condition.startsWith("=")) { // It's a = condition.
|
||||
String stringOrNumber = condition.substring(1);
|
||||
// Distinguish between string and number.
|
||||
boolean itsANumber = false;
|
||||
try {
|
||||
Integer.parseInt(stringOrNumber);
|
||||
itsANumber = true;
|
||||
} catch (NumberFormatException e) { // It's not an int.
|
||||
try {
|
||||
Double.parseDouble(stringOrNumber);
|
||||
itsANumber = true;
|
||||
} catch (NumberFormatException e2) { // It's a string.
|
||||
itsANumber = false;
|
||||
}
|
||||
}
|
||||
if(itsANumber) {
|
||||
return testNumericCondition(value, operator.equal, stringOrNumber);
|
||||
} else { // It's a string.
|
||||
String valueString = getStringFromValueEval(value);
|
||||
return stringOrNumber.equals(valueString);
|
||||
}
|
||||
} else { // It's a text starts-with condition.
|
||||
String valueString = getStringFromValueEval(value);
|
||||
return valueString.startsWith(condition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a value matches a numeric condition.
|
||||
* @param valueEval Value to check.
|
||||
* @param op Comparator to use.
|
||||
* @param condition Value to check against.
|
||||
* @return whether the condition holds.
|
||||
* @throws EvaluationException If it's impossible to turn the condition into a number.
|
||||
*/
|
||||
private static boolean testNumericCondition(
|
||||
ValueEval valueEval, operator op, String condition)
|
||||
throws EvaluationException {
|
||||
// Construct double from ValueEval.
|
||||
if(!(valueEval instanceof NumericValueEval))
|
||||
return false;
|
||||
double value = ((NumericValueEval)valueEval).getNumberValue();
|
||||
|
||||
// Construct double from condition.
|
||||
double conditionValue = 0.0;
|
||||
try {
|
||||
int intValue = Integer.parseInt(condition);
|
||||
conditionValue = intValue;
|
||||
} catch (NumberFormatException e) { // It's not an int.
|
||||
try {
|
||||
conditionValue = Double.parseDouble(condition);
|
||||
} catch (NumberFormatException e2) { // It's not a double.
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
int result = NumberComparer.compare(value, conditionValue);
|
||||
switch(op) {
|
||||
case largerThan:
|
||||
return result > 0;
|
||||
case largerEqualThan:
|
||||
return result >= 0;
|
||||
case smallerThan:
|
||||
return result < 0;
|
||||
case smallerEqualThan:
|
||||
return result <= 0;
|
||||
case equal:
|
||||
return result == 0;
|
||||
}
|
||||
return false; // Can not be reached.
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a ValueEval and tries to retrieve a String value from it.
|
||||
* It tries to resolve references if there are any.
|
||||
*
|
||||
* @param value ValueEval to retrieve the string from.
|
||||
* @return String corresponding to the given ValueEval.
|
||||
* @throws EvaluationException If it's not possible to retrieve a String value.
|
||||
*/
|
||||
private static String getStringFromValueEval(ValueEval value)
|
||||
throws EvaluationException {
|
||||
value = solveReference(value);
|
||||
if(value instanceof BlankEval)
|
||||
return "";
|
||||
if(!(value instanceof StringValueEval))
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
return ((StringValueEval)value).getStringValue();
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Interface specifying how an algorithm to be used by {@link DStarRunner} should look like.
|
||||
* Each implementing class should correspond to one of the D* functions.
|
||||
*/
|
||||
public interface IDStarAlgorithm {
|
||||
/**
|
||||
* Reset the state of this algorithm.
|
||||
* This is called before each run through a database.
|
||||
*/
|
||||
void reset();
|
||||
/**
|
||||
* Process a match that is found during a run through a database.
|
||||
* @param eval ValueEval of the cell in the matching row. References will already be resolved.
|
||||
* @return Whether we should continue iterating through the database.
|
||||
*/
|
||||
boolean processMatch(ValueEval eval);
|
||||
/**
|
||||
* Return a result ValueEval that will be the result of the calculation.
|
||||
* This is always called at the end of a run through the database.
|
||||
* @return a ValueEval
|
||||
*/
|
||||
ValueEval getResult();
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests DGET() as loaded from a test data spreadsheet.
|
||||
*/
|
||||
public class TestDGetFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
|
||||
|
||||
protected String getFilename() {
|
||||
return "DGet.xls";
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests D*() functions as loaded from a test data spreadsheet.
|
||||
*/
|
||||
public class TestDStarFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
|
||||
|
||||
protected String getFilename() {
|
||||
return "DStar.xls";
|
||||
}
|
||||
}
|
BIN
test-data/spreadsheet/DGet.xls
Normal file
BIN
test-data/spreadsheet/DGet.xls
Normal file
Binary file not shown.
BIN
test-data/spreadsheet/DStar.xls
Normal file
BIN
test-data/spreadsheet/DStar.xls
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user