Bugzilla 48036 - added IntersectionEval to allow evaluation of the intersection formula operator.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@828244 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-10-21 23:00:09 +00:00
parent 47086ce5bd
commit c856343fc0
5 changed files with 135 additions and 30 deletions

View File

@ -33,6 +33,7 @@
<changes>
<release version="3.6-beta1" date="2009-??-??">
<action dev="POI-DEVELOPERS" type="fix">48036 - added IntersectionEval to allow evaluation of the intersection formula operator</action>
<action dev="POI-DEVELOPERS" type="fix">47999 - avoid un-needed call to the JVM Garbage Collector when working on OOXML OPC Packages</action>
<action dev="POI-DEVELOPERS" type="add">47922 - added example HSMF application that converts a .msg file to text and extracts attachments</action>
<action dev="POI-DEVELOPERS" type="add">47903 - added Ant target to compile scratchpad examples</action>

View File

@ -0,0 +1,98 @@
/* ====================================================================
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.eval;
import org.apache.poi.hssf.record.formula.functions.Function;
/**
* @author Josh Micich
*/
public final class IntersectionEval implements Function {
public static final Function instance = new IntersectionEval();
private IntersectionEval() {
// enforces singleton
}
public ValueEval evaluate(ValueEval[] args, int srcRow, short srcCol) {
if(args.length != 2) {
return ErrorEval.VALUE_INVALID;
}
try {
AreaEval reA = evaluateRef(args[0]);
AreaEval reB = evaluateRef(args[1]);
AreaEval result = resolveRange(reA, reB);
if (result == null) {
return ErrorEval.NULL_INTERSECTION;
}
return result;
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
/**
* @return simple rectangular {@link AreaEval} which represents the intersection of areas
* <tt>aeA</tt> and <tt>aeB</tt>. If the two areas do not intersect, the result is <code>null</code>.
*/
private static AreaEval resolveRange(AreaEval aeA, AreaEval aeB) {
int aeAfr = aeA.getFirstRow();
int aeAfc = aeA.getFirstColumn();
int aeBlc = aeB.getLastColumn();
if (aeAfc > aeBlc) {
return null;
}
int aeBfc = aeB.getFirstColumn();
if (aeBfc > aeA.getLastColumn()) {
return null;
}
int aeBlr = aeB.getLastRow();
if (aeAfr > aeBlr) {
return null;
}
int aeBfr = aeB.getFirstRow();
int aeAlr = aeA.getLastRow();
if (aeBfr > aeAlr) {
return null;
}
int top = Math.max(aeAfr, aeBfr);
int bottom = Math.min(aeAlr, aeBlr);
int left = Math.max(aeAfc, aeBfc);
int right = Math.min(aeA.getLastColumn(), aeBlc);
return aeA.offset(top-aeAfr, bottom-aeAfr, left-aeAfc, right-aeAfc);
}
private static AreaEval evaluateRef(ValueEval arg) throws EvaluationException {
if (arg instanceof AreaEval) {
return (AreaEval) arg;
}
if (arg instanceof RefEval) {
return ((RefEval) arg).offset(0, 0, 0, 0);
}
if (arg instanceof ErrorEval) {
throw new EvaluationException((ErrorEval)arg);
}
throw new IllegalArgumentException("Unexpected ref arg class (" + arg.getClass().getName() + ")");
}
}

View File

@ -29,6 +29,7 @@ import org.apache.poi.hssf.record.formula.DividePtg;
import org.apache.poi.hssf.record.formula.EqualPtg;
import org.apache.poi.hssf.record.formula.GreaterEqualPtg;
import org.apache.poi.hssf.record.formula.GreaterThanPtg;
import org.apache.poi.hssf.record.formula.IntersectionPtg;
import org.apache.poi.hssf.record.formula.LessEqualPtg;
import org.apache.poi.hssf.record.formula.LessThanPtg;
import org.apache.poi.hssf.record.formula.MultiplyPtg;
@ -42,6 +43,7 @@ import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
import org.apache.poi.hssf.record.formula.eval.ConcatEval;
import org.apache.poi.hssf.record.formula.eval.FunctionEval;
import org.apache.poi.hssf.record.formula.eval.IntersectionEval;
import org.apache.poi.hssf.record.formula.eval.OperationEval;
import org.apache.poi.hssf.record.formula.eval.PercentEval;
import org.apache.poi.hssf.record.formula.eval.RangeEval;
@ -86,6 +88,7 @@ final class OperationEvaluatorFactory {
put(m, 1, UnaryMinusPtg.instance, UnaryMinusEval.instance);
put(m, 1, UnaryPlusPtg.instance, UnaryPlusEval.instance);
put(m, 2, RangePtg.instance, RangeEval.instance);
put(m, 2, IntersectionPtg.instance, IntersectionEval.instance);
return m;
}

View File

@ -33,6 +33,7 @@ import org.apache.poi.hssf.record.formula.ErrPtg;
import org.apache.poi.hssf.record.formula.ExpPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.IntPtg;
import org.apache.poi.hssf.record.formula.MemAreaPtg;
import org.apache.poi.hssf.record.formula.MemErrPtg;
import org.apache.poi.hssf.record.formula.MemFuncPtg;
import org.apache.poi.hssf.record.formula.MissingArgPtg;
@ -348,11 +349,13 @@ public final class WorkbookEvaluator {
// skip Parentheses, Attr, etc
continue;
}
if (ptg instanceof MemFuncPtg) {
if (ptg instanceof MemFuncPtg || ptg instanceof MemAreaPtg) {
// can ignore, rest of tokens for this expression are in OK RPN order
continue;
}
if (ptg instanceof MemErrPtg) { continue; }
if (ptg instanceof MemErrPtg) {
continue;
}
ValueEval opResult;
if (ptg instanceof OperationPtg) {

View File

@ -66,7 +66,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
/**
* Row (zero-based) in the test spreadsheet where the function examples start.
*/
public static final int START_FUNCTIONS_ROW_INDEX = 87; // Row '88'
public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/**
* Index of the column that contains the function names
*/