/* ==================================================================== | |
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 java.util.Locale; | |
import org.apache.poi.ss.formula.OperationEvaluationContext; | |
import org.apache.poi.ss.formula.eval.ErrorEval; | |
import org.apache.poi.ss.formula.eval.EvaluationException; | |
import org.apache.poi.ss.formula.eval.OperandResolver; | |
import org.apache.poi.ss.formula.eval.StringEval; | |
import org.apache.poi.ss.formula.eval.ValueEval; | |
/** | |
* Implementation for Excel COMPLEX () function.<p/> | |
* <p/> | |
* <b>Syntax</b>:<br/> <b>COMPLEX </b>(<b>real_num</b>,<b>i_num</b>,<b>suffix </b> )<br/> | |
* <p/> | |
* Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj. | |
* <p/> | |
* <p/> | |
* All complex number functions accept "i" and "j" for suffix, but neither "I" nor "J". | |
* Using uppercase results in the #VALUE! error value. All functions that accept two | |
* or more complex numbers require that all suffixes match. | |
* <p/> | |
* <b>real_num</b> The real coefficient of the complex number. | |
* If this argument is nonnumeric, this function returns the #VALUE! error value. | |
* <p/> | |
* <p/> | |
* <b>i_num</b> The imaginary coefficient of the complex number. | |
* If this argument is nonnumeric, this function returns the #VALUE! error value. | |
* <p/> | |
* <p/> | |
* <b>suffix</b> The suffix for the imaginary component of the complex number. | |
* <ul> | |
* <li>If omitted, suffix is assumed to be "i".</li> | |
* <li>If suffix is neither "i" nor "j", COMPLEX returns the #VALUE! error value.</li> | |
* </ul> | |
* | |
* @author cedric dot walter @ gmail dot com | |
*/ | |
public class Complex extends Var2or3ArgFunction implements FreeRefFunction { | |
public static final FreeRefFunction instance = new Complex(); | |
public static final String DEFAULT_SUFFIX = "i"; | |
public static final String SUPPORTED_SUFFIX = "j"; | |
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num) { | |
return this.evaluate(srcRowIndex, srcColumnIndex, real_num, i_num, new StringEval(DEFAULT_SUFFIX)); | |
} | |
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num, ValueEval suffix) { | |
ValueEval veText1; | |
try { | |
veText1 = OperandResolver.getSingleValue(real_num, srcRowIndex, srcColumnIndex); | |
} catch (EvaluationException e) { | |
return e.getErrorEval(); | |
} | |
double realNum = 0; | |
try { | |
realNum = OperandResolver.coerceValueToDouble(veText1); | |
} catch (EvaluationException e) { | |
return ErrorEval.VALUE_INVALID; | |
} | |
ValueEval veINum; | |
try { | |
veINum = OperandResolver.getSingleValue(i_num, srcRowIndex, srcColumnIndex); | |
} catch (EvaluationException e) { | |
return e.getErrorEval(); | |
} | |
double realINum = 0; | |
try { | |
realINum = OperandResolver.coerceValueToDouble(veINum); | |
} catch (EvaluationException e) { | |
return ErrorEval.VALUE_INVALID; | |
} | |
String suffixValue = OperandResolver.coerceValueToString(suffix); | |
if (suffixValue.length() == 0) { | |
suffixValue = DEFAULT_SUFFIX; | |
} | |
if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase(Locale.ROOT)) || | |
suffixValue.equals(SUPPORTED_SUFFIX.toUpperCase(Locale.ROOT))) { | |
return ErrorEval.VALUE_INVALID; | |
} | |
if (!(suffixValue.equals(DEFAULT_SUFFIX) || suffixValue.equals(SUPPORTED_SUFFIX))) { | |
return ErrorEval.VALUE_INVALID; | |
} | |
StringBuffer strb = new StringBuffer(""); | |
if (realNum != 0) { | |
if (isDoubleAnInt(realNum)) { | |
strb.append((int)realNum); | |
} else { | |
strb.append(realNum); | |
} | |
} | |
if (realINum != 0) { | |
if (strb.length() != 0) { | |
if (realINum > 0) { | |
strb.append("+"); | |
} | |
} | |
if (realINum != 1 && realINum != -1) { | |
if (isDoubleAnInt(realINum)) { | |
strb.append((int)realINum); | |
} else { | |
strb.append(realINum); | |
} | |
} | |
strb.append(suffixValue); | |
} | |
return new StringEval(strb.toString()); | |
} | |
private boolean isDoubleAnInt(double number) { | |
return (number == Math.floor(number)) && !Double.isInfinite(number); | |
} | |
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { | |
if (args.length == 2) { | |
return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); | |
} | |
if (args.length == 3) { | |
return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1], args[2]); | |
} | |
return ErrorEval.VALUE_INVALID; | |
} | |
} |