From: Cédric Walter Date: Fri, 11 Oct 2013 18:49:19 +0000 (+0000) Subject: Bug 55116: patch for missing function Dec2Bin X-Git-Tag: REL_3_10_FINAL~98 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f7f52a98e50b20337028f09109c60c2167cd6db7;p=poi.git Bug 55116: patch for missing function Dec2Bin git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1531390 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java index 9139c2e1bb..bf9f8b743b 100644 --- a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java +++ b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java @@ -88,7 +88,7 @@ public final class AnalysisToolPak implements UDFFinder { r(m, "CUBEVALUE", null); r(m, "CUMIPMT", null); r(m, "CUMPRINC", null); - r(m, "DEC2BIN", null); + r(m, "DEC2BIN", Dec2Bin.instance); r(m, "DEC2HEX", null); r(m, "DEC2OCT", null); r(m, "DELTA", Delta.instance); diff --git a/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java b/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java new file mode 100644 index 0000000000..a275c103a3 --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java @@ -0,0 +1,111 @@ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +/** + * Implementation for Excel Bin2Dec() function.

+ *

+ * Syntax:
Bin2Dec (number,[places] )
+ *

+ * Converts a decimal number to binary. + *

+ * The DEC2BIN function syntax has the following arguments: + *

+ *

+ * Remarks + *

+ * + * @author cedric dot walter @ gmail dot com + */ +public class Dec2Bin extends Var1or2ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Dec2Bin(); + + private final static long MIN_VALUE = Long.parseLong("-512"); + private final static long MAX_VALUE = Long.parseLong("512"); + private final static int DEFAULT_PLACES_VALUE = 10; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval placesVE) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String strText1 = OperandResolver.coerceValueToString(veText1); + Double number = OperandResolver.parseDouble(strText1); + + //If this number argument is non numeric, this function returns the #VALUE! error value. + if (number == null) { + return ErrorEval.VALUE_INVALID; + } + + //If number < -512 or if number > 512, this function returns the #NUM! error value. + if (number.longValue() < MIN_VALUE || number.longValue() > MAX_VALUE) { + return ErrorEval.NUM_ERROR; + } + + int placesNumber; + if (number < 0 || placesVE == null) { + placesNumber = DEFAULT_PLACES_VALUE; + } else { + ValueEval placesValueEval; + try { + placesValueEval = OperandResolver.getSingleValue(placesVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String placesStr = OperandResolver.coerceValueToString(placesValueEval); + Double placesNumberDouble = OperandResolver.parseDouble(placesStr); + + //non numeric value + if (placesNumberDouble == null) { + return ErrorEval.VALUE_INVALID; + } + + //If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. + placesNumber = placesNumberDouble.intValue(); + + if (placesNumber < 0 || placesNumber == 0) { + return ErrorEval.NUM_ERROR; + } + } + String binary = Integer.toBinaryString(number.intValue()); + + if (binary.length() > DEFAULT_PLACES_VALUE) { + binary = binary.substring(binary.length() - DEFAULT_PLACES_VALUE, binary.length()); + } + //If DEC2BIN requires more than places characters, it returns the #NUM! error value. + if (binary.length() > placesNumber) { + return ErrorEval.NUM_ERROR; + } + + return new StringEval(binary); + } + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + return this.evaluate(srcRowIndex, srcColumnIndex, numberVE, null); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 1) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + + return ErrorEval.VALUE_INVALID; + } +} diff --git a/test-data/spreadsheet/FormulaEvalTestData.xls b/test-data/spreadsheet/FormulaEvalTestData.xls index 3b3f724b70..f7de0a1d77 100644 Binary files a/test-data/spreadsheet/FormulaEvalTestData.xls and b/test-data/spreadsheet/FormulaEvalTestData.xls differ