Index: poi/src/java/org/apache/poi/ss/formula/functions/Roman.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- poi/src/java/org/apache/poi/ss/formula/functions/Roman.java (revision ) +++ poi/src/java/org/apache/poi/ss/formula/functions/Roman.java (revision ) @@ -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; + } +} Index: poi/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- poi/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java (revision 1490713) +++ poi/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java (revision ) @@ -236,6 +236,8 @@ retval[346] = new Countif(); retval[347] = new Countblank(); + retval[354] = new Roman(); + retval[359] = new Hyperlink(); retval[362] = MinaMaxa.MAXA; Index: poi/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- poi/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java (revision ) +++ poi/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java (revision ) @@ -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"; + } +} \ No newline at end of file