import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.usermodel.DataFormatter;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* @author Stephen Wolke (smwolke at geistig.com)
*/
public abstract class TextFunction implements Function {
-
- protected static final String EMPTY_STRING = "";
+ protected static final DataFormatter formatter = new DataFormatter();
+ protected static final String EMPTY_STRING = "";
protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol);
* TEXT returns a number value formatted with the given
* number formatting string. This function is not a complete implementation of
* the Excel function. This function implements decimal formatting
- * with the Java class DecimalFormat. For date formatting this function uses
- * the SimpleDateFormat class.<p/>
+ * with the Java class DecimalFormat. For date formatting, this function uses
+ * {@link DataFormatter}, which attempts to replicate the Excel date
+ * format string.
+ *
+ * TODO Merge much of this logic with {@link DataFormatter}
*
* <b>Syntax<b>:<br/> <b>TEXT</b>(<b>value</b>, <b>format_text</b>)<br/>
*
}
} else {
try {
- DateFormat dateFormatter = new SimpleDateFormat(s1);
- Calendar cal = new GregorianCalendar(1899, 11, 30, 0, 0, 0);
- cal.add(Calendar.DATE, (int)Math.floor(s0));
- double dayFraction = s0 - Math.floor(s0);
- cal.add(Calendar.MILLISECOND, (int) Math.round(dayFraction * 24 * 60 * 60 * 1000));
- return new StringEval(dateFormatter.format(cal.getTime()));
+ // Ask DataFormatter to handle the Date string for us
+ String formattedDate = formatter.formatRawCellContents(s0, -1, s1);
+ return new StringEval(formattedDate);
} catch (Exception e) {
return ErrorEval.VALUE_INVALID;
}
assertEquals(testResult.toString(), result.toString());
}
- public void testTextWithDateFormatSecondArg() {
-
- ValueEval numArg = new NumberEval(321.321);
- ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
- ValueEval[] args = { numArg, formatArg };
- ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
- ValueEval testResult = new StringEval("16:11:1900 07:42:14");
- assertEquals(testResult.toString(), result.toString());
-
- // this line is intended to compute how "November" would look like in the current locale
- String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime());
-
- formatArg = new StringEval("MMMM dd, yyyy");
- args[1] = formatArg;
- result = T.TEXT.evaluate(args, -1, (short)-1);
- testResult = new StringEval(november + " 16, 1900");
- assertEquals(testResult.toString(), result.toString());
- }
+ public void testTextWithDateFormatSecondArg() {
+ // Test with Java style M=Month
+ ValueEval numArg = new NumberEval(321.321);
+ ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
+ ValueEval[] args = { numArg, formatArg };
+ ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
+ ValueEval testResult = new StringEval("16:11:1900 07:42:14");
+ assertEquals(testResult.toString(), result.toString());
+
+ // Excel also supports "m before h is month"
+ formatArg = new StringEval("dd:mm:yyyy hh:mm:ss");
+ args[1] = formatArg;
+ result = T.TEXT.evaluate(args, -1, (short)-1);
+ testResult = new StringEval("16:11:1900 07:42:14");
+ assertEquals(testResult.toString(), result.toString());
+
+ // this line is intended to compute how "November" would look like in the current locale
+ String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime());
+
+ // Again with Java style
+ formatArg = new StringEval("MMMM dd, yyyy");
+ args[1] = formatArg;
+ result = T.TEXT.evaluate(args, -1, (short)-1);
+ testResult = new StringEval(november + " 16, 1900");
+ assertEquals(testResult.toString(), result.toString());
+
+ // And Excel style
+ formatArg = new StringEval("mmmm dd, yyyy");
+ args[1] = formatArg;
+ result = T.TEXT.evaluate(args, -1, (short)-1);
+ testResult = new StringEval(november + " 16, 1900");
+ assertEquals(testResult.toString(), result.toString());
+ }
}