我正在使用Apache POI 3.9,我需要使用Excel公式PERCENTILE并从Java中评估公式。
问题是不支持PERCENTILE。
我收到org.apache.poi.ss.formula.eval.NotImplementedException:
错误
我有3个可能解决问题的方法。
在java中编写我自己的百分位函数并将其贡献给Apache POI库(参见http://poi.apache.org/spreadsheet/eval-devguide.html)
将Excel工作表中的相关单元格转换为java并使用Percentile calculation
将PERCENTILE转换为SMALL函数
比如=PERCENTILE(A1:A10,95%)
而不是=(SMALL(A1:A10,9)+SMALL(A1:A10,10))/2
然后{{1}}
此时我需要一个快速的解决方案。对我来说,第三个是最好的,但它没有给出完全相同的结果。
在我回到选项2之前有没有人有任何想法,这有点乱?
答案 0 :(得分:1)
感谢Gagravarr的鼓励,也感谢你的帖子Apache POI - How to register a function非常有帮助
我通过以下方式在库中实现了PERCENTILE函数:
retval[328] = AggregateFunction.PERCENTILE;
到文件org.apache.poi.ss.formula.eval.FunctionEval.java public static final Function PERCENTILE = new Percentile();
到适当位置的文件org.apache.poi.ss.formula.functions.AggregateFunction.java。我在同一个文件中添加了以下代码(我基于LargeSmall函数;我已经查找了与我想要的函数最相似的现有代码/函数类型)
private static final class Percentile extends Fixed2ArgFunction {
protected Percentile() {
}
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
ValueEval arg1) {
double dn;
try {
ValueEval ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
dn = OperandResolver.coerceValueToDouble(ve1);
} catch (EvaluationException e1) {
// all errors in the second arg translate to #VALUE!
return ErrorEval.VALUE_INVALID;
}
if (dn < 0 || dn > 1) { // has to be percentage
return ErrorEval.NUM_ERROR;
}
double result;
try {
double[] ds = ValueCollector.collectValues(arg0);
int N = ds.length;
double n = (N - 1) * dn + 1;
if (n == 1d) {
result = StatsLib.kthSmallest(ds, 1);
} else if (n == N) {
result = StatsLib.kthLargest(ds, 1);
} else {
int k = (int) n;
double d = n - k;
result = StatsLib.kthSmallest(ds, k) + d
* (StatsLib.kthSmallest(ds, k + 1) - StatsLib.kthSmallest(ds, k));
}
NumericFunction.checkValue(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
return new NumberEval(result);
}
}
然后我分别上传了这两个文件,然后可以正常使用PERCENTILE功能。