git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@692614 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_2_FINAL
@@ -109,8 +109,8 @@ public final class AnalysisToolPak { | |||
r(m, "IMSUB", null); | |||
r(m, "IMSUM", null); | |||
r(m, "INTRATE", null); | |||
r(m, "ISEVEN", null); | |||
r(m, "ISODD", null); | |||
r(m, "ISEVEN", ParityFunction.IS_EVEN); | |||
r(m, "ISODD", ParityFunction.IS_ODD); | |||
r(m, "LCM", null); | |||
r(m, "MDURATION", null); | |||
r(m, "MROUND", null); |
@@ -0,0 +1,74 @@ | |||
/* ==================================================================== | |||
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.hssf.record.formula.atp; | |||
import org.apache.poi.hssf.record.formula.eval.BlankEval; | |||
import org.apache.poi.hssf.record.formula.eval.BoolEval; | |||
import org.apache.poi.hssf.record.formula.eval.ErrorEval; | |||
import org.apache.poi.hssf.record.formula.eval.Eval; | |||
import org.apache.poi.hssf.record.formula.eval.EvaluationException; | |||
import org.apache.poi.hssf.record.formula.eval.OperandResolver; | |||
import org.apache.poi.hssf.record.formula.eval.ValueEval; | |||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; | |||
import org.apache.poi.hssf.usermodel.HSSFSheet; | |||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||
/** | |||
* Implementation of Excel 'Analysis ToolPak' function ISEVEN() ISODD()<br/> | |||
* | |||
* @author Josh Micich | |||
*/ | |||
final class ParityFunction implements FreeRefFunction { | |||
public static final FreeRefFunction IS_EVEN = new ParityFunction(0); | |||
public static final FreeRefFunction IS_ODD = new ParityFunction(1); | |||
private final int _desiredParity; | |||
private ParityFunction(int desiredParity) { | |||
_desiredParity = desiredParity; | |||
} | |||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, | |||
HSSFSheet sheet) { | |||
if (args.length != 1) { | |||
return ErrorEval.VALUE_INVALID; | |||
} | |||
int val; | |||
try { | |||
val = evaluateArgParity(args[0], srcCellRow, srcCellCol); | |||
} catch (EvaluationException e) { | |||
return e.getErrorEval(); | |||
} | |||
return BoolEval.valueOf(val == _desiredParity); | |||
} | |||
private static int evaluateArgParity(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { | |||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); | |||
if (ve == BlankEval.INSTANCE) { | |||
return 0; | |||
} | |||
double d = OperandResolver.coerceValueToDouble(ve); | |||
if (d < 0) { | |||
d = -d; | |||
} | |||
long v = (long) Math.floor(d); | |||
return (int) (v & 0x0001); | |||
} | |||
} |
@@ -21,6 +21,7 @@ import java.util.Calendar; | |||
import java.util.GregorianCalendar; | |||
import java.util.regex.Pattern; | |||
import org.apache.poi.hssf.record.formula.eval.BlankEval; | |||
import org.apache.poi.hssf.record.formula.eval.ErrorEval; | |||
import org.apache.poi.hssf.record.formula.eval.Eval; | |||
import org.apache.poi.hssf.record.formula.eval.EvaluationException; | |||
@@ -96,6 +97,9 @@ final class YearFrac implements FreeRefFunction { | |||
Calendar date = parseDate(strVal); | |||
return HSSFDateUtil.getExcelDate(date, false); | |||
} | |||
if (ve instanceof BlankEval) { | |||
return 0.0; | |||
} | |||
return OperandResolver.coerceValueToDouble(ve); | |||
} | |||
@@ -120,7 +124,7 @@ final class YearFrac implements FreeRefFunction { | |||
} catch (NumberFormatException e) { | |||
throw new EvaluationException(ErrorEval.VALUE_INVALID); | |||
} | |||
if (f0<0 || f1<0 || f2<0 || f0>12 || f1>12 || f2>12) { | |||
if (f0<0 || f1<0 || f2<0 || (f0>12 && f1>12 && f2>12)) { | |||
// easy to see this cannot be a valid date | |||
throw new EvaluationException(ErrorEval.VALUE_INVALID); | |||
} | |||
@@ -150,6 +154,7 @@ final class YearFrac implements FreeRefFunction { | |||
if (day <1 || day>cal.getActualMaximum(Calendar.DAY_OF_MONTH)) { | |||
throw new EvaluationException(ErrorEval.VALUE_INVALID); | |||
} | |||
cal.set(Calendar.DAY_OF_MONTH, day); | |||
return cal; | |||
} | |||
@@ -74,9 +74,18 @@ public final class TestExternalFunctionFormulas extends TestCase { | |||
public void testEvaluate() { | |||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls"); | |||
HSSFSheet sheet = wb.getSheetAt(0); | |||
HSSFCell cell = sheet.getRow(0).getCell(0); | |||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb); | |||
CellValue evalResult = fe.evaluate(cell); | |||
evalResult.toString(); | |||
confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.0); | |||
confirmCellEval(sheet, 1, 0, fe, "YEARFRAC(B2,C2)", 0.0); | |||
confirmCellEval(sheet, 2, 0, fe, "IF(ISEVEN(3),1.2,1.6)", 1.6); | |||
confirmCellEval(sheet, 3, 0, fe, "IF(ISODD(3),1.2,1.6)", 1.2); | |||
} | |||
private static void confirmCellEval(HSSFSheet sheet, int rowIx, int colIx, | |||
HSSFFormulaEvaluator fe, String expectedFormula, double expectedResult) { | |||
HSSFCell cell = sheet.getRow(rowIx).getCell(colIx); | |||
assertEquals(expectedFormula, cell.getCellFormula()); | |||
CellValue cv = fe.evaluate(cell); | |||
assertEquals(expectedResult, cv.getNumberValue(), 0.0); | |||
} | |||
} |
@@ -38,6 +38,7 @@ public final class TestYearFracCalculator extends TestCase { | |||
confirm(md(1999, 3, 31), md(1999, 4, 3), 1, 0.008219178); | |||
confirm(md(1999, 4, 5), md(1999, 4, 8), 1, 0.008219178); | |||
confirm(md(1999, 4, 4), md(1999, 4, 7), 1, 0.008219178); | |||
confirm(md(2000, 2, 5), md(2000, 6, 1), 0, 0.322222222); | |||
} | |||
private void confirm(double startDate, double endDate, int basis, double expectedValue) { |