From ce4501452f16c19fd79c813305b87953ce79e698 Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Walter?= Date: Fri, 16 Aug 2013 18:28:18 +0000 Subject: [PATCH] Bug 55082: patch for missing function ROMAN git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1514834 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/formula/eval/FunctionEval.java | 2 + .../poi/ss/formula/functions/Roman.java | 148 ++++++++++++++++++ .../TestRomanFunctionsFromSpreadsheet.java | 30 ++++ .../spreadsheet/RomanFunctionTestCaseData.xls | Bin 0 -> 38912 bytes 4 files changed, 180 insertions(+) create mode 100644 src/java/org/apache/poi/ss/formula/functions/Roman.java create mode 100644 src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java create mode 100644 test-data/spreadsheet/RomanFunctionTestCaseData.xls diff --git a/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java b/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java index d66e878c92..9be8a72fb2 100644 --- a/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java +++ b/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java @@ -236,6 +236,8 @@ public final class FunctionEval { retval[346] = new Countif(); retval[347] = new Countblank(); + retval[354] = new Roman(); + retval[359] = new Hyperlink(); retval[362] = MinaMaxa.MAXA; diff --git a/src/java/org/apache/poi/ss/formula/functions/Roman.java b/src/java/org/apache/poi/ss/formula/functions/Roman.java new file mode 100644 index 0000000000..d1abd9acc4 --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/functions/Roman.java @@ -0,0 +1,148 @@ +/* ==================================================================== + 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 org.apache.poi.ss.formula.eval.*; + +/** + * Implementation for Excel WeekNum() function.

+ *

+ * Syntax:
WeekNum (Serial_num,Return_type)
+ *

+ * Returns a number that indicates where the week falls numerically within a year. + *

+ *

+ * Serial_num is a date within the week. Dates should be entered by using the DATE function, + * or as results of other formulas or functions. For example, use DATE(2008,5,23) + * for the 23rd day of May, 2008. Problems can occur if dates are entered as text. + * Return_type is a number that determines on which day the week begins. The default is 1. + * 1 Week begins on Sunday. Weekdays are numbered 1 through 7. + * 2 Week begins on Monday. Weekdays are numbered 1 through 7. + * + * @author cedric dot walter @ gmail dot com + */ +public class Roman extends Fixed2ArgFunction { + + //M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) and I (1). + public static final int[] VALUES = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + public static final String[] ROMAN = new String[] + {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval formVE) { + int number = 0; + try { + ValueEval ve = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); + number = OperandResolver.coerceValueToInt(ve); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + if (number < 0) { + return ErrorEval.VALUE_INVALID; + } + if (number > 3999) { + return ErrorEval.VALUE_INVALID; + } + if (number == 0) { + return new StringEval(""); + } + + int form = 0; + try { + ValueEval ve = OperandResolver.getSingleValue(formVE, srcRowIndex, srcColumnIndex); + form = OperandResolver.coerceValueToInt(ve); + } catch (EvaluationException e) { + return ErrorEval.NUM_ERROR; + } + + if (form > 4 || form < 0) { + return ErrorEval.VALUE_INVALID; + } + + String result = this.integerToRoman(number); + + if (form == 0) { + return new StringEval(result); + } + + return new StringEval(makeConcise(result, form)); + } + + /** + * Classic conversion. + * + * @param number + * @return + */ + private String integerToRoman(int number) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < 13; i++) { + while (number >= VALUES[i]) { + number -= VALUES[i]; + result.append(ROMAN[i]); + } + } + return result.toString(); + } + + /** + * Use conversion rule to factor some parts and make them more concise + * + * @param result + * @param form + * @return + */ + public String makeConcise(String result, int form) { + if (form > 0) { + result = result.replaceAll("XLV", "VL"); //45 + result = result.replaceAll("XCV", "VC"); //95 + result = result.replaceAll("CDL", "LD"); //450 + result = result.replaceAll("CML", "LM"); //950 + result = result.replaceAll("CMVC", "LMVL"); //995 + } + if (form == 1) { + result = result.replaceAll("CDXC", "LDXL"); //490 + result = result.replaceAll("CDVC", "LDVL"); //495 + result = result.replaceAll("CMXC", "LMXL"); //990 + result = result.replaceAll("XCIX", "VCIV"); //99 + result = result.replaceAll("XLIX", "VLIV"); //49 + } + if (form > 1) { + result = result.replaceAll("XLIX", "IL"); //49 + result = result.replaceAll("XCIX", "IC"); //99 + result = result.replaceAll("CDXC", "XD"); //490 + result = result.replaceAll("CDVC", "XDV"); //495 + result = result.replaceAll("CDIC", "XDIX"); //499 + result = result.replaceAll("LMVL", "XMV"); //995 + result = result.replaceAll("CMIC", "XMIX"); //999 + result = result.replaceAll("CMXC", "XM"); // 990 + } + if (form > 2) { + result = result.replaceAll("XDV", "VD"); //495 + result = result.replaceAll("XDIX", "VDIV"); //499 + result = result.replaceAll("XMV", "VM"); // 995 + result = result.replaceAll("XMIX", "VMIV"); //999 + } + if (form == 4) { + result = result.replaceAll("VDIV", "ID"); //499 + result = result.replaceAll("VMIV", "IM"); //999 + } + + return result; + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java new file mode 100644 index 0000000000..a17b9f8974 --- /dev/null +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java @@ -0,0 +1,30 @@ +/* ==================================================================== + 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; + +/** + * Tests Roman() as loaded from a test data spreadsheet.

+ * + * @author cedric dot walter @ gmail dot com + */ +public class TestRomanFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + + protected String getFilename() { + return "RomanFunctionTestCaseData.xls"; + } +} diff --git a/test-data/spreadsheet/RomanFunctionTestCaseData.xls b/test-data/spreadsheet/RomanFunctionTestCaseData.xls new file mode 100644 index 0000000000000000000000000000000000000000..f630275f7312053e3d2c1ff348e25c1af8d4d68c GIT binary patch literal 38912 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 bZzb@$D1HQtGN@mMotivbe~0=vTloJkEzoz{ literal 0 HcmV?d00001 -- 2.39.5