在Apache POI中使用Excel PERCENTILE函数
我使用的是Apache POI 3.9,我需要使用Excel公式PERCENTILE,并从Java中评估公式。
问题是不支持PERCENTILE。
我得到一个org.apache.poi.ss.formula.eval.NotImplementedException:
错误
我有3个可能的解决scheme,我的问题。
-
在java中编写我自己的percentile函数,并将其贡献给Apache POI库(请参阅http://poi.apache.org/spreadsheet/eval-devguide.html )
-
从Excel表单中的相关单元格转换为Java,并使用一个函数(如百分比计算中的函数)来计算它们
-
将PERCENTILE转换为小函数,例如
=PERCENTILE(A1:A10,95%)
然后=(SMALL(A1:A10,9)+SMALL(A1:A10,10))/2
在这个时候,我需要一个快速的解决scheme。 对我来说,第三个将是最好的,但是并没有给出完全相同的结果。
有没有人有任何想法之前,备选案文2备份有点杂乱?
谢谢Gagravarr为你的鼓励,也为你的后期Apache POI – 如何注册一个非常有用的function
我以如下方式在库中实现了PERCENTILE函数:
- 我下载了Apache POI 3.9的源代码
- 我检查了src / resources / main / org / apache / poi / ss / formula / function / functionMetadata.txt( 或联机 )中的PERCENTILE函数的ID号码,结果是328
- 我因此增加了
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函数;我查找了与我想要做的最相似的函数的现有代码/types)
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); }
}
-
然后,我分别上传这两个文件,然后可以正常使用PERCENTILEfunction。