View | Details | Raw Unified | Return to bug 58341
Collapse All | Expand All

(-)a/src/java/org/apache/poi/ss/formula/functions/DStarRunner.java (-45 / +97 lines)
Lines 24-29 import org.apache.poi.ss.formula.eval.EvaluationException; Link Here
24
import org.apache.poi.ss.formula.eval.NotImplementedException;
24
import org.apache.poi.ss.formula.eval.NotImplementedException;
25
import org.apache.poi.ss.formula.eval.NumericValueEval;
25
import org.apache.poi.ss.formula.eval.NumericValueEval;
26
import org.apache.poi.ss.formula.eval.RefEval;
26
import org.apache.poi.ss.formula.eval.RefEval;
27
import org.apache.poi.ss.formula.eval.StringEval;
27
import org.apache.poi.ss.formula.eval.StringValueEval;
28
import org.apache.poi.ss.formula.eval.StringValueEval;
28
import org.apache.poi.ss.formula.eval.ValueEval;
29
import org.apache.poi.ss.formula.eval.ValueEval;
29
import org.apache.poi.ss.util.NumberComparer;
30
import org.apache.poi.ss.util.NumberComparer;
Lines 234-256 public final class DStarRunner implements Function3Arg { Link Here
234
                targetHeader = solveReference(targetHeader);
235
                targetHeader = solveReference(targetHeader);
235
236
236
237
237
                if(!(targetHeader instanceof StringValueEval))
238
                if(!(targetHeader instanceof StringValueEval)) {
238
                    columnCondition = false;
239
                    throw new EvaluationException(ErrorEval.VALUE_INVALID);
239
                else if (getColumnForName(targetHeader, db) == -1)
240
                }
241
                
242
                if (getColumnForName(targetHeader, db) == -1)
240
                    // No column found, it's again a special column that accepts formulas.
243
                    // No column found, it's again a special column that accepts formulas.
241
                    columnCondition = false;
244
                    columnCondition = false;
242
245
243
                if(columnCondition == true) { // normal column condition
246
                if(columnCondition == true) { // normal column condition
244
                    // Should not throw, checked above.
247
                    // Should not throw, checked above.
245
                    ValueEval target = db.getValue(
248
                    ValueEval value = db.getValue(
246
                            row, getColumnForName(targetHeader, db));
249
                            row, getColumnForName(targetHeader, db));
247
                    // Must be a string.
250
                    if(!testNormalCondition(value, condition)) {
248
                    String conditionString = getStringFromValueEval(condition);
249
                    if(!testNormalCondition(target, conditionString)) {
250
                        matches = false;
251
                        matches = false;
251
                        break;
252
                        break;
252
                    }
253
                    }
253
                } else { // It's a special formula condition.
254
                } else { // It's a special formula condition.
255
                    if(getStringFromValueEval(condition).isEmpty()) {
256
                        throw new EvaluationException(ErrorEval.VALUE_INVALID);
257
                    }
254
                    throw new NotImplementedException(
258
                    throw new NotImplementedException(
255
                            "D* function with formula conditions");
259
                            "D* function with formula conditions");
256
                }
260
                }
Lines 270-319 public final class DStarRunner implements Function3Arg { Link Here
270
     * @return Whether the condition holds.
274
     * @return Whether the condition holds.
271
     * @throws EvaluationException If comparison operator and operands don't match.
275
     * @throws EvaluationException If comparison operator and operands don't match.
272
     */
276
     */
273
    private static boolean testNormalCondition(ValueEval value, String condition)
277
    private static boolean testNormalCondition(ValueEval value, ValueEval condition)
274
            throws EvaluationException {
278
            throws EvaluationException {
275
        if(condition.startsWith("<")) { // It's a </<= condition.
279
        if(condition instanceof StringEval) {
276
            String number = condition.substring(1);
280
            String conditionString = ((StringEval)condition).getStringValue();
277
            if(number.startsWith("=")) {
281
        
278
                number = number.substring(1);
282
            if(conditionString.startsWith("<")) { // It's a </<= condition.
279
                return testNumericCondition(value, operator.smallerEqualThan, number);
283
                String number = conditionString.substring(1);
280
            } else {
284
                if(number.startsWith("=")) {
281
                return testNumericCondition(value, operator.smallerThan, number);
285
                    number = number.substring(1);
286
                    return testNumericCondition(value, operator.smallerEqualThan, number);
287
                } else {
288
                    return testNumericCondition(value, operator.smallerThan, number);
289
                }
282
            }
290
            }
283
        }
291
            else if(conditionString.startsWith(">")) { // It's a >/>= condition.
284
        else if(condition.startsWith(">")) { // It's a >/>= condition.
292
                String number = conditionString.substring(1);
285
            String number = condition.substring(1);
293
                if(number.startsWith("=")) {
286
            if(number.startsWith("=")) {
294
                    number = number.substring(1);
287
                number = number.substring(1);
295
                    return testNumericCondition(value, operator.largerEqualThan, number);
288
                return testNumericCondition(value, operator.largerEqualThan, number);
296
                } else {
289
            } else {
297
                    return testNumericCondition(value, operator.largerThan, number);
290
                return testNumericCondition(value, operator.largerThan, number);
298
                }
291
            }
299
            }
292
        }
300
            else if(conditionString.startsWith("=")) { // It's a = condition.
293
        else if(condition.startsWith("=")) { // It's a = condition.
301
                String stringOrNumber = conditionString.substring(1);
294
            String stringOrNumber = condition.substring(1);
302
295
            // Distinguish between string and number.
303
                if(stringOrNumber.isEmpty()) {
296
            boolean itsANumber = false;
304
                    return value instanceof BlankEval;
297
            try {
305
                }
298
                Integer.parseInt(stringOrNumber);
306
                // Distinguish between string and number.
299
                itsANumber = true;
307
                boolean itsANumber = false;
300
            } catch (NumberFormatException e) { // It's not an int.
301
                try {
308
                try {
302
                    Double.parseDouble(stringOrNumber);
309
                    Integer.parseInt(stringOrNumber);
303
                    itsANumber = true;
310
                    itsANumber = true;
304
                } catch (NumberFormatException e2) { // It's a string.
311
                } catch (NumberFormatException e) { // It's not an int.
305
                    itsANumber = false;
312
                    try {
313
                        Double.parseDouble(stringOrNumber);
314
                        itsANumber = true;
315
                    } catch (NumberFormatException e2) { // It's a string.
316
                        itsANumber = false;
317
                    }
318
                }
319
                if(itsANumber) {
320
                    return testNumericCondition(value, operator.equal, stringOrNumber);
321
                } else { // It's a string.
322
                    String valueString = value instanceof BlankEval ? "" : getStringFromValueEval(value);
323
                    return stringOrNumber.equals(valueString);
324
                }
325
            } else { // It's a text starts-with condition.
326
                if(conditionString.isEmpty()) {
327
                    return value instanceof StringEval;
328
                }
329
                else {
330
                    String valueString = value instanceof BlankEval ? "" : getStringFromValueEval(value);
331
                    return valueString.startsWith(conditionString);
306
                }
332
                }
307
            }
333
            }
308
            if(itsANumber) {
334
        }
309
                return testNumericCondition(value, operator.equal, stringOrNumber);
335
        else if(condition instanceof NumericValueEval) {
310
            } else { // It's a string.
336
            double conditionNumber = ((NumericValueEval)condition).getNumberValue();
311
                String valueString = getStringFromValueEval(value);
337
            Double valueNumber = getNumerFromValueEval(value);
312
                return stringOrNumber.equals(valueString);
338
            if(valueNumber == null) {
339
                return false;
340
            }
341
            
342
            return conditionNumber == valueNumber;
343
        }
344
        else if(condition instanceof ErrorEval) {
345
            if(value instanceof ErrorEval) {
346
                return ((ErrorEval)condition).getErrorCode() == ((ErrorEval)value).getErrorCode();
347
            }
348
            else {
349
                return false;
313
            }
350
            }
314
        } else { // It's a text starts-with condition.
351
        }
315
            String valueString = getStringFromValueEval(value);
352
        else {
316
            return valueString.startsWith(condition);
353
            return false;
317
        }
354
        }
318
    }
355
    }
319
356
Lines 361-366 public final class DStarRunner implements Function3Arg { Link Here
361
        }
398
        }
362
        return false; // Can not be reached.
399
        return false; // Can not be reached.
363
    }
400
    }
401
    
402
    private static Double getNumerFromValueEval(ValueEval value) {
403
        if(value instanceof NumericValueEval) {
404
            return ((NumericValueEval)value).getNumberValue();
405
        }
406
        else if(value instanceof StringValueEval) {
407
            String stringValue = ((StringValueEval)value).getStringValue();
408
            try {
409
                return Double.parseDouble(stringValue);
410
            } catch (NumberFormatException e2) {
411
                return null;
412
            }
413
        }
414
        else {
415
            return null;
416
        }
417
    }
364
418
365
    /**
419
    /**
366
     * Takes a ValueEval and tries to retrieve a String value from it.
420
     * Takes a ValueEval and tries to retrieve a String value from it.
Lines 373-380 public final class DStarRunner implements Function3Arg { Link Here
373
    private static String getStringFromValueEval(ValueEval value)
427
    private static String getStringFromValueEval(ValueEval value)
374
            throws EvaluationException {
428
            throws EvaluationException {
375
        value = solveReference(value);
429
        value = solveReference(value);
376
        if(value instanceof BlankEval)
377
            return "";
378
        if(!(value instanceof StringValueEval))
430
        if(!(value instanceof StringValueEval))
379
            throw new EvaluationException(ErrorEval.VALUE_INVALID);
431
            throw new EvaluationException(ErrorEval.VALUE_INVALID);
380
        return ((StringValueEval)value).getStringValue();
432
        return ((StringValueEval)value).getStringValue();

Return to bug 58341