Bug 58326 - Forbidden APIs patches - first set of changes for locale and timezone settings

also includes fixes for
- name shadowing 
- unused deprecated method "getClipRect" in classes extending Graphics2d
- HexDump - replaced intermediate String.format calls with custom padding
- convert testcases to junit4
- closing resources

also tested with an arbitary timezone (PST) and locale (ru)

supresses forbidden apis check for
- LocaleUtil (the only place where Locale.getDefault() and TimeZone.getDefault() should be called)
- Classes using FontMetrics - without the actual text it's difficult to return something sane

Some usage of UTC and Locale.ROOT might be still wrong, e.g. in MapiMessage we don't access the
extended mapi properties, which might contain the timezone

DataFormatter has now a Observable property which need to be observed when custom formats are used
and the Locale changes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1701688 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-09-07 20:19:50 +00:00
parent 3166646249
commit aaafb0270d
100 changed files with 3149 additions and 2507 deletions

View File

@ -1105,6 +1105,7 @@ under the License.
failureproperty="ooxml.test.failed"> failureproperty="ooxml.test.failed">
<classpath refid="@{classpath}"/> <classpath refid="@{classpath}"/>
<syspropertyset refid="junit.properties"/> <syspropertyset refid="junit.properties"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/> <jvmarg value="-ea"/>
<formatter type="plain"/> <formatter type="plain"/>
<formatter type="xml"/> <formatter type="xml"/>
@ -1126,6 +1127,7 @@ under the License.
<path refid="ooxml.xmlsec.classpath"/> <path refid="ooxml.xmlsec.classpath"/>
</classpath> </classpath>
<syspropertyset refid="junit.properties"/> <syspropertyset refid="junit.properties"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/> <jvmarg value="-ea"/>
<formatter type="plain"/> <formatter type="plain"/>
<formatter type="xml"/> <formatter type="xml"/>
@ -1715,6 +1717,7 @@ under the License.
<exclude name="resources/ooxml/org/apache/poi/xslf/usermodel/empty.pptx" /> <exclude name="resources/ooxml/org/apache/poi/xslf/usermodel/empty.pptx" />
<exclude name="resources/main/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml" /> <exclude name="resources/main/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml" />
<exclude name="examples/src/org/apache/poi/xslf/usermodel/pie-chart-data.txt" /> <exclude name="examples/src/org/apache/poi/xslf/usermodel/pie-chart-data.txt" />
<exclude name="**/*.iml" />
</fileset> </fileset>
</rat:report> </rat:report>
@ -1733,23 +1736,22 @@ under the License.
<taskdef name="forbiddenapis" <taskdef name="forbiddenapis"
classname="de.thetaphi.forbiddenapis.AntTask" classname="de.thetaphi.forbiddenapis.AntTask"
classpath="${forbidden.jar}"/> classpath="${forbidden.jar}"/>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${main.output.dir}"/>
</antcall>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${scratchpad.output.dir}"/>
</antcall>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${ooxml.output.dir}"/>
</antcall>
</target>
<target name="-do-forbidden-apis-check">
<forbiddenapis <forbiddenapis
internalRuntimeForbidden="true" internalRuntimeForbidden="true"
classpathref="javadoc.classpath" classpathref="javadoc.classpath"
dir="${dir}"> suppressAnnotation="org.apache.poi.util.SuppressForbidden"
>
<bundledsignatures name="jdk-unsafe-${jdk.version.source}"/> <bundledsignatures name="jdk-unsafe-${jdk.version.source}"/>
<bundledsignatures name="jdk-deprecated-${jdk.version.source}"/> <bundledsignatures name="jdk-deprecated-${jdk.version.source}"/>
<signaturesFileset file="src/resources/devtools/forbidden-signatures.txt"/>
<fileset dir="${main.output.dir}"/>
<fileset dir="${scratchpad.output.dir}"/>
<fileset dir="${ooxml.output.dir}"/>
<!--
<fileset dir="${main.output.test.dir}"/>
<fileset dir="${scratchpad.output.test.dir}"/>
<fileset dir="${ooxml.output.test.dir}"/>
-->
</forbiddenapis> </forbiddenapis>
</target> </target>

View File

@ -31,6 +31,7 @@ import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter; import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -52,7 +53,7 @@ public class FormatTrackingHSSFListener implements HSSFListener {
* the {@link Locale#getDefault() default locale} for the formats. * the {@link Locale#getDefault() default locale} for the formats.
*/ */
public FormatTrackingHSSFListener(HSSFListener childListener) { public FormatTrackingHSSFListener(HSSFListener childListener) {
this(childListener, Locale.getDefault()); this(childListener, LocaleUtil.getUserLocale());
} }
/** /**

View File

@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -96,6 +95,7 @@ import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -1774,7 +1774,7 @@ public final class InternalWorkbook {
retval.setDefaultCountry(( short ) 1); retval.setDefaultCountry(( short ) 1);
// from Russia with love ;) // from Russia with love ;)
if ( Locale.getDefault().toString().equals( "ru_RU" ) ) { if ( LocaleUtil.getUserLocale().toString().equals( "ru_RU" ) ) {
retval.setCurrentCountry(( short ) 7); retval.setCurrentCountry(( short ) 7);
} }
else { else {

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.text.MessageFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@ -463,7 +462,7 @@ public class DVConstraint implements DataValidationConstraint {
case ValidationType.FORMULA: case ValidationType.FORMULA:
return createCustomFormulaConstraint(toFormulaString(dvRecord.getFormula1(), book).string()); return createCustomFormulaConstraint(toFormulaString(dvRecord.getFormula1(), book).string());
default: default:
throw new UnsupportedOperationException(MessageFormat.format("validationType={0}", dvRecord.getDataType())); throw new UnsupportedOperationException("validationType="+dvRecord.getDataType());
} }
} }

View File

@ -34,13 +34,13 @@ import java.util.Map;
public class DummyGraphics2d public class DummyGraphics2d
extends Graphics2D extends Graphics2D
{ {
BufferedImage img; private BufferedImage bufimg;
private Graphics2D g2D; private Graphics2D g2D;
public DummyGraphics2d() public DummyGraphics2d()
{ {
img = new BufferedImage(1000, 1000, 2); bufimg = new BufferedImage(1000, 1000, 2);
g2D = (Graphics2D)img.getGraphics(); g2D = (Graphics2D)bufimg.getGraphics();
} }
public void addRenderingHints(Map<?,?> hints) public void addRenderingHints(Map<?,?> hints)
@ -710,12 +710,6 @@ public class DummyGraphics2d
return g2D.getClipBounds( r ); return g2D.getClipBounds( r );
} }
@SuppressWarnings("deprecation")
public Rectangle getClipRect() {
System.out.println( "getClipRect():" );
return g2D.getClipRect();
}
public Color getColor() public Color getColor()
{ {
System.out.println( "getColor():" ); System.out.println( "getColor():" );

View File

@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.SuppressForbidden;
import java.awt.*; import java.awt.*;
import java.awt.image.ImageObserver; import java.awt.image.ImageObserver;
@ -57,8 +58,7 @@ import java.text.AttributedCharacterIterator;
* <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>. * <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>.
* </blockquote> * </blockquote>
*/ */
public class EscherGraphics public class EscherGraphics extends Graphics
extends Graphics
{ {
private HSSFShapeGroup escherGroup; private HSSFShapeGroup escherGroup;
private HSSFWorkbook workbook; private HSSFWorkbook workbook;
@ -293,18 +293,18 @@ public class EscherGraphics
textbox.setString( s ); textbox.setString( s );
} }
private HSSFFont matchFont( Font font ) private HSSFFont matchFont( Font matchFont )
{ {
HSSFColor hssfColor = workbook.getCustomPalette() HSSFColor hssfColor = workbook.getCustomPalette()
.findColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue()); .findColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
if (hssfColor == null) if (hssfColor == null)
hssfColor = workbook.getCustomPalette().findSimilarColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue()); hssfColor = workbook.getCustomPalette().findSimilarColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
boolean bold = (font.getStyle() & Font.BOLD) != 0; boolean bold = (matchFont.getStyle() & Font.BOLD) != 0;
boolean italic = (font.getStyle() & Font.ITALIC) != 0; boolean italic = (matchFont.getStyle() & Font.ITALIC) != 0;
HSSFFont hssfFont = workbook.findFont(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0, HSSFFont hssfFont = workbook.findFont(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0,
hssfColor.getIndex(), hssfColor.getIndex(),
(short)(font.getSize() * 20), (short)(matchFont.getSize() * 20),
font.getName(), matchFont.getName(),
italic, italic,
false, false,
(short)0, (short)0,
@ -314,8 +314,8 @@ public class EscherGraphics
hssfFont = workbook.createFont(); hssfFont = workbook.createFont();
hssfFont.setBoldweight(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0); hssfFont.setBoldweight(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0);
hssfFont.setColor(hssfColor.getIndex()); hssfFont.setColor(hssfColor.getIndex());
hssfFont.setFontHeight((short)(font.getSize() * 20)); hssfFont.setFontHeight((short)(matchFont.getSize() * 20));
hssfFont.setFontName(font.getName()); hssfFont.setFontName(matchFont.getName());
hssfFont.setItalic(italic); hssfFont.setItalic(italic);
hssfFont.setStrikeout(false); hssfFont.setStrikeout(false);
hssfFont.setTypeOffset((short) 0); hssfFont.setTypeOffset((short) 0);
@ -431,11 +431,6 @@ public class EscherGraphics
return null; return null;
} }
public Rectangle getClipRect()
{
return getClipBounds();
}
public Color getColor() public Color getColor()
{ {
return foreground; return foreground;
@ -447,6 +442,7 @@ public class EscherGraphics
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressForbidden
public FontMetrics getFontMetrics(Font f) public FontMetrics getFontMetrics(Font f)
{ {
return Toolkit.getDefaultToolkit().getFontMetrics(f); return Toolkit.getDefaultToolkit().getFontMetrics(f);

View File

@ -52,6 +52,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.NumberToTextConverter; import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -989,7 +990,7 @@ public class HSSFCell implements Cell {
case CELL_TYPE_NUMERIC: case CELL_TYPE_NUMERIC:
//TODO apply the dataformat for this cell //TODO apply the dataformat for this cell
if (HSSFDateUtil.isCellDateFormatted(this)) { if (HSSFDateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy"); DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue()); return sdf.format(getDateCellValue());
} }
return String.valueOf(getNumericCellValue()); return String.valueOf(getNumericCellValue());

View File

@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.util.LocaleUtil;
/** /**
* HSSFDataFormatter contains methods for formatting the value stored in an * HSSFDataFormatter contains methods for formatting the value stored in an
@ -76,7 +77,7 @@ public final class HSSFDataFormatter extends DataFormatter {
* Creates a formatter using the {@link Locale#getDefault() default locale}. * Creates a formatter using the {@link Locale#getDefault() default locale}.
*/ */
public HSSFDataFormatter() { public HSSFDataFormatter() {
this(Locale.getDefault()); this(LocaleUtil.getUserLocale());
} }
} }

View File

@ -19,6 +19,7 @@
package org.apache.poi.poifs.filesystem; package org.apache.poi.poifs.filesystem;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -85,6 +86,22 @@ public class POIFSFileSystem
super(stream); super(stream);
} }
/**
* <p>Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
* creating from an <tt>InputStream</tt>. The File will be opened read-only</p>
*
* <p>Note that with this constructor, you will need to call {@link #close()}
* when you're done to have the underlying file closed, as the file is
* kept open during normal operation to read the data out.</p>
*
* @param file the File from which to read the data
*
* @exception IOException on errors reading, or on invalid data
*/
public POIFSFileSystem(File file) throws IOException {
super(file);
}
/** /**
* Checks that the supplied InputStream (which MUST * Checks that the supplied InputStream (which MUST
* support mark and reset, or be a PushbackInputStream) * support mark and reset, or be a PushbackInputStream)

View File

@ -24,19 +24,14 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Formatter; import java.util.Formatter;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import org.apache.poi.util.LocaleUtil;
/** /**
* Formats a date value. * Formats a date value.
*/ */
public class CellDateFormatter extends CellFormatter { public class CellDateFormatter extends CellFormatter {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
private boolean amPmUpper; private boolean amPmUpper;
private boolean showM; private boolean showM;
private boolean showAmPm; private boolean showAmPm;
@ -50,8 +45,7 @@ public class CellDateFormatter extends CellFormatter {
"mm/d/y"); "mm/d/y");
static { static {
Calendar c = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar c = LocaleUtil.getLocaleCalendar(1904, 0, 1, 0, 0, 0);
c.set(1904, 0, 1, 0, 0, 0);
EXCEL_EPOCH_DATE = c.getTime(); EXCEL_EPOCH_DATE = c.getTime();
EXCEL_EPOCH_TIME = c.getTimeInMillis(); EXCEL_EPOCH_TIME = c.getTimeInMillis();
} }

View File

@ -524,4 +524,8 @@ public class CellFormatPart {
String str = m.group(g); String str = m.group(g);
return (str == null ? "" : str); return (str == null ? "" : str);
} }
public String toString() {
return format.format;
}
} }

View File

@ -57,7 +57,7 @@ public class CellGeneralFormatter extends CellFormatter {
stripZeros = false; stripZeros = false;
} }
Formatter formatter = new Formatter(toAppendTo); Formatter formatter = new Formatter(toAppendTo, LOCALE);
try { try {
formatter.format(LOCALE, fmt, value); formatter.format(LOCALE, fmt, value);
} finally { } finally {

View File

@ -17,6 +17,7 @@
package org.apache.poi.ss.format; package org.apache.poi.ss.format;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition; import java.text.FieldPosition;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
@ -30,6 +31,7 @@ import java.util.TreeSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import org.apache.poi.ss.format.CellFormatPart.PartHandler; import org.apache.poi.ss.format.CellFormatPart.PartHandler;
import org.apache.poi.util.LocaleUtil;
/** /**
* This class implements printing out a value using a number format. * This class implements printing out a value using a number format.
@ -182,8 +184,8 @@ public class CellNumberFormatter extends CellFormatter {
private char insertSignForExponent; private char insertSignForExponent;
public String handlePart(Matcher m, String part, CellFormatType type, public String handlePart(Matcher m, String part, CellFormatType type,
StringBuffer desc) { StringBuffer descBuf) {
int pos = desc.length(); int pos = descBuf.length();
char firstCh = part.charAt(0); char firstCh = part.charAt(0);
switch (firstCh) { switch (firstCh) {
case 'e': case 'e':
@ -203,7 +205,7 @@ public class CellNumberFormatter extends CellFormatter {
case '#': case '#':
if (insertSignForExponent != '\0') { if (insertSignForExponent != '\0') {
specials.add(new Special(insertSignForExponent, pos)); specials.add(new Special(insertSignForExponent, pos));
desc.append(insertSignForExponent); descBuf.append(insertSignForExponent);
insertSignForExponent = '\0'; insertSignForExponent = '\0';
pos++; pos++;
} }
@ -354,7 +356,8 @@ public class CellNumberFormatter extends CellFormatter {
fmtBuf.append('E'); fmtBuf.append('E');
placeZeros(fmtBuf, exponentSpecials.subList(2, placeZeros(fmtBuf, exponentSpecials.subList(2,
exponentSpecials.size())); exponentSpecials.size()));
decimalFmt = new DecimalFormat(fmtBuf.toString()); DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
decimalFmt = new DecimalFormat(fmtBuf.toString(), dfs);
} }
if (exponent != null) if (exponent != null)
@ -594,7 +597,7 @@ public class CellNumberFormatter extends CellFormatter {
writeFraction(value, null, fractional, output, mods); writeFraction(value, null, fractional, output, mods);
} else { } else {
StringBuffer result = new StringBuffer(); StringBuffer result = new StringBuffer();
Formatter f = new Formatter(result); Formatter f = new Formatter(result, LOCALE);
try { try {
f.format(LOCALE, printfFmt, value); f.format(LOCALE, printfFmt, value);
} finally { } finally {
@ -767,6 +770,7 @@ public class CellNumberFormatter extends CellFormatter {
writeInteger(exponentNum, output, exponentDigitSpecials, mods, false); writeInteger(exponentNum, output, exponentDigitSpecials, mods, false);
} }
@SuppressWarnings("unchecked")
private void writeFraction(double value, StringBuffer result, private void writeFraction(double value, StringBuffer result,
double fractional, StringBuffer output, Set<StringMod> mods) { double fractional, StringBuffer output, Set<StringMod> mods) {
@ -869,7 +873,7 @@ public class CellNumberFormatter extends CellFormatter {
List<Special> numSpecials, Set<StringMod> mods) { List<Special> numSpecials, Set<StringMod> mods) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
Formatter formatter = new Formatter(sb); Formatter formatter = new Formatter(sb, LOCALE);
try { try {
formatter.format(LOCALE, fmt, num); formatter.format(LOCALE, fmt, num);
} finally { } finally {

View File

@ -18,24 +18,16 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.util.LocaleUtil;
/** /**
* Parser for java dates. * Parser for java dates.
*/ */
public class DateParser { public class DateParser {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public DateParser instance = new DateParser(); public DateParser instance = new DateParser();
private DateParser() { private DateParser() {
@ -80,10 +72,10 @@ public class DateParser {
return makeDate(f0, f1, f2); return makeDate(f0, f1, f2);
} }
// otherwise the format seems to depend on OS settings (default date format) // otherwise the format seems to depend on OS settings (default date format)
if (false) { // if (false) {
// MM/DD/YYYY is probably a good guess, if the in the US // // MM/DD/YYYY is probably a good guess, if the in the US
return makeDate(f2, f0, f1); // return makeDate(f2, f0, f1);
} // }
// TODO - find a way to choose the correct date format // TODO - find a way to choose the correct date format
throw new RuntimeException("Unable to determine date format for text '" + strVal + "'"); throw new RuntimeException("Unable to determine date format for text '" + strVal + "'");
} }
@ -95,9 +87,7 @@ public class DateParser {
if (month < 1 || month > 12) { if (month < 1 || month > 12) {
throw new EvaluationException(ErrorEval.VALUE_INVALID); throw new EvaluationException(ErrorEval.VALUE_INVALID);
} }
Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT); Calendar cal = LocaleUtil.getLocaleCalendar(year, month - 1, 1, 0, 0, 0);
cal.set(year, month - 1, 1, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
if (day < 1 || day > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) { if (day < 1 || day > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
throw new EvaluationException(ErrorEval.VALUE_INVALID); throw new EvaluationException(ErrorEval.VALUE_INVALID);
} }

View File

@ -19,21 +19,14 @@ package org.apache.poi.ss.formula.atp;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* A calculator for workdays, considering dates as excel representations. * A calculator for workdays, considering dates as excel representations.
*/ */
public class WorkdayCalculator { public class WorkdayCalculator {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final WorkdayCalculator instance = new WorkdayCalculator(); public static final WorkdayCalculator instance = new WorkdayCalculator();
/** /**
@ -69,7 +62,7 @@ public class WorkdayCalculator {
public Date calculateWorkdays(double start, int workdays, double[] holidays) { public Date calculateWorkdays(double start, int workdays, double[] holidays) {
Date startDate = DateUtil.getJavaDate(start); Date startDate = DateUtil.getJavaDate(start);
int direction = workdays < 0 ? -1 : 1; int direction = workdays < 0 ? -1 : 1;
Calendar endDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar endDate = LocaleUtil.getLocaleCalendar();
endDate.setTime(startDate); endDate.setTime(startDate);
double excelEndDate = DateUtil.getExcelDate(endDate.getTime()); double excelEndDate = DateUtil.getExcelDate(endDate.getTime());
while (workdays != 0) { while (workdays != 0) {
@ -97,7 +90,7 @@ public class WorkdayCalculator {
int startDay = (int) Math.floor(start < end ? start : end); int startDay = (int) Math.floor(start < end ? start : end);
int endDay = (int) Math.floor(end > start ? end : start); int endDay = (int) Math.floor(end > start ? end : start);
for (; startDay <= endDay; startDay++) { for (; startDay <= endDay; startDay++) {
Calendar today = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar today = LocaleUtil.getLocaleCalendar();
today.setTime(DateUtil.getJavaDate(startDay)); today.setTime(DateUtil.getJavaDate(startDay));
if (today.get(Calendar.DAY_OF_WEEK) == dayOfWeek) { if (today.get(Calendar.DAY_OF_WEEK) == dayOfWeek) {
pastDaysOfWeek++; pastDaysOfWeek++;
@ -133,7 +126,7 @@ public class WorkdayCalculator {
* @return <code>true</code> if date is weekend, <code>false</code> otherwise. * @return <code>true</code> if date is weekend, <code>false</code> otherwise.
*/ */
protected boolean isWeekend(double aDate) { protected boolean isWeekend(double aDate) {
Calendar date = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar date = LocaleUtil.getLocaleCalendar();
date.setTime(DateUtil.getJavaDate(aDate)); date.setTime(DateUtil.getJavaDate(aDate));
return date.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY; return date.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
} }

View File

@ -18,13 +18,11 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
@ -35,8 +33,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @author Josh Micich * @author Josh Micich
*/ */
final class YearFracCalculator { final class YearFracCalculator {
/** use UTC time-zone to avoid daylight savings issues */
private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
private static final int MS_PER_HOUR = 60 * 60 * 1000; private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int MS_PER_DAY = 24 * MS_PER_HOUR; private static final int MS_PER_DAY = 24 * MS_PER_HOUR;
private static final int DAYS_PER_NORMAL_YEAR = 365; private static final int DAYS_PER_NORMAL_YEAR = 365;
@ -317,9 +313,10 @@ final class YearFracCalculator {
} }
private static SimpleDate createDate(int dayCount) { private static SimpleDate createDate(int dayCount) {
GregorianCalendar calendar = new GregorianCalendar(UTC_TIME_ZONE, Locale.ROOT); /** use UTC time-zone to avoid daylight savings issues */
DateUtil.setCalendar(calendar, dayCount, 0, false, false); Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
return new SimpleDate(calendar); DateUtil.setCalendar(cal, dayCount, 0, false, false);
return new SimpleDate(cal);
} }
private static final class SimpleDate { private static final class SimpleDate {

View File

@ -30,16 +30,16 @@ import java.util.Set;
*/ */
final class FunctionDataBuilder { final class FunctionDataBuilder {
private int _maxFunctionIndex; private int _maxFunctionIndex;
private final Map _functionDataByName; private final Map<String,FunctionMetadata> _functionDataByName;
private final Map _functionDataByIndex; private final Map<Integer,FunctionMetadata> _functionDataByIndex;
/** stores indexes of all functions with footnotes (i.e. whose definitions might change) */ /** stores indexes of all functions with footnotes (i.e. whose definitions might change) */
private final Set _mutatingFunctionIndexes; private final Set<Integer> _mutatingFunctionIndexes;
public FunctionDataBuilder(int sizeEstimate) { public FunctionDataBuilder(int sizeEstimate) {
_maxFunctionIndex = -1; _maxFunctionIndex = -1;
_functionDataByName = new HashMap(sizeEstimate * 3 / 2); _functionDataByName = new HashMap<String,FunctionMetadata>(sizeEstimate * 3 / 2);
_functionDataByIndex = new HashMap(sizeEstimate * 3 / 2); _functionDataByIndex = new HashMap<Integer,FunctionMetadata>(sizeEstimate * 3 / 2);
_mutatingFunctionIndexes = new HashSet(); _mutatingFunctionIndexes = new HashSet<Integer>();
} }
public void add(int functionIndex, String functionName, int minParams, int maxParams, public void add(int functionIndex, String functionName, int minParams, int maxParams,
@ -55,14 +55,14 @@ final class FunctionDataBuilder {
} }
// allow function definitions to change only if both previous and the new items have footnotes // allow function definitions to change only if both previous and the new items have footnotes
FunctionMetadata prevFM; FunctionMetadata prevFM;
prevFM = (FunctionMetadata) _functionDataByName.get(functionName); prevFM = _functionDataByName.get(functionName);
if(prevFM != null) { if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function name '" + functionName + "'"); throw new RuntimeException("Multiple entries for function name '" + functionName + "'");
} }
_functionDataByIndex.remove(Integer.valueOf(prevFM.getIndex())); _functionDataByIndex.remove(Integer.valueOf(prevFM.getIndex()));
} }
prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey); prevFM = _functionDataByIndex.get(indexKey);
if(prevFM != null) { if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")"); throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")");

View File

@ -27,18 +27,13 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation for the Excel function DATE * Implementation for the Excel function DATE
*/ */
public final class DateFunc extends Fixed3ArgFunction { public final class DateFunc extends Fixed3ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final Function instance = new DateFunc(); public static final Function instance = new DateFunc();
private DateFunc() { private DateFunc() {
@ -91,9 +86,7 @@ public final class DateFunc extends Fixed3ArgFunction {
} }
// Turn this into a Java date // Turn this into a Java date
Calendar c = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT); Calendar c = LocaleUtil.getLocaleCalendar(year, month, day);
c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
// Handle negative days of the week, that pull us across // Handle negative days of the week, that pull us across
// the 29th of Feb 1900 // the 29th of Feb 1900

View File

@ -17,14 +17,13 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver; import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* <p>Calculates the number of days between two dates based on a 360-day year * <p>Calculates the number of days between two dates based on a 360-day year
@ -67,12 +66,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @see <a href="https://support.microsoft.com/en-us/kb/235575">DAYS360 Function Produces Different Values Depending on the Version of Excel</a> * @see <a href="https://support.microsoft.com/en-us/kb/235575">DAYS360 Function Produces Different Values Depending on the Version of Excel</a>
*/ */
public class Days360 extends Var2or3ArgFunction { public class Days360 extends Var2or3ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result; double result;
try { try {
@ -112,8 +105,8 @@ public class Days360 extends Var2or3ArgFunction {
} }
private static Calendar getDate(double date) { private static Calendar getDate(double date) {
Calendar processedDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar processedDate = LocaleUtil.getLocaleCalendar();
processedDate.setTime(DateUtil.getJavaDate(date, false, DEFAULT_TIMEZONE)); processedDate.setTime(DateUtil.getJavaDate(date, false));
return processedDate; return processedDate;
} }

View File

@ -109,7 +109,7 @@ public final class Dec2Hex extends Var1or2ArgFunction implements FreeRefFunction
String hex; String hex;
if (placesNumber != 0) { if (placesNumber != 0) {
hex = String.format("%0"+placesNumber+"X", number1.intValue(), Locale.ROOT); hex = String.format(Locale.ROOT, "%0"+placesNumber+"X", number1.intValue());
} }
else { else {
hex = Integer.toHexString(number1.intValue()); hex = Integer.toHexString(number1.intValue());

View File

@ -30,17 +30,12 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval; import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation for Excel EDATE () function. * Implementation for Excel EDATE () function.
*/ */
public class EDate implements FreeRefFunction { public class EDate implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final FreeRefFunction instance = new EDate(); public static final FreeRefFunction instance = new EDate();
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
@ -52,7 +47,7 @@ public class EDate implements FreeRefFunction {
int offsetInMonthAsNumber = (int) getValue(args[1]); int offsetInMonthAsNumber = (int) getValue(args[1]);
Date startDate = DateUtil.getJavaDate(startDateAsNumber); Date startDate = DateUtil.getJavaDate(startDateAsNumber);
Calendar calendar = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT); Calendar calendar = LocaleUtil.getLocaleCalendar();
calendar.setTime(startDate); calendar.setTime(startDate);
calendar.add(Calendar.MONTH, offsetInMonthAsNumber); calendar.add(Calendar.MONTH, offsetInMonthAsNumber);
return new NumberEval(DateUtil.getExcelDate(calendar.getTime())); return new NumberEval(DateUtil.getExcelDate(calendar.getTime()));

View File

@ -19,9 +19,6 @@ package org.apache.poi.ss.formula.functions;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.formula.OperationEvaluationContext; import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
@ -29,6 +26,7 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation for the Excel EOMONTH() function.<p/> * Implementation for the Excel EOMONTH() function.<p/>
@ -45,12 +43,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* zero or negative (in the past). * zero or negative (in the past).
*/ */
public class EOMonth implements FreeRefFunction { public class EOMonth implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final FreeRefFunction instance = new EOMonth(); public static final FreeRefFunction instance = new EOMonth();
@Override @Override
@ -70,10 +62,13 @@ public class EOMonth implements FreeRefFunction {
Date startDate = DateUtil.getJavaDate(startDateAsNumber, false); Date startDate = DateUtil.getJavaDate(startDateAsNumber, false);
Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT); Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(startDate); cal.setTime(startDate);
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0); cal.clear(Calendar.HOUR);
cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
cal.add(Calendar.MONTH, months + 1); cal.add(Calendar.MONTH, months + 1);
cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.DAY_OF_MONTH, 1);

View File

@ -36,7 +36,7 @@ import org.apache.poi.ss.usermodel.DataFormatter;
*/ */
public abstract class TextFunction implements Function { public abstract class TextFunction implements Function {
protected static final DataFormatter formatter = new DataFormatter(); protected static final DataFormatter formatter = new DataFormatter();
protected static final String EMPTY_STRING = ""; protected static final String EMPTY_STRING = "";
protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException { protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol); ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol);

View File

@ -18,28 +18,23 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation of Excel TODAY() Function<br/> * Implementation of Excel TODAY() Function<br/>
*/ */
public final class Today extends Fixed0ArgFunction { public final class Today extends Fixed0ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
Calendar now = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT); Calendar now = LocaleUtil.getLocaleCalendar();
now.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DATE),0,0,0); now.clear(Calendar.HOUR);
now.set(Calendar.MILLISECOND, 0); now.set(Calendar.HOUR_OF_DAY,0);
now.clear(Calendar.MINUTE);
now.clear(Calendar.SECOND);
now.clear(Calendar.MILLISECOND);
return new NumberEval(DateUtil.getExcelDate(now.getTime())); return new NumberEval(DateUtil.getExcelDate(now.getTime()));
} }
} }

View File

@ -17,14 +17,16 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.usermodel.DateUtil;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale; import org.apache.poi.ss.formula.OperationEvaluationContext;
import java.util.TimeZone; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation for Excel WeekNum() function.<p/> * Implementation for Excel WeekNum() function.<p/>
@ -42,12 +44,6 @@ import java.util.TimeZone;
* 2 Week begins on Monday. Weekdays are numbered 1 through 7. * 2 Week begins on Monday. Weekdays are numbered 1 through 7.
*/ */
public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction { public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final FreeRefFunction instance = new WeekNum(); public static final FreeRefFunction instance = new WeekNum();
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) {
@ -57,7 +53,7 @@ public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
} catch (EvaluationException e) { } catch (EvaluationException e) {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
Calendar serialNumCalendar = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT); Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar();
serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false)); serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false));
int returnType = 0; int returnType = 0;

View File

@ -36,10 +36,13 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.poi.ss.util.NumberToTextConverter; import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.util.LocaleUtil;
/** /**
@ -100,7 +103,7 @@ import org.apache.poi.ss.util.NumberToTextConverter;
* Excel will output "", <code>DataFormatter</code> will output "0". * Excel will output "", <code>DataFormatter</code> will output "0".
* </ul> * </ul>
*/ */
public class DataFormatter { public class DataFormatter implements Observer {
private static final String defaultFractionWholePartFormat = "#"; private static final String defaultFractionWholePartFormat = "#";
private static final String defaultFractionFractionPartFormat = "#/##"; private static final String defaultFractionFractionPartFormat = "#/##";
/** Pattern to find a number format: "0" or "#" */ /** Pattern to find a number format: "0" or "#" */
@ -153,18 +156,18 @@ public class DataFormatter {
/** /**
* The decimal symbols of the locale used for formatting values. * The decimal symbols of the locale used for formatting values.
*/ */
private final DecimalFormatSymbols decimalSymbols; private DecimalFormatSymbols decimalSymbols;
/** /**
* The date symbols of the locale used for formatting values. * The date symbols of the locale used for formatting values.
*/ */
private final DateFormatSymbols dateSymbols; private DateFormatSymbols dateSymbols;
/** <em>General</em> format for whole numbers. */ /** <em>General</em> format for whole numbers. */
private final Format generalWholeNumFormat; private Format generalWholeNumFormat;
/** <em>General</em> format for decimal numbers. */ /** <em>General</em> format for decimal numbers. */
private final Format generalDecimalNumFormat; private Format generalDecimalNumFormat;
/** A default format to use when a number pattern cannot be parsed. */ /** A default format to use when a number pattern cannot be parsed. */
private Format defaultNumFormat; private Format defaultNumFormat;
@ -173,15 +176,37 @@ public class DataFormatter {
* A map to cache formats. * A map to cache formats.
* Map<String,Format> formats * Map<String,Format> formats
*/ */
private final Map<String,Format> formats; private final Map<String,Format> formats = new HashMap<String,Format>();
private boolean emulateCsv = false; private boolean emulateCsv = false;
/** stores the locale valid it the last formatting call */
private Locale locale;
/** stores if the locale should change according to {@link LocaleUtil#getUserLocale()} */
private boolean localeIsAdapting = true;
private class LocaleChangeObservable extends Observable {
void checkForLocaleChange() {
checkForLocaleChange(LocaleUtil.getUserLocale());
}
void checkForLocaleChange(Locale newLocale) {
if (!localeIsAdapting) return;
if (newLocale.equals(locale)) return;
super.setChanged();
notifyObservers(newLocale);
}
}
/** the Observable to notify, when the locale has been changed */
private final LocaleChangeObservable localeChangedObervable = new LocaleChangeObservable();
/** /**
* Creates a formatter using the {@link Locale#getDefault() default locale}. * Creates a formatter using the {@link Locale#getDefault() default locale}.
*/ */
public DataFormatter() { public DataFormatter() {
this(false); this(false);
this.localeIsAdapting = true;
} }
/** /**
@ -190,8 +215,8 @@ public class DataFormatter {
* @param emulateCsv whether to emulate CSV output. * @param emulateCsv whether to emulate CSV output.
*/ */
public DataFormatter(boolean emulateCsv) { public DataFormatter(boolean emulateCsv) {
this(Locale.getDefault()); this(LocaleUtil.getUserLocale(), emulateCsv);
this.emulateCsv = emulateCsv; this.localeIsAdapting = true;
} }
/** /**
@ -208,29 +233,9 @@ public class DataFormatter {
* Creates a formatter using the given locale. * Creates a formatter using the given locale.
*/ */
public DataFormatter(Locale locale) { public DataFormatter(Locale locale) {
dateSymbols = new DateFormatSymbols(locale); localeChangedObervable.addObserver(this);
decimalSymbols = new DecimalFormatSymbols(locale); localeChangedObervable.checkForLocaleChange(locale);
generalWholeNumFormat = new DecimalFormat("#", decimalSymbols); this.localeIsAdapting = false;
generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);
formats = new HashMap<String,Format>();
// init built-in formats
Format zipFormat = ZipPlusFourFormat.instance;
addFormat("00000\\-0000", zipFormat);
addFormat("00000-0000", zipFormat);
Format phoneFormat = PhoneFormat.instance;
// allow for format string variations
addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("###-####;(###) ###-####", phoneFormat);
Format ssnFormat = SSNFormat.instance;
addFormat("000\\-00\\-0000", ssnFormat);
addFormat("000-00-0000", ssnFormat);
} }
/** /**
@ -260,6 +265,8 @@ public class DataFormatter {
} }
private Format getFormat(double cellValue, int formatIndex, String formatStrIn) { private Format getFormat(double cellValue, int formatIndex, String formatStrIn) {
localeChangedObervable.checkForLocaleChange();
// // Might be better to separate out the n p and z formats, falling back to p when n and z are not set. // // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
// // That however would require other code to be re factored. // // That however would require other code to be re factored.
// String[] formatBits = formatStrIn.split(";"); // String[] formatBits = formatStrIn.split(";");
@ -329,6 +336,8 @@ public class DataFormatter {
} }
private Format createFormat(double cellValue, int formatIndex, String sFormat) { private Format createFormat(double cellValue, int formatIndex, String sFormat) {
localeChangedObervable.checkForLocaleChange();
String formatStr = sFormat; String formatStr = sFormat;
// Remove colour formatting if present // Remove colour formatting if present
@ -666,6 +675,8 @@ public class DataFormatter {
return getDefaultFormat(cell.getNumericCellValue()); return getDefaultFormat(cell.getNumericCellValue());
} }
private Format getDefaultFormat(double cellValue) { private Format getDefaultFormat(double cellValue) {
localeChangedObervable.checkForLocaleChange();
// for numeric cells try user supplied default // for numeric cells try user supplied default
if (defaultNumFormat != null) { if (defaultNumFormat != null) {
return defaultNumFormat; return defaultNumFormat;
@ -742,6 +753,8 @@ public class DataFormatter {
* @see #formatCellValue(Cell) * @see #formatCellValue(Cell)
*/ */
public String formatRawCellContents(double value, int formatIndex, String formatString, boolean use1904Windowing) { public String formatRawCellContents(double value, int formatIndex, String formatString, boolean use1904Windowing) {
localeChangedObervable.checkForLocaleChange();
// Is it a date? // Is it a date?
if(DateUtil.isADateFormat(formatIndex,formatString)) { if(DateUtil.isADateFormat(formatIndex,formatString)) {
if(DateUtil.isValidExcelDate(value)) { if(DateUtil.isValidExcelDate(value)) {
@ -820,6 +833,7 @@ public class DataFormatter {
* @return a string value of the cell * @return a string value of the cell
*/ */
public String formatCellValue(Cell cell, FormulaEvaluator evaluator) { public String formatCellValue(Cell cell, FormulaEvaluator evaluator) {
localeChangedObervable.checkForLocaleChange();
if (cell == null) { if (cell == null) {
return ""; return "";
@ -927,6 +941,59 @@ public class DataFormatter {
format.setRoundingMode(roundingMode); format.setRoundingMode(roundingMode);
} }
/**
* If the Locale has been changed via {@link LocaleUtil#setUserLocale(Locale)} the stored
* formats need to be refreshed. All formats which aren't originated from DataFormatter
* itself, i.e. all Formats added via {@link DataFormatter#addFormat(String, Format)} and
* {@link DataFormatter#setDefaultNumberFormat(Format)}, need to be added again.
* To notify callers, the returned {@link Observable} should be used.
* The Object in {@link Observer#update(Observable, Object)} is the new Locale.
*
* @return the listener object, where callers can register themself
*/
public Observable getLocaleChangedObservable() {
return localeChangedObervable;
}
/**
* Update formats when locale has been changed
*
* @param observable usually this is our own Observable instance
* @param localeObj only reacts on Locale objects
*/
public void update(Observable observable, Object localeObj) {
if (!(localeObj instanceof Locale)) return;
Locale newLocale = (Locale)localeObj;
if (!localeIsAdapting || newLocale.equals(locale)) return;
locale = newLocale;
dateSymbols = DateFormatSymbols.getInstance(locale);
decimalSymbols = DecimalFormatSymbols.getInstance(locale);
generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);
// init built-in formats
formats.clear();
Format zipFormat = ZipPlusFourFormat.instance;
addFormat("00000\\-0000", zipFormat);
addFormat("00000-0000", zipFormat);
Format phoneFormat = PhoneFormat.instance;
// allow for format string variations
addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("###-####;(###) ###-####", phoneFormat);
Format ssnFormat = SSNFormat.instance;
addFormat("000\\-00\\-0000", ssnFormat);
addFormat("000-00-0000", ssnFormat);
}
/** /**
* Format class for Excel's SSN format. This class mimics Excel's built-in * Format class for Excel's SSN format. This class mimics Excel's built-in
* SSN formatting. * SSN formatting.

View File

@ -20,10 +20,11 @@ package org.apache.poi.ss.usermodel;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.poi.util.LocaleUtil;
/** /**
* Contains methods for dealing with Excel dates. * Contains methods for dealing with Excel dates.
*/ */
@ -52,13 +53,6 @@ public class DateUtil {
// elapsed time patterns: [h],[m] and [s] // elapsed time patterns: [h],[m] and [s]
private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)\\]"); private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)\\]");
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
/** /**
* Given a Date, converts it into a double representing its internal Excel representation, * Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds. * which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
@ -78,7 +72,7 @@ public class DateUtil {
* @param use1904windowing Should 1900 or 1904 date windowing be used? * @param use1904windowing Should 1900 or 1904 date windowing be used?
*/ */
public static double getExcelDate(Date date, boolean use1904windowing) { public static double getExcelDate(Date date, boolean use1904windowing) {
Calendar calStart = Calendar.getInstance(getUserTimeZone(), Locale.ROOT); Calendar calStart = LocaleUtil.getLocaleCalendar();
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0 calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
return internalGetExcelDate(calStart, use1904windowing); return internalGetExcelDate(calStart, use1904windowing);
} }
@ -242,6 +236,9 @@ public class DateUtil {
} }
calendar.set(startYear,0, wholeDays + dayAdjust, 0, 0, 0); calendar.set(startYear,0, wholeDays + dayAdjust, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, millisecondsInDay); calendar.set(Calendar.MILLISECOND, millisecondsInDay);
if (calendar.get(Calendar.MILLISECOND) == 0) {
calendar.clear(Calendar.MILLISECOND);
}
if (roundSeconds) { if (roundSeconds) {
calendar.add(Calendar.MILLISECOND, 500); calendar.add(Calendar.MILLISECOND, 500);
calendar.clear(Calendar.MILLISECOND); calendar.clear(Calendar.MILLISECOND);
@ -281,7 +278,7 @@ public class DateUtil {
* @return Java representation of the date in UTC, or null if date is not a valid Excel date * @return Java representation of the date in UTC, or null if date is not a valid Excel date
*/ */
public static Calendar getJavaCalendarUTC(double date, boolean use1904windowing) { public static Calendar getJavaCalendarUTC(double date, boolean use1904windowing) {
return getJavaCalendar(date, use1904windowing, TIMEZONE_UTC, false); return getJavaCalendar(date, use1904windowing, LocaleUtil.TIMEZONE_UTC, false);
} }
@ -314,9 +311,9 @@ public class DateUtil {
int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5); int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5);
Calendar calendar; Calendar calendar;
if (timeZone != null) { if (timeZone != null) {
calendar = Calendar.getInstance(timeZone, Locale.ROOT); calendar = LocaleUtil.getLocaleCalendar(timeZone);
} else { } else {
calendar = Calendar.getInstance(getUserTimeZone(), Locale.ROOT); // using default time-zone calendar = LocaleUtil.getLocaleCalendar(); // using default time-zone
} }
setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds); setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds);
return calendar; return calendar;
@ -334,13 +331,6 @@ public class DateUtil {
private static ThreadLocal<String> lastFormatString = new ThreadLocal<String>(); private static ThreadLocal<String> lastFormatString = new ThreadLocal<String>();
private static ThreadLocal<Boolean> lastCachedResult = new ThreadLocal<Boolean>(); private static ThreadLocal<Boolean> lastCachedResult = new ThreadLocal<Boolean>();
private static ThreadLocal<TimeZone> userTimeZone = new ThreadLocal<TimeZone>() {
@Override
protected TimeZone initialValue() {
return TIMEZONE_UTC;
}
};
private static boolean isCached(String formatString, int formatIndex) { private static boolean isCached(String formatString, int formatIndex) {
String cachedFormatString = lastFormatString.get(); String cachedFormatString = lastFormatString.get();
return cachedFormatString != null && formatIndex == lastFormatIndex.get() return cachedFormatString != null && formatIndex == lastFormatIndex.get()
@ -353,23 +343,6 @@ public class DateUtil {
lastCachedResult.set(Boolean.valueOf(cached)); lastCachedResult.set(Boolean.valueOf(cached));
} }
/**
* as timezone information is not stored in any format, it can be
* set before any date calculations take place
*
* @param timezone the timezone under which date calculations take place
*/
public static void setUserTimeZone(TimeZone timezone) {
userTimeZone.set(timezone);
}
/**
* @return the time zone which is used for date calculations
*/
public static TimeZone getUserTimeZone() {
return userTimeZone.get();
}
/** /**
* Given a format ID and its format String, will check to see if the * Given a format ID and its format String, will check to see if the
* format represents a date format or not. * format represents a date format or not.
@ -684,9 +657,7 @@ public class DateUtil {
int month = parseInt(monthStr, "month", 1, 12); int month = parseInt(monthStr, "month", 1, 12);
int day = parseInt(dayStr, "day", 1, 31); int day = parseInt(dayStr, "day", 1, 31);
Calendar cal = Calendar.getInstance(getUserTimeZone(), Locale.ROOT); Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
cal.set(year, month-1, day, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime(); return cal.getTime();
} }
private static int parseInt(String strVal, String fieldName, int rangeMax) throws FormatException { private static int parseInt(String strVal, String fieldName, int rangeMax) throws FormatException {

View File

@ -17,6 +17,9 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import java.util.*; import java.util.*;
import org.apache.poi.util.LocaleUtil;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.*; import java.text.*;
@ -56,16 +59,15 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
DataFormatter.setExcelStyleRoundingMode(format2digits, RoundingMode.DOWN); DataFormatter.setExcelStyleRoundingMode(format2digits, RoundingMode.DOWN);
DataFormatter.setExcelStyleRoundingMode(format3digit); DataFormatter.setExcelStyleRoundingMode(format3digit);
DataFormatter.setExcelStyleRoundingMode(format4digits); DataFormatter.setExcelStyleRoundingMode(format4digits);
setTimeZone(LocaleUtil.getUserTimeZone());
} }
private double dateToBeFormatted = 0.0; private double dateToBeFormatted = 0.0;
public ExcelStyleDateFormatter() { // no-arg constructor is private because of undefined super call with locale
super();
}
public ExcelStyleDateFormatter(String pattern) { public ExcelStyleDateFormatter(String pattern) {
super(processFormatPattern(pattern)); super(processFormatPattern(pattern), LocaleUtil.getUserLocale());
} }
public ExcelStyleDateFormatter(String pattern, public ExcelStyleDateFormatter(String pattern,

View File

@ -18,7 +18,10 @@
package org.apache.poi.util; package org.apache.poi.util;
import java.awt.*; import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
@ -26,6 +29,7 @@ import java.util.Properties;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class FontMetricsDumper public class FontMetricsDumper
{ {
@SuppressForbidden
public static void main( String[] args ) throws IOException public static void main( String[] args ) throws IOException
{ {

View File

@ -149,14 +149,15 @@ public class HexDump {
chars_read = 16; chars_read = 16;
} }
buffer.append(String.format(Locale.ROOT, "%08X ", display_offset)); buffer.append(xpad(display_offset, 8, ""));
for (int k = 0; k < 16; k++) { for (int k = 0; k < 16; k++) {
if (k < chars_read) { if (k < chars_read) {
buffer.append(String.format(Locale.ROOT, "%02X ", data[ k + j ])); buffer.append(xpad(data[ k + j ], 2, " "));
} else { } else {
buffer.append(" "); buffer.append(" ");
} }
} }
buffer.append(' ');
for (int k = 0; k < chars_read; k++) { for (int k = 0; k < chars_read; k++) {
buffer.append(toAscii(data[ k + j ])); buffer.append(toAscii(data[ k + j ]));
} }
@ -232,20 +233,19 @@ public class HexDump {
* will be written to a new line * will be written to a new line
* @return A String representing the array of bytes * @return A String representing the array of bytes
*/ */
public static String toHex(final byte[] value, final int bytesPerLine) public static String toHex(final byte[] value, final int bytesPerLine) {
{ if (value.length == 0) {
final int digits = return ": 0";
(int) Math.round(Math.log(value.length) / Math.log(10) + 0.5); }
final String formatString = (digits == 0 ? ": %d" : "%0"+digits+"d: "); final int digits = (int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
StringBuffer retVal = new StringBuffer(); StringBuilder retVal = new StringBuilder();
retVal.append(String.format(Locale.ROOT, formatString, 0)); retVal.append(xpad(0, digits, ""));
int i = -1; retVal.append(": ");
for(int x = 0; x < value.length; x++) for(int x=0, i=-1; x < value.length; x++) {
{ if (++i == bytesPerLine) {
if (++i == bytesPerLine)
{
retVal.append('\n'); retVal.append('\n');
retVal.append(String.format(Locale.ROOT, formatString, x)); retVal.append(xpad(x, digits, ""));
retVal.append(": ");
i = 0; i = 0;
} else if (x>0) { } else if (x>0) {
retVal.append(", "); retVal.append(", ");
@ -262,7 +262,7 @@ public class HexDump {
* @return The result right padded with 0 * @return The result right padded with 0
*/ */
public static String toHex(final short value) { public static String toHex(final short value) {
return String.format(Locale.ROOT, "%04X", value); return xpad(value & 0xFFFF, 4, "");
} }
/** /**
@ -272,7 +272,7 @@ public class HexDump {
* @return The result right padded with 0 * @return The result right padded with 0
*/ */
public static String toHex(final byte value) { public static String toHex(final byte value) {
return String.format(Locale.ROOT, "%02X", value); return xpad(value & 0xFF, 2, "");
} }
/** /**
@ -282,7 +282,7 @@ public class HexDump {
* @return The result right padded with 0 * @return The result right padded with 0
*/ */
public static String toHex(final int value) { public static String toHex(final int value) {
return String.format(Locale.ROOT, "%08X", value); return xpad(value & 0xFFFFFFFF, 8, "");
} }
/** /**
@ -292,7 +292,7 @@ public class HexDump {
* @return The result right padded with 0 * @return The result right padded with 0
*/ */
public static String toHex(final long value) { public static String toHex(final long value) {
return String.format(Locale.ROOT, "%016X", value); return xpad(value & 0xFFFFFFFF, 16, "");
} }
/** /**
@ -336,30 +336,46 @@ public class HexDump {
* @return string of 16 (zero padded) uppercase hex chars and prefixed with '0x' * @return string of 16 (zero padded) uppercase hex chars and prefixed with '0x'
*/ */
public static String longToHex(long value) { public static String longToHex(long value) {
return String.format(Locale.ROOT, "0x%016X", value); return xpad(value, 16, "0x");
} }
/** /**
* @return string of 8 (zero padded) uppercase hex chars and prefixed with '0x' * @return string of 8 (zero padded) uppercase hex chars and prefixed with '0x'
*/ */
public static String intToHex(int value) { public static String intToHex(int value) {
return String.format(Locale.ROOT, "0x%08X", value & 0xFFFFFFFF); return xpad(value & 0xFFFFFFFF, 8, "0x");
} }
/** /**
* @return string of 4 (zero padded) uppercase hex chars and prefixed with '0x' * @return string of 4 (zero padded) uppercase hex chars and prefixed with '0x'
*/ */
public static String shortToHex(int value) { public static String shortToHex(int value) {
return String.format(Locale.ROOT, "0x%04X", value & 0xFFFF); return xpad(value & 0xFFFF, 4, "0x");
} }
/** /**
* @return string of 2 (zero padded) uppercase hex chars and prefixed with '0x' * @return string of 2 (zero padded) uppercase hex chars and prefixed with '0x'
*/ */
public static String byteToHex(int value) { public static String byteToHex(int value) {
return String.format(Locale.ROOT, "0x%02X", value & 0xFF); return xpad(value & 0xFF, 2, "0x");
} }
private static String xpad(long value, int pad, String prefix) {
String sv = Long.toHexString(value).toUpperCase(Locale.ROOT);
int len = sv.length();
if ((pad == 0 || len == pad) && "".equals(prefix)) return sv;
StringBuilder sb = new StringBuilder(prefix);
if (len < pad) {
sb.append("0000000000000000", 0, pad-len);
sb.append(sv);
} else if (len > pad) {
sb.append(sv, len-pad, len);
} else {
sb.append(sv);
}
return sb.toString();
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
File file = new File(args[0]); File file = new File(args[0]);
InputStream in = new BufferedInputStream(new FileInputStream(file)); InputStream in = new BufferedInputStream(new FileInputStream(file));

View File

@ -0,0 +1,136 @@
/* ====================================================================
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.util;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
/**
* This utility class is used to set locale and time zone settings beside
* of the JDK internal {@link java.util.Locale#setDefault(Locale)} and
* {@link java.util.TimeZone#setDefault(TimeZone)} methods, because
* the locale/time zone specific handling of certain office documents -
* maybe for different time zones / locales ... - shouldn't affect
* other java components.
*
* The settings are saved in a {@link java.lang.ThreadLocal},
* so they only apply to the current thread and can't be set globally.
*/
public class LocaleUtil {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
private static final ThreadLocal<TimeZone> userTimeZone = new ThreadLocal<TimeZone>() {
@Override
@SuppressForbidden
protected TimeZone initialValue() {
return TimeZone.getDefault();
}
};
private static final ThreadLocal<Locale> userLocale = new ThreadLocal<Locale>() {
@Override
@SuppressForbidden
protected Locale initialValue() {
return Locale.getDefault();
}
};
/**
* As time zone information is not stored in any format, it can be
* set before any date calculations take place.
* This setting is specific to the current thread.
*
* @param timezone the timezone under which date calculations take place
*/
public static void setUserTimeZone(TimeZone timezone) {
userTimeZone.set(timezone);
}
/**
* @return the time zone which is used for date calculations, defaults to UTC
*/
public static TimeZone getUserTimeZone() {
return userTimeZone.get();
}
/**
* Sets default user locale.
* This setting is specific to the current thread.
*/
public static void setUserLocale(Locale locale) {
userLocale.set(locale);
}
/**
* @return the default user locale, defaults to {@link Locale#ROOT}
*/
public static Locale getUserLocale() {
return userLocale.get();
}
/**
* @return a calendar for the user locale and time zone
*/
public static Calendar getLocaleCalendar() {
return getLocaleCalendar(getUserTimeZone());
}
/**
* Convenience method - month is 0-based as in java.util.Calendar
*
* @param year
* @param month
* @param day
* @return a calendar for the user locale and time zone, and the given date
*/
public static Calendar getLocaleCalendar(int year, int month, int day) {
return getLocaleCalendar(year, month, day, 0, 0, 0);
}
/**
* Convenience method - month is 0-based as in java.util.Calendar
*
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
* @return a calendar for the user locale and time zone, and the given date
*/
public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) {
Calendar cal = getLocaleCalendar();
cal.set(year, month, day, hour, minute, second);
cal.clear(Calendar.MILLISECOND);
return cal;
}
/**
* @return a calendar for the user locale and time zone
*/
public static Calendar getLocaleCalendar(TimeZone timeZone) {
return Calendar.getInstance(timeZone, getUserLocale());
}
}

View File

@ -0,0 +1,32 @@
/* ====================================================================
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.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* Marking class for elements to be ignored by the forbidden apis check
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SuppressForbidden {
}

View File

@ -22,8 +22,7 @@ import java.io.OutputStream;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
@ -33,6 +32,7 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageProperties; import org.apache.poi.openxml4j.opc.PackageProperties;
import org.apache.poi.openxml4j.util.Nullable; import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.LocaleUtil;
/** /**
* Represents the core properties part of a package. * Represents the core properties part of a package.
@ -559,9 +559,8 @@ public final class PackagePropertiesPart extends PackagePart implements
if (s == null || s.equals("")) { if (s == null || s.equals("")) {
return new Nullable<Date>(); return new Nullable<Date>();
} }
SimpleDateFormat df = new SimpleDateFormat( SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
"yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d = df.parse(s, new ParsePosition(0)); Date d = df.parse(s, new ParsePosition(0));
if (d == null) { if (d == null) {
throw new InvalidFormatException("Date not well formated"); throw new InvalidFormatException("Date not well formated");
@ -586,9 +585,8 @@ public final class PackagePropertiesPart extends PackagePart implements
return ""; return "";
} }
SimpleDateFormat df = new SimpleDateFormat( SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
"yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
return df.format(date); return df.format(date);
} }

View File

@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
@ -196,7 +197,7 @@ public class OOXMLSignatureFacet extends SignatureFacet {
/* /*
* SignatureTime * SignatureTime
*/ */
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
fmt.setTimeZone(TimeZone.getTimeZone("UTC")); fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String nowStr = fmt.format(signatureConfig.getExecutionTime()); String nowStr = fmt.format(signatureConfig.getExecutionTime());
LOG.log(POILogger.DEBUG, "now: " + nowStr); LOG.log(POILogger.DEBUG, "now: " + nowStr);

View File

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
@ -115,8 +116,7 @@ public class XAdESSignatureFacet extends SignatureFacet {
SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties(); SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties();
// SigningTime // SigningTime
Calendar xmlGregorianCalendar = Calendar.getInstance(); Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));
xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime()); xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime());
xmlGregorianCalendar.clear(Calendar.MILLISECOND); xmlGregorianCalendar.clear(Calendar.MILLISECOND);
signedSignatureProperties.setSigningTime(xmlGregorianCalendar); signedSignatureProperties.setSigningTime(xmlGregorianCalendar);

View File

@ -39,6 +39,8 @@ import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import javax.xml.crypto.MarshalException; import javax.xml.crypto.MarshalException;
@ -214,7 +216,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier(); CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier();
String issuerName = crl.getIssuerDN().getName().replace(",", ", "); String issuerName = crl.getIssuerDN().getName().replace(",", ", ");
crlIdentifier.setIssuer(issuerName); crlIdentifier.setIssuer(issuerName);
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(crl.getThisUpdate()); cal.setTime(crl.getThisUpdate());
crlIdentifier.setIssueTime(cal); crlIdentifier.setIssueTime(cal);
crlIdentifier.setNumber(getCrlNumber(crl)); crlIdentifier.setNumber(getCrlNumber(crl));
@ -238,7 +240,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject(); BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject();
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(basicOcspResp.getProducedAt()); cal.setTime(basicOcspResp.getProducedAt());
ocspIdentifier.setProducedAt(cal); ocspIdentifier.setProducedAt(cal);

View File

@ -26,6 +26,7 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@ -155,7 +156,7 @@ public class PPTX2PNG {
// save the result // save the result
if (!"null".equals(format)) { if (!"null".equals(format)) {
String outname = file.getName().replaceFirst(".pptx?", ""); String outname = file.getName().replaceFirst(".pptx?", "");
outname = String.format("%1$s-%2$04d.%3$s", outname, slideNo, format); outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format);
File outfile = new File(outdir, outname); File outfile = new File(outdir, outname);
ImageIO.write(img, format, outfile); ImageIO.write(img, format, outfile);
} }

View File

@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Vector; import java.util.Vector;
@ -314,7 +315,7 @@ public class XSSFExportToXml implements Comparator<String>{
} }
private String getFormattedDate(XSSFCell cell) { private String getFormattedDate(XSSFCell cell) {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
return sdf.format(cell.getDateCellValue()); return sdf.format(cell.getDateCellValue());
} }

View File

@ -35,6 +35,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFHyperlink; import org.apache.poi.xssf.usermodel.XSSFHyperlink;
@ -653,7 +654,7 @@ public class SXSSFCell implements Cell {
return getCellFormula(); return getCellFormula();
case CELL_TYPE_NUMERIC: case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) { if (DateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy"); DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue()); return sdf.format(getDateCellValue());
} }
return getNumericCellValue() + ""; return getNumericCellValue() + "";

View File

@ -21,6 +21,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaParser;
@ -840,7 +841,7 @@ public final class XSSFCell implements Cell {
return getCellFormula(); return getCellFormula();
case CELL_TYPE_NUMERIC: case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) { if (DateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy"); DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ROOT);
return sdf.format(getDateCellValue()); return sdf.format(getDateCellValue());
} }
return Double.toString(getNumericCellValue()); return Double.toString(getNumericCellValue());

View File

@ -17,37 +17,49 @@
package org.apache.poi; package org.apache.poi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import junit.framework.TestCase;
import org.apache.poi.POIXMLProperties.CoreProperties; import org.apache.poi.POIXMLProperties.CoreProperties;
import org.apache.poi.openxml4j.util.Nullable; import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/** /**
* Test setting extended and custom OOXML properties * Test setting extended and custom OOXML properties
*/ */
public final class TestPOIXMLProperties extends TestCase { public final class TestPOIXMLProperties {
private XWPFDocument sampleDoc;
private POIXMLProperties _props; private POIXMLProperties _props;
private CoreProperties _coreProperties; private CoreProperties _coreProperties;
@Before
public void setUp() throws IOException { public void setUp() throws IOException {
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx"); sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
_props = sampleDoc.getProperties(); _props = sampleDoc.getProperties();
_coreProperties = _props.getCoreProperties(); _coreProperties = _props.getCoreProperties();
assertNotNull(_props); assertNotNull(_props);
} }
@After
public void closeResources() throws Exception {
sampleDoc.close();
}
public void testWorkbookExtendedProperties() { @Test
public void testWorkbookExtendedProperties() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook(); XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties(); POIXMLProperties props = workbook.getProperties();
assertNotNull(props); assertNotNull(props);
@ -71,7 +83,7 @@ public final class TestPOIXMLProperties extends TestCase {
XSSFWorkbook newWorkbook = XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook); XSSFTestDataSamples.writeOutAndReadBack(workbook);
workbook.close();
assertTrue(workbook != newWorkbook); assertTrue(workbook != newWorkbook);
@ -88,16 +100,19 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals(application, newCtProps.getApplication()); assertEquals(application, newCtProps.getApplication());
assertEquals(appVersion, newCtProps.getAppVersion()); assertEquals(appVersion, newCtProps.getAppVersion());
newWorkbook.close();
} }
/** /**
* Test usermodel API for setting custom properties * Test usermodel API for setting custom properties
*/ */
public void testCustomProperties() { @Test
POIXMLDocument wb = new XSSFWorkbook(); public void testCustomProperties() throws Exception {
POIXMLDocument wb1 = new XSSFWorkbook();
POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties(); POIXMLProperties.CustomProperties customProps = wb1.getProperties().getCustomProperties();
customProps.addProperty("test-1", "string val"); customProps.addProperty("test-1", "string val");
customProps.addProperty("test-2", 1974); customProps.addProperty("test-2", 1974);
customProps.addProperty("test-3", 36.6); customProps.addProperty("test-3", 36.6);
@ -110,9 +125,10 @@ public final class TestPOIXMLProperties extends TestCase {
} }
customProps.addProperty("test-4", true); customProps.addProperty("test-4", true);
wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb); POIXMLDocument wb2 = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb1);
wb1.close();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps = org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps =
wb.getProperties().getCustomProperties().getUnderlyingProperties(); wb2.getProperties().getCustomProperties().getUnderlyingProperties();
assertEquals(4, ctProps.sizeOfPropertyArray()); assertEquals(4, ctProps.sizeOfPropertyArray());
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p; org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p;
@ -131,7 +147,7 @@ public final class TestPOIXMLProperties extends TestCase {
p = ctProps.getPropertyArray(2); p = ctProps.getPropertyArray(2);
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-3", p.getName()); assertEquals("test-3", p.getName());
assertEquals(36.6, p.getR8()); assertEquals(36.6, p.getR8(), 0);
assertEquals(4, p.getPid()); assertEquals(4, p.getPid());
p = ctProps.getPropertyArray(3); p = ctProps.getPropertyArray(3);
@ -139,9 +155,12 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("test-4", p.getName()); assertEquals("test-4", p.getName());
assertEquals(true, p.getBool()); assertEquals(true, p.getBool());
assertEquals(5, p.getPid()); assertEquals(5, p.getPid());
wb2.close();
} }
public void testDocumentProperties() { @Test
public void testDocumentProperties() {
String category = _coreProperties.getCategory(); String category = _coreProperties.getCategory();
assertEquals("test", category); assertEquals("test", category);
String contentStatus = "Draft"; String contentStatus = "Draft";
@ -158,21 +177,25 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("Hello World", title); assertEquals("Hello World", title);
} }
public void testTransitiveSetters() throws IOException { @Test
public void testTransitiveSetters() throws IOException {
XWPFDocument doc = new XWPFDocument(); XWPFDocument doc = new XWPFDocument();
CoreProperties cp = doc.getProperties().getCoreProperties(); CoreProperties cp = doc.getProperties().getCoreProperties();
Date dateCreated = new GregorianCalendar(2010, 6, 15, 10, 0, 0).getTime();
Date dateCreated = LocaleUtil.getLocaleCalendar(2010, 6, 15, 10, 0, 0).getTime();
cp.setCreated(new Nullable<Date>(dateCreated)); cp.setCreated(new Nullable<Date>(dateCreated));
assertEquals(dateCreated.toString(), cp.getCreated().toString()); assertEquals(dateCreated.toString(), cp.getCreated().toString());
doc = XWPFTestDataSamples.writeOutAndReadBack(doc); XWPFDocument doc2 = XWPFTestDataSamples.writeOutAndReadBack(doc);
doc.close();
cp = doc.getProperties().getCoreProperties(); cp = doc.getProperties().getCoreProperties();
Date dt3 = cp.getCreated(); Date dt3 = cp.getCreated();
assertEquals(dateCreated.toString(), dt3.toString()); assertEquals(dateCreated.toString(), dt3.toString());
doc2.close();
} }
@Test
public void testGetSetRevision() { public void testGetSetRevision() {
String revision = _coreProperties.getRevision(); String revision = _coreProperties.getRevision();
assertTrue("Revision number is 1", Integer.parseInt(revision) > 1); assertTrue("Revision number is 1", Integer.parseInt(revision) > 1);
@ -183,7 +206,7 @@ public final class TestPOIXMLProperties extends TestCase {
} }
public static boolean dateTimeEqualToUTCString(Date dateTime, String utcString) { public static boolean dateTimeEqualToUTCString(Date dateTime, String utcString) {
Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.UK); Calendar utcCalendar = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
utcCalendar.setTimeInMillis(dateTime.getTime()); utcCalendar.setTimeInMillis(dateTime.getTime());
String dateTimeUtcString = utcCalendar.get(Calendar.YEAR) + "-" + String dateTimeUtcString = utcCalendar.get(Calendar.YEAR) + "-" +
zeroPad((utcCalendar.get(Calendar.MONTH)+1)) + "-" + zeroPad((utcCalendar.get(Calendar.MONTH)+1)) + "-" +

View File

@ -17,111 +17,97 @@
package org.apache.poi.openxml4j.opc; package org.apache.poi.openxml4j.opc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.Locale;
import junit.framework.TestCase;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable; import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
public final class TestPackageCoreProperties extends TestCase { public final class TestPackageCoreProperties {
private static final POILogger logger = POILogFactory.getLogger(TestPackageCoreProperties.class);
/** /**
* Test package core properties getters. * Test package core properties getters.
*/ */
public void testGetProperties() { @Test
try { public void testGetProperties() throws Exception {
// Open the package // Open the package
OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx")); @SuppressWarnings("resource")
compareProperties(p); OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx"));
p.revert(); compareProperties(p);
} catch (OpenXML4JException e) { p.revert();
logger.log(POILogger.DEBUG, e.getMessage());
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
/** /**
* Test package core properties setters. * Test package core properties setters.
*/ */
public void testSetProperties() throws Exception { @Test
public void testSetProperties() throws Exception {
String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx"); String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx");
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx"); File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx");
// Open package // Open package
OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE); @SuppressWarnings("resource")
try { OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(TimeZone.getTimeZone("UTC")); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition( Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));
0));
PackageProperties props = p.getPackageProperties();
PackageProperties props = p.getPackageProperties(); props.setCategoryProperty("MyCategory");
props.setCategoryProperty("MyCategory"); props.setContentStatusProperty("MyContentStatus");
props.setContentStatusProperty("MyContentStatus"); props.setContentTypeProperty("MyContentType");
props.setContentTypeProperty("MyContentType"); props.setCreatedProperty(new Nullable<Date>(dateToInsert));
props.setCreatedProperty(new Nullable<Date>(dateToInsert)); props.setCreatorProperty("MyCreator");
props.setCreatorProperty("MyCreator"); props.setDescriptionProperty("MyDescription");
props.setDescriptionProperty("MyDescription"); props.setIdentifierProperty("MyIdentifier");
props.setIdentifierProperty("MyIdentifier"); props.setKeywordsProperty("MyKeywords");
props.setKeywordsProperty("MyKeywords"); props.setLanguageProperty("MyLanguage");
props.setLanguageProperty("MyLanguage"); props.setLastModifiedByProperty("Julien Chable");
props.setLastModifiedByProperty("Julien Chable"); props.setLastPrintedProperty(new Nullable<Date>(dateToInsert));
props.setLastPrintedProperty(new Nullable<Date>(dateToInsert)); props.setModifiedProperty(new Nullable<Date>(dateToInsert));
props.setModifiedProperty(new Nullable<Date>(dateToInsert)); props.setRevisionProperty("2");
props.setRevisionProperty("2"); props.setTitleProperty("MyTitle");
props.setTitleProperty("MyTitle"); props.setSubjectProperty("MySubject");
props.setSubjectProperty("MySubject"); props.setVersionProperty("2");
props.setVersionProperty("2"); // Save the package in the output directory
// Save the package in the output directory p.save(outputFile);
p.save(outputFile); p.revert();
// Open the newly created file to check core properties saved values. // Open the newly created file to check core properties saved values.
OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ); @SuppressWarnings("resource")
try { OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ);
compareProperties(p2); compareProperties(p2);
p2.revert(); p2.revert();
} finally { outputFile.delete();
p2.close();
}
outputFile.delete();
} finally {
// use revert to not re-write the input file
p.revert();
}
} }
private void compareProperties(OPCPackage p) throws InvalidFormatException { private void compareProperties(OPCPackage p) throws InvalidFormatException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(TimeZone.getTimeZone("UTC")); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition( Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));
0));
// Gets the core properties // Gets the core properties
PackageProperties props = p.getPackageProperties(); PackageProperties props = p.getPackageProperties();
assertEquals("MyCategory", props.getCategoryProperty().getValue()); assertEquals("MyCategory", props.getCategoryProperty().getValue());
assertEquals("MyContentStatus", props.getContentStatusProperty() assertEquals("MyContentStatus", props.getContentStatusProperty().getValue());
.getValue());
assertEquals("MyContentType", props.getContentTypeProperty().getValue()); assertEquals("MyContentType", props.getContentTypeProperty().getValue());
assertEquals(expectedDate, props.getCreatedProperty().getValue()); assertEquals(expectedDate, props.getCreatedProperty().getValue());
assertEquals("MyCreator", props.getCreatorProperty().getValue()); assertEquals("MyCreator", props.getCreatorProperty().getValue());
@ -129,8 +115,7 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("MyIdentifier", props.getIdentifierProperty().getValue()); assertEquals("MyIdentifier", props.getIdentifierProperty().getValue());
assertEquals("MyKeywords", props.getKeywordsProperty().getValue()); assertEquals("MyKeywords", props.getKeywordsProperty().getValue());
assertEquals("MyLanguage", props.getLanguageProperty().getValue()); assertEquals("MyLanguage", props.getLanguageProperty().getValue());
assertEquals("Julien Chable", props.getLastModifiedByProperty() assertEquals("Julien Chable", props.getLastModifiedByProperty().getValue());
.getValue());
assertEquals(expectedDate, props.getLastPrintedProperty().getValue()); assertEquals(expectedDate, props.getLastPrintedProperty().getValue());
assertEquals(expectedDate, props.getModifiedProperty().getValue()); assertEquals(expectedDate, props.getModifiedProperty().getValue());
assertEquals("2", props.getRevisionProperty().getValue()); assertEquals("2", props.getRevisionProperty().getValue());
@ -139,9 +124,10 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("2", props.getVersionProperty().getValue()); assertEquals("2", props.getVersionProperty().getValue());
} }
public void testCoreProperties_bug51374() throws Exception { @Test
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); public void testCoreProperties_bug51374() throws Exception {
df.setTimeZone(TimeZone.getTimeZone("UTC")); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
String strDate = "2007-05-12T08:00:00Z"; String strDate = "2007-05-12T08:00:00Z";
Date date = df.parse(strDate); Date date = df.parse(strDate);
@ -197,7 +183,8 @@ public final class TestPackageCoreProperties extends TestCase {
pkg.close(); pkg.close();
} }
public void testGetPropertiesLO() throws Exception { @Test
public void testGetPropertiesLO() throws Exception {
// Open the package // Open the package
OPCPackage pkg1 = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("51444.xlsx")); OPCPackage pkg1 = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("51444.xlsx"));
PackageProperties props1 = pkg1.getPackageProperties(); PackageProperties props1 = pkg1.getPackageProperties();
@ -206,13 +193,16 @@ public final class TestPackageCoreProperties extends TestCase {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
pkg1.save(out); pkg1.save(out);
out.close(); out.close();
pkg1.close();
OPCPackage pkg2 = OPCPackage.open(new ByteArrayInputStream(out.toByteArray())); OPCPackage pkg2 = OPCPackage.open(new ByteArrayInputStream(out.toByteArray()));
PackageProperties props2 = pkg2.getPackageProperties(); PackageProperties props2 = pkg2.getPackageProperties();
props2.setTitleProperty("Bug 51444 fixed"); props2.setTitleProperty("Bug 51444 fixed");
pkg2.close();
} }
public void testEntitiesInCoreProps_56164() throws Exception { @Test
public void testEntitiesInCoreProps_56164() throws Exception {
InputStream is = OpenXML4JTestDataSamples.openSampleStream("CorePropertiesHasEntities.ooxml"); InputStream is = OpenXML4JTestDataSamples.openSampleStream("CorePropertiesHasEntities.ooxml");
OPCPackage p = OPCPackage.open(is); OPCPackage p = OPCPackage.open(is);
is.close(); is.close();
@ -236,9 +226,12 @@ public final class TestPackageCoreProperties extends TestCase {
// Check // Check
assertEquals("Stefan Kopf", props.getCreatorProperty().getValue()); assertEquals("Stefan Kopf", props.getCreatorProperty().getValue());
p.close();
} }
public void testListOfCustomProperties() throws Exception { @Test
public void testListOfCustomProperties() throws Exception {
File inp = POIDataSamples.getSpreadSheetInstance().getFile("ExcelWithAttachments.xlsm"); File inp = POIDataSamples.getSpreadSheetInstance().getFile("ExcelWithAttachments.xlsm");
OPCPackage pkg = OPCPackage.open(inp, PackageAccess.READ); OPCPackage pkg = OPCPackage.open(inp, PackageAccess.READ);
XSSFWorkbook wb = new XSSFWorkbook(pkg); XSSFWorkbook wb = new XSSFWorkbook(pkg);

View File

@ -16,14 +16,36 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.ss.format; package org.apache.poi.ss.format;
import org.apache.poi.ss.usermodel.Cell; import static org.junit.Assert.assertEquals;
import org.apache.poi.xssf.XSSFITestDataProvider;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/** Test the individual CellFormatPart types. */ /** Test the individual CellFormatPart types. */
public class TestCellFormatPart extends CellFormatTestBase { public class TestCellFormatPart extends CellFormatTestBase {
private static Locale userLocale;
@BeforeClass
public static void setLocale() {
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
}
@AfterClass
public static void unsetLocale() {
LocaleUtil.setUserLocale(userLocale);
}
private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile( private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile(
"([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))", "([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))",
Pattern.CASE_INSENSITIVE); Pattern.CASE_INSENSITIVE);
@ -32,6 +54,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
super(XSSFITestDataProvider.instance); super(XSSFITestDataProvider.instance);
} }
@Test
public void testGeneralFormat() throws Exception { public void testGeneralFormat() throws Exception {
runFormatTests("GeneralFormatTests.xlsx", new CellValue() { runFormatTests("GeneralFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) { public Object getValue(Cell cell) {
@ -54,6 +77,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
}); });
} }
@Test
public void testNumberApproxFormat() throws Exception { public void testNumberApproxFormat() throws Exception {
runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() { runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() {
public Object getValue(Cell cell) { public Object getValue(Cell cell) {
@ -73,14 +97,22 @@ public class TestCellFormatPart extends CellFormatTestBase {
}); });
} }
@Test
public void testDateFormat() throws Exception { public void testDateFormat() throws Exception {
runFormatTests("DateFormatTests.xlsx", new CellValue() { TimeZone tz = LocaleUtil.getUserTimeZone();
public Object getValue(Cell cell) { LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
return cell.getDateCellValue(); try {
} runFormatTests("DateFormatTests.xlsx", new CellValue() {
}); public Object getValue(Cell cell) {
return cell.getDateCellValue();
}
});
} finally {
LocaleUtil.setUserTimeZone(tz);
}
} }
@Test
public void testElapsedFormat() throws Exception { public void testElapsedFormat() throws Exception {
runFormatTests("ElapsedFormatTests.xlsx", new CellValue() { runFormatTests("ElapsedFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) { public Object getValue(Cell cell) {
@ -89,6 +121,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
}); });
} }
@Test
public void testTextFormat() throws Exception { public void testTextFormat() throws Exception {
runFormatTests("TextFormatTests.xlsx", new CellValue() { runFormatTests("TextFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) { public Object getValue(Cell cell) {
@ -100,6 +133,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
}); });
} }
@Test
public void testConditions() throws Exception { public void testConditions() throws Exception {
runFormatTests("FormatConditionTests.xlsx", new CellValue() { runFormatTests("FormatConditionTests.xlsx", new CellValue() {
Object getValue(Cell cell) { Object getValue(Cell cell) {

View File

@ -17,13 +17,13 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import static org.junit.Assert.assertEquals;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.streaming.SXSSFCell; import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCell;
import org.junit.Test;
/** /**
* Class for combined testing of XML-specific functionality of * Class for combined testing of XML-specific functionality of
@ -37,6 +37,7 @@ public abstract class BaseTestXCell extends BaseTestCell {
super(testDataProvider); super(testDataProvider);
} }
@Test
public void testXmlEncoding(){ public void testXmlEncoding(){
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet(); Sheet sh = wb.createSheet();

View File

@ -19,6 +19,8 @@
package org.apache.poi.xssf.streaming; package org.apache.poi.xssf.streaming;
import static org.junit.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
@ -30,6 +32,8 @@ import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlCursor;
import org.junit.AfterClass;
import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
/** /**
@ -42,11 +46,12 @@ public class TestSXSSFCell extends BaseTestXCell {
super(SXSSFITestDataProvider.instance); super(SXSSFITestDataProvider.instance);
} }
@Override @AfterClass
public void tearDown(){ public static void tearDown(){
SXSSFITestDataProvider.instance.cleanup(); SXSSFITestDataProvider.instance.cleanup();
} }
@Test
public void testPreserveSpaces() throws IOException { public void testPreserveSpaces() throws IOException {
String[] samplesWithSpaces = { String[] samplesWithSpaces = {
" POI", " POI",

View File

@ -17,14 +17,18 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import java.io.InputStream; import static org.junit.Assert.assertEquals;
import java.io.PrintStream; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import junit.framework.Assert; import java.util.ArrayList;
import junit.framework.AssertionFailedError; import java.util.Collection;
import junit.framework.TestCase; import java.util.List;
import java.util.Locale;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet; import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet;
import org.apache.poi.ss.formula.functions.TestMathX; import org.apache.poi.ss.formula.functions.TestMathX;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
@ -32,7 +36,13 @@ import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
/** /**
* Performs much the same role as {@link TestFormulasFromSpreadsheet}, * Performs much the same role as {@link TestFormulasFromSpreadsheet},
@ -44,206 +54,127 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
* Excel 2007, and re-save it as FormulaEvalTestData_Copy.xlsx * Excel 2007, and re-save it as FormulaEvalTestData_Copy.xlsx
* *
*/ */
public final class TestFormulaEvaluatorOnXSSF extends TestCase { @RunWith(Parameterized.class)
public final class TestFormulaEvaluatorOnXSSF {
private static final class Result {
public static final int SOME_EVALUATIONS_FAILED = -1;
public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
public static final int NO_EVALUATIONS_FOUND = 0;
}
private static XSSFWorkbook workbook;
private static Sheet sheet;
private static FormulaEvaluator evaluator;
private static Locale userLocale;
/** /**
* This class defines constants for navigating around the test data spreadsheet used for these tests. * This class defines constants for navigating around the test data spreadsheet used for these tests.
*/ */
private static final class SS { private static interface SS {
/** /**
* Name of the test spreadsheet (found in the standard test data folder) * Name of the test spreadsheet (found in the standard test data folder)
*/ */
public final static String FILENAME = "FormulaEvalTestData_Copy.xlsx"; String FILENAME = "FormulaEvalTestData_Copy.xlsx";
/** /**
* Row (zero-based) in the test spreadsheet where the operator examples start. * Row (zero-based) in the test spreadsheet where the operator examples start.
*/ */
public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23' int START_OPERATORS_ROW_INDEX = 22; // Row '23'
/** /**
* Row (zero-based) in the test spreadsheet where the function examples start. * Row (zero-based) in the test spreadsheet where the function examples start.
*/ */
public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96' int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/** /**
* Index of the column that contains the function names * Index of the column that contains the function names
*/ */
public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B' int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
/** /**
* Used to indicate when there are no more functions left * Used to indicate when there are no more functions left
*/ */
public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>"; String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
/** /**
* Index of the column where the test values start (for each function) * Index of the column where the test values start (for each function)
*/ */
public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D' short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
/** /**
* Each function takes 4 rows in the test spreadsheet * Each function takes 4 rows in the test spreadsheet
*/ */
public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4; int NUMBER_OF_ROWS_PER_FUNCTION = 4;
} }
private XSSFWorkbook workbook; @Parameter(value = 0)
private Sheet sheet; public String targetFunctionName;
// Note - multiple failures are aggregated before ending. @Parameter(value = 1)
// If one or more functions fail, a single AssertionFailedError is thrown at the end public int formulasRowIdx;
private int _functionFailureCount; @Parameter(value = 2)
private int _functionSuccessCount; public int expectedValuesRowIdx;
private int _evaluationFailureCount;
private int _evaluationSuccessCount;
private static final Cell getExpectedValueCell(Row row, short columnIndex) { @AfterClass
if (row == null) { public static void closeResource() throws Exception {
return null; LocaleUtil.setUserLocale(userLocale);
} workbook.close();
return row.getCell(columnIndex); }
}
@Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
// Function "Text" uses custom-formats which are locale specific
// can't set the locale on a per-testrun execution, as some settings have been
// already set, when we would try to change the locale by then
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
workbook = new XSSFWorkbook( OPCPackage.open(HSSFTestDataSamples.getSampleFile(SS.FILENAME), PackageAccess.READ) );
sheet = workbook.getSheetAt( 0 );
evaluator = new XSSFFormulaEvaluator(workbook);
List<Object[]> data = new ArrayList<Object[]>();
processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, "Text");
return data;
}
/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private static void processFunctionGroup(List<Object[]> data, int startRowIndex, String testFocusFunctionName) {
for (int rowIndex = startRowIndex; true; rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
if(targetFunctionName == null) {
fail("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'");
}
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
if(expectedValuesRow == null) {
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
fail("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")");
}
data.add(new Object[]{targetFunctionName, rowIndex, rowIndex + 1});
}
}
}
private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) { @Test
if (expected == null) { public void processFunctionRow() {
throw new AssertionFailedError(msg + " - Bad setup data expected value is null"); Row formulasRow = sheet.getRow(formulasRowIdx);
} Row expectedValuesRow = sheet.getRow(expectedValuesRowIdx);
if(actual == null) {
throw new AssertionFailedError(msg + " - actual value was null");
}
switch (expected.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType());
assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType());
if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
assertEquals(msg, expected.getErrorCellValue(), actual.getErrorValue());
}
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
// double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
// assertTrue(msg, delta <= pctExpected);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
break;
}
}
protected void setUp() throws Exception {
if (workbook == null) {
InputStream is = HSSFTestDataSamples.openSampleFileStream(SS.FILENAME);
OPCPackage pkg = OPCPackage.open(is);
workbook = new XSSFWorkbook( pkg );
sheet = workbook.getSheetAt( 0 );
}
_functionFailureCount = 0;
_functionSuccessCount = 0;
_evaluationFailureCount = 0;
_evaluationSuccessCount = 0;
}
/**
* Checks that we can actually open the file
*/
public void testOpen() {
assertNotNull(workbook);
}
/**
* Disabled for now, as many things seem to break
* for XSSF, which is a shame
*/
public void testFunctionsFromTestSpreadsheet() {
processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
// confirm results
String successMsg = "There were "
+ _evaluationSuccessCount + " successful evaluation(s) and "
+ _functionSuccessCount + " function(s) without error";
if(_functionFailureCount > 0) {
String msg = _functionFailureCount + " function(s) failed in "
+ _evaluationFailureCount + " evaluation(s). " + successMsg;
throw new AssertionFailedError(msg);
}
if(false) { // normally no output for successful tests
System.out.println(getClass().getName() + ": " + successMsg);
}
}
/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
FormulaEvaluator evaluator = new XSSFFormulaEvaluator(workbook);
int rowIndex = startRowIndex;
while (true) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
if(targetFunctionName == null) {
throw new AssertionFailedError("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'");
}
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
if(expectedValuesRow == null) {
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
throw new AssertionFailedError("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")");
}
switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
default:
throw new RuntimeException("unexpected result");
case Result.NO_EVALUATIONS_FOUND: // do nothing
}
}
rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
}
}
/**
*
* @return a constant from the local Result class denoting whether there were any evaluation
* cases, and whether they all succeeded.
*/
private int processFunctionRow(FormulaEvaluator evaluator, String targetFunctionName,
Row formulasRow, Row expectedValuesRow) {
int result = Result.NO_EVALUATIONS_FOUND; // so far
short endcolnum = formulasRow.getLastCellNum(); short endcolnum = formulasRow.getLastCellNum();
// iterate across the row for all the evaluation cases // iterate across the row for all the evaluation cases
@ -256,31 +187,44 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
continue; continue;
} }
CellValue actualValue; CellValue actValue = evaluator.evaluate(c);
try { Cell expValue = (expectedValuesRow == null) ? null : expectedValuesRow.getCell(colnum);
actualValue = evaluator.evaluate(c);
} catch (RuntimeException e) {
_evaluationFailureCount ++;
printShortStackTrace(System.err, e);
result = Result.SOME_EVALUATIONS_FAILED;
continue;
}
Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum); String msg = String.format(Locale.ROOT, "Function '%s': Formula: %s @ %d:%d"
try { , targetFunctionName, c.getCellFormula(), formulasRow.getRowNum(), colnum);
confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
expectedValueCell, actualValue); assertNotNull(msg + " - Bad setup data expected value is null", expValue);
_evaluationSuccessCount ++; assertNotNull(msg + " - actual value was null", actValue);
if(result != Result.SOME_EVALUATIONS_FAILED) {
result = Result.ALL_EVALUATIONS_SUCCEEDED; switch (expValue.getCellType()) {
} case Cell.CELL_TYPE_BLANK:
} catch (AssertionFailedError e) { assertEquals(msg, Cell.CELL_TYPE_BLANK, actValue.getCellType());
_evaluationFailureCount ++; break;
printShortStackTrace(System.err, e); case Cell.CELL_TYPE_BOOLEAN:
result = Result.SOME_EVALUATIONS_FAILED; assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actValue.getCellType());
} assertEquals(msg, expValue.getBooleanCellValue(), actValue.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actValue.getCellType());
// if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
// assertEquals(msg, expValue.getErrorCellValue(), actValue.getErrorValue());
// }
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actValue.getCellType());
TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expValue.getNumericCellValue()-actValue.getNumberValue());
// double pctExpValue = Math.abs(0.00001*expValue.getNumericCellValue());
// assertTrue(msg, delta <= pctExpValue);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actValue.getCellType());
assertEquals(msg, expValue.getRichStringCellValue().getString(), actValue.getStringValue());
break;
}
} }
return result;
} }
/* /*
@ -301,40 +245,6 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
return false; return false;
} }
/**
* Useful to keep output concise when expecting many failures to be reported by this test case
*/
private static void printShortStackTrace(PrintStream ps, Throwable e) {
StackTraceElement[] stes = e.getStackTrace();
int startIx = 0;
// skip any top frames inside junit.framework.Assert
while(startIx<stes.length) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}
/** /**
* @return <code>null</code> if cell is missing, empty or blank * @return <code>null</code> if cell is missing, empty or blank
*/ */
@ -355,7 +265,7 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
return cell.getRichStringCellValue().getString(); return cell.getRichStringCellValue().getString();
} }
throw new AssertionFailedError("Bad cell type for 'function name' column: (" fail("Bad cell type for 'function name' column: ("+cell.getColumnIndex()+") row ("+(r.getRowNum()+1)+")");
+ cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")"); return null;
} }
} }

View File

@ -17,6 +17,12 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -25,10 +31,6 @@ import java.io.OutputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
@ -42,6 +44,7 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil; import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook;
@ -57,7 +60,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
* Bugzilla id's PLEASE MOVE tests from this class to TestBugs once the bugs are * Bugzilla id's PLEASE MOVE tests from this class to TestBugs once the bugs are
* fixed, so that they are then run automatically. * fixed, so that they are then run automatically.
*/ */
public final class TestUnfixedBugs extends TestCase { public final class TestUnfixedBugs {
@Test
public void testBug54084Unicode() throws IOException { public void testBug54084Unicode() throws IOException {
// sample XLSX with the same text-contents as the text-file above // sample XLSX with the same text-contents as the text-file above
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx"); XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx");
@ -76,8 +80,14 @@ public final class TestUnfixedBugs extends TestCase {
verifyBug54084Unicode(wbWritten); verifyBug54084Unicode(wbWritten);
// finally also write it out via the streaming interface and verify that we still can read it back in // finally also write it out via the streaming interface and verify that we still can read it back in
Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(new SXSSFWorkbook(wb)); SXSSFWorkbook swb = new SXSSFWorkbook(wb);
Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb);
verifyBug54084Unicode(wbStreamingWritten); verifyBug54084Unicode(wbStreamingWritten);
wbWritten.close();
swb.close();
wbStreamingWritten.close();
wb.close();
} }
private void verifyBug54084Unicode(Workbook wb) { private void verifyBug54084Unicode(Workbook wb) {
@ -95,7 +105,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value); assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value);
} }
public void test54071() { @Test
public void test54071() throws Exception {
Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx"); Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx");
Sheet sheet = workbook.getSheetAt(0); Sheet sheet = workbook.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows(); int rows = sheet.getPhysicalNumberOfRows();
@ -120,8 +131,11 @@ public final class TestUnfixedBugs extends TestCase {
} }
} }
} }
workbook.close();
} }
@Test
public void test54071Simple() { public void test54071Simple() {
double value1 = 41224.999988425923; double value1 = 41224.999988425923;
double value2 = 41224.999988368058; double value2 = 41224.999988368058;
@ -143,15 +157,13 @@ public final class TestUnfixedBugs extends TestCase {
// second to be different here! // second to be different here!
int startYear = 1900; int startYear = 1900;
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
Calendar calendar1 = new GregorianCalendar(Locale.ROOT); Calendar calendar1 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays1 + dayAdjust);
calendar1.set(startYear,0, wholeDays1 + dayAdjust, 0, 0, 0);
calendar1.set(Calendar.MILLISECOND, millisecondsInDay1); calendar1.set(Calendar.MILLISECOND, millisecondsInDay1);
// this is the rounding part: // this is the rounding part:
calendar1.add(Calendar.MILLISECOND, 500); calendar1.add(Calendar.MILLISECOND, 500);
calendar1.clear(Calendar.MILLISECOND); calendar1.clear(Calendar.MILLISECOND);
Calendar calendar2 = new GregorianCalendar(Locale.ROOT); Calendar calendar2 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays2 + dayAdjust);
calendar2.set(startYear,0, wholeDays2 + dayAdjust, 0, 0, 0);
calendar2.set(Calendar.MILLISECOND, millisecondsInDay2); calendar2.set(Calendar.MILLISECOND, millisecondsInDay2);
// this is the rounding part: // this is the rounding part:
calendar2.add(Calendar.MILLISECOND, 500); calendar2.add(Calendar.MILLISECOND, 500);
@ -163,7 +175,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals(DateUtil.getJavaDate(value1, false), DateUtil.getJavaDate(value2, false)); assertEquals(DateUtil.getJavaDate(value1, false), DateUtil.getJavaDate(value2, false));
} }
public void test57236() { @Test
public void test57236() throws Exception {
// Having very small numbers leads to different formatting, Excel uses the scientific notation, but POI leads to "0" // Having very small numbers leads to different formatting, Excel uses the scientific notation, but POI leads to "0"
/* /*
@ -189,10 +202,12 @@ public final class TestUnfixedBugs extends TestCase {
} }
} }
} }
wb.close();
} }
// When this is fixed, the test case should go to BaseTestXCell with // When this is fixed, the test case should go to BaseTestXCell with
// adjustments to use _testDataProvider to also verify this for XSSF // adjustments to use _testDataProvider to also verify this for XSSF
@Test
public void testBug57294() throws IOException { public void testBug57294() throws IOException {
Workbook wb = SXSSFITestDataProvider.instance.createWorkbook(); Workbook wb = SXSSFITestDataProvider.instance.createWorkbook();
@ -217,6 +232,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals(0, strBack.getIndexOfFormattingRun(0)); assertEquals(0, strBack.getIndexOfFormattingRun(0));
assertEquals(2, strBack.getIndexOfFormattingRun(1)); assertEquals(2, strBack.getIndexOfFormattingRun(1));
assertEquals(4, strBack.getIndexOfFormattingRun(2)); assertEquals(4, strBack.getIndexOfFormattingRun(2));
wbBack.close();
} }
@Test @Test

View File

@ -17,6 +17,11 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
@ -34,6 +39,7 @@ import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.SharedStringsTable;
import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
@ -50,6 +56,7 @@ public final class TestXSSFCell extends BaseTestXCell {
* Bug 47026: trouble changing cell type when workbook doesn't contain * Bug 47026: trouble changing cell type when workbook doesn't contain
* Shared String Table * Shared String Table
*/ */
@Test
public void test47026_1() { public void test47026_1() {
Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm"); Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm");
Sheet sheet = source.getSheetAt(0); Sheet sheet = source.getSheetAt(0);
@ -59,6 +66,7 @@ public final class TestXSSFCell extends BaseTestXCell {
cell.setCellValue("456"); cell.setCellValue("456");
} }
@Test
public void test47026_2() { public void test47026_2() {
Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm"); Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm");
Sheet sheet = source.getSheetAt(0); Sheet sheet = source.getSheetAt(0);
@ -75,6 +83,7 @@ public final class TestXSSFCell extends BaseTestXCell {
* Some programs, for example, Microsoft Excel Driver for .xlsx insert inline string * Some programs, for example, Microsoft Excel Driver for .xlsx insert inline string
* instead of using the shared string table. See bug 47206 * instead of using the shared string table. See bug 47206
*/ */
@Test
public void testInlineString() { public void testInlineString() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("xlsx-jdbc.xlsx"); XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("xlsx-jdbc.xlsx");
XSSFSheet sheet = wb.getSheetAt(0); XSSFSheet sheet = wb.getSheetAt(0);
@ -99,6 +108,7 @@ public final class TestXSSFCell extends BaseTestXCell {
/** /**
* Bug 47278 - xsi:nil attribute for <t> tag caused Excel 2007 to fail to open workbook * Bug 47278 - xsi:nil attribute for <t> tag caused Excel 2007 to fail to open workbook
*/ */
@Test
public void test47278() { public void test47278() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook(); XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();
@ -121,6 +131,7 @@ public final class TestXSSFCell extends BaseTestXCell {
assertEquals(Cell.CELL_TYPE_BLANK, cell_1.getCellType()); assertEquals(Cell.CELL_TYPE_BLANK, cell_1.getCellType());
} }
@Test
public void testFormulaString() throws IOException { public void testFormulaString() throws IOException {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook(); XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook();
try { try {
@ -162,6 +173,7 @@ public final class TestXSSFCell extends BaseTestXCell {
/** /**
* Bug 47889: problems when calling XSSFCell.getStringCellValue() on a workbook created in Gnumeric * Bug 47889: problems when calling XSSFCell.getStringCellValue() on a workbook created in Gnumeric
*/ */
@Test
public void test47889() { public void test47889() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("47889.xlsx"); XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("47889.xlsx");
XSSFSheet sh = wb.getSheetAt(0); XSSFSheet sh = wb.getSheetAt(0);
@ -180,13 +192,14 @@ public final class TestXSSFCell extends BaseTestXCell {
//try a numeric cell //try a numeric cell
cell = sh.getRow(1).getCell(0); cell = sh.getRow(1).getCell(0);
assertEquals(XSSFCell.CELL_TYPE_NUMERIC, cell.getCellType()); assertEquals(XSSFCell.CELL_TYPE_NUMERIC, cell.getCellType());
assertEquals(1.0, cell.getNumericCellValue()); assertEquals(1.0, cell.getNumericCellValue(), 0);
assertEquals("1.0", cell.toString()); assertEquals("1.0", cell.toString());
//Gnumeric produces spreadsheets without styles //Gnumeric produces spreadsheets without styles
//make sure we return null for that instead of throwing OutOfBounds //make sure we return null for that instead of throwing OutOfBounds
assertEquals(null, cell.getCellStyle()); assertEquals(null, cell.getCellStyle());
} }
@Test
public void testMissingRAttribute() { public void testMissingRAttribute() {
XSSFWorkbook wb = new XSSFWorkbook(); XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet(); XSSFSheet sheet = wb.createSheet();
@ -238,6 +251,7 @@ public final class TestXSSFCell extends BaseTestXCell {
assertEquals("F1", a6.getReference()); assertEquals("F1", a6.getReference());
} }
@Test
public void testMissingRAttributeBug54288() { public void testMissingRAttributeBug54288() {
// workbook with cells missing the R attribute // workbook with cells missing the R attribute
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("54288.xlsx"); XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("54288.xlsx");
@ -278,6 +292,7 @@ public final class TestXSSFCell extends BaseTestXCell {
} }
} }
@Test
public void test56170() throws IOException { public void test56170() throws IOException {
final Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56170.xlsx"); final Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56170.xlsx");
final XSSFSheet sheet = (XSSFSheet) wb.getSheetAt(0); final XSSFSheet sheet = (XSSFSheet) wb.getSheetAt(0);
@ -326,6 +341,7 @@ public final class TestXSSFCell extends BaseTestXCell {
stream.close();*/ stream.close();*/
} }
@Test
public void test56170Reproduce() throws IOException { public void test56170Reproduce() throws IOException {
final Workbook wb = new XSSFWorkbook(); final Workbook wb = new XSSFWorkbook();
try { try {
@ -370,6 +386,7 @@ public final class TestXSSFCell extends BaseTestXCell {
} }
} }
@Test
public void testBug56644ReturnNull() throws IOException { public void testBug56644ReturnNull() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx"); Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try { try {
@ -382,6 +399,7 @@ public final class TestXSSFCell extends BaseTestXCell {
} }
} }
@Test
public void testBug56644ReturnBlank() throws IOException { public void testBug56644ReturnBlank() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx"); Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try { try {
@ -394,6 +412,7 @@ public final class TestXSSFCell extends BaseTestXCell {
} }
} }
@Test
public void testBug56644CreateBlank() throws IOException { public void testBug56644CreateBlank() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx"); Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try { try {
@ -406,6 +425,7 @@ public final class TestXSSFCell extends BaseTestXCell {
} }
} }
@Test
public void testEncodingbeloAscii(){ public void testEncodingbeloAscii(){
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
// test all possible characters // test all possible characters

View File

@ -0,0 +1,25 @@
# (C) Copyright Uwe Schindler (Generics Policeman) and others.
# Parts of this work are licensed to the Apache Software Foundation (ASF)
# under one or more contributor license agreements.
#
# Licensed 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.
#
# This file contains API signatures which are specific to POI.
# The goal is to minimize implicit defaults
@ignoreUnresolvable
@defaultMessage POI forbidden APIs
java.util.Locale#getDefault()
java.util.Locale#setDefault(java.util.Locale)
java.util.TimeZone#getDefault()

View File

@ -21,12 +21,12 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.TimeZone;
import org.apache.poi.hmef.Attachment; import org.apache.poi.hmef.Attachment;
import org.apache.poi.hmef.HMEFMessage; import org.apache.poi.hmef.HMEFMessage;
import org.apache.poi.hpsf.Util; import org.apache.poi.hpsf.Util;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -53,7 +53,7 @@ public final class TNEFDateAttribute extends TNEFAttribute {
); );
} else if(data.length == 14) { } else if(data.length == 14) {
// It's the 7 date fields. We think it's in UTC... // It's the 7 date fields. We think it's in UTC...
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); Calendar c = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
c.set(Calendar.YEAR, LittleEndian.getUShort(data, 0)); c.set(Calendar.YEAR, LittleEndian.getUShort(data, 0));
c.set(Calendar.MONTH, LittleEndian.getUShort(data, 2) - 1); // Java months are 0 based! c.set(Calendar.MONTH, LittleEndian.getUShort(data, 2) - 1); // Java months are 0 based!
c.set(Calendar.DAY_OF_MONTH, LittleEndian.getUShort(data, 4)); c.set(Calendar.DAY_OF_MONTH, LittleEndian.getUShort(data, 4));
@ -61,7 +61,7 @@ public final class TNEFDateAttribute extends TNEFAttribute {
c.set(Calendar.MINUTE, LittleEndian.getUShort(data, 8)); c.set(Calendar.MINUTE, LittleEndian.getUShort(data, 8));
c.set(Calendar.SECOND, LittleEndian.getUShort(data, 10)); c.set(Calendar.SECOND, LittleEndian.getUShort(data, 10));
// The 7th field is day of week, which we don't require // The 7th field is day of week, which we don't require
c.set(Calendar.MILLISECOND, 0); // Not set in the file c.clear(Calendar.MILLISECOND); // Not set in the file
this.data = c.getTime(); this.data = c.getTime();
} else { } else {
throw new IllegalArgumentException("Invalid date, found " + data.length + " bytes"); throw new IllegalArgumentException("Invalid date, found " + data.length + " bytes");

View File

@ -63,6 +63,7 @@ import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.SuppressForbidden;
/** /**
* Translates Graphics2D calls into PowerPoint. * Translates Graphics2D calls into PowerPoint.
@ -1716,6 +1717,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable {
* @see java.awt.Graphics#getFontMetrics() * @see java.awt.Graphics#getFontMetrics()
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressForbidden
public FontMetrics getFontMetrics(Font f) { public FontMetrics getFontMetrics(Font f) {
return Toolkit.getDefaultToolkit().getFontMetrics(f); return Toolkit.getDefaultToolkit().getFontMetrics(f);
} }

View File

@ -19,10 +19,9 @@ package org.apache.poi.hslf.util;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;
/** /**
* A helper class for dealing with SystemTime Structs, as defined at * A helper class for dealing with SystemTime Structs, as defined at
@ -33,9 +32,6 @@ import org.apache.poi.util.LittleEndian;
* - that the day of the week (0) starts on Sunday in SYSTEMTIME, and Monday in Calendar * - that the day of the week (0) starts on Sunday in SYSTEMTIME, and Monday in Calendar
* It is also the case that this does not store the timezone, and no... it is not * It is also the case that this does not store the timezone, and no... it is not
* stored as UTC either, but rather the local system time (yuck.) * stored as UTC either, but rather the local system time (yuck.)
*
* @author Daniel Noll
* @author Nick Burch
*/ */
public final class SystemTimeUtils { public final class SystemTimeUtils {
/** /**
@ -48,7 +44,7 @@ public final class SystemTimeUtils {
* Get the date found in the byte array, as a java Data object * Get the date found in the byte array, as a java Data object
*/ */
public static Date getDate(byte[] data, int offset) { public static Date getDate(byte[] data, int offset) {
Calendar cal = new GregorianCalendar(Locale.ROOT); Calendar cal = LocaleUtil.getLocaleCalendar();
cal.set(Calendar.YEAR, LittleEndian.getShort(data,offset)); cal.set(Calendar.YEAR, LittleEndian.getShort(data,offset));
cal.set(Calendar.MONTH, LittleEndian.getShort(data,offset+2)-1); cal.set(Calendar.MONTH, LittleEndian.getShort(data,offset+2)-1);
@ -75,7 +71,7 @@ public final class SystemTimeUtils {
* into the supplied byte array. * into the supplied byte array.
*/ */
public static void storeDate(Date date, byte[] dest, int offset) { public static void storeDate(Date date, byte[] dest, int offset) {
Calendar cal = new GregorianCalendar(); Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(date); cal.setTime(date);
LittleEndian.putShort(dest, offset + 0, (short) cal.get(Calendar.YEAR)); LittleEndian.putShort(dest, offset + 0, (short) cal.get(Calendar.YEAR));

View File

@ -81,7 +81,7 @@ public class MAPIMessage extends POIDocument {
*/ */
public MAPIMessage() { public MAPIMessage() {
// TODO - make writing possible // TODO - make writing possible
super(new POIFSFileSystem()); super(new NPOIFSFileSystem());
} }
@ -91,7 +91,7 @@ public class MAPIMessage extends POIDocument {
* @throws IOException * @throws IOException
*/ */
public MAPIMessage(String filename) throws IOException { public MAPIMessage(String filename) throws IOException {
this(new FileInputStream(new File(filename))); this(new NPOIFSFileSystem(new File(filename)));
} }
/** /**
@ -102,14 +102,6 @@ public class MAPIMessage extends POIDocument {
public MAPIMessage(InputStream in) throws IOException { public MAPIMessage(InputStream in) throws IOException {
this(new NPOIFSFileSystem(in)); this(new NPOIFSFileSystem(in));
} }
/**
* Constructor for reading MSG Files from a POIFS filesystem
* @param fs
* @throws IOException
*/
public MAPIMessage(POIFSFileSystem fs) throws IOException {
this(fs.getRoot());
}
/** /**
* Constructor for reading MSG Files from a POIFS filesystem * Constructor for reading MSG Files from a POIFS filesystem
* @param fs * @param fs

View File

@ -26,6 +26,7 @@ import java.util.regex.Pattern;
import org.apache.poi.hsmf.datatypes.Types.MAPIType; import org.apache.poi.hsmf.datatypes.Types.MAPIType;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -85,7 +86,7 @@ public class MessageSubmissionChunk extends Chunk {
// Should be yymmddhhmmssZ // Should be yymmddhhmmssZ
Matcher m = datePatern.matcher(dateS); Matcher m = datePatern.matcher(dateS);
if(m.matches()) { if(m.matches()) {
date = Calendar.getInstance(); date = LocaleUtil.getLocaleCalendar();
// work around issues with dates like 1989, which appear as "89" here // work around issues with dates like 1989, which appear as "89" here
int year = Integer.parseInt(m.group(1)); int year = Integer.parseInt(m.group(1));
@ -96,7 +97,7 @@ public class MessageSubmissionChunk extends Chunk {
date.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4))); date.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
date.set(Calendar.MINUTE, Integer.parseInt(m.group(5))); date.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
date.set(Calendar.SECOND, Integer.parseInt(m.group(6))); date.set(Calendar.SECOND, Integer.parseInt(m.group(6)));
date.set(Calendar.MILLISECOND, 0); date.clear(Calendar.MILLISECOND);
} else { } else {
logger.log(POILogger.WARN, "Warning - unable to make sense of date " + dateS); logger.log(POILogger.WARN, "Warning - unable to make sense of date " + dateS);
} }

View File

@ -19,9 +19,9 @@ package org.apache.poi.hsmf.datatypes;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Calendar; import java.util.Calendar;
import java.util.TimeZone;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;
/** /**
* An instance of a {@link MAPIProperty} inside a {@link PropertiesChunk}. * An instance of a {@link MAPIProperty} inside a {@link PropertiesChunk}.
@ -218,7 +218,7 @@ public class PropertyValue {
long time = LittleEndian.getLong(data); long time = LittleEndian.getLong(data);
time = (time / 10 / 1000) - OFFSET; time = (time / 10 / 1000) - OFFSET;
Calendar timeC = Calendar.getInstance(TimeZone.getTimeZone("UTC")); Calendar timeC = LocaleUtil.getLocaleCalendar();
timeC.setTimeInMillis(time); timeC.setTimeInMillis(time);
return timeC; return timeC;

View File

@ -17,7 +17,7 @@
package org.apache.poi.hsmf.dev; package org.apache.poi.hsmf.dev;
import java.io.FileInputStream; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
@ -27,14 +27,14 @@ import org.apache.poi.hsmf.datatypes.MAPIProperty;
import org.apache.poi.hsmf.datatypes.PropertiesChunk; import org.apache.poi.hsmf.datatypes.PropertiesChunk;
import org.apache.poi.hsmf.datatypes.PropertyValue; import org.apache.poi.hsmf.datatypes.PropertyValue;
import org.apache.poi.hsmf.parsers.POIFSChunkParser; import org.apache.poi.hsmf.parsers.POIFSChunkParser;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
/** /**
* Dumps out the chunk details, and where possible contents * Dumps out the chunk details, and where possible contents
*/ */
public class HSMFDump { public class HSMFDump {
private POIFSFileSystem fs; private NPOIFSFileSystem fs;
public HSMFDump(POIFSFileSystem fs) { public HSMFDump(NPOIFSFileSystem fs) {
this.fs = fs; this.fs = fs;
} }
@ -84,9 +84,10 @@ public class HSMFDump {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
for(String file : args) { for(String file : args) {
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(file)); NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(file), true);
HSMFDump dump = new HSMFDump(fs); HSMFDump dump = new HSMFDump(fs);
dump.dump(); dump.dump();
fs.close();
} }
} }
} }

View File

@ -21,7 +21,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.POIOLE2TextExtractor; import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hsmf.MAPIMessage; import org.apache.poi.hsmf.MAPIMessage;
@ -31,6 +30,7 @@ import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.StringUtil.StringsIterator; import org.apache.poi.util.StringUtil.StringsIterator;
/** /**
@ -51,9 +51,6 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
public OutlookTextExtactor(DirectoryNode poifsDir) throws IOException { public OutlookTextExtactor(DirectoryNode poifsDir) throws IOException {
this(new MAPIMessage(poifsDir)); this(new MAPIMessage(poifsDir));
} }
public OutlookTextExtactor(POIFSFileSystem fs) throws IOException {
this(new MAPIMessage(fs));
}
public OutlookTextExtactor(NPOIFSFileSystem fs) throws IOException { public OutlookTextExtactor(NPOIFSFileSystem fs) throws IOException {
this(new MAPIMessage(fs)); this(new MAPIMessage(fs));
} }
@ -63,11 +60,16 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
for(String filename : args) { for(String filename : args) {
OutlookTextExtactor extractor = new OutlookTextExtactor( NPOIFSFileSystem poifs = null;
new NPOIFSFileSystem(new File(filename)) OutlookTextExtactor extractor = null;
); try {
System.out.println( extractor.getText() ); poifs = new NPOIFSFileSystem(new File(filename));
extractor.close(); extractor = new OutlookTextExtactor(poifs);
System.out.println( extractor.getText() );
} finally {
if (extractor != null) extractor.close();
if (poifs != null) poifs.close();
}
} }
} }
@ -120,8 +122,8 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
// Date - try two ways to find it // Date - try two ways to find it
try { try {
// First try via the proper chunk // First try via the proper chunk
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z"); SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.ROOT);
f.setTimeZone(TimeZone.getTimeZone("UTC")); f.setTimeZone(LocaleUtil.getUserTimeZone());
s.append("Date: " + f.format(msg.getMessageDate().getTime()) + "\n"); s.append("Date: " + f.format(msg.getMessageDate().getTime()) + "\n");
} catch(ChunkNotFoundException e) { } catch(ChunkNotFoundException e) {
try { try {

View File

@ -40,7 +40,7 @@ import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.DocumentNode; import org.apache.poi.poifs.filesystem.DocumentNode;
import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -52,7 +52,7 @@ import org.apache.poi.util.POILogger;
public final class POIFSChunkParser { public final class POIFSChunkParser {
private static POILogger logger = POILogFactory.getLogger(POIFSChunkParser.class); private static POILogger logger = POILogFactory.getLogger(POIFSChunkParser.class);
public static ChunkGroup[] parse(POIFSFileSystem fs) throws IOException { public static ChunkGroup[] parse(NPOIFSFileSystem fs) throws IOException {
return parse(fs.getRoot()); return parse(fs.getRoot());
} }
public static ChunkGroup[] parse(DirectoryNode node) throws IOException { public static ChunkGroup[] parse(DirectoryNode node) throws IOException {
@ -205,12 +205,15 @@ public final class POIFSChunkParser {
if(chunk != null) { if(chunk != null) {
if(entry instanceof DocumentNode) { if(entry instanceof DocumentNode) {
DocumentInputStream inp = null;
try { try {
DocumentInputStream inp = new DocumentInputStream((DocumentNode)entry); inp = new DocumentInputStream((DocumentNode)entry);
chunk.readValue(inp); chunk.readValue(inp);
grouping.record(chunk); grouping.record(chunk);
} catch(IOException e) { } catch(IOException e) {
logger.log(POILogger.ERROR, "Error reading from part " + entry.getName() + " - " + e.toString()); logger.log(POILogger.ERROR, "Error reading from part " + entry.getName() + " - " + e.toString());
} finally {
if (inp != null) inp.close();
} }
} else { } else {
grouping.record(chunk); grouping.record(chunk);

View File

@ -19,7 +19,7 @@
package org.apache.poi.hwpf.model; package org.apache.poi.hwpf.model;
import java.text.MessageFormat; import java.util.Locale;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
@ -63,11 +63,9 @@ public class PlexOfField
return fld; return fld;
} }
public String toString() public String toString() {
{ String str = String.format(Locale.ROOT, "[%d, %d) - FLD - 0x%x; 0x%x"
return MessageFormat.format( "[{0}, {1}) - FLD - 0x{2}; 0x{3}", , getFcStart(), getFcEnd(), fld.getBoundaryType(), fld.getFlt());
getFcStart(), getFcEnd(), return str;
Integer.toHexString( 0xff & fld.getBoundaryType() ),
Integer.toHexString( 0xff & fld.getFlt() ) );
} }
} }

View File

@ -22,6 +22,7 @@ import java.util.Calendar;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;
/** /**
* This class is used to represent a date and time in a Word document. * This class is used to represent a date and time in a Word document.
@ -39,7 +40,7 @@ public final class DateAndTime
private short _info2; private short _info2;
private static final BitField _months = BitFieldFactory.getInstance(0xf); private static final BitField _months = BitFieldFactory.getInstance(0xf);
private static final BitField _years = BitFieldFactory.getInstance(0x1ff0); private static final BitField _years = BitFieldFactory.getInstance(0x1ff0);
private static final BitField _weekday = BitFieldFactory.getInstance(0xe000); // private static final BitField _weekday = BitFieldFactory.getInstance(0xe000);
public DateAndTime() public DateAndTime()
{ {
@ -53,8 +54,7 @@ public final class DateAndTime
public Calendar getDate() { public Calendar getDate() {
// TODO Discover if the timezone is stored somewhere else or not // TODO Discover if the timezone is stored somewhere else or not
Calendar cal = Calendar.getInstance(); Calendar cal = LocaleUtil.getLocaleCalendar(
cal.set(
_years.getValue(_info2)+1900, _years.getValue(_info2)+1900,
_months.getValue(_info2)-1, _months.getValue(_info2)-1,
_dom.getValue(_info), _dom.getValue(_info),
@ -62,7 +62,6 @@ public final class DateAndTime
_minutes.getValue(_info), _minutes.getValue(_info),
0 0
); );
cal.set(Calendar.MILLISECOND, 0);
return cal; return cal;
} }

View File

@ -18,10 +18,19 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import junit.framework.TestCase; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Tests that Comment2000 works properly. * Tests that Comment2000 works properly.
@ -29,7 +38,7 @@ import java.util.Date;
* *
* @author Nick Burch (nick at torchbox dot com) * @author Nick Burch (nick at torchbox dot com)
*/ */
public final class TestComment2000 extends TestCase { public final class TestComment2000 {
// From a real file // From a real file
private byte[] data_a = new byte[] { private byte[] data_a = new byte[] {
0x0F, 00, 0xE0-256, 0x2E, 0x9C-256, 00, 00, 00, 0x0F, 00, 0xE0-256, 0x2E, 0x9C-256, 00, 00, 00,
@ -82,22 +91,35 @@ public final class TestComment2000 extends TestCase {
0x0A, 00, 00, 00 0x0A, 00, 00, 00
}; };
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}
@Test
public void testRecordType() { public void testRecordType() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals(12000l, ca.getRecordType()); assertEquals(12000l, ca.getRecordType());
} }
public void testAuthor() {
@Test
public void testAuthor() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals("Dumbledore", ca.getAuthor()); assertEquals("Dumbledore", ca.getAuthor());
assertEquals("D", ca.getAuthorInitials()); assertEquals("D", ca.getAuthorInitials());
} }
public void testText() {
@Test
public void testText() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals("Yes, they certainly are, aren't they!", ca.getText()); assertEquals("Yes, they certainly are, aren't they!", ca.getText());
} }
public void testCommentAtom() throws Exception {
@Test
public void testCommentAtom() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
Comment2000Atom c2a = ca.getComment2000Atom(); Comment2000Atom c2a = ca.getComment2000Atom();
@ -107,7 +129,9 @@ public final class TestComment2000 extends TestCase {
Date exp_a = sdf.parse("2006-01-24 10:26:15.205"); Date exp_a = sdf.parse("2006-01-24 10:26:15.205");
assertEquals(exp_a, c2a.getDate()); assertEquals(exp_a, c2a.getDate());
} }
public void testCommentAtomB() throws Exception {
@Test
public void testCommentAtomB() throws Exception {
Comment2000 cb = new Comment2000(data_b, 0, data_b.length); Comment2000 cb = new Comment2000(data_b, 0, data_b.length);
Comment2000Atom c2b = cb.getComment2000Atom(); Comment2000Atom c2b = cb.getComment2000Atom();
@ -118,7 +142,8 @@ public final class TestComment2000 extends TestCase {
assertEquals(exp_b, c2b.getDate()); assertEquals(exp_b, c2b.getDate());
} }
public void testWrite() throws Exception { @Test
public void testWrite() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
ca.writeOut(baos); ca.writeOut(baos);
@ -131,7 +156,8 @@ public final class TestComment2000 extends TestCase {
} }
// Change a few things // Change a few things
public void testChange() throws Exception { @Test
public void testChange() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length); Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
Comment2000 cb = new Comment2000(data_b, 0, data_b.length); Comment2000 cb = new Comment2000(data_b, 0, data_b.length);
Comment2000 cn = new Comment2000(); Comment2000 cn = new Comment2000();
@ -196,6 +222,7 @@ public final class TestComment2000 extends TestCase {
/** /**
* A Comment2000 records with missing commentTextAtom * A Comment2000 records with missing commentTextAtom
*/ */
@Test
public void testBug44770() { public void testBug44770() {
byte[] data = { byte[] data = {
0x0F, 0x00, (byte)0xE0, 0x2E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xBA, 0x0F, 0x0F, 0x00, (byte)0xE0, 0x2E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xBA, 0x0F,

View File

@ -18,17 +18,23 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import junit.framework.TestCase; import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Tests that Comment2000Atom works properly. * Tests that Comment2000Atom works properly.
* *
* @author Nick Burch (nick at torchbox dot com) * @author Nick Burch (nick at torchbox dot com)
*/ */
public final class TestComment2000Atom extends TestCase { public final class TestComment2000Atom {
// From a real file // From a real file
private byte[] data_a = new byte[] { private byte[] data_a = new byte[] {
00, 00, 0xE1-256, 0x2E, 0x1C, 00, 00, 00, 00, 00, 0xE1-256, 0x2E, 0x1C, 00, 00, 00,
@ -45,14 +51,22 @@ public final class TestComment2000Atom extends TestCase {
0x0E, 00, 00, 00 0x0E, 00, 00, 00
}; };
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}
@Test
public void testRecordType() { public void testRecordType() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
assertEquals(12001l, ca.getRecordType()); assertEquals(12001l, ca.getRecordType());
} }
public void testGetDate() throws Exception { @Test
public void testGetDate() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);
@ -65,7 +79,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(exp_b, cb.getDate()); assertEquals(exp_b, cb.getDate());
} }
public void testGetNums() { @Test
public void testGetNums() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);
@ -75,7 +90,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(5, cb.getNumber()); assertEquals(5, cb.getNumber());
} }
public void testGetPos() { @Test
public void testGetPos() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);
@ -88,7 +104,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(0x0E, cb.getYOffset()); assertEquals(0x0E, cb.getYOffset());
} }
public void testWrite() throws Exception { @Test
public void testWrite() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
ca.writeOut(baos); ca.writeOut(baos);
@ -101,7 +118,8 @@ public final class TestComment2000Atom extends TestCase {
} }
// Create A from scratch // Create A from scratch
public void testCreate() throws Exception { @Test
public void testCreate() throws Exception {
Comment2000Atom a = new Comment2000Atom(); Comment2000Atom a = new Comment2000Atom();
// Set number, x and y // Set number, x and y
@ -125,7 +143,8 @@ public final class TestComment2000Atom extends TestCase {
} }
// Try to turn a into b // Try to turn a into b
public void testChange() throws Exception { @Test
public void testChange() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
// Change the number // Change the number

View File

@ -18,17 +18,22 @@
package org.apache.poi.hslf.util; package org.apache.poi.hslf.util;
import static org.junit.Assert.assertEquals;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import junit.framework.TestCase; import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Tests that SystemTimeUtils works properly. * Tests that SystemTimeUtils works properly.
* *
* @author Nick Burch (nick at torchbox dot com) * @author Nick Burch (nick at torchbox dot com)
*/ */
public final class TestSystemTimeUtils extends TestCase { public final class TestSystemTimeUtils {
// From real files // From real files
private byte[] data_a = new byte[] { private byte[] data_a = new byte[] {
0xD6-256, 07, 01, 00, 0xD6-256, 07, 01, 00,
@ -43,9 +48,16 @@ public final class TestSystemTimeUtils extends TestCase {
0x0A, 00, 00, 00 0x0A, 00, 00, 00
}; };
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS"); private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}
public void testGetDateA() throws Exception { @Test
public void testGetDateA() throws Exception {
Date date = SystemTimeUtils.getDate(data_a); Date date = SystemTimeUtils.getDate(data_a);
// Is 2006-01-24 (2nd day of week) 10:26:15.205 // Is 2006-01-24 (2nd day of week) 10:26:15.205
@ -54,6 +66,7 @@ public final class TestSystemTimeUtils extends TestCase {
assertEquals(exp, date); assertEquals(exp, date);
} }
@Test
public void testGetDateB() throws Exception { public void testGetDateB() throws Exception {
Date date = SystemTimeUtils.getDate(data_b, 8+4); Date date = SystemTimeUtils.getDate(data_b, 8+4);
@ -63,6 +76,7 @@ public final class TestSystemTimeUtils extends TestCase {
assertEquals(exp, date); assertEquals(exp, date);
} }
@Test
public void testWriteDateA() throws Exception { public void testWriteDateA() throws Exception {
byte[] out_a = new byte[data_a.length]; byte[] out_a = new byte[data_a.length];
Date date = sdf.parse("2006-01-24 10:26:15.205"); Date date = sdf.parse("2006-01-24 10:26:15.205");
@ -73,6 +87,7 @@ public final class TestSystemTimeUtils extends TestCase {
} }
} }
@Test
public void testWriteDateB() throws Exception { public void testWriteDateB() throws Exception {
byte[] out_b = new byte[data_b.length]; byte[] out_b = new byte[data_b.length];
// Copy over start and end, ignoring the 16 byte date field in the middle // Copy over start and end, ignoring the 16 byte date field in the middle

View File

@ -17,30 +17,28 @@
package org.apache.poi.hsmf; package org.apache.poi.hsmf;
import junit.framework.Test; import org.apache.poi.hsmf.datatypes.TestChunkData;
import junit.framework.TestSuite; import org.apache.poi.hsmf.datatypes.TestSorters;
import org.apache.poi.hsmf.datatypes.TestTypes;
import org.apache.poi.hsmf.datatypes.*;
import org.apache.poi.hsmf.extractor.TestOutlookTextExtractor; import org.apache.poi.hsmf.extractor.TestOutlookTextExtractor;
import org.apache.poi.hsmf.parsers.*; import org.apache.poi.hsmf.parsers.TestPOIFSChunkParser;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
public final class AllHSMFTests { @RunWith(Suite.class)
public static Test suite() { @Suite.SuiteClasses({
TestSuite suite = new TestSuite(AllHSMFTests.class.getName()); TestBasics.class,
TestBlankFileRead.class,
suite.addTestSuite(TestBasics.class); TestSimpleFileRead.class,
suite.addTestSuite(TestBlankFileRead.class); TestOutlook30FileRead.class,
suite.addTestSuite(TestSimpleFileRead.class); TestFileWithAttachmentsRead.class,
suite.addTestSuite(TestOutlook30FileRead.class); TestChunkData.class,
suite.addTestSuite(TestFileWithAttachmentsRead.class); TestTypes.class,
suite.addTestSuite(TestChunkData.class); TestSorters.class,
suite.addTestSuite(TestTypes.class); TestOutlookTextExtractor.class,
suite.addTestSuite(TestSorters.class); TestPOIFSChunkParser.class,
suite.addTestSuite(TestOutlookTextExtractor.class); TestMessageSubmissionChunkY2KRead.class,
suite.addTestSuite(TestPOIFSChunkParser.class); TestMessageSubmissionChunk.class
suite.addTestSuite(TestMessageSubmissionChunkY2KRead.class); })
suite.addTestSuite(TestMessageSubmissionChunk.class); public class AllHSMFTests {
return suite;
}
} }

View File

@ -17,19 +17,24 @@
package org.apache.poi.hsmf; package org.apache.poi.hsmf;
import static org.apache.poi.POITestCase.assertContains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.hsmf.datatypes.ChunkBasedPropertyValue; import org.apache.poi.hsmf.datatypes.ChunkBasedPropertyValue;
import org.apache.poi.hsmf.datatypes.Chunks; import org.apache.poi.hsmf.datatypes.Chunks;
import org.apache.poi.hsmf.datatypes.MAPIProperty; import org.apache.poi.hsmf.datatypes.MAPIProperty;
@ -38,41 +43,58 @@ import org.apache.poi.hsmf.datatypes.PropertyValue.LongPropertyValue;
import org.apache.poi.hsmf.datatypes.PropertyValue.TimePropertyValue; import org.apache.poi.hsmf.datatypes.PropertyValue.TimePropertyValue;
import org.apache.poi.hsmf.dev.HSMFDump; import org.apache.poi.hsmf.dev.HSMFDump;
import org.apache.poi.hsmf.extractor.OutlookTextExtactor; import org.apache.poi.hsmf.extractor.OutlookTextExtactor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Tests that we can read fixed sized properties, as well as variable * Tests that we can read fixed sized properties, as well as variable
* ones, for example Submission Dates * ones, for example Submission Dates
*/ */
public final class TestFixedSizedProperties extends POITestCase { public final class TestFixedSizedProperties {
protected static final String messageSucceeds = "53784_succeeds.msg"; private static final String messageSucceeds = "53784_succeeds.msg";
protected static final String messageFails = "53784_fails.msg"; private static final String messageFails = "53784_fails.msg";
private MAPIMessage mapiMessageSucceeds; private static MAPIMessage mapiMessageSucceeds;
private MAPIMessage mapiMessageFails; private static MAPIMessage mapiMessageFails;
private POIFSFileSystem fsMessageSucceeds; private static NPOIFSFileSystem fsMessageSucceeds;
private POIFSFileSystem fsMessageFails; private static NPOIFSFileSystem fsMessageFails;
private SimpleDateFormat messageDateFormat; private static SimpleDateFormat messageDateFormat;
private static TimeZone userTimeZone;
/** /**
* Initialize this test, load up the messages. * Initialize this test, load up the messages.
*/ */
public TestFixedSizedProperties() throws Exception { @BeforeClass
public static void initMapi() throws Exception {
POIDataSamples samples = POIDataSamples.getHSMFInstance(); POIDataSamples samples = POIDataSamples.getHSMFInstance();
this.mapiMessageSucceeds = new MAPIMessage( fsMessageSucceeds = new NPOIFSFileSystem(samples.getFile(messageSucceeds));
samples.openResourceAsStream(messageSucceeds)); fsMessageFails = new NPOIFSFileSystem(samples.getFile(messageFails));
this.mapiMessageFails = new MAPIMessage(
samples.openResourceAsStream(messageFails)); mapiMessageSucceeds = new MAPIMessage(fsMessageSucceeds);
this.fsMessageSucceeds = new POIFSFileSystem(new FileInputStream(samples.getFile(messageSucceeds))); mapiMessageFails = new MAPIMessage(fsMessageFails);
this.fsMessageFails = new POIFSFileSystem(new FileInputStream(samples.getFile(messageFails)));
messageDateFormat = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss"); messageDateFormat = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss", Locale.ROOT);
messageDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); messageDateFormat.setTimeZone(LocaleUtil.TIMEZONE_UTC);
userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(LocaleUtil.TIMEZONE_UTC);
}
@AfterClass
public static void closeFS() throws Exception {
LocaleUtil.setUserTimeZone(userTimeZone);
fsMessageSucceeds.close();
fsMessageFails.close();
} }
/** /**
* Check we can find a sensible number of properties on a few * Check we can find a sensible number of properties on a few
* of our test files * of our test files
*/ */
@Test
public void testPropertiesFound() throws Exception { public void testPropertiesFound() throws Exception {
Map<MAPIProperty,List<PropertyValue>> props; Map<MAPIProperty,List<PropertyValue>> props;
@ -86,6 +108,7 @@ public final class TestFixedSizedProperties extends POITestCase {
/** /**
* Check we find properties of a variety of different types * Check we find properties of a variety of different types
*/ */
@Test
public void testPropertyValueTypes() throws Exception { public void testPropertyValueTypes() throws Exception {
Chunks mainChunks = mapiMessageSucceeds.getMainChunks(); Chunks mainChunks = mapiMessageSucceeds.getMainChunks();
@ -116,30 +139,32 @@ public final class TestFixedSizedProperties extends POITestCase {
/** /**
* Test to see if we can read the Date Chunk with OutlookTextExtractor. * Test to see if we can read the Date Chunk with OutlookTextExtractor.
* TODO Work out why the Fri 22nd vs Monday 25th problem is occurring and fix
*/ */
public void DISABLEDtestReadMessageDateSucceedsWithOutlookTextExtractor() { @Test
// @Ignore("TODO Work out why the Fri 22nd vs Monday 25th problem is occurring and fix")
public void testReadMessageDateSucceedsWithOutlookTextExtractor() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageSucceeds); OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageSucceeds);
String text = ext.getText(); String text = ext.getText();
assertContains(text, "Date: Fri, 22 Jun 2012 18:32:54 +0000\n");
assertContains(text, "Date: Fri, 22 Jun 2012 21:32:54\n"); ext.close();
} }
/** /**
* Test to see if we can read the Date Chunk with OutlookTextExtractor. * Test to see if we can read the Date Chunk with OutlookTextExtractor.
* TODO Work out why the Thu 21st vs Monday 25th problem is occurring and fix
*/ */
public void DISABLEDtestReadMessageDateFailsWithOutlookTextExtractor() { @Test
// @Ignore("TODO Work out why the Thu 21st vs Monday 25th problem is occurring and fix")
public void testReadMessageDateFailsWithOutlookTextExtractor() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageFails); OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageFails);
String text = ext.getText(); String text = ext.getText();
assertContains(text, "Date: Thu, 21 Jun 2012 14:14:04 +0000\n");
assertContains(text, "Date: Thu, 21 Jun 2012 17:14:04\n"); ext.close();
} }
/** /**
* Test to see if we can read the Date Chunk with HSMFDump. * Test to see if we can read the Date Chunk with HSMFDump.
* @throws IOException
*/ */
@Test
public void testReadMessageDateSucceedsWithHSMFDump() throws IOException { public void testReadMessageDateSucceedsWithHSMFDump() throws IOException {
PrintStream stream = new PrintStream(new ByteArrayOutputStream()); PrintStream stream = new PrintStream(new ByteArrayOutputStream());
HSMFDump dump = new HSMFDump(fsMessageSucceeds); HSMFDump dump = new HSMFDump(fsMessageSucceeds);
@ -148,8 +173,8 @@ public final class TestFixedSizedProperties extends POITestCase {
/** /**
* Test to see if we can read the Date Chunk with HSMFDump. * Test to see if we can read the Date Chunk with HSMFDump.
* @throws Exception
*/ */
@Test
public void testReadMessageDateFailsWithHSMFDump() throws Exception { public void testReadMessageDateFailsWithHSMFDump() throws Exception {
PrintStream stream = new PrintStream(new ByteArrayOutputStream()); PrintStream stream = new PrintStream(new ByteArrayOutputStream());
HSMFDump dump = new HSMFDump(fsMessageFails); HSMFDump dump = new HSMFDump(fsMessageFails);
@ -159,6 +184,7 @@ public final class TestFixedSizedProperties extends POITestCase {
/** /**
* Will be based on the ClientSubmit time * Will be based on the ClientSubmit time
*/ */
@Test
public void testClientSubmitTime() throws Exception { public void testClientSubmitTime() throws Exception {
// Check via the message date // Check via the message date
Calendar clientSubmitTime = mapiMessageSucceeds.getMessageDate(); Calendar clientSubmitTime = mapiMessageSucceeds.getMessageDate();

View File

@ -17,33 +17,47 @@
package org.apache.poi.hsmf.extractor; package org.apache.poi.hsmf.extractor;
import static org.apache.poi.POITestCase.assertContains;
import static org.apache.poi.POITestCase.assertNotContained;
import static org.junit.Assert.assertEquals;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.hsmf.MAPIMessage; import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Tests to verify that the text extractor works * Tests to verify that the text extractor works
*/ */
public final class TestOutlookTextExtractor extends POITestCase { public final class TestOutlookTextExtractor {
private POIDataSamples samples; private POIDataSamples samples = POIDataSamples.getHSMFInstance();
public TestOutlookTextExtractor() throws IOException {
samples = POIDataSamples.getHSMFInstance();
}
private static TimeZone userTZ;
@BeforeClass
public static void initTimeZone() {
userTZ = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(LocaleUtil.TIMEZONE_UTC);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTZ);
}
@Test
public void testQuick() throws Exception { public void testQuick() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
new FileInputStream(samples.getFile("quick.msg")) MAPIMessage msg = new MAPIMessage(poifs);
);
MAPIMessage msg = new MAPIMessage(simple);
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -54,20 +68,21 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertEquals(-1, text.indexOf("BCC:")); assertEquals(-1, text.indexOf("BCC:"));
assertEquals(-1, text.indexOf("Attachment:")); assertEquals(-1, text.indexOf("Attachment:"));
assertContains(text, "Subject: Test the content transformer\n"); assertContains(text, "Subject: Test the content transformer\n");
Calendar cal = new GregorianCalendar(2007, 5, 14, 9, 42, 55); Calendar cal = LocaleUtil.getLocaleCalendar(2007, 5, 14, 9, 42, 55);
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z"); SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.ROOT);
f.setTimeZone(TimeZone.getTimeZone("UTC")); f.setTimeZone(LocaleUtil.getUserTimeZone());
String dateText = f.format(cal.getTime()); String dateText = f.format(cal.getTime());
assertContains(text, "Date: " + dateText + "\n"); assertContains(text, "Date: " + dateText + "\n");
assertContains(text, "The quick brown fox jumps over the lazy dog"); assertContains(text, "The quick brown fox jumps over the lazy dog");
ext.close(); ext.close();
poifs.close();
} }
@Test
public void testSimple() throws Exception { public void testSimple() throws Exception {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
new FileInputStream(samples.getFile("simple_test_msg.msg")) MAPIMessage msg = new MAPIMessage(poifs);
));
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -81,25 +96,30 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "This is a test message."); assertContains(text, "This is a test message.");
ext.close(); ext.close();
poifs.close();
} }
@Test
public void testConstructors() throws Exception { public void testConstructors() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(new FileInputStream( FileInputStream fis = new FileInputStream(samples.getFile("simple_test_msg.msg"));
samples.getFile("simple_test_msg.msg"))); OutlookTextExtactor ext = new OutlookTextExtactor(fis);
String inp = ext.getText(); String inp = ext.getText();
ext.close(); ext.close();
fis.close();
ext = new OutlookTextExtactor(new POIFSFileSystem(new FileInputStream( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
samples.getFile("simple_test_msg.msg")))); ext = new OutlookTextExtactor(poifs);
String poifs = ext.getText(); String poifsTxt = ext.getText();
ext.close(); ext.close();
poifs.close();
ext = new OutlookTextExtactor(new MAPIMessage(new FileInputStream( fis = new FileInputStream(samples.getFile("simple_test_msg.msg"));
samples.getFile("simple_test_msg.msg")))); ext = new OutlookTextExtactor(new MAPIMessage(fis));
String mapi = ext.getText(); String mapi = ext.getText();
ext.close(); ext.close();
fis.close();
assertEquals(inp, poifs); assertEquals(inp, poifsTxt);
assertEquals(inp, mapi); assertEquals(inp, mapi);
} }
@ -107,6 +127,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
* Test that we correctly handle multiple To+CC+BCC * Test that we correctly handle multiple To+CC+BCC
* recipients in an email we sent. * recipients in an email we sent.
*/ */
@Test
public void testSentWithMulipleRecipients() throws Exception { public void testSentWithMulipleRecipients() throws Exception {
// To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>, // To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>,
// 'Paul Holmes-Higgin' <paul.hh@alfresco.com>, // 'Paul Holmes-Higgin' <paul.hh@alfresco.com>,
@ -120,9 +141,8 @@ public final class TestOutlookTextExtractor extends POITestCase {
"example_sent_regular.msg", "example_sent_unicode.msg" "example_sent_regular.msg", "example_sent_unicode.msg"
}; };
for(String file : files) { for(String file : files) {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile(file), true);
new FileInputStream(samples.getFile(file)) MAPIMessage msg = new MAPIMessage(poifs);
));
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -139,6 +159,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "The quick brown fox jumps over the lazy dog"); assertContains(text, "The quick brown fox jumps over the lazy dog");
ext.close(); ext.close();
poifs.close();
} }
} }
@ -146,6 +167,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
* Test that we correctly handle multiple To+CC * Test that we correctly handle multiple To+CC
* recipients in an email we received. * recipients in an email we received.
*/ */
@Test
public void testReceivedWithMultipleRecipients() throws Exception { public void testReceivedWithMultipleRecipients() throws Exception {
// To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>, // To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>,
// 'Paul Holmes-Higgin' <paul.hh@alfresco.com>, // 'Paul Holmes-Higgin' <paul.hh@alfresco.com>,
@ -159,9 +181,9 @@ public final class TestOutlookTextExtractor extends POITestCase {
"example_received_regular.msg", "example_received_unicode.msg" "example_received_regular.msg", "example_received_unicode.msg"
}; };
for(String file : files) { for(String file : files) {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile(file), true);
new FileInputStream(samples.getFile(file)) MAPIMessage msg = new MAPIMessage(poifs);
));
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -177,6 +199,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "The quick brown fox jumps over the lazy dog"); assertContains(text, "The quick brown fox jumps over the lazy dog");
ext.close(); ext.close();
poifs.close();
} }
} }
@ -184,10 +207,8 @@ public final class TestOutlookTextExtractor extends POITestCase {
* See also {@link org.apache.poi.extractor.TestExtractorFactory#testEmbeded()} * See also {@link org.apache.poi.extractor.TestExtractorFactory#testEmbeded()}
*/ */
public void testWithAttachments() throws Exception { public void testWithAttachments() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true);
new FileInputStream(samples.getFile("attachment_test_msg.msg")) MAPIMessage msg = new MAPIMessage(poifs);
);
MAPIMessage msg = new MAPIMessage(simple);
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
// Check the normal bits // Check the normal bits
@ -207,13 +228,12 @@ public final class TestOutlookTextExtractor extends POITestCase {
// TestExtractorFactory // TestExtractorFactory
ext.close(); ext.close();
poifs.close();
} }
public void testWithAttachedMessage() throws Exception { public void testWithAttachedMessage() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("58214_with_attachment.msg"), true);
new FileInputStream(samples.getFile("58214_with_attachment.msg")) MAPIMessage msg = new MAPIMessage(poifs);
);
MAPIMessage msg = new MAPIMessage(simple);
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -226,13 +246,12 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertNotContained(text, "Lorem ipsum dolor sit"); assertNotContained(text, "Lorem ipsum dolor sit");
ext.close(); ext.close();
poifs.close();
} }
public void testEncodings() throws Exception { public void testEncodings() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("chinese-traditional.msg"), true);
new FileInputStream(samples.getFile("chinese-traditional.msg")) MAPIMessage msg = new MAPIMessage(poifs);
);
MAPIMessage msg = new MAPIMessage(simple);
OutlookTextExtactor ext = new OutlookTextExtactor(msg); OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText(); String text = ext.getText();
@ -245,5 +264,6 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "( MSG \u683c\u5f0f\u6e2c\u8a66 )"); assertContains(text, "( MSG \u683c\u5f0f\u6e2c\u8a66 )");
ext.close(); ext.close();
poifs.close();
} }
} }

View File

@ -17,13 +17,16 @@
package org.apache.poi.hsmf.parsers; package org.apache.poi.hsmf.parsers;
import java.io.FileInputStream; import static org.junit.Assert.assertEquals;
import java.io.FileNotFoundException; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hsmf.MAPIMessage; import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks; import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.datatypes.ChunkGroup; import org.apache.poi.hsmf.datatypes.ChunkGroup;
@ -35,25 +38,19 @@ import org.apache.poi.hsmf.datatypes.RecipientChunks.RecipientChunksSorter;
import org.apache.poi.hsmf.datatypes.StringChunk; import org.apache.poi.hsmf.datatypes.StringChunk;
import org.apache.poi.hsmf.datatypes.Types; import org.apache.poi.hsmf.datatypes.Types;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.POIDataSamples; import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
import junit.framework.TestCase;
/** /**
* Tests to verify that the chunk parser works properly * Tests to verify that the chunk parser works properly
*/ */
public final class TestPOIFSChunkParser extends TestCase { public final class TestPOIFSChunkParser {
private POIDataSamples samples; private POIDataSamples samples = POIDataSamples.getHSMFInstance();
public TestPOIFSChunkParser() throws IOException { @Test
samples = POIDataSamples.getHSMFInstance(); public void testFindsCore() throws Exception {
} NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
public void testFindsCore() throws IOException {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
// Check a few core things are present // Check a few core things are present
simple.getRoot().getEntry( simple.getRoot().getEntry(
@ -65,29 +62,20 @@ public final class TestPOIFSChunkParser extends TestCase {
// Now load the file // Now load the file
MAPIMessage msg = new MAPIMessage(simple); MAPIMessage msg = new MAPIMessage(simple);
try { assertEquals("Kevin Roast", msg.getDisplayTo());
assertEquals("Kevin Roast", msg.getDisplayTo()); assertEquals("Kevin Roast", msg.getDisplayFrom());
assertEquals("Kevin Roast", msg.getDisplayFrom()); assertEquals("Test the content transformer", msg.getSubject());
assertEquals("Test the content transformer", msg.getSubject());
} catch(ChunkNotFoundException e) {
fail();
}
// Check date too // Check date too
try { Calendar calExp = LocaleUtil.getLocaleCalendar(2007,5,14,9,42,55);
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar calAct = msg.getMessageDate();
assertEquals( calExp, calAct );
Calendar c = msg.getMessageDate();
assertEquals( "2007-06-14 09:42:55", f.format(c.getTime()) ); simple.close();
} catch(ChunkNotFoundException e) {
fail();
}
} }
public void testFindsRecips() throws IOException, ChunkNotFoundException { public void testFindsRecips() throws IOException, ChunkNotFoundException {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
new FileInputStream(samples.getFile("quick.msg"))
);
simple.getRoot().getEntry("__recip_version1.0_#00000000"); simple.getRoot().getEntry("__recip_version1.0_#00000000");
@ -121,11 +109,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks()[0].recipientSMTPChunk.getValue()); assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks()[0].recipientSMTPChunk.getValue());
assertEquals("/O=HOSTEDSERVICE2/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=Kevin.roast@ben", assertEquals("/O=HOSTEDSERVICE2/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=Kevin.roast@ben",
msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue()); msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue());
simple.close();
// Now look at another message // Now look at another message
msg = new MAPIMessage(new POIFSFileSystem( simple = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
new FileInputStream(samples.getFile("simple_test_msg.msg")) msg = new MAPIMessage(simple);
));
assertNotNull(msg.getRecipientDetailsChunks()); assertNotNull(msg.getRecipientDetailsChunks());
assertEquals(1, msg.getRecipientDetailsChunks().length); assertEquals(1, msg.getRecipientDetailsChunks().length);
@ -134,12 +123,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(null, msg.getRecipientDetailsChunks()[0].recipientNameChunk); assertEquals(null, msg.getRecipientDetailsChunks()[0].recipientNameChunk);
assertEquals("travis@overwrittenstack.com", msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue()); assertEquals("travis@overwrittenstack.com", msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue());
assertEquals("travis@overwrittenstack.com", msg.getRecipientEmailAddress()); assertEquals("travis@overwrittenstack.com", msg.getRecipientEmailAddress());
simple.close();
} }
public void testFindsMultipleRecipients() throws IOException, ChunkNotFoundException { public void testFindsMultipleRecipients() throws IOException, ChunkNotFoundException {
POIFSFileSystem multiple = new POIFSFileSystem( NPOIFSFileSystem multiple = new NPOIFSFileSystem(samples.getFile("example_received_unicode.msg"), true);
new FileInputStream(samples.getFile("example_received_unicode.msg"))
);
multiple.getRoot().getEntry("__recip_version1.0_#00000000"); multiple.getRoot().getEntry("__recip_version1.0_#00000000");
multiple.getRoot().getEntry("__recip_version1.0_#00000001"); multiple.getRoot().getEntry("__recip_version1.0_#00000001");
@ -225,12 +214,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals("nickb@alfresco.com", msg.getRecipientEmailAddressList()[3]); assertEquals("nickb@alfresco.com", msg.getRecipientEmailAddressList()[3]);
assertEquals("nick.burch@alfresco.com", msg.getRecipientEmailAddressList()[4]); assertEquals("nick.burch@alfresco.com", msg.getRecipientEmailAddressList()[4]);
assertEquals("roy.wetherall@alfresco.com", msg.getRecipientEmailAddressList()[5]); assertEquals("roy.wetherall@alfresco.com", msg.getRecipientEmailAddressList()[5]);
multiple.close();
} }
public void testFindsNameId() throws IOException { public void testFindsNameId() throws IOException {
POIFSFileSystem simple = new POIFSFileSystem( NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
new FileInputStream(samples.getFile("quick.msg"))
);
simple.getRoot().getEntry("__nameid_version1.0"); simple.getRoot().getEntry("__nameid_version1.0");
@ -247,15 +236,13 @@ public final class TestPOIFSChunkParser extends TestCase {
MAPIMessage msg = new MAPIMessage(simple); MAPIMessage msg = new MAPIMessage(simple);
assertNotNull(msg.getNameIdChunks()); assertNotNull(msg.getNameIdChunks());
assertEquals(10, msg.getNameIdChunks().getAll().length); assertEquals(10, msg.getNameIdChunks().getAll().length);
simple.close();
} }
public void testFindsAttachments() throws IOException { public void testFindsAttachments() throws Exception {
POIFSFileSystem with = new POIFSFileSystem( NPOIFSFileSystem with = new NPOIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true);
new FileInputStream(samples.getFile("attachment_test_msg.msg")) NPOIFSFileSystem without = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
);
POIFSFileSystem without = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
AttachmentChunks attachment; AttachmentChunks attachment;
@ -284,15 +271,8 @@ public final class TestPOIFSChunkParser extends TestCase {
// Check raw details on one without // Check raw details on one without
try { assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000000"));
without.getRoot().getEntry("__attach_version1.0_#00000000"); assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000001"));
fail();
} catch(FileNotFoundException e) {}
try {
without.getRoot().getEntry("__attach_version1.0_#00000001");
fail();
} catch(FileNotFoundException e) {}
// One with, from the top // One with, from the top
MAPIMessage msgWith = new MAPIMessage(with); MAPIMessage msgWith = new MAPIMessage(with);
@ -309,14 +289,9 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(89, attachment.attachData.getValue().length); assertEquals(89, attachment.attachData.getValue().length);
// Plus check core details are there // Plus check core details are there
try { assertEquals("'nicolas1.23456@free.fr'", msgWith.getDisplayTo());
assertEquals("'nicolas1.23456@free.fr'", msgWith.getDisplayTo()); assertEquals("Nicolas1 23456", msgWith.getDisplayFrom());
assertEquals("Nicolas1 23456", msgWith.getDisplayFrom()); assertEquals("test pi\u00e8ce jointe 1", msgWith.getSubject());
assertEquals("test pi\u00e8ce jointe 1", msgWith.getSubject());
} catch(ChunkNotFoundException e) {
fail();
}
// One without, from the top // One without, from the top
MAPIMessage msgWithout = new MAPIMessage(without); MAPIMessage msgWithout = new MAPIMessage(without);
@ -325,13 +300,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(0, msgWithout.getAttachmentFiles().length); assertEquals(0, msgWithout.getAttachmentFiles().length);
// But has core details // But has core details
try { assertEquals("Kevin Roast", msgWithout.getDisplayTo());
assertEquals("Kevin Roast", msgWithout.getDisplayTo()); assertEquals("Kevin Roast", msgWithout.getDisplayFrom());
assertEquals("Kevin Roast", msgWithout.getDisplayFrom()); assertEquals("Test the content transformer", msgWithout.getSubject());
assertEquals("Test the content transformer", msgWithout.getSubject());
} catch(ChunkNotFoundException e) { without.close();
fail(); with.close();
}
} }
/** /**
@ -340,13 +314,13 @@ public final class TestPOIFSChunkParser extends TestCase {
* such as "Olk10SideProps_0001" * such as "Olk10SideProps_0001"
*/ */
public void testOlk10SideProps() throws Exception { public void testOlk10SideProps() throws Exception {
POIFSFileSystem poifs = new POIFSFileSystem( NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("51873.msg"), true);
new FileInputStream(samples.getFile("51873.msg"))
);
MAPIMessage msg = new MAPIMessage(poifs); MAPIMessage msg = new MAPIMessage(poifs);
// Check core details came through // Check core details came through
assertEquals("bubba@bubbasmith.com", msg.getDisplayTo()); assertEquals("bubba@bubbasmith.com", msg.getDisplayTo());
assertEquals("Test with Olk10SideProps_ Chunk", msg.getSubject()); assertEquals("Test with Olk10SideProps_ Chunk", msg.getSubject());
poifs.close();
} }
} }

View File

@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
@ -117,8 +118,8 @@ public class TestWrite
* *
* @exception IOException if an I/O exception occurs * @exception IOException if an I/O exception occurs
*/ */
@Test @Test(expected=NoFormatIDException.class)
public void withoutAFormatID() throws IOException public void withoutAFormatID() throws Exception
{ {
final File filename = TempFile.createTempFile(POI_FS, ".doc"); final File filename = TempFile.createTempFile(POI_FS, ".doc");
@ -131,8 +132,7 @@ public class TestWrite
ps.addSection(new MutableSection()); ps.addSection(new MutableSection());
/* Write it to a POIFS and the latter to disk: */ /* Write it to a POIFS and the latter to disk: */
try try {
{
final ByteArrayOutputStream psStream = new ByteArrayOutputStream(); final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
ps.write(psStream); ps.write(psStream);
psStream.close(); psStream.close();
@ -140,15 +140,8 @@ public class TestWrite
poiFs.createDocument(new ByteArrayInputStream(streamData), poiFs.createDocument(new ByteArrayInputStream(streamData),
SummaryInformation.DEFAULT_STREAM_NAME); SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
out.close(); } finally {
fail("Should have thrown a NoFormatIDException."); poiFs.close();
}
catch (Exception ex)
{
assertTrue(ex instanceof NoFormatIDException);
}
finally
{
out.close(); out.close();
} }
} }
@ -185,6 +178,7 @@ public class TestWrite
poiFs.createDocument(new ByteArrayInputStream(streamData), poiFs.createDocument(new ByteArrayInputStream(streamData),
SummaryInformation.DEFAULT_STREAM_NAME); SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
poiFs.close();
out.close(); out.close();
/* Read the POIFS: */ /* Read the POIFS: */
@ -236,6 +230,7 @@ public class TestWrite
poiFs.createDocument(ps.toInputStream(), poiFs.createDocument(ps.toInputStream(),
SummaryInformation.DEFAULT_STREAM_NAME); SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
poiFs.close();
out.close(); out.close();
/* Read the POIFS: */ /* Read the POIFS: */
@ -317,6 +312,7 @@ public class TestWrite
poiFs.createDocument(ps.toInputStream(), STREAM_NAME); poiFs.createDocument(ps.toInputStream(), STREAM_NAME);
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
poiFs.close();
out.close(); out.close();
/* Read the POIFS: */ /* Read the POIFS: */
@ -755,6 +751,7 @@ public class TestWrite
psf1[i].getName()); psf1[i].getName());
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
} }
poiFs.close();
out.close(); out.close();
@ -805,6 +802,7 @@ public class TestWrite
Integer.valueOf(codepage)); Integer.valueOf(codepage));
poiFs.createDocument(ps1.toInputStream(), "Test"); poiFs.createDocument(ps1.toInputStream(), "Test");
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
poiFs.close();
out.close(); out.close();
/* Read back: */ /* Read back: */
@ -1010,7 +1008,7 @@ public class TestWrite
// or via sun.misc.Cleaner, but this is regarded unsafe // or via sun.misc.Cleaner, but this is regarded unsafe
// http://stackoverflow.com/questions/2972986 // http://stackoverflow.com/questions/2972986
// http://bugs.java.com/view_bug.do?bug_id=4724038 // http://bugs.java.com/view_bug.do?bug_id=4724038
Assume.assumeFalse(System.getProperty("os.name").toLowerCase().contains("win")); Assume.assumeFalse(System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win"));
throw e; throw e;
} }
} }
@ -1022,7 +1020,7 @@ public class TestWrite
* @throws IOException * @throws IOException
* @throws HPSFException * @throws HPSFException
*/ */
@Test @Test(expected=IllegalPropertySetDataException.class)
public void dictionaryWithInvalidCodepage() throws IOException, HPSFException public void dictionaryWithInvalidCodepage() throws IOException, HPSFException
{ {
final File copy = TempFile.createTempFile("Test-HPSF", "ole2"); final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
@ -1039,8 +1037,7 @@ public class TestWrite
m.put(Long.valueOf(2), "String 2"); m.put(Long.valueOf(2), "String 2");
m.put(Long.valueOf(3), "String 3"); m.put(Long.valueOf(3), "String 3");
try try {
{
s.setDictionary(m); s.setDictionary(m);
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]); s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
int codepage = 12345; int codepage = 12345;
@ -1048,13 +1045,9 @@ public class TestWrite
Integer.valueOf(codepage)); Integer.valueOf(codepage));
poiFs.createDocument(ps1.toInputStream(), "Test"); poiFs.createDocument(ps1.toInputStream(), "Test");
poiFs.writeFilesystem(out); poiFs.writeFilesystem(out);
} finally {
poiFs.close();
out.close(); out.close();
fail("This testcase did not detect the invalid codepage value.");
}
catch (IllegalPropertySetDataException ex)
{
out.close();
assertTrue(true);
} }
} }
@ -1069,7 +1062,7 @@ public class TestWrite
{ {
final String charSetName = System.getProperty("file.encoding"); final String charSetName = System.getProperty("file.encoding");
final Charset charSet = Charset.forName(charSetName); final Charset charSet = Charset.forName(charSetName);
return charSet.displayName(); return charSet.displayName(Locale.ROOT);
} }

View File

@ -17,6 +17,12 @@
package org.apache.poi.hpsf.basic; package org.apache.poi.hpsf.basic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -26,45 +32,47 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import junit.framework.TestCase;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.hpsf.*; import org.apache.poi.hpsf.CustomProperties;
import org.apache.poi.hpsf.CustomProperty;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.MarkUnsupportedException;
import org.apache.poi.hpsf.MutableProperty;
import org.apache.poi.hpsf.MutableSection;
import org.apache.poi.hpsf.NoPropertySetStreamException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
import org.apache.poi.hpsf.Variant;
import org.apache.poi.hpsf.VariantSupport;
import org.apache.poi.hpsf.WritingNotSupportedException;
import org.apache.poi.hpsf.wellknown.SectionIDMap; import org.apache.poi.hpsf.wellknown.SectionIDMap;
import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* <p>Tests HPSF's high-level writing functionality for the well-known property * <p>Tests HPSF's high-level writing functionality for the well-known property
* set "SummaryInformation" and "DocumentSummaryInformation".</p> * set "SummaryInformation" and "DocumentSummaryInformation".</p>
*
* @author Rainer Klute
* <a href="mailto:klute@rainer-klute.de">klute@rainer-klute.de</a>
*/ */
public class TestWriteWellKnown extends TestCase { public class TestWriteWellKnown {
private static final String POI_FS = "TestWriteWellKnown.doc"; private static final String POI_FS = "TestWriteWellKnown.doc";
@BeforeClass
/** public static void setUp() {
* @see TestCase#setUp()
*/
@Override
public void setUp()
{
VariantSupport.setLogUnsupportedTypes(false); VariantSupport.setLogUnsupportedTypes(false);
} }
/** /**
* <p>This test method checks whether DocumentSummary information streams * <p>This test method checks whether DocumentSummary information streams
* can be read. This is done by opening all "Test*" files in the 'poifs' directrory * can be read. This is done by opening all "Test*" files in the 'poifs' directrory
@ -72,6 +80,7 @@ public class TestWriteWellKnown extends TestCase {
* the document summary information stream in the root directory and calling * the document summary information stream in the root directory and calling
* its get... methods.</p> * its get... methods.</p>
*/ */
@Test
public void testReadDocumentSummaryInformation() public void testReadDocumentSummaryInformation()
throws FileNotFoundException, IOException, throws FileNotFoundException, IOException,
NoPropertySetStreamException, MarkUnsupportedException, NoPropertySetStreamException, MarkUnsupportedException,
@ -88,36 +97,18 @@ public class TestWriteWellKnown extends TestCase {
} }
}); });
for (int i = 0; i < docs.length; i++) for (final File doc : docs) {
{ NPOIFSFileSystem poifs = null;
try { try {
final File doc = docs[i];
/* Read a test document <em>doc</em> into a POI filesystem. */ /* Read a test document <em>doc</em> into a POI filesystem. */
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc)); poifs = new NPOIFSFileSystem(doc, true);
final DirectoryEntry dir = poifs.getRoot(); final DirectoryEntry dir = poifs.getRoot();
DocumentEntry dsiEntry = null;
try
{
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
}
catch (FileNotFoundException ex)
{
/*
* A missing document summary information stream is not an error
* and therefore silently ignored here.
*/
}
/* /*
* If there is a document summry information stream, read it from * If there is a document summry information stream, read it from
* the POI filesystem. * the POI filesystem.
*/ */
if (dsiEntry != null) if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
{ final DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
final DocumentInputStream dis = new DocumentInputStream(dsiEntry);
final PropertySet ps = new PropertySet(dis);
final DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
/* Execute the get... methods. */ /* Execute the get... methods. */
dsi.getByteCount(); dsi.getByteCount();
@ -139,12 +130,72 @@ public class TestWriteWellKnown extends TestCase {
dsi.getSlideCount(); dsi.getSlideCount();
} }
} catch (Exception e) { } catch (Exception e) {
throw new IOException("While handling file " + docs[i], e); throw new IOException("While handling file " + doc, e);
} finally {
if (poifs != null) poifs.close();
} }
} }
} }
static final String P_APPLICATION_NAME = "ApplicationName";
static final String P_AUTHOR = "Author";
static final int P_CHAR_COUNT = 4712;
static final String P_COMMENTS = "Comments";
static final Date P_CREATE_DATE_TIME;
static final long P_EDIT_TIME = 4713 * 1000 * 10;
static final String P_KEYWORDS = "Keywords";
static final String P_LAST_AUTHOR = "LastAuthor";
static final Date P_LAST_PRINTED;
static final Date P_LAST_SAVE_DATE_TIME;
static final int P_PAGE_COUNT = 4714;
static final String P_REV_NUMBER = "RevNumber";
static final int P_SECURITY = 1;
static final String P_SUBJECT = "Subject";
static final String P_TEMPLATE = "Template";
// FIXME (byte array properties not yet implemented): static final byte[] P_THUMBNAIL = new byte[123];
static final String P_TITLE = "Title";
static final int P_WORD_COUNT = 4715;
static final int P_BYTE_COUNT = 4716;
static final String P_CATEGORY = "Category";
static final String P_COMPANY = "Company";
// FIXME (byte array properties not yet implemented): static final byte[] P_DOCPARTS = new byte[123];
// FIXME (byte array properties not yet implemented): static final byte[] P_HEADING_PAIR = new byte[123];
static final int P_HIDDEN_COUNT = 4717;
static final int P_LINE_COUNT = 4718;
static final boolean P_LINKS_DIRTY = true;
static final String P_MANAGER = "Manager";
static final int P_MM_CLIP_COUNT = 4719;
static final int P_NOTE_COUNT = 4720;
static final int P_PAR_COUNT = 4721;
static final String P_PRESENTATION_FORMAT = "PresentationFormat";
static final boolean P_SCALE = false;
static final int P_SLIDE_COUNT = 4722;
static final Date now = new Date();
static final Integer POSITIVE_INTEGER = new Integer(2222);
static final Long POSITIVE_LONG = new Long(3333);
static final Double POSITIVE_DOUBLE = new Double(4444);
static final Integer NEGATIVE_INTEGER = new Integer(2222);
static final Long NEGATIVE_LONG = new Long(3333);
static final Double NEGATIVE_DOUBLE = new Double(4444);
static final Integer MAX_INTEGER = new Integer(Integer.MAX_VALUE);
static final Integer MIN_INTEGER = new Integer(Integer.MIN_VALUE);
static final Long MAX_LONG = new Long(Long.MAX_VALUE);
static final Long MIN_LONG = new Long(Long.MIN_VALUE);
static final Double MAX_DOUBLE = new Double(Double.MAX_VALUE);
static final Double MIN_DOUBLE = new Double(Double.MIN_VALUE);
static {
Calendar cal = LocaleUtil.getLocaleCalendar(2000, 6, 6, 6, 6, 6);
P_CREATE_DATE_TIME = cal.getTime();
cal.set(2001, 7, 7, 7, 7, 7);
P_LAST_PRINTED = cal.getTime();
cal.set(2002, 8, 8, 8, 8, 8);
P_LAST_SAVE_DATE_TIME = cal.getTime();
}
/** /**
* <p>This test method test the writing of properties in the well-known * <p>This test method test the writing of properties in the well-known
* property set streams "SummaryInformation" and * property set streams "SummaryInformation" and
@ -192,19 +243,35 @@ public class TestWriteWellKnown extends TestCase {
* @throws UnexpectedPropertySetTypeException * @throws UnexpectedPropertySetTypeException
* @throws WritingNotSupportedException * @throws WritingNotSupportedException
*/ */
public void testWriteWellKnown() throws IOException, @Test
NoPropertySetStreamException, MarkUnsupportedException, public void testWriteWellKnown() throws Exception {
UnexpectedPropertySetTypeException, WritingNotSupportedException
{
POIDataSamples _samples = POIDataSamples.getHPSFInstance(); POIDataSamples _samples = POIDataSamples.getHPSFInstance();
final File dataDir = _samples.getFile("");
final File doc1 = new File(dataDir, POI_FS); final File doc1 = TempFile.createTempFile("POI_HPSF_Test1.", ".tmp");
final File doc2 = TempFile.createTempFile("POI_HPSF_Test2.", ".tmp");
final File doc3 = TempFile.createTempFile("POI_HPSF_Test3.", ".tmp");
FileInputStream fis = new FileInputStream(_samples.getFile(POI_FS));
FileOutputStream fos = new FileOutputStream(doc1);
IOUtils.copy(fis, fos);
fos.close();
fis.close();
CustomProperties cps1 = write1stFile(doc1, doc2);
CustomProperties cps2 = write2ndFile(doc2, doc3);
write3rdFile(doc3, null);
assertEquals(cps1, cps2);
}
/*
* Write all properties supported by HPSF to the summary information
* (e.g. author, edit date, application name) and to the document
* summary information (e.g. company, manager).
*/
private static CustomProperties write1stFile(File fileIn, File fileOut) throws Exception {
/* Read a test document <em>doc1</em> into a POI filesystem. */ /* Read a test document <em>doc1</em> into a POI filesystem. */
POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc1)); NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
DirectoryEntry dir = poifs.getRoot();
DocumentEntry siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
/* /*
* Read the summary information stream and the document summary * Read the summary information stream and the document summary
@ -216,76 +283,8 @@ public class TestWriteWellKnown extends TestCase {
* explicitly (overwriting the former contents). Then the POI filesystem * explicitly (overwriting the former contents). Then the POI filesystem
* should be saved to a file. * should be saved to a file.
*/ */
DocumentInputStream dis = new DocumentInputStream(siEntry); SummaryInformation si = getSummaryInformation(poifs);
PropertySet ps = new PropertySet(dis); DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
SummaryInformation si = new SummaryInformation(ps);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
/*
* Write all properties supported by HPSF to the summary information
* (e.g. author, edit date, application name) and to the document
* summary information (e.g. company, manager).
*/
Calendar cal = new GregorianCalendar(Locale.ROOT);
cal.set(2000, 6, 6, 6, 6, 6);
final long time1 = cal.getTimeInMillis();
cal.set(2001, 7, 7, 7, 7, 7);
final long time2 = cal.getTimeInMillis();
cal.set(2002, 8, 8, 8, 8, 8);
final long time3 = cal.getTimeInMillis();
int nr = 4711;
final String P_APPLICATION_NAME = "ApplicationName";
final String P_AUTHOR = "Author";
final int P_CHAR_COUNT = ++nr;
final String P_COMMENTS = "Comments";
final Date P_CREATE_DATE_TIME = new Date(time1);
final long P_EDIT_TIME = ++nr * 1000 * 10;
final String P_KEYWORDS = "Keywords";
final String P_LAST_AUTHOR = "LastAuthor";
final Date P_LAST_PRINTED = new Date(time2);
final Date P_LAST_SAVE_DATE_TIME = new Date(time3);
final int P_PAGE_COUNT = ++nr;
final String P_REV_NUMBER = "RevNumber";
final int P_SECURITY = 1;
final String P_SUBJECT = "Subject";
final String P_TEMPLATE = "Template";
// FIXME (byte array properties not yet implemented): final byte[] P_THUMBNAIL = new byte[123];
final String P_TITLE = "Title";
final int P_WORD_COUNT = ++nr;
final int P_BYTE_COUNT = ++nr;
final String P_CATEGORY = "Category";
final String P_COMPANY = "Company";
// FIXME (byte array properties not yet implemented): final byte[] P_DOCPARTS = new byte[123];
// FIXME (byte array properties not yet implemented): final byte[] P_HEADING_PAIR = new byte[123];
final int P_HIDDEN_COUNT = ++nr;
final int P_LINE_COUNT = ++nr;
final boolean P_LINKS_DIRTY = true;
final String P_MANAGER = "Manager";
final int P_MM_CLIP_COUNT = ++nr;
final int P_NOTE_COUNT = ++nr;
final int P_PAR_COUNT = ++nr;
final String P_PRESENTATION_FORMAT = "PresentationFormat";
final boolean P_SCALE = false;
final int P_SLIDE_COUNT = ++nr;
final Date now = new Date();
final Integer POSITIVE_INTEGER = new Integer(2222);
final Long POSITIVE_LONG = new Long(3333);
final Double POSITIVE_DOUBLE = new Double(4444);
final Integer NEGATIVE_INTEGER = new Integer(2222);
final Long NEGATIVE_LONG = new Long(3333);
final Double NEGATIVE_DOUBLE = new Double(4444);
final Integer MAX_INTEGER = new Integer(Integer.MAX_VALUE);
final Integer MIN_INTEGER = new Integer(Integer.MIN_VALUE);
final Long MAX_LONG = new Long(Long.MAX_VALUE);
final Long MIN_LONG = new Long(Long.MIN_VALUE);
final Double MAX_DOUBLE = new Double(Double.MAX_VALUE);
final Double MIN_DOUBLE = new Double(Double.MIN_VALUE);
si.setApplicationName(P_APPLICATION_NAME); si.setApplicationName(P_APPLICATION_NAME);
si.setAuthor(P_AUTHOR); si.setAuthor(P_AUTHOR);
@ -322,76 +321,71 @@ public class TestWriteWellKnown extends TestCase {
dsi.setScale(P_SCALE); dsi.setScale(P_SCALE);
dsi.setSlideCount(P_SLIDE_COUNT); dsi.setSlideCount(P_SLIDE_COUNT);
CustomProperties customProperties = dsi.getCustomProperties(); CustomProperties cps = dsi.getCustomProperties();
if (customProperties == null) assertNull(cps);
customProperties = new CustomProperties(); cps = new CustomProperties();
customProperties.put("Schl\u00fcssel \u00e4", "Wert \u00e4"); cps.put("Schl\u00fcssel \u00e4", "Wert \u00e4");
customProperties.put("Schl\u00fcssel \u00e4\u00f6", "Wert \u00e4\u00f6"); cps.put("Schl\u00fcssel \u00e4\u00f6", "Wert \u00e4\u00f6");
customProperties.put("Schl\u00fcssel \u00e4\u00f6\u00fc", "Wert \u00e4\u00f6\u00fc"); cps.put("Schl\u00fcssel \u00e4\u00f6\u00fc", "Wert \u00e4\u00f6\u00fc");
customProperties.put("Schl\u00fcssel \u00e4\u00f6\u00fc\u00d6", "Wert \u00e4\u00f6\u00fc\u00d6"); cps.put("Schl\u00fcssel \u00e4\u00f6\u00fc\u00d6", "Wert \u00e4\u00f6\u00fc\u00d6");
customProperties.put("positive_Integer", POSITIVE_INTEGER); cps.put("positive_Integer", POSITIVE_INTEGER);
customProperties.put("positive_Long", POSITIVE_LONG); cps.put("positive_Long", POSITIVE_LONG);
customProperties.put("positive_Double", POSITIVE_DOUBLE); cps.put("positive_Double", POSITIVE_DOUBLE);
customProperties.put("negative_Integer", NEGATIVE_INTEGER); cps.put("negative_Integer", NEGATIVE_INTEGER);
customProperties.put("negative_Long", NEGATIVE_LONG); cps.put("negative_Long", NEGATIVE_LONG);
customProperties.put("negative_Double", NEGATIVE_DOUBLE); cps.put("negative_Double", NEGATIVE_DOUBLE);
customProperties.put("Boolean", Boolean.TRUE); cps.put("Boolean", Boolean.TRUE);
customProperties.put("Date", now); cps.put("Date", now);
customProperties.put("max_Integer", MAX_INTEGER); cps.put("max_Integer", MAX_INTEGER);
customProperties.put("min_Integer", MIN_INTEGER); cps.put("min_Integer", MIN_INTEGER);
customProperties.put("max_Long", MAX_LONG); cps.put("max_Long", MAX_LONG);
customProperties.put("min_Long", MIN_LONG); cps.put("min_Long", MIN_LONG);
customProperties.put("max_Double", MAX_DOUBLE); cps.put("max_Double", MAX_DOUBLE);
customProperties.put("min_Double", MIN_DOUBLE); cps.put("min_Double", MIN_DOUBLE);
// Check the keys went in // Check the keys went in
assertTrue(customProperties.containsKey("Schl\u00fcssel \u00e4")); assertTrue(cps.containsKey("Schl\u00fcssel \u00e4"));
assertTrue(customProperties.containsKey("Boolean")); assertTrue(cps.containsKey("Boolean"));
// Check the values went in // Check the values went in
assertEquals("Wert \u00e4", customProperties.get("Schl\u00fcssel \u00e4")); assertEquals("Wert \u00e4", cps.get("Schl\u00fcssel \u00e4"));
assertEquals(Boolean.TRUE, customProperties.get("Boolean")); assertEquals(Boolean.TRUE, cps.get("Boolean"));
assertTrue(customProperties.containsValue(Boolean.TRUE)); assertTrue(cps.containsValue(Boolean.TRUE));
assertTrue(customProperties.containsValue("Wert \u00e4")); assertTrue(cps.containsValue("Wert \u00e4"));
// Check that things that aren't in aren't in // Check that things that aren't in aren't in
assertFalse(customProperties.containsKey("False Boolean")); assertFalse(cps.containsKey("False Boolean"));
assertFalse(customProperties.containsValue(Boolean.FALSE)); assertFalse(cps.containsValue(Boolean.FALSE));
// Save as our custom properties // Save as our custom properties
dsi.setCustomProperties(customProperties); dsi.setCustomProperties(cps);
/* Write the summary information stream and the document summary /* Write the summary information stream and the document summary
* information stream to the POI filesystem. */ * information stream to the POI filesystem. */
si.write(dir, siEntry.getName()); si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
dsi.write(dir, dsiEntry.getName()); dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
/* Write the POI filesystem to a (temporary) file <em>doc2</em> /* Write the POI filesystem to a (temporary) file <em>doc2</em>
* and close the latter. */ * and close the latter. */
final File doc2 = TempFile.createTempFile("POI_HPSF_Test.", ".tmp"); OutputStream out = new FileOutputStream(fileOut);
doc2.deleteOnExit();
OutputStream out = new FileOutputStream(doc2);
poifs.writeFilesystem(out); poifs.writeFilesystem(out);
out.close(); out.close();
poifs.close();
/*
* Open <em>doc2</em> for reading and check summary information and return cps;
* document summary information. All properties written before must be }
* found in the property streams of <em>doc2</em> and have the correct
* values. /*
*/ * Open <em>doc2</em> for reading and check summary information and
poifs = new POIFSFileSystem(new FileInputStream(doc2)); * document summary information. All properties written before must be
dir = poifs.getRoot(); * found in the property streams of <em>doc2</em> and have the correct
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); * values.
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); */
private static CustomProperties write2ndFile(File fileIn, File fileOut) throws Exception {
dis = new DocumentInputStream(siEntry); NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
ps = new PropertySet(dis); SummaryInformation si = getSummaryInformation(poifs);
si = new SummaryInformation(ps); DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);
assertEquals(P_APPLICATION_NAME, si.getApplicationName()); assertEquals(P_APPLICATION_NAME, si.getApplicationName());
assertEquals(P_AUTHOR, si.getAuthor()); assertEquals(P_AUTHOR, si.getAuthor());
@ -429,7 +423,7 @@ public class TestWriteWellKnown extends TestCase {
assertEquals(P_SLIDE_COUNT, dsi.getSlideCount()); assertEquals(P_SLIDE_COUNT, dsi.getSlideCount());
final CustomProperties cps = dsi.getCustomProperties(); final CustomProperties cps = dsi.getCustomProperties();
assertEquals(customProperties, cps); assertNotNull(cps);
assertNull(cps.get("No value available")); assertNull(cps.get("No value available"));
assertEquals("Wert \u00e4", cps.get("Schl\u00fcssel \u00e4")); assertEquals("Wert \u00e4", cps.get("Schl\u00fcssel \u00e4"));
assertEquals("Wert \u00e4\u00f6", cps.get("Schl\u00fcssel \u00e4\u00f6")); assertEquals("Wert \u00e4\u00f6", cps.get("Schl\u00fcssel \u00e4\u00f6"));
@ -492,93 +486,108 @@ public class TestWriteWellKnown extends TestCase {
/* /*
* <li><p>Write the summary information stream and the document summary * <li><p>Write the summary information stream and the document summary
* information stream to the POI filesystem. */ * information stream to the POI filesystem. */
si.write(dir, siEntry.getName()); si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
dsi.write(dir, dsiEntry.getName()); dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
/* /*
* <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em> * <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em>
* and close the latter. */ * and close the latter. */
final File doc3 = TempFile.createTempFile("POI_HPSF_Test.", ".tmp"); FileOutputStream out = new FileOutputStream(fileOut);
doc3.deleteOnExit();
out = new FileOutputStream(doc3);
poifs.writeFilesystem(out); poifs.writeFilesystem(out);
out.close(); out.close();
poifs.close();
return cps;
}
/*
* Open <em>doc3</em> for reading and check summary information
* and document summary information. All properties removed before must not
* be found in the property streams of <em>doc3</em>.
*/
private static CustomProperties write3rdFile(File fileIn, File fileOut) throws Exception {
NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
SummaryInformation si = getSummaryInformation(poifs);
DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
/* assertNull(si.getApplicationName());
* Open <em>doc3</em> for reading and check summary information assertNull(si.getAuthor());
* and document summary information. All properties removed before must not
* be found in the property streams of <em>doc3</em>.
*/
poifs = new POIFSFileSystem(new FileInputStream(doc3));
dir = poifs.getRoot();
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
dis = new DocumentInputStream(siEntry);
ps = new PropertySet(dis);
si = new SummaryInformation(ps);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);
assertEquals(null, si.getApplicationName());
assertEquals(null, si.getAuthor());
assertEquals(0, si.getCharCount()); assertEquals(0, si.getCharCount());
assertTrue(si.wasNull()); assertTrue(si.wasNull());
assertEquals(null, si.getComments()); assertNull(si.getComments());
assertEquals(null, si.getCreateDateTime()); assertNull(si.getCreateDateTime());
assertEquals(0, si.getEditTime()); assertEquals(0, si.getEditTime());
assertTrue(si.wasNull()); assertTrue(si.wasNull());
assertEquals(null, si.getKeywords()); assertNull(si.getKeywords());
assertEquals(null, si.getLastAuthor()); assertNull(si.getLastAuthor());
assertEquals(null, si.getLastPrinted()); assertNull(si.getLastPrinted());
assertEquals(null, si.getLastSaveDateTime()); assertNull(si.getLastSaveDateTime());
assertEquals(0, si.getPageCount()); assertEquals(0, si.getPageCount());
assertTrue(si.wasNull()); assertTrue(si.wasNull());
assertEquals(null, si.getRevNumber()); assertNull(si.getRevNumber());
assertEquals(0, si.getSecurity()); assertEquals(0, si.getSecurity());
assertTrue(si.wasNull()); assertTrue(si.wasNull());
assertEquals(null, si.getSubject()); assertNull(si.getSubject());
assertEquals(null, si.getTemplate()); assertNull(si.getTemplate());
assertEquals(null, si.getThumbnail()); assertNull(si.getThumbnail());
assertEquals(null, si.getTitle()); assertNull(si.getTitle());
assertEquals(0, si.getWordCount()); assertEquals(0, si.getWordCount());
assertTrue(si.wasNull()); assertTrue(si.wasNull());
assertEquals(0, dsi.getByteCount()); assertEquals(0, dsi.getByteCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(null, dsi.getCategory()); assertNull(dsi.getCategory());
assertEquals(null, dsi.getCustomProperties()); assertNull(dsi.getCustomProperties());
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getDocparts()); // FIXME (byte array properties not yet implemented): assertNull(dsi.getDocparts());
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getHeadingPair()); // FIXME (byte array properties not yet implemented): assertNull(dsi.getHeadingPair());
assertEquals(0, dsi.getHiddenCount()); assertEquals(0, dsi.getHiddenCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(0, dsi.getLineCount()); assertEquals(0, dsi.getLineCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(false, dsi.getLinksDirty()); assertFalse(dsi.getLinksDirty());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(null, dsi.getManager()); assertNull(dsi.getManager());
assertEquals(0, dsi.getMMClipCount()); assertEquals(0, dsi.getMMClipCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(0, dsi.getNoteCount()); assertEquals(0, dsi.getNoteCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(0, dsi.getParCount()); assertEquals(0, dsi.getParCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(null, dsi.getPresentationFormat()); assertNull(dsi.getPresentationFormat());
assertEquals(false, dsi.getScale()); assertFalse(dsi.getScale());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
assertEquals(0, dsi.getSlideCount()); assertEquals(0, dsi.getSlideCount());
assertTrue(dsi.wasNull()); assertTrue(dsi.wasNull());
poifs.close();
return dsi.getCustomProperties();
} }
private static SummaryInformation getSummaryInformation(NPOIFSFileSystem poifs) throws Exception {
DocumentInputStream dis = poifs.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME);
PropertySet ps = new PropertySet(dis);
SummaryInformation si = new SummaryInformation(ps);
dis.close();
return si;
}
private static DocumentSummaryInformation getDocumentSummaryInformation(NPOIFSFileSystem poifs) throws Exception {
DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
PropertySet ps = new PropertySet(dis);
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
dis.close();
return dsi;
}
/** /**
* <p>Tests the simplified custom properties by reading them from the * <p>Tests the simplified custom properties by reading them from the
* available test files.</p> * available test files.</p>
* *
* @throws Throwable if anything goes wrong. * @throws Throwable if anything goes wrong.
*/ */
@Test
public void testReadCustomPropertiesFromFiles() throws Throwable public void testReadCustomPropertiesFromFiles() throws Throwable
{ {
final AllDataFilesTester.TestTask task = new AllDataFilesTester.TestTask() final AllDataFilesTester.TestTask task = new AllDataFilesTester.TestTask()
@ -590,43 +599,35 @@ public class TestWriteWellKnown extends TestCase {
UnexpectedPropertySetTypeException UnexpectedPropertySetTypeException
{ {
/* Read a test document <em>doc</em> into a POI filesystem. */ /* Read a test document <em>doc</em> into a POI filesystem. */
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(file)); NPOIFSFileSystem poifs = null;
final DirectoryEntry dir = poifs.getRoot(); try {
DocumentEntry dsiEntry = null; poifs = new NPOIFSFileSystem(file);
try final DirectoryEntry dir = poifs.getRoot();
{
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
}
catch (FileNotFoundException ex)
{
/* /*
* A missing document summary information stream is not an error * If there is a document summry information stream, read it from
* and therefore silently ignored here. * the POI filesystem, else create a new one.
*/ */
} DocumentSummaryInformation dsi;
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
/* final DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
* If there is a document summry information stream, read it from final PropertySet ps = new PropertySet(dis);
* the POI filesystem, else create a new one. dsi = new DocumentSummaryInformation(ps);
*/ dis.close();
DocumentSummaryInformation dsi; } else {
if (dsiEntry != null) dsi = PropertySetFactory.newDocumentSummaryInformation();
{ }
final DocumentInputStream dis = new DocumentInputStream(dsiEntry); final CustomProperties cps = dsi.getCustomProperties();
final PropertySet ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps); if (cps == null)
} /* The document does not have custom properties. */
else return;
dsi = PropertySetFactory.newDocumentSummaryInformation();
final CustomProperties cps = dsi.getCustomProperties(); for (CustomProperty cp : cps.values()) {
cp.getName();
if (cps == null) cp.getValue();
/* The document does not have custom properties. */ }
return; } finally {
if (poifs != null) poifs.close();
for (CustomProperty cp : cps.values()) {
cp.getName();
cp.getValue();
} }
} }
}; };
@ -657,6 +658,7 @@ public class TestWriteWellKnown extends TestCase {
/** /**
* <p>Tests basic custom property features.</p> * <p>Tests basic custom property features.</p>
*/ */
@Test
public void testCustomerProperties() public void testCustomerProperties()
{ {
final String KEY = "Schl\u00fcssel \u00e4"; final String KEY = "Schl\u00fcssel \u00e4";
@ -695,6 +697,7 @@ public class TestWriteWellKnown extends TestCase {
* <p>Tests reading custom properties from a section including reading * <p>Tests reading custom properties from a section including reading
* custom properties which are not pure.</p> * custom properties which are not pure.</p>
*/ */
@Test
public void testGetCustomerProperties() public void testGetCustomerProperties()
{ {
final int ID_1 = 2; final int ID_1 = 2;
@ -709,7 +712,7 @@ public class TestWriteWellKnown extends TestCase {
/* A document summary information set stream by default does have custom properties. */ /* A document summary information set stream by default does have custom properties. */
cps = dsi.getCustomProperties(); cps = dsi.getCustomProperties();
assertEquals(null, cps); assertNull(cps);
/* Test an empty custom properties set. */ /* Test an empty custom properties set. */
s = new MutableSection(); s = new MutableSection();

View File

@ -17,10 +17,13 @@
package org.apache.poi.hssf.extractor; package org.apache.poi.hssf.extractor;
import java.io.IOException; import static org.junit.Assert.assertEquals;
import java.io.InputStream; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import junit.framework.TestCase; import java.io.File;
import java.io.IOException;
import java.util.Locale;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
@ -28,24 +31,22 @@ import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** /**
* *
*/ */
public final class TestExcelExtractor extends TestCase { public final class TestExcelExtractor {
private static ExcelExtractor createExtractor(String sampleFileName) { @SuppressWarnings("resource")
private static ExcelExtractor createExtractor(String sampleFileName) throws IOException {
InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleFileName); File file = HSSFTestDataSamples.getSampleFile(sampleFileName);
return new ExcelExtractor(new POIFSFileSystem(file));
try {
return new ExcelExtractor(new POIFSFileSystem(is));
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
@Test
public void testSimple() throws IOException { public void testSimple() throws IOException {
ExcelExtractor extractor = createExtractor("Simple.xls"); ExcelExtractor extractor = createExtractor("Simple.xls");
@ -60,7 +61,8 @@ public final class TestExcelExtractor extends TestCase {
} }
} }
public void testNumericFormula() { @Test
public void testNumericFormula() throws IOException {
ExcelExtractor extractor = createExtractor("sumifformula.xls"); ExcelExtractor extractor = createExtractor("sumifformula.xls");
@ -87,9 +89,12 @@ public final class TestExcelExtractor extends TestCase {
"Sheet2\nSheet3\n", "Sheet2\nSheet3\n",
extractor.getText() extractor.getText()
); );
extractor.close();
} }
public void testwithContinueRecords() { @Test
public void testwithContinueRecords() throws IOException {
ExcelExtractor extractor = createExtractor("StringContinueRecords.xls"); ExcelExtractor extractor = createExtractor("StringContinueRecords.xls");
@ -99,9 +104,12 @@ public final class TestExcelExtractor extends TestCase {
// Until we fixed bug #41064, this would've // Until we fixed bug #41064, this would've
// failed by now // failed by now
assertTrue(extractor.getText().length() > 40960); assertTrue(extractor.getText().length() > 40960);
extractor.close();
} }
public void testStringConcat() { @Test
public void testStringConcat() throws IOException {
ExcelExtractor extractor = createExtractor("SimpleWithFormula.xls"); ExcelExtractor extractor = createExtractor("SimpleWithFormula.xls");
@ -112,9 +120,12 @@ public final class TestExcelExtractor extends TestCase {
extractor.setFormulasNotResults(true); extractor.setFormulasNotResults(true);
assertEquals("Sheet1\nreplaceme\nreplaceme\nCONCATENATE(A1,A2)\nSheet2\nSheet3\n", extractor.getText()); assertEquals("Sheet1\nreplaceme\nreplaceme\nCONCATENATE(A1,A2)\nSheet2\nSheet3\n", extractor.getText());
extractor.close();
} }
public void testStringFormula() { @Test
public void testStringFormula() throws IOException {
ExcelExtractor extractor = createExtractor("StringFormulas.xls"); ExcelExtractor extractor = createExtractor("StringFormulas.xls");
@ -125,40 +136,49 @@ public final class TestExcelExtractor extends TestCase {
extractor.setFormulasNotResults(true); extractor.setFormulasNotResults(true);
assertEquals("Sheet1\nUPPER(\"xyz\")\nSheet2\nSheet3\n", extractor.getText()); assertEquals("Sheet1\nUPPER(\"xyz\")\nSheet2\nSheet3\n", extractor.getText());
extractor.close();
} }
public void testEventExtractor() throws Exception { @Test
public void testEventExtractor() throws Exception {
// First up, a simple file with string // First up, a simple file with string
// based formulas in it // based formulas in it
EventBasedExcelExtractor extractor = new EventBasedExcelExtractor( EventBasedExcelExtractor extractor1 = null;
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls")
)
);
try { try {
extractor.setIncludeSheetNames(true); extractor1 = new EventBasedExcelExtractor(
new POIFSFileSystem(
String text = extractor.getText(); HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls")
)
);
extractor1.setIncludeSheetNames(true);
String text = extractor1.getText();
assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text); assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text);
extractor.setIncludeSheetNames(false); extractor1.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true); extractor1.setFormulasNotResults(true);
text = extractor.getText(); text = extractor1.getText();
assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text); assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text);
} finally {
if (extractor1 != null) extractor1.close();
}
// Now, a slightly longer file with numeric formulas
EventBasedExcelExtractor extractor2 = null;
try {
extractor2 = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("sumifformula.xls")
)
);
extractor2.setIncludeSheetNames(false);
extractor2.setFormulasNotResults(true);
String text = extractor2.getText();
// Now, a slightly longer file with numeric formulas
extractor = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("sumifformula.xls")
)
);
extractor.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true);
text = extractor.getText();
assertEquals( assertEquals(
"1000\t1\tSUMIF(A1:A5,\">4000\",B1:B5)\n" + "1000\t1\tSUMIF(A1:A5,\">4000\",B1:B5)\n" +
"2000\t2\n" + "2000\t2\n" +
@ -168,11 +188,12 @@ public final class TestExcelExtractor extends TestCase {
text text
); );
} finally { } finally {
extractor.close(); if (extractor2 != null) extractor2.close();
} }
} }
public void testWithComments() { @Test
public void testWithComments() throws IOException {
ExcelExtractor extractor = createExtractor("SimpleWithComments.xls"); ExcelExtractor extractor = createExtractor("SimpleWithComments.xls");
extractor.setIncludeSheetNames(false); extractor.setIncludeSheetNames(false);
@ -192,9 +213,12 @@ public final class TestExcelExtractor extends TestCase {
"3\tthree Comment by Yegor Kozlov: Yegor Kozlov: third cell\n", "3\tthree Comment by Yegor Kozlov: Yegor Kozlov: third cell\n",
extractor.getText() extractor.getText()
); );
extractor.close();
} }
public void testWithBlank() { @Test
public void testWithBlank() throws IOException {
ExcelExtractor extractor = createExtractor("MissingBits.xls"); ExcelExtractor extractor = createExtractor("MissingBits.xls");
String def = extractor.getText(); String def = extractor.getText();
extractor.setIncludeBlankCells(true); extractor.setIncludeBlankCells(true);
@ -213,136 +237,145 @@ public final class TestExcelExtractor extends TestCase {
"Hello\n" + "Hello\n" +
"11\t\t\t23\n" "11\t\t\t23\n"
)); ));
extractor.close();
} }
public void testFormatting() throws Exception { @Test
ExcelExtractor extractor = createExtractor("Formatting.xls"); public void testFormatting() throws Exception {
extractor.setIncludeBlankCells(false); Locale userLocale = LocaleUtil.getUserLocale();
extractor.setIncludeSheetNames(false); LocaleUtil.setUserLocale(Locale.ROOT);
String text = extractor.getText(); try {
ExcelExtractor extractor = createExtractor("Formatting.xls");
// Note - not all the formats in the file extractor.setIncludeBlankCells(false);
// actually quite match what they claim to extractor.setIncludeSheetNames(false);
// be, as some are auto-local builtins... String text = extractor.getText();
assertTrue(text.startsWith( // Note - not all the formats in the file
"Dates, all 24th November 2006\n" // actually quite match what they claim to
)); // be, as some are auto-local builtins...
assertTrue(
text.indexOf( assertTrue(text.startsWith(
"yyyy/mm/dd\t2006/11/24\n" "Dates, all 24th November 2006\n"
) > -1 ));
); assertTrue(
assertTrue( text.indexOf(
text.indexOf( "yyyy/mm/dd\t2006/11/24\n"
"yyyy-mm-dd\t2006-11-24\n" ) > -1
) > -1 );
); assertTrue(
assertTrue( text.indexOf(
text.indexOf( "yyyy-mm-dd\t2006-11-24\n"
"dd-mm-yy\t24-11-06\n" ) > -1
) > -1 );
); assertTrue(
text.indexOf(
assertTrue("Had: " + text + ", but should contain 'nn.nn\\t10.52\\n'", "dd-mm-yy\t24-11-06\n"
text.indexOf( ) > -1
"nn.nn\t10.52\n" );
) > -1
); assertTrue("Had: " + text + ", but should contain 'nn.nn\\t10.52\\n'",
assertTrue( text.indexOf(
text.indexOf( "nn.nn\t10.52\n"
"nn.nnn\t10.520\n" ) > -1
) > -1 );
); assertTrue(
assertTrue( text.indexOf(
text.indexOf( "nn.nnn\t10.520\n"
"\u00a3nn.nn\t\u00a310.52\n" ) > -1
) > -1 );
); assertTrue(
text.indexOf(
"\u00a3nn.nn\t\u00a310.52\n"
) > -1
);
extractor.close();
} finally {
LocaleUtil.setUserLocale(userLocale);
}
} }
/** /**
* Embeded in a non-excel file * Embeded in a non-excel file
*/ */
public void testWithEmbeded() throws Exception { @Test
POIFSFileSystem fs = new POIFSFileSystem( public void testWithEmbeded() throws Exception {
POIDataSamples.getDocumentInstance().openResourceAsStream("word_with_embeded.doc") POIFSFileSystem fs = null;
);
HSSFWorkbook wbA = null, wbB = null;
ExcelExtractor exA = null, exB = null;
DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntry("ObjectPool");
DirectoryNode dirA = (DirectoryNode) objPool.getEntry("_1269427460");
DirectoryNode dirB = (DirectoryNode) objPool.getEntry("_1269427461");
HSSFWorkbook wbA = new HSSFWorkbook(dirA, fs, true);
HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true);
ExcelExtractor exA = new ExcelExtractor(wbA);
try { try {
ExcelExtractor exB = new ExcelExtractor(wbB); fs = new POIFSFileSystem(POIDataSamples.getDocumentInstance().getFile("word_with_embeded.doc"));
try {
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntry("ObjectPool");
exA.getText()); DirectoryNode dirA = (DirectoryNode) objPool.getEntry("_1269427460");
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle()); DirectoryNode dirB = (DirectoryNode) objPool.getEntry("_1269427461");
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", wbA = new HSSFWorkbook(dirA, fs, true);
exB.getText()); exA = new ExcelExtractor(wbA);
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); wbB = new HSSFWorkbook(dirB, fs, true);
} finally { exB = new ExcelExtractor(wbB);
exB.close();
} assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
} finally { } finally {
exA.close(); if (exB != null) exB.close();
if (wbB != null) wbB.close();
if (exA != null) exA.close();
if (wbA != null) wbA.close();
if (fs != null) fs.close();
} }
} }
/** /**
* Excel embeded in excel * Excel embeded in excel
*/ */
public void testWithEmbededInOwn() throws Exception { @Test
public void testWithEmbededInOwn() throws Exception {
POIDataSamples ssSamples = POIDataSamples.getSpreadSheetInstance(); POIDataSamples ssSamples = POIDataSamples.getSpreadSheetInstance();
POIFSFileSystem fs = new POIFSFileSystem( POIFSFileSystem fs = null;
ssSamples.openResourceAsStream("excel_with_embeded.xls") HSSFWorkbook wbA = null, wbB = null;
); ExcelExtractor exA = null, exB = null, ex = null;
DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B5");
DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B4");
HSSFWorkbook wbA = new HSSFWorkbook(dirA, fs, true);
HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true);
ExcelExtractor exA = new ExcelExtractor(wbA);
try { try {
ExcelExtractor exB = new ExcelExtractor(wbB); fs = new POIFSFileSystem(ssSamples.getFile("excel_with_embeded.xls"));
try {
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B5");
exA.getText()); DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B4");
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
wbA = new HSSFWorkbook(dirA, fs, true);
wbB = new HSSFWorkbook(dirB, fs, true);
exA = new ExcelExtractor(wbA);
exB = new ExcelExtractor(wbB);
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", // And the base file too
exB.getText()); ex = new ExcelExtractor(fs);
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n", ex.getText());
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle());
// And the base file too } finally {
ExcelExtractor ex = new ExcelExtractor(fs); if (ex != null) ex.close();
try { if (exB != null) exB.close();
assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n", if (exA != null) exA.close();
ex.getText()); if (wbB != null) wbB.close();
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle()); if (wbA != null) wbA.close();
} finally { if (fs != null) fs.close();
ex.close();
}
} finally {
exB.close();
}
} finally {
exA.close();
} }
} }
/** /**
* Test that we get text from headers and footers * Test that we get text from headers and footers
*/ */
public void test45538() { @Test
public void test45538() throws IOException {
String[] files = { String[] files = {
"45538_classic_Footer.xls", "45538_form_Footer.xls", "45538_classic_Footer.xls", "45538_form_Footer.xls",
"45538_classic_Header.xls", "45538_form_Header.xls" "45538_classic_Header.xls", "45538_form_Header.xls"
@ -352,21 +385,26 @@ public final class TestExcelExtractor extends TestCase {
String text = extractor.getText(); String text = extractor.getText();
assertTrue("Unable to find expected word in text\n" + text, text.indexOf("testdoc") >=0); assertTrue("Unable to find expected word in text\n" + text, text.indexOf("testdoc") >=0);
assertTrue("Unable to find expected word in text\n" + text, text.indexOf("test phrase") >= 0); assertTrue("Unable to find expected word in text\n" + text, text.indexOf("test phrase") >= 0);
extractor.close();
} }
} }
public void testPassword() { @Test
public void testPassword() throws IOException {
Biff8EncryptionKey.setCurrentUserPassword("password"); Biff8EncryptionKey.setCurrentUserPassword("password");
ExcelExtractor extractor = createExtractor("password.xls"); ExcelExtractor extractor = createExtractor("password.xls");
String text = extractor.getText(); String text = extractor.getText();
Biff8EncryptionKey.setCurrentUserPassword(null); Biff8EncryptionKey.setCurrentUserPassword(null);
assertTrue(text.contains("ZIP")); assertTrue(text.contains("ZIP"));
extractor.close();
} }
public void testNullPointerException() { @Test
public void testNullPointerException() throws IOException {
ExcelExtractor extractor = createExtractor("ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls"); ExcelExtractor extractor = createExtractor("ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls");
assertNotNull(extractor); assertNotNull(extractor);
assertNotNull(extractor.getText()); assertNotNull(extractor.getText());
extractor.close();
} }
} }

View File

@ -36,9 +36,9 @@ import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
@ -69,13 +69,13 @@ import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -2193,10 +2193,9 @@ public final class TestBugs extends BaseTestBugzillaIssues {
@Test @Test
public void bug48968() throws Exception { public void bug48968() throws Exception {
TimeZone tz = DateUtil.getUserTimeZone(); TimeZone userTimeZone = LocaleUtil.getUserTimeZone();
try { LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
DateUtil.setUserTimeZone(TimeZone.getTimeZone("CET")); try {
HSSFWorkbook wb = openSample("48968.xls"); HSSFWorkbook wb = openSample("48968.xls");
assertEquals(1, wb.getNumberOfSheets()); assertEquals(1, wb.getNumberOfSheets());
@ -2241,9 +2240,9 @@ public final class TestBugs extends BaseTestBugzillaIssues {
assertEquals(39.0+14.0+1, s.getRow(6).getCell(0).getNumericCellValue(), 0); assertEquals(39.0+14.0+1, s.getRow(6).getCell(0).getNumericCellValue(), 0);
assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula()); assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula());
assertEquals(54.0+24.0-60, s.getRow(7).getCell(0).getNumericCellValue(), 0); assertEquals(54.0+24.0-60, s.getRow(7).getCell(0).getNumericCellValue(), 0);
} finally { } finally {
DateUtil.setUserTimeZone(tz); LocaleUtil.setUserTimeZone(userTimeZone);
} }
} }
@ -2474,12 +2473,13 @@ public final class TestBugs extends BaseTestBugzillaIssues {
Sheet sheet = wb.getSheet("test-sheet"); Sheet sheet = wb.getSheet("test-sheet");
int rowCount = sheet.getLastRowNum() + 1; int rowCount = sheet.getLastRowNum() + 1;
int newRows = 5; int newRows = 5;
Calendar cal = LocaleUtil.getLocaleCalendar();
for (int r = rowCount; r < rowCount + newRows; r++) { for (int r = rowCount; r < rowCount + newRows; r++) {
Row row = sheet.createRow((short) r); Row row = sheet.createRow((short) r);
row.createCell(0).setCellValue(1.03 * (r + 7)); row.createCell(0).setCellValue(1.03 * (r + 7));
row.createCell(1).setCellValue(new Date()); row.createCell(1).setCellValue(cal.getTime());
row.createCell(2).setCellValue(Calendar.getInstance()); row.createCell(2).setCellValue(cal);
row.createCell(3).setCellValue(String.format("row:%d/col:%d", r, 3)); row.createCell(3).setCellValue(String.format(Locale.ROOT, "row:%d/col:%d", r, 3));
row.createCell(4).setCellValue(true); row.createCell(4).setCellValue(true);
row.createCell(5).setCellType(Cell.CELL_TYPE_ERROR); row.createCell(5).setCellType(Cell.CELL_TYPE_ERROR);
row.createCell(6).setCellValue("added cells."); row.createCell(6).setCellValue("added cells.");

View File

@ -32,12 +32,11 @@ import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
/** /**
* Class to test cell styling functionality * Class to test cell styling functionality
*
* @author Andrew C. Oliver
*/ */
public final class TestCellStyle extends TestCase { public final class TestCellStyle extends TestCase {
@ -115,8 +114,7 @@ public final class TestCellStyle extends TestCase {
cell = row.createCell(2); cell = row.createCell(2);
cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy")); cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
cell.setCellStyle(cs); cell.setCellStyle(cs);
Calendar cal = Calendar.getInstance(); Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(new Date());
cell.setCellValue(cal); cell.setCellValue(cal);
wb.write(out); wb.write(out);

View File

@ -17,15 +17,14 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator; import java.util.Iterator;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
@ -43,15 +42,19 @@ import org.apache.poi.ss.formula.ptg.RefPtg;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* *
*/ */
public final class TestFormulaEvaluatorBugs extends TestCase { public final class TestFormulaEvaluatorBugs {
private static boolean OUTPUT_TEST_FILES = false; private static boolean OUTPUT_TEST_FILES = false;
private String tmpDirName; private static String tmpDirName;
protected void setUp() { @BeforeClass
public static void setUp() {
tmpDirName = System.getProperty("java.io.tmpdir"); tmpDirName = System.getProperty("java.io.tmpdir");
OUTPUT_TEST_FILES = Boolean.parseBoolean( OUTPUT_TEST_FILES = Boolean.parseBoolean(
System.getProperty("org.apache.poi.test.output_test_files", "False")); System.getProperty("org.apache.poi.test.output_test_files", "False"));
@ -66,6 +69,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
* WARNING - tedious bug where you actually have to * WARNING - tedious bug where you actually have to
* open up excel * open up excel
*/ */
@Test
public void test44636() throws Exception { public void test44636() throws Exception {
// Open the existing file, tweak one value and // Open the existing file, tweak one value and
// re-calculate // re-calculate
@ -80,15 +84,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb); HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001); assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001);
FileOutputStream out;
if (OUTPUT_TEST_FILES) { if (OUTPUT_TEST_FILES) {
// Save // Save
File existing = new File(tmpDirName, "44636-existing.xls"); File existing = new File(tmpDirName, "44636-existing.xls");
out = new FileOutputStream(existing); FileOutputStream out = new FileOutputStream(existing);
wb.write(out); wb.write(out);
out.close(); out.close();
System.err.println("Existing file for bug #44636 written to " + existing.toString()); System.err.println("Existing file for bug #44636 written to " + existing.toString());
} }
wb.close();
// Now, do a new file from scratch // Now, do a new file from scratch
wb = new HSSFWorkbook(); wb = new HSSFWorkbook();
sheet = wb.createSheet(); sheet = wb.createSheet();
@ -106,21 +111,21 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
if (OUTPUT_TEST_FILES) { if (OUTPUT_TEST_FILES) {
// Save // Save
File scratch = new File(tmpDirName, "44636-scratch.xls"); File scratch = new File(tmpDirName, "44636-scratch.xls");
out = new FileOutputStream(scratch); FileOutputStream out = new FileOutputStream(scratch);
wb.write(out); wb.write(out);
out.close(); out.close();
System.err.println("New file for bug #44636 written to " + scratch.toString()); System.err.println("New file for bug #44636 written to " + scratch.toString());
} }
wb.close();
} }
/** /**
* Bug 44297: 32767+32768 is evaluated to -1 * Bug 44297: 32767+32768 is evaluated to -1
* Fix: IntPtg must operate with unsigned short. Reading signed short results in incorrect formula calculation * Fix: IntPtg must operate with unsigned short. Reading signed short results in incorrect formula calculation
* if a formula has values in the interval [Short.MAX_VALUE, (Short.MAX_VALUE+1)*2] * if a formula has values in the interval [Short.MAX_VALUE, (Short.MAX_VALUE+1)*2]
*
* @author Yegor Kozlov
*/ */
public void test44297() { @Test
public void test44297() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls");
@ -175,13 +180,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
cell = row.getCell(0); cell = row.getCell(0);
assertEquals("-1000000-3000000", cell.getCellFormula()); assertEquals("-1000000-3000000", cell.getCellFormula());
assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0); assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0);
wb.close();
} }
/** /**
* Bug 44410: SUM(C:C) is valid in excel, and means a sum * Bug 44410: SUM(C:C) is valid in excel, and means a sum
* of all the rows in Column C * of all the rows in Column C
*/ */
public void test44410() { @Test
public void test44410() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls");
HSSFSheet sheet = wb.getSheetAt(0); HSSFSheet sheet = wb.getSheetAt(0);
@ -233,12 +241,15 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
HSSFCell cellSUM2D = rowSUM2D.getCell(0); HSSFCell cellSUM2D = rowSUM2D.getCell(0);
assertEquals("SUM(C:D)", cellSUM2D.getCellFormula()); assertEquals("SUM(C:D)", cellSUM2D.getCellFormula());
assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0); assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0);
wb.close();
} }
/** /**
* Tests that we can evaluate boolean cells properly * Tests that we can evaluate boolean cells properly
*/ */
public void testEvaluateBooleanInCell_bug44508() { @Test
public void testEvaluateBooleanInCell_bug44508() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(); HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1"); wb.setSheetName(0, "Sheet1");
@ -254,9 +265,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
fail("Identified bug 44508"); fail("Identified bug 44508");
} }
assertEquals(true, cell.getBooleanCellValue()); assertEquals(true, cell.getBooleanCellValue());
wb.close();
} }
public void testClassCast_bug44861() { @Test
public void testClassCast_bug44861() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls");
// Check direct // Check direct
@ -276,9 +290,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
} }
} }
} }
wb.close();
} }
public void testEvaluateInCellWithErrorCode_bug44950() { @Test
public void testEvaluateInCellWithErrorCode_bug44950() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1"); HSSFSheet sheet = wb.createSheet("Sheet1");
HSSFRow row = sheet.createRow(1); HSSFRow row = sheet.createRow(1);
@ -289,13 +306,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
fe.evaluateInCell(cell); fe.evaluateInCell(cell);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
if (e.getMessage().equals("You cannot get an error value from a non-error cell")) { if (e.getMessage().equals("You cannot get an error value from a non-error cell")) {
throw new AssertionFailedError("Identified bug 44950 b"); fail("Identified bug 44950 b");
} }
throw e; throw e;
} finally {
wb.close();
} }
} }
public void testDateWithNegativeParts_bug48528() { @Test
public void testDateWithNegativeParts_bug48528() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1"); HSSFSheet sheet = wb.createSheet("Sheet1");
HSSFRow row = sheet.createRow(1); HSSFRow row = sheet.createRow(1);
@ -310,31 +330,33 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
cell.setCellFormula("DATE(2012,2,1)"); cell.setCellFormula("DATE(2012,2,1)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40940.0, fe.evaluate(cell).getNumberValue()); assertEquals(40940.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2,1+4)"); cell.setCellFormula("DATE(2012,2,1+4)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40944.0, fe.evaluate(cell).getNumberValue()); assertEquals(40944.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2-1,1+4)"); cell.setCellFormula("DATE(2012,2-1,1+4)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40913.0, fe.evaluate(cell).getNumberValue()); assertEquals(40913.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2,1-27)"); cell.setCellFormula("DATE(2012,2,1-27)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40913.0, fe.evaluate(cell).getNumberValue()); assertEquals(40913.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2-2,1+4)"); cell.setCellFormula("DATE(2012,2-2,1+4)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40882.0, fe.evaluate(cell).getNumberValue()); assertEquals(40882.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2,1-58)"); cell.setCellFormula("DATE(2012,2,1-58)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40882.0, fe.evaluate(cell).getNumberValue()); assertEquals(40882.0, fe.evaluate(cell).getNumberValue(), 0);
cell.setCellFormula("DATE(2012,2-12,1+4)"); cell.setCellFormula("DATE(2012,2-12,1+4)");
fe.notifyUpdateCell(cell); fe.notifyUpdateCell(cell);
assertEquals(40579.0, fe.evaluate(cell).getNumberValue()); assertEquals(40579.0, fe.evaluate(cell).getNumberValue(), 0);
wb.close();
} }
private static final class EvalListener extends EvaluationListener { private static final class EvalListener extends EvaluationListener {
@ -363,7 +385,8 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
/** /**
* The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values * The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values
*/ */
public void testSlowEvaluate45376() { @Test
public void testSlowEvaluate45376() throws Exception {
/* /*
* Note - to observe behaviour without caching, disable the call to * Note - to observe behaviour without caching, disable the call to
* updateValue() from FormulaCellCacheEntry.updateFormulaResult(). * updateValue() from FormulaCellCacheEntry.updateFormulaResult().
@ -384,7 +407,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
"DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())"; "DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())";
cell.setCellFormula(formula); cell.setCellFormula(formula);
} }
Calendar cal = new GregorianCalendar(2000, 0, 1, 0, 0, 0); Calendar cal = LocaleUtil.getLocaleCalendar(2000, 0, 1, 0, 0, 0);
row.createCell(0).setCellValue(cal); row.createCell(0).setCellValue(cal);
// Choose cell A9 instead of A10, so that the failing test case doesn't take too long to execute. // Choose cell A9 instead of A10, so that the failing test case doesn't take too long to execute.
@ -397,8 +420,8 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes // Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
// much time (~3 sec on Core 2 Duo 2.2GHz) // much time (~3 sec on Core 2 Duo 2.2GHz)
// short-circuit-if optimisation cuts this down to 255 evaluations which is still too high // short-circuit-if optimisation cuts this down to 255 evaluations which is still too high
System.err.println("Cell A9 took " + evalCount + " intermediate evaluations"); // System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
throw new AssertionFailedError("Identifed bug 45376 - Formula evaluator should cache values"); fail("Identifed bug 45376 - Formula evaluator should cache values");
} }
// With caching, the evaluationCount is 8 which is exactly the // With caching, the evaluationCount is 8 which is exactly the
// number of formula cells that needed to be evaluated. // number of formula cells that needed to be evaluated.
@ -413,9 +436,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
// confirm the evaluation result too // confirm the evaluation result too
assertEquals(ErrorEval.NA, ve); assertEquals(ErrorEval.NA, ve);
wb.close();
} }
@SuppressWarnings("resource") @SuppressWarnings("resource")
@Test
public void test55747_55324() throws Exception { public void test55747_55324() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFFormulaEvaluator ev = wb.getCreationHelper().createFormulaEvaluator(); HSSFFormulaEvaluator ev = wb.getCreationHelper().createFormulaEvaluator();

View File

@ -17,12 +17,15 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
@ -38,15 +41,14 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
/** /**
* Tests various functionality having to do with {@link HSSFCell}. For instance support for * Tests various functionality having to do with {@link HSSFCell}. For instance support for
* particular datatypes, etc. * particular datatypes, etc.
* @author Andrew C. Oliver (andy at superlinksoftware dot com)
* @author Dan Sherman (dsherman at isisph.com)
* @author Alex Jacoby (ajacoby at gmail.com)
*/ */
public final class TestHSSFCell extends BaseTestCell { public final class TestHSSFCell extends BaseTestCell {
@ -59,27 +61,28 @@ public final class TestHSSFCell extends BaseTestCell {
* is working properly. Conversion of the date is also an issue, * is working properly. Conversion of the date is also an issue,
* but there's a separate unit test for that. * but there's a separate unit test for that.
*/ */
public void testDateWindowingRead() { @Test
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT); public void testDateWindowingRead() throws Exception {
cal.set(2000, 0, 1, 0, 0, 0); // Jan. 1, 2000 Calendar cal = LocaleUtil.getLocaleCalendar(2000, 0, 1, 0, 0, 0);// Jan. 1, 2000
cal.clear(Calendar.MILLISECOND);
Date date = cal.getTime(); Date date = cal.getTime();
// first check a file with 1900 Date Windowing // first check a file with 1900 Date Windowing
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
HSSFSheet sheet = workbook.getSheetAt(0); HSSFSheet sheet = wb.getSheetAt(0);
assertEquals("Date from file using 1900 Date Windowing", assertEquals("Date from file using 1900 Date Windowing",
date.getTime(), date.getTime(),
sheet.getRow(0).getCell(0).getDateCellValue().getTime()); sheet.getRow(0).getCell(0).getDateCellValue().getTime());
wb.close();
// now check a file with 1904 Date Windowing // now check a file with 1904 Date Windowing
workbook = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls"); wb = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
sheet = workbook.getSheetAt(0); sheet = wb.getSheetAt(0);
assertEquals("Date from file using 1904 Date Windowing", assertEquals("Date from file using 1904 Date Windowing",
date.getTime(), date.getTime(),
sheet.getRow(0).getCell(0).getDateCellValue().getTime()); sheet.getRow(0).getCell(0).getDateCellValue().getTime());
wb.close();
} }
@ -90,28 +93,32 @@ public final class TestHSSFCell extends BaseTestCell {
* previous test ({@link #testDateWindowingRead}) fails, the * previous test ({@link #testDateWindowingRead}) fails, the
* results of this test are meaningless. * results of this test are meaningless.
*/ */
public void testDateWindowingWrite() { @Test
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000 public void testDateWindowingWrite() throws Exception {
Calendar cal = LocaleUtil.getLocaleCalendar(2000,0,1,0,0,0); // Jan. 1, 2000
Date date = cal.getTime(); Date date = cal.getTime();
// first check a file with 1900 Date Windowing // first check a file with 1900 Date Windowing
HSSFWorkbook wb; HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
wb = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
setCell(wb, 0, 1, date); setCell(wb1, 0, 1, date);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
assertEquals("Date from file using 1900 Date Windowing", assertEquals("Date from file using 1900 Date Windowing",
date.getTime(), date.getTime(),
readCell(wb, 0, 1).getTime()); readCell(wb2, 0, 1).getTime());
wb1.close();
wb2.close();
// now check a file with 1904 Date Windowing // now check a file with 1904 Date Windowing
wb = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls"); wb1 = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
setCell(wb, 0, 1, date); setCell(wb1, 0, 1, date);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
assertEquals("Date from file using 1900 Date Windowing", assertEquals("Date from file using 1900 Date Windowing",
date.getTime(), date.getTime(),
readCell(wb, 0, 1).getTime()); readCell(wb2, 0, 1).getTime());
wb1.close();
wb2.close();
} }
private static void setCell(HSSFWorkbook workbook, int rowIdx, int colIdx, Date date) { private static void setCell(HSSFWorkbook workbook, int rowIdx, int colIdx, Date date) {
@ -135,12 +142,13 @@ public final class TestHSSFCell extends BaseTestCell {
/** /**
* Tests that the active cell can be correctly read and set * Tests that the active cell can be correctly read and set
*/ */
public void testActiveCell() { @Test
public void testActiveCell() throws Exception {
//read in sample //read in sample
HSSFWorkbook book = HSSFTestDataSamples.openSampleWorkbook("Simple.xls"); HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("Simple.xls");
//check initial position //check initial position
HSSFSheet umSheet = book.getSheetAt(0); HSSFSheet umSheet = wb1.getSheetAt(0);
InternalSheet s = umSheet.getSheet(); InternalSheet s = umSheet.getSheet();
assertEquals("Initial active cell should be in col 0", assertEquals("Initial active cell should be in col 0",
(short) 0, s.getActiveCellCol()); (short) 0, s.getActiveCellCol());
@ -156,18 +164,22 @@ public final class TestHSSFCell extends BaseTestCell {
3, s.getActiveCellRow()); 3, s.getActiveCellRow());
//write book to temp file; read and verify that position is serialized //write book to temp file; read and verify that position is serialized
book = HSSFTestDataSamples.writeOutAndReadBack(book); HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
wb1.close();
umSheet = book.getSheetAt(0); umSheet = wb2.getSheetAt(0);
s = umSheet.getSheet(); s = umSheet.getSheet();
assertEquals("After serialize, active cell should be in col 2", assertEquals("After serialize, active cell should be in col 2",
(short) 2, s.getActiveCellCol()); (short) 2, s.getActiveCellCol());
assertEquals("After serialize, active cell should be on row 3", assertEquals("After serialize, active cell should be on row 3",
3, s.getActiveCellRow()); 3, s.getActiveCellRow());
wb2.close();
} }
@Test
public void testActiveCellBug56114() throws IOException { public void testActiveCellBug56114() throws IOException {
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
Sheet sh = wb.createSheet(); Sheet sh = wb.createSheet();
@ -222,7 +234,8 @@ public final class TestHSSFCell extends BaseTestCell {
/** /**
* Test reading hyperlinks * Test reading hyperlinks
*/ */
public void testWithHyperlink() { @Test
public void testWithHyperlink() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithHyperlink.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithHyperlink.xls");
@ -235,12 +248,15 @@ public final class TestHSSFCell extends BaseTestCell {
assertEquals("http://poi.apache.org/", link.getAddress()); assertEquals("http://poi.apache.org/", link.getAddress());
assertEquals(4, link.getFirstRow()); assertEquals(4, link.getFirstRow());
assertEquals(0, link.getFirstColumn()); assertEquals(0, link.getFirstColumn());
wb.close();
} }
/** /**
* Test reading hyperlinks * Test reading hyperlinks
*/ */
public void testWithTwoHyperlinks() { @Test
public void testWithTwoHyperlinks() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithTwoHyperLinks.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithTwoHyperLinks.xls");
@ -261,13 +277,16 @@ public final class TestHSSFCell extends BaseTestCell {
assertEquals("http://poi.apache.org/hssf/", link2.getAddress()); assertEquals("http://poi.apache.org/hssf/", link2.getAddress());
assertEquals(8, link2.getFirstRow()); assertEquals(8, link2.getFirstRow());
assertEquals(1, link2.getFirstColumn()); assertEquals(1, link2.getFirstColumn());
wb.close();
} }
/** /**
* Test to ensure we can only assign cell styles that belong * Test to ensure we can only assign cell styles that belong
* to our workbook, and not those from other workbooks. * to our workbook, and not those from other workbooks.
*/ */
public void testCellStyleWorkbookMatch() { @Test
public void testCellStyleWorkbookMatch() throws Exception {
HSSFWorkbook wbA = new HSSFWorkbook(); HSSFWorkbook wbA = new HSSFWorkbook();
HSSFWorkbook wbB = new HSSFWorkbook(); HSSFWorkbook wbB = new HSSFWorkbook();
@ -306,6 +325,9 @@ public final class TestHSSFCell extends BaseTestCell {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// expected during successful test // expected during successful test
} }
wbB.close();
wbA.close();
} }
/** /**
@ -315,6 +337,7 @@ public final class TestHSSFCell extends BaseTestCell {
* versions (prior to bug 46213 / r717883) crash instead. * versions (prior to bug 46213 / r717883) crash instead.
* @throws IOException * @throws IOException
*/ */
@Test
public void testCachedTypeChange() throws IOException { public void testCachedTypeChange() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1"); HSSFSheet sheet = wb.createSheet("Sheet1");
@ -362,22 +385,27 @@ public final class TestHSSFCell extends BaseTestCell {
/** /**
* HSSF prior to version 3.7 had a bug: it could write a NaN but could not read such a file back. * HSSF prior to version 3.7 had a bug: it could write a NaN but could not read such a file back.
*/ */
public void testReadNaN() { @Test
public void testReadNaN() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49761.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49761.xls");
assertNotNull(wb); assertNotNull(wb);
wb.close();
} }
public void testHSSFCell() { @Test
public void testHSSFCell() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(); HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0); HSSFRow row = sheet.createRow(0);
row.createCell(0); row.createCell(0);
HSSFCell cell = new HSSFCell(wb, sheet, 0, (short)0); HSSFCell cell = new HSSFCell(wb, sheet, 0, (short)0);
assertNotNull(cell); assertNotNull(cell);
wb.close();
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void testDeprecatedMethods() { @Test
public void testDeprecatedMethods() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(); HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0); HSSFRow row = sheet.createRow(0);
@ -402,8 +430,11 @@ public final class TestHSSFCell extends BaseTestCell {
cell.removeCellComment(); cell.removeCellComment();
cell.removeCellComment(); cell.removeCellComment();
wb.close();
} }
@Test
public void testCellType() throws IOException { public void testCellType() throws IOException {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();

View File

@ -17,18 +17,25 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.Format; import java.text.Format;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.GregorianCalendar; import java.util.Calendar;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import junit.framework.TestCase; import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Unit tests for HSSFDataFormatter.java * Unit tests for HSSFDataFormatter.java
@ -36,9 +43,25 @@ import junit.framework.TestCase;
* @author James May (james dot may at fmr dot com) * @author James May (james dot may at fmr dot com)
* *
*/ */
public final class TestHSSFDataFormatter extends TestCase { public final class TestHSSFDataFormatter {
private final HSSFDataFormatter formatter; private static TimeZone userTimeZone;
@BeforeClass
public static void setTimeZone() {
userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
LocaleUtil.setUserLocale(Locale.US);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTimeZone);
LocaleUtil.setUserLocale(Locale.ROOT);
}
private final HSSFDataFormatter formatter;
private final HSSFWorkbook wb; private final HSSFWorkbook wb;
public TestHSSFDataFormatter() { public TestHSSFDataFormatter() {
@ -197,6 +220,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/** /**
* Test getting formatted values from numeric and date cells. * Test getting formatted values from numeric and date cells.
*/ */
@Test
public void testGetFormattedCellValueHSSFCell() { public void testGetFormattedCellValueHSSFCell() {
// Valid date formats -- cell values should be date formatted & not "555.555" // Valid date formats -- cell values should be date formatted & not "555.555"
HSSFRow row = wb.getSheetAt(0).getRow(0); HSSFRow row = wb.getSheetAt(0).getRow(0);
@ -216,7 +240,9 @@ public final class TestHSSFDataFormatter extends TestCase {
//assert the correct month form, as in the original Excel format //assert the correct month form, as in the original Excel format
String monthPtrn = fmt.indexOf("mmmm") != -1 ? "MMMM" : "MMM"; String monthPtrn = fmt.indexOf("mmmm") != -1 ? "MMMM" : "MMM";
// this line is intended to compute how "July" would look like in the current locale // this line is intended to compute how "July" would look like in the current locale
String jul = new SimpleDateFormat(monthPtrn).format(new GregorianCalendar(2010,6,15).getTime()); SimpleDateFormat sdf = new SimpleDateFormat(monthPtrn, LocaleUtil.getUserLocale());
Calendar calDef = LocaleUtil.getLocaleCalendar(2010, 6, 15, 0, 0, 0);
String jul = sdf.format(calDef.getTime());
// special case for MMMMM = 1st letter of month name // special case for MMMMM = 1st letter of month name
if(fmt.indexOf("mmmmm") > -1) { if(fmt.indexOf("mmmmm") > -1) {
jul = jul.substring(0,1); jul = jul.substring(0,1);
@ -228,7 +254,6 @@ public final class TestHSSFDataFormatter extends TestCase {
row = wb.getSheetAt(0).getRow(1); row = wb.getSheetAt(0).getRow(1);
it = row.cellIterator(); it = row.cellIterator();
log("==== VALID TIME FORMATS ===="); log("==== VALID TIME FORMATS ====");
while (it.hasNext()) { while (it.hasNext()) {
Cell cell = it.next(); Cell cell = it.next();
String fmt = cell.getCellStyle().getDataFormatString(); String fmt = cell.getCellStyle().getDataFormatString();
@ -265,7 +290,7 @@ public final class TestHSSFDataFormatter extends TestCase {
log(formatter.formatCellValue(cell)); log(formatter.formatCellValue(cell));
// should be equal to "1234567890.12345" // should be equal to "1234567890.12345"
// in some locales the the decimal delimiter is a comma, not a dot // in some locales the the decimal delimiter is a comma, not a dot
char decimalSeparator = new DecimalFormatSymbols().getDecimalSeparator(); char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
assertEquals("1234567890" + decimalSeparator + "12345", formatter.formatCellValue(cell)); assertEquals("1234567890" + decimalSeparator + "12345", formatter.formatCellValue(cell));
} }
@ -297,6 +322,7 @@ public final class TestHSSFDataFormatter extends TestCase {
assertEquals(formatter.formatCellValue(null), ""); assertEquals(formatter.formatCellValue(null), "");
} }
@Test
public void testGetFormattedCellValueHSSFCellHSSFFormulaEvaluator() { public void testGetFormattedCellValueHSSFCellHSSFFormulaEvaluator() {
// test formula format // test formula format
HSSFRow row = wb.getSheetAt(0).getRow(7); HSSFRow row = wb.getSheetAt(0).getRow(7);
@ -310,7 +336,7 @@ public final class TestHSSFDataFormatter extends TestCase {
// now with a formula evaluator // now with a formula evaluator
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb); HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
log(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)"); log(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)");
char decimalSeparator = new DecimalFormatSymbols().getDecimalSeparator(); char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
assertEquals("24" + decimalSeparator + "50%", formatter.formatCellValue(cell,evaluator)); assertEquals("24" + decimalSeparator + "50%", formatter.formatCellValue(cell,evaluator));
} }
@ -319,10 +345,12 @@ public final class TestHSSFDataFormatter extends TestCase {
* Test using a default number format. The format should be used when a * Test using a default number format. The format should be used when a
* format pattern cannot be parsed by DecimalFormat. * format pattern cannot be parsed by DecimalFormat.
*/ */
@Test
public void testSetDefaultNumberFormat() { public void testSetDefaultNumberFormat() {
HSSFRow row = wb.getSheetAt(0).getRow(3); HSSFRow row = wb.getSheetAt(0).getRow(3);
Iterator<Cell> it = row.cellIterator(); Iterator<Cell> it = row.cellIterator();
Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD"); DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD", dfs);
formatter.setDefaultNumberFormat(defaultFormat); formatter.setDefaultNumberFormat(defaultFormat);
log("\n==== DEFAULT NUMBER FORMAT ===="); log("\n==== DEFAULT NUMBER FORMAT ====");
@ -338,6 +366,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/** /**
* A format of "@" means use the general format * A format of "@" means use the general format
*/ */
@Test
public void testGeneralAtFormat() { public void testGeneralAtFormat() {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("47154.xls"); HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("47154.xls");
HSSFSheet sheet = workbook.getSheetAt(0); HSSFSheet sheet = workbook.getSheetAt(0);
@ -356,6 +385,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/** /**
* Tests various formattings of dates and numbers * Tests various formattings of dates and numbers
*/ */
@Test
public void testFromFile() { public void testFromFile() {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("Formatting.xls"); HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("Formatting.xls");
HSSFSheet sheet = workbook.getSheetAt(0); HSSFSheet sheet = workbook.getSheetAt(0);

View File

@ -17,41 +17,38 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.*; import static java.util.Calendar.AUGUST;
import static java.util.Calendar.FEBRUARY;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.JULY;
import static java.util.Calendar.MARCH;
import static java.util.Calendar.MAY;
import static java.util.Calendar.OCTOBER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test; import org.junit.Test;
/** /**
* Class TestHSSFDateUtil * Class TestHSSFDateUtil
*
*
* @author Dan Sherman (dsherman at isisph.com)
* @author Hack Kampbjorn (hak at 2mba.dk)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
* @author Alex Jacoby (ajacoby at gmail.com)
* @version %I%, %G%
*/ */
public final class TestHSSFDateUtil { public final class TestHSSFDateUtil {
public static final int CALENDAR_JANUARY = 0;
public static final int CALENDAR_FEBRUARY = 1;
public static final int CALENDAR_MARCH = 2;
public static final int CALENDAR_APRIL = 3;
public static final int CALENDAR_JULY = 6;
public static final int CALENDAR_OCTOBER = 9;
/** /**
* Checks the date conversion functions in the HSSFDateUtil class. * Checks the date conversion functions in the HSSFDateUtil class.
*/ */
@ -59,25 +56,24 @@ public final class TestHSSFDateUtil {
public void dateConversion() { public void dateConversion() {
// Iteratating over the hours exposes any rounding issues. // Iteratating over the hours exposes any rounding issues.
for (int hour = 0; hour < 23; hour++) Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,0,1,1);
{ for (int hour = 0; hour < 23; hour++) {
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
hour, 1, 1);
double excelDate =
HSSFDateUtil.getExcelDate(date.getTime(), false);
assertEquals("Checking hour = " + hour, date.getTime().getTime(), assertEquals("Checking hour = " + hour, cal.getTime().getTime(),
HSSFDateUtil.getJavaDate(excelDate, false).getTime()); HSSFDateUtil.getJavaDate(excelDate, false).getTime());
cal.add(Calendar.HOUR_OF_DAY, 1);
} }
// check 1900 and 1904 date windowing conversions // check 1900 and 1904 date windowing conversions
double excelDate = 36526.0; double excelDate = 36526.0;
// with 1900 windowing, excelDate is Jan. 1, 2000 // with 1900 windowing, excelDate is Jan. 1, 2000
// with 1904 windowing, excelDate is Jan. 2, 2004 // with 1904 windowing, excelDate is Jan. 2, 2004
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000 cal.set(2000,JANUARY,1,0,0,0); // Jan. 1, 2000
Date dateIf1900 = cal.getTime(); Date dateIf1900 = cal.getTime();
cal.add(GregorianCalendar.YEAR,4); // now Jan. 1, 2004 cal.add(Calendar.YEAR,4); // now Jan. 1, 2004
cal.add(GregorianCalendar.DATE,1); // now Jan. 2, 2004 cal.add(Calendar.DATE,1); // now Jan. 2, 2004
Date dateIf1904 = cal.getTime(); Date dateIf1904 = cal.getTime();
// 1900 windowing // 1900 windowing
assertEquals("Checking 1900 Date Windowing", assertEquals("Checking 1900 Date Windowing",
@ -95,11 +91,9 @@ public final class TestHSSFDateUtil {
*/ */
@Test @Test
public void excelConversionOnDSTStart() { public void excelConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
for (int hour = 0; hour < 24; hour++) { for (int hour = 0; hour < 24; hour++) {
// Skip 02:00 CET as that is the Daylight change time // Skip 02:00 CET as that is the Daylight change time
// and Java converts it automatically to 03:00 CEST // and Java converts it automatically to 03:00 CEST
if (hour == 2) { if (hour == 2) {
@ -108,6 +102,8 @@ public final class TestHSSFDateUtil {
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime(); Date javaDate = cal.getTime();
double excelDate = HSSFDateUtil.getExcelDate(javaDate, false); double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
double difference = excelDate - Math.floor(excelDate); double difference = excelDate - Math.floor(excelDate);
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60; int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
@ -126,9 +122,7 @@ public final class TestHSSFDateUtil {
*/ */
@Test @Test
public void javaConversionOnDSTStart() { public void javaConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false); double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24; double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60; double oneMinute = oneHour / 60;
@ -154,9 +148,7 @@ public final class TestHSSFDateUtil {
*/ */
@Test @Test
public void excelConversionOnDSTEnd() { public void excelConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
for (int hour = 0; hour < 24; hour++) { for (int hour = 0; hour < 24; hour++) {
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime(); Date javaDate = cal.getTime();
@ -178,9 +170,7 @@ public final class TestHSSFDateUtil {
*/ */
@Test @Test
public void javaConversionOnDSTEnd() { public void javaConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false); double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24; double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60; double oneMinute = oneHour / 60;
@ -198,40 +188,45 @@ public final class TestHSSFDateUtil {
*/ */
@Test @Test
public void calendarConversion() { public void calendarConversion() {
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1); TimeZone userTZ = LocaleUtil.getUserTimeZone();
Date expected = date.getTime(); LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
// Iterating over the hours exposes any rounding issues. Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,12,1,1);
for (int hour = -12; hour <= 12; hour++) Date expected = cal.getTime();
{
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00"; // Iterating over the hours exposes any rounding issues.
date.setTimeZone(TimeZone.getTimeZone(id)); for (int hour = -12; hour <= 12; hour++)
date.set(Calendar.HOUR_OF_DAY, 12); {
double excelDate = HSSFDateUtil.getExcelDate(date, false); String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
Date javaDate = HSSFDateUtil.getJavaDate(excelDate); cal.setTimeZone(TimeZone.getTimeZone(id));
cal.set(Calendar.HOUR_OF_DAY, 12);
// Should match despite time-zone double excelDate = HSSFDateUtil.getExcelDate(cal, false);
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime()); Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
// Should match despite time-zone
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
}
// Check that the timezone aware getter works correctly
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
// 12:45 on 27th April 2012
double excelDate = 41026.53125;
// Same, no change
assertEquals(
HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
);
// London vs Copenhagen, should differ by an hour
Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
} finally {
LocaleUtil.setUserTimeZone(userTZ);
} }
// Check that the timezone aware getter works correctly
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
TimeZone.setDefault(cet);
// 12:45 on 27th April 2012
double excelDate = 41026.53125;
// Same, no change
assertEquals(
HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
);
// London vs Copenhagen, should differ by an hour
Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
} }
/** /**
@ -405,7 +400,8 @@ public final class TestHSSFDateUtil {
@Test @Test
public void excelDateBorderCases() throws ParseException { public void excelDateBorderCases() throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
df.setTimeZone(LocaleUtil.getUserTimeZone());
assertEquals(1.0, DateUtil.getExcelDate(df.parse("1900-01-01")), 0.00001); assertEquals(1.0, DateUtil.getExcelDate(df.parse("1900-01-01")), 0.00001);
assertEquals(31.0, DateUtil.getExcelDate(df.parse("1900-01-31")), 0.00001); assertEquals(31.0, DateUtil.getExcelDate(df.parse("1900-01-31")), 0.00001);
@ -415,38 +411,38 @@ public final class TestHSSFDateUtil {
@Test @Test
public void dateBug_2Excel() { public void dateBug_2Excel() {
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28), false), 0.00001); assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, FEBRUARY, 28), false), 0.00001);
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1), false), 0.00001); assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, MARCH, 1), false), 0.00001);
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28), false), 0.00001); assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, FEBRUARY, 28), false), 0.00001);
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1), false), 0.00001); assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, MARCH, 1), false), 0.00001);
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1), false), 0.00001); assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, JANUARY, 1), false), 0.00001);
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28), false), 0.00001); assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, MARCH, 28), false), 0.00001);
} }
@Test @Test
public void dateBug_2Java() { public void dateBug_2Java() {
assertEquals(createDate(1900, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false)); assertEquals(createDate(1900, FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
assertEquals(createDate(1900, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false)); assertEquals(createDate(1900, MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
assertEquals(createDate(2002, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false)); assertEquals(createDate(2002, FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
assertEquals(createDate(2002, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false)); assertEquals(createDate(2002, MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
assertEquals(createDate(2002, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false)); assertEquals(createDate(2002, JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
assertEquals(createDate(2004, CALENDAR_MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false)); assertEquals(createDate(2004, MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
} }
@Test @Test
public void date1904() { public void date1904() {
assertEquals(createDate(1904, CALENDAR_JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true)); assertEquals(createDate(1904, JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
assertEquals(createDate(1904, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true)); assertEquals(createDate(1904, JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 1), true), 0.00001); assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 1), true), 0.00001);
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 2), true), 0.00001); assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 2), true), 0.00001);
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(35981, false)); assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(34519, true)); assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), false), 0.00001); assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), false), 0.00001);
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001); assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), true), 0.00001);
} }
/** /**
@ -462,9 +458,7 @@ public final class TestHSSFDateUtil {
* @param day one based * @param day one based
*/ */
private static Date createDate(int year, int month, int day, int hour, int minute, int second) { private static Date createDate(int year, int month, int day, int hour, int minute, int second) {
Calendar c = new GregorianCalendar(Locale.ROOT); Calendar c = LocaleUtil.getLocaleCalendar(year, month, day, hour, minute, second);
c.set(year, month, day, hour, minute, second);
c.set(Calendar.MILLISECOND, 0);
return c.getTime(); return c.getTime();
} }
@ -474,26 +468,26 @@ public final class TestHSSFDateUtil {
@Test @Test
public void absoluteDay() { public void absoluteDay() {
// 1 Jan 1900 is 1 day after 31 Dec 1899 // 1 Jan 1900 is 1 day after 31 Dec 1899
GregorianCalendar calendar = new GregorianCalendar(1900, 0, 1); Calendar cal = LocaleUtil.getLocaleCalendar(1900,JANUARY,1,0,0,0);
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(calendar, false)); assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(cal, false));
// 1 Jan 1901 is 366 days after 31 Dec 1899 // 1 Jan 1901 is 366 days after 31 Dec 1899
calendar = new GregorianCalendar(1901, 0, 1); cal.set(1901,JANUARY,1,0,0,0);
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false)); assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(cal, false));
} }
@Test @Test
public void absoluteDayYearTooLow() { public void absoluteDayYearTooLow() {
GregorianCalendar calendar = new GregorianCalendar(1899, 0, 1); Calendar cal = LocaleUtil.getLocaleCalendar(1899,JANUARY,1,0,0,0);
try { try {
HSSFDateUtil.absoluteDay(calendar, false); HSSFDateUtil.absoluteDay(cal, false);
fail("Should fail here"); fail("Should fail here");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// expected here // expected here
} }
try { try {
calendar = new GregorianCalendar(1903, 0, 1); cal.set(1903,JANUARY,1,0,0,0);
HSSFDateUtil.absoluteDay(calendar, true); HSSFDateUtil.absoluteDay(cal, true);
fail("Should fail here"); fail("Should fail here");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// expected here // expected here
@ -512,8 +506,8 @@ public final class TestHSSFDateUtil {
@Test @Test
public void parseDate() { public void parseDate() {
assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03")); assertEquals(createDate(2008, AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01")); assertEquals(createDate(1994, MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
} }
/** /**
@ -540,10 +534,8 @@ public final class TestHSSFDateUtil {
HSSFSheet sheet = workbook.createSheet(); HSSFSheet sheet = workbook.createSheet();
HSSFCell cell = sheet.createRow(0).createCell(0); HSSFCell cell = sheet.createRow(0).createCell(0);
Calendar cal = Calendar.getInstance();
// A pseudo special Excel dates // A pseudo special Excel dates
cal.set(1900, 0, 1); Calendar cal = LocaleUtil.getLocaleCalendar(1900, JANUARY, 1);
Date valueToTest = cal.getTime(); Date valueToTest = cal.getTime();

View File

@ -17,42 +17,50 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.GregorianCalendar; import static org.junit.Assert.assertEquals;
import java.util.List; import static org.junit.Assert.assertTrue;
import junit.framework.TestCase; import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** /**
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public final class TestReadWriteChart extends TestCase { public final class TestReadWriteChart {
/** /**
* In the presence of a chart we need to make sure BOF/EOF records still exist. * In the presence of a chart we need to make sure BOF/EOF records still exist.
*/ */
public void testBOFandEOFRecords() { @Test
public void testBOFandEOFRecords() throws Exception {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("SimpleChart.xls"); HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("SimpleChart.xls");
HSSFSheet sheet = workbook.getSheetAt(0); HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow firstRow = sheet.getRow(0); HSSFRow firstRow = sheet.getRow(0);
HSSFCell firstCell = firstRow.getCell(0); HSSFCell firstCell = firstRow.getCell(0);
//System.out.println("first assertion for date"); //System.out.println("first assertion for date");
assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(), Calendar calExp = LocaleUtil.getLocaleCalendar(2000, 0, 1, 10, 51, 2);
HSSFDateUtil Date dateAct = HSSFDateUtil.getJavaDate(firstCell.getNumericCellValue(), false);
.getJavaDate(firstCell.getNumericCellValue(), false)); assertEquals(calExp.getTime(), dateAct);
HSSFRow row = sheet.createRow(15); HSSFRow row = sheet.createRow(15);
HSSFCell cell = row.createCell(1); HSSFCell cell = row.createCell(1);
cell.setCellValue(22); cell.setCellValue(22);
InternalSheet newSheet = workbook.getSheetAt(0).getSheet(); InternalSheet newSheet = workbook.getSheetAt(0).getSheet();
List records = newSheet.getRecords(); List<RecordBase> records = newSheet.getRecords();
assertTrue(records.get(0) instanceof BOFRecord); assertTrue(records.get(0) instanceof BOFRecord);
assertTrue(records.get(records.size() - 1) instanceof EOFRecord); assertTrue(records.get(records.size() - 1) instanceof EOFRecord);
workbook.close();
} }
} }

View File

@ -18,21 +18,23 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import junit.framework.TestCase; import static org.junit.Assert.assertEquals;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper; import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord; import org.apache.poi.hssf.record.TextObjectRecord;
import org.junit.Test;
/** /**
* @author Evgeniy Berlog * @author Evgeniy Berlog
* @date 25.06.12 * @date 25.06.12
*/ */
public class TestText extends TestCase { public class TestText {
public void testResultEqualsToAbstractShape() { @Test
public void testResultEqualsToAbstractShape() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -81,11 +83,14 @@ public class TestText extends TestCase {
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertArrayEquals(expected, actual); assertArrayEquals(expected, actual);
wb.close();
} }
public void testAddTextToExistingFile() { @Test
HSSFWorkbook wb = new HSSFWorkbook(); public void testAddTextToExistingFile() throws Exception {
HSSFSheet sh = wb.createSheet(); HSSFWorkbook wb1 = new HSSFWorkbook();
HSSFSheet sh = wb1.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("just for test")); textbox.setString(new HSSFRichTextString("just for test"));
@ -94,8 +99,9 @@ public class TestText extends TestCase {
assertEquals(patriarch.getChildren().size(), 2); assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
sh = wb.getSheetAt(0); wb1.close();
sh = wb2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2); assertEquals(patriarch.getChildren().size(), 2);
@ -103,19 +109,23 @@ public class TestText extends TestCase {
text3.setString(new HSSFRichTextString("text3")); text3.setString(new HSSFRichTextString("text3"));
assertEquals(patriarch.getChildren().size(), 3); assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2);
sh = wb.getSheetAt(0); wb2.close();
sh = wb3.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3); assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test"); assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2"); assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3"); assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3");
wb3.close();
} }
public void testSetGetProperties() { @Test
HSSFWorkbook wb = new HSSFWorkbook(); public void testSetGetProperties() throws Exception {
HSSFSheet sh = wb.createSheet(); HSSFWorkbook wb1 = new HSSFWorkbook();
HSSFSheet sh = wb1.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("test")); textbox.setString(new HSSFRichTextString("test"));
@ -139,8 +149,9 @@ public class TestText extends TestCase {
textbox.setMarginTop(10); textbox.setMarginTop(10);
assertEquals(textbox.getMarginTop(), 10); assertEquals(textbox.getMarginTop(), 10);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
sh = wb.getSheetAt(0); wb1.close();
sh = wb2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0); textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test"); assertEquals(textbox.getString().getString(), "test");
@ -167,8 +178,9 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginRight(), 91); assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101); assertEquals(textbox.getMarginTop(), 101);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2);
sh = wb.getSheetAt(0); wb2.close();
sh = wb3.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0); textbox = (HSSFTextbox) patriarch.getChildren().get(0);
@ -179,9 +191,12 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginLeft(), 81); assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91); assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101); assertEquals(textbox.getMarginTop(), 101);
wb3.close();
} }
public void testExistingFileWithText(){ @Test
public void testExistingFileWithText() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("text"); HSSFSheet sheet = wb.getSheet("text");
HSSFPatriarch drawing = sheet.getDrawingPatriarch(); HSSFPatriarch drawing = sheet.getDrawingPatriarch();
@ -194,5 +209,6 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginLeft(), 3600000); assertEquals(textbox.getMarginLeft(), 3600000);
assertEquals(textbox.getMarginRight(), 0); assertEquals(textbox.getMarginRight(), 0);
assertEquals(textbox.getString().getString(), "teeeeesssstttt"); assertEquals(textbox.getString().getString(), "teeeeesssstttt");
wb.close();
} }
} }

View File

@ -25,10 +25,12 @@ import static java.awt.Color.ORANGE;
import static java.awt.Color.RED; import static java.awt.Color.RED;
import static java.awt.Color.WHITE; import static java.awt.Color.WHITE;
import static java.awt.Color.YELLOW; import static java.awt.Color.YELLOW;
import static org.junit.Assert.assertEquals;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
@ -36,15 +38,14 @@ import java.util.TreeSet;
import javax.swing.JLabel; import javax.swing.JLabel;
import junit.framework.TestCase;
import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.POILogger; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/** /**
* This class is a base class for spreadsheet-based tests, such as are used for * This class is a base class for spreadsheet-based tests, such as are used for
@ -57,9 +58,7 @@ import org.apache.poi.util.POILogFactory;
* flag "Categories" is not empty, only tests that have at least one category * flag "Categories" is not empty, only tests that have at least one category
* listed in "Categories" are run. * listed in "Categories" are run.
*/ */
@SuppressWarnings( public class CellFormatTestBase {
{"JUnitTestCaseWithNoTests", "JUnitTestClassNamingConvention"})
public class CellFormatTestBase extends TestCase {
private static final POILogger logger = POILogFactory.getLogger(CellFormatTestBase.class); private static final POILogger logger = POILogFactory.getLogger(CellFormatTestBase.class);
private final ITestDataProvider _testDataProvider; private final ITestDataProvider _testDataProvider;
@ -86,7 +85,6 @@ public class CellFormatTestBase extends TestCase {
abstract static class CellValue { abstract static class CellValue {
abstract Object getValue(Cell cell); abstract Object getValue(Cell cell);
@SuppressWarnings({"UnusedDeclaration"})
Color getColor(Cell cell) { Color getColor(Cell cell) {
return TEST_COLOR; return TEST_COLOR;
} }
@ -114,20 +112,19 @@ public class CellFormatTestBase extends TestCase {
} }
Sheet sheet = workbook.getSheet("Tests"); Sheet sheet = workbook.getSheet("Tests");
int end = sheet.getLastRowNum(); Iterator<Row> rowIter = sheet.rowIterator();
// Skip the header row, therefore "+ 1" // Skip the header row
for (int r = sheet.getFirstRowNum() + 1; r <= end; r++) { rowIter.next();
Row row = sheet.getRow(r); while (rowIter.hasNext()) {
if (row == null) Row row = rowIter.next();
continue; if (row == null) continue;
int cellnum = 0; String expectedText = row.getCell(0).getStringCellValue();
String expectedText = row.getCell(cellnum).getStringCellValue(); String format = row.getCell(1).getStringCellValue();
String format = row.getCell(1).getStringCellValue(); Cell value = row.getCell(2);
String testCategoryList = row.getCell(3).getStringCellValue(); String testCategoryList = row.getCell(3).getStringCellValue();
boolean byCategory = runByCategory(runCategories, testCategoryList); boolean byCategory = runByCategory(runCategories, testCategoryList);
if ((expectedText.length() > 0 || format.length() > 0) && byCategory) { if ((expectedText.length() > 0 || format.length() > 0) && byCategory) {
Cell cell = row.getCell(2); tryFormat(row.getRowNum(), expectedText, format, valueGetter, value);
tryFormat(r, expectedText, format, valueGetter, cell);
} }
} }
} }
@ -216,16 +213,17 @@ public class CellFormatTestBase extends TestCase {
label.setForeground(testColor); label.setForeground(testColor);
label.setText("xyzzy"); label.setText("xyzzy");
logger.log(POILogger.INFO, String.format("Row %d: \"%s\" -> \"%s\": expected \"%s\"", row + 1, logger.log(POILogger.INFO, String.format(LocaleUtil.getUserLocale(),
String.valueOf(value), desc, expectedText)); "Row %d: \"%s\" -> \"%s\": expected \"%s\"",
row + 1, String.valueOf(value), desc, expectedText));
String actualText = tryColor(desc, null, getter, value, expectedText, String actualText = tryColor(desc, null, getter, value, expectedText,
testColor); testColor);
logger.log(POILogger.INFO, String.format(", actual \"%s\")%n", actualText)); logger.log(POILogger.INFO, String.format(LocaleUtil.getUserLocale(),
", actual \"%s\")%n", actualText));
if (tryAllColors && testColor != TEST_COLOR) { if (tryAllColors && testColor != TEST_COLOR) {
for (int i = 0; i < COLOR_NAMES.length; i++) { for (int i = 0; i < COLOR_NAMES.length; i++) {
String cname = COLOR_NAMES[i]; tryColor(desc, COLOR_NAMES[i], getter, value, expectedText, COLORS[i]);
tryColor(desc, cname, getter, value, expectedText, COLORS[i]);
} }
} }
} }

View File

@ -16,23 +16,45 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.ss.format; package org.apache.poi.ss.format;
import static org.junit.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import javax.swing.JLabel; import javax.swing.JLabel;
import junit.framework.TestCase;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestCellFormat extends TestCase { public class TestCellFormat {
private static TimeZone userTimeZone;
@BeforeClass
public static void setTimeZone() {
userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
LocaleUtil.setUserLocale(Locale.US);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTimeZone);
LocaleUtil.setUserLocale(Locale.ROOT);
}
private static final String _255_POUND_SIGNS; private static final String _255_POUND_SIGNS;
static { static {
@ -43,6 +65,7 @@ public class TestCellFormat extends TestCase {
_255_POUND_SIGNS = sb.toString(); _255_POUND_SIGNS = sb.toString();
} }
@Test
public void testSome() { public void testSome() {
JLabel l = new JLabel(); JLabel l = new JLabel();
CellFormat fmt = CellFormat.getInstance( CellFormat fmt = CellFormat.getInstance(
@ -50,48 +73,56 @@ public class TestCellFormat extends TestCase {
fmt.apply(l, 1.1); fmt.apply(l, 1.1);
} }
@Test
public void testPositiveFormatHasOnePart() { public void testPositiveFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00"); CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(12.345); CellFormatResult result = fmt.apply(12.345);
assertEquals("12.35", result.text); assertEquals("12.35", result.text);
} }
@Test
public void testNegativeFormatHasOnePart() { public void testNegativeFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00"); CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(-12.345); CellFormatResult result = fmt.apply(-12.345);
assertEquals("-12.35", result.text); assertEquals("-12.35", result.text);
} }
@Test
public void testZeroFormatHasOnePart() { public void testZeroFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00"); CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(0.0); CellFormatResult result = fmt.apply(0.0);
assertEquals("0.00", result.text); assertEquals("0.00", result.text);
} }
@Test
public void testPositiveFormatHasPosAndNegParts() { public void testPositiveFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00"); CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(12.345); CellFormatResult result = fmt.apply(12.345);
assertEquals("12.35", result.text); assertEquals("12.35", result.text);
} }
@Test
public void testNegativeFormatHasPosAndNegParts() { public void testNegativeFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00"); CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(-12.345); CellFormatResult result = fmt.apply(-12.345);
assertEquals("-12.35", result.text); assertEquals("-12.35", result.text);
} }
@Test
public void testNegativeFormatHasPosAndNegParts2() { public void testNegativeFormatHasPosAndNegParts2() {
CellFormat fmt = CellFormat.getInstance("0.00;(0.00)"); CellFormat fmt = CellFormat.getInstance("0.00;(0.00)");
CellFormatResult result = fmt.apply(-12.345); CellFormatResult result = fmt.apply(-12.345);
assertEquals("(12.35)", result.text); assertEquals("(12.35)", result.text);
} }
@Test
public void testZeroFormatHasPosAndNegParts() { public void testZeroFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00"); CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(0.0); CellFormatResult result = fmt.apply(0.0);
assertEquals("0.00", result.text); assertEquals("0.00", result.text);
} }
@Test
public void testFormatWithThreeSections() { public void testFormatWithThreeSections() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-"); CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-");
@ -101,6 +132,7 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", fmt.apply("abc").text); assertEquals("abc", fmt.apply("abc").text);
} }
@Test
public void testFormatWithFourSections() { public void testFormatWithFourSections() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-; @ "); CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-; @ ");
@ -110,7 +142,8 @@ public class TestCellFormat extends TestCase {
assertEquals(" abc ", fmt.apply("abc").text); assertEquals(" abc ", fmt.apply("abc").text);
} }
public void testApplyCellForGeneralFormat() { @Test
public void testApplyCellForGeneralFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -147,9 +180,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result4 = cf.apply(cell4); CellFormatResult result4 = cf.apply(cell4);
assertEquals("abc", result4.text); assertEquals("abc", result4.text);
wb.close();
} }
public void testApplyCellForAtFormat() { @Test
public void testApplyCellForAtFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -186,9 +221,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result4 = cf.apply(cell4); CellFormatResult result4 = cf.apply(cell4);
assertEquals("abc", result4.text); assertEquals("abc", result4.text);
wb.close();
} }
public void testApplyCellForDateFormat() { @Test
public void testApplyCellForDateFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -207,9 +244,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result1 = cf.apply(cell1); CellFormatResult result1 = cf.apply(cell1);
assertEquals(_255_POUND_SIGNS, result1.text); assertEquals(_255_POUND_SIGNS, result1.text);
wb.close();
} }
public void testApplyCellForTimeFormat() { @Test
public void testApplyCellForTimeFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -223,9 +262,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result = cf.apply(cell); CellFormatResult result = cf.apply(cell);
assertEquals("03:04", result.text); assertEquals("03:04", result.text);
wb.close();
} }
public void testApplyCellForDateFormatAndNegativeFormat() { @Test
public void testApplyCellForDateFormatAndNegativeFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -244,9 +285,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result1 = cf.apply(cell1); CellFormatResult result1 = cf.apply(cell1);
assertEquals("(1)", result1.text); assertEquals("(1)", result1.text);
wb.close();
} }
public void testApplyJLabelCellForGeneralFormat() { @Test
public void testApplyJLabelCellForGeneralFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -294,9 +337,11 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", result4.text); assertEquals("abc", result4.text);
assertEquals("abc", label4.getText()); assertEquals("abc", label4.getText());
wb.close();
} }
public void testApplyJLabelCellForAtFormat() { @Test
public void testApplyJLabelCellForAtFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -344,9 +389,11 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", result4.text); assertEquals("abc", result4.text);
assertEquals("abc", label4.getText()); assertEquals("abc", label4.getText());
wb.close();
} }
public void testApplyJLabelCellForDateFormat() { @Test
public void testApplyJLabelCellForDateFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -370,9 +417,11 @@ public class TestCellFormat extends TestCase {
assertEquals(_255_POUND_SIGNS, result1.text); assertEquals(_255_POUND_SIGNS, result1.text);
assertEquals(_255_POUND_SIGNS, label1.getText()); assertEquals(_255_POUND_SIGNS, label1.getText());
wb.close();
} }
public void testApplyJLabelCellForTimeFormat() { @Test
public void testApplyJLabelCellForTimeFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -389,9 +438,11 @@ public class TestCellFormat extends TestCase {
assertEquals("03:04", result.text); assertEquals("03:04", result.text);
assertEquals("03:04", label.getText()); assertEquals("03:04", label.getText());
wb.close();
} }
public void testApplyJLabelCellForDateFormatAndNegativeFormat() { @Test
public void testApplyJLabelCellForDateFormatAndNegativeFormat() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -415,9 +466,11 @@ public class TestCellFormat extends TestCase {
assertEquals("(1)", result1.text); assertEquals("(1)", result1.text);
assertEquals("(1)", label1.getText()); assertEquals("(1)", label1.getText());
wb.close();
} }
public void testApplyFormatHasOnePartAndPartHasCondition() { @Test
public void testApplyFormatHasOnePartAndPartHasCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -442,9 +495,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasTwoPartsFirstHasCondition() { @Test
public void testApplyFormatHasTwoPartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -475,9 +530,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("TRUE"); cell.setCellValue("TRUE");
assertEquals("TRUE", cf.apply(cell).text); assertEquals("TRUE", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasTwoPartsBothHaveCondition() { @Test
public void testApplyFormatHasTwoPartsBothHaveCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -505,9 +562,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasThreePartsFirstHasCondition() { @Test
public void testApplyFormatHasThreePartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -537,9 +596,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasThreePartsFirstTwoHaveCondition() { @Test
public void testApplyFormatHasThreePartsFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -564,9 +625,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasThreePartsFirstIsDateFirstTwoHaveCondition() { @Test
public void testApplyFormatHasThreePartsFirstIsDateFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -591,9 +654,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasTwoPartsFirstHasConditionSecondIsGeneral() { @Test
public void testApplyFormatHasTwoPartsFirstHasConditionSecondIsGeneral() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -618,9 +683,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasThreePartsFirstTwoHaveConditionThirdIsGeneral() { @Test
public void testApplyFormatHasThreePartsFirstTwoHaveConditionThirdIsGeneral() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -645,9 +712,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text); assertEquals("abc", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasFourPartsFirstHasCondition() { @Test
public void testApplyFormatHasFourPartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -677,9 +746,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc"); cell.setCellValue("abc");
assertEquals("~~abc~~", cf.apply(cell).text); assertEquals("~~abc~~", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasFourPartsSecondHasCondition() { @Test
public void testApplyFormatHasFourPartsSecondHasCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -710,9 +781,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(true); cell.setCellValue(true);
assertEquals("~~TRUE~~", cf.apply(cell).text); assertEquals("~~TRUE~~", cf.apply(cell).text);
wb.close();
} }
public void testApplyFormatHasFourPartsFirstTwoHaveCondition() { @Test
public void testApplyFormatHasFourPartsFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -739,11 +812,14 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(true); cell.setCellValue(true);
assertEquals("~~TRUE~~", cf.apply(cell).text); assertEquals("~~TRUE~~", cf.apply(cell).text);
wb.close();
} }
/* /*
* Test apply(Object value) with a number as parameter * Test apply(Object value) with a number as parameter
*/ */
@Test
public void testApplyObjectNumber() { public void testApplyObjectNumber() {
CellFormat cf1 = CellFormat.getInstance("0.000"); CellFormat cf1 = CellFormat.getInstance("0.000");
@ -771,15 +847,17 @@ public class TestCellFormat extends TestCase {
/* /*
* Test apply(Object value) with a Date as parameter * Test apply(Object value) with a Date as parameter
*/ */
@Test
public void testApplyObjectDate() throws ParseException { public void testApplyObjectDate() throws ParseException {
CellFormat cf1 = CellFormat.getInstance("m/d/yyyy"); CellFormat cf1 = CellFormat.getInstance("m/d/yyyy");
Date date1 = new SimpleDateFormat("M/d/y").parse("01/11/2012"); Date date1 = new SimpleDateFormat("M/d/y", Locale.ROOT).parse("01/11/2012");
assertEquals("1/11/2012", cf1.apply(date1).text); assertEquals("1/11/2012", cf1.apply(date1).text);
} }
public void testApplyCellForDateFormatWithConditions() { @Test
public void testApplyCellForDateFormatWithConditions() throws Exception {
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook(); Workbook wb = new HSSFWorkbook();
@ -798,11 +876,13 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(-1); cell.setCellValue(-1);
assertEquals(_255_POUND_SIGNS, cf.apply(cell).text); assertEquals(_255_POUND_SIGNS, cf.apply(cell).text);
wb.close();
} }
/* /*
* Test apply(Object value) with a String as parameter * Test apply(Object value) with a String as parameter
*/ */
@Test
public void testApplyObjectString() { public void testApplyObjectString() {
CellFormat cf = CellFormat.getInstance("0.00"); CellFormat cf = CellFormat.getInstance("0.00");
@ -814,6 +894,7 @@ public class TestCellFormat extends TestCase {
/* /*
* Test apply(Object value) with a Boolean as parameter * Test apply(Object value) with a Boolean as parameter
*/ */
@Test
public void testApplyObjectBoolean() { public void testApplyObjectBoolean() {
CellFormat cf1 = CellFormat.getInstance("0"); CellFormat cf1 = CellFormat.getInstance("0");
@ -826,6 +907,7 @@ public class TestCellFormat extends TestCase {
} }
@Test
public void testSimpleFractionFormat() throws IOException { public void testSimpleFractionFormat() throws IOException {
CellFormat cf1 = CellFormat.getInstance("# ?/?"); CellFormat cf1 = CellFormat.getInstance("# ?/?");
// Create a workbook, row and cell to test with // Create a workbook, row and cell to test with

View File

@ -17,21 +17,18 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import static java.util.Calendar.OCTOBER; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** public class TestDateParser {
* @author jfaenomoto@gmail.com @Test
*/
public class TestDateParser extends TestCase {
public void testFailWhenNoDate() { public void testFailWhenNoDate() {
try { try {
DateParser.parseDate("potato"); DateParser.parseDate("potato");
@ -41,6 +38,7 @@ public class TestDateParser extends TestCase {
} }
} }
@Test
public void testFailWhenLooksLikeDateButItIsnt() { public void testFailWhenLooksLikeDateButItIsnt() {
try { try {
DateParser.parseDate("potato/cucumber/banana"); DateParser.parseDate("potato/cucumber/banana");
@ -50,6 +48,7 @@ public class TestDateParser extends TestCase {
} }
} }
@Test
public void testFailWhenIsInvalidDate() { public void testFailWhenIsInvalidDate() {
try { try {
DateParser.parseDate("13/13/13"); DateParser.parseDate("13/13/13");
@ -59,18 +58,18 @@ public class TestDateParser extends TestCase {
} }
} }
@SuppressWarnings("deprecation") @Test
public void testShouldParseValidDate() throws EvaluationException { public void testShouldParseValidDate() throws EvaluationException {
Calendar aDate = Calendar.getInstance(); Calendar expDate = LocaleUtil.getLocaleCalendar(1984, Calendar.OCTOBER, 20);
aDate.setTime(new Date(84, OCTOBER, 20)); Calendar actDate = DateParser.parseDate("1984/10/20");
assertEquals(aDate, DateParser.parseDate("1984/10/20")); assertEquals(expDate, actDate);
} }
@SuppressWarnings("deprecation") @Test
public void testShouldIgnoreTimestamp() throws EvaluationException { public void testShouldIgnoreTimestamp() throws EvaluationException {
Calendar aDate = Calendar.getInstance(); Calendar expDate = LocaleUtil.getLocaleCalendar(1984, Calendar.OCTOBER, 20);
aDate.setTime(new Date(84, OCTOBER, 20)); Calendar actDate = DateParser.parseDate("1984/10/20 12:34:56");
assertEquals(aDate, DateParser.parseDate("1984/10/20 12:34:56")); assertEquals(expDate, actDate);
} }
} }

View File

@ -17,21 +17,12 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.MARCH;
import static java.util.Calendar.NOVEMBER;
import static java.util.Calendar.OCTOBER;
import static org.apache.poi.ss.formula.eval.ErrorEval.NAME_INVALID; import static org.apache.poi.ss.formula.eval.ErrorEval.NAME_INVALID;
import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID; import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.OperationEvaluationContext; import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.TwoDEval; import org.apache.poi.ss.formula.TwoDEval;
import org.apache.poi.ss.formula.eval.AreaEval; import org.apache.poi.ss.formula.eval.AreaEval;
@ -40,23 +31,15 @@ import org.apache.poi.ss.formula.eval.NumericValueEval;
import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
/** import junit.framework.TestCase;
* @author jfaenomoto@gmail.com
*/
@SuppressWarnings("deprecation") // YK: uses deprecated {@link java.util.Date(int year, int month, int date)}
public class TestNetworkdaysFunction extends TestCase { public class TestNetworkdaysFunction extends TestCase {
private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd"); private static final String STARTING_DATE = "2008/10/01";
private static final String END_DATE = "2009/03/01";
private static final String STARTING_DATE = formatter.format(new Date(108, OCTOBER, 1)); private static final String FIRST_HOLIDAY = "2008/11/26";
private static final String SECOND_HOLIDAY = "2008/12/04";
private static final String END_DATE = formatter.format(new Date(109, MARCH, 1)); private static final String THIRD_HOLIDAY = "2009/01/21";
private static final String FIRST_HOLIDAY = formatter.format(new Date(108, NOVEMBER, 26));
private static final String SECOND_HOLIDAY = formatter.format(new Date(108, DECEMBER, 4));
private static final String THIRD_HOLIDAY = formatter.format(new Date(109, JANUARY, 21));
private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null); private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null);

View File

@ -17,87 +17,100 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.SATURDAY; import static java.util.Calendar.SATURDAY;
import static org.junit.Assert.assertEquals;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import junit.framework.TestCase;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** public class TestWorkdayCalculator {
* @author jfaenomoto@gmail.com
*/
@SuppressWarnings("deprecation") // YK: heavily uses deprecated {@link java.util.Date(int year, int month, int date)}
public class TestWorkdayCalculator extends TestCase {
@Test
public void testCalculateWorkdaysShouldReturnJustWeekdaysWhenNoWeekend() { public void testCalculateWorkdaysShouldReturnJustWeekdaysWhenNoWeekend() {
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 12)); final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 12));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16)); final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
assertEquals(5, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[0])); assertEquals(5, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[0]));
} }
@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoSaturdays() { public void testCalculateWorkdaysShouldReturnAllDaysButNoSaturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 14)); final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 14));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 18)); final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 18));
assertEquals(3, WorkdayCalculator.instance.calculateWorkdays(A_WEDNESDAY, A_SATURDAY, new double[0])); assertEquals(3, WorkdayCalculator.instance.calculateWorkdays(A_WEDNESDAY, A_SATURDAY, new double[0]));
} }
@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoSundays() { public void testCalculateWorkdaysShouldReturnAllDaysButNoSundays() {
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11)); final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 15)); final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 15));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_SUNDAY, A_THURSDAY, new double[0])); assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_SUNDAY, A_THURSDAY, new double[0]));
} }
@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoHolidays() { public void testCalculateWorkdaysShouldReturnAllDaysButNoHolidays() {
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 12)); final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 12));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16)); final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 14)); final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 14));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[]{ A_WEDNESDAY })); assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[]{ A_WEDNESDAY }));
} }
@Test
public void testCalculateWorkdaysShouldIgnoreWeekendHolidays() { public void testCalculateWorkdaysShouldIgnoreWeekendHolidays() {
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16)); final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 17)); final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 17));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 18)); final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 18));
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 21)); final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 21));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_FRIDAY, A_WEDNESDAY, new double[]{ A_SATURDAY, A_SUNDAY })); assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_FRIDAY, A_WEDNESDAY, new double[]{ A_SATURDAY, A_SUNDAY }));
} }
@Test
public void testCalculateWorkdaysNumberOfDays() { public void testCalculateWorkdaysNumberOfDays() {
double start = 41553.0; double start = 41553.0;
int days = 1; int days = 1;
assertEquals(new Date(113, 9, 7), WorkdayCalculator.instance.calculateWorkdays(start, days, new double[0])); assertEquals(d(2013, 10, 7), WorkdayCalculator.instance.calculateWorkdays(start, days, new double[0]));
} }
@Test
public void testPastDaysOfWeekShouldReturn0Past0Saturdays() { public void testPastDaysOfWeekShouldReturn0Past0Saturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 7)); final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 7));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 9)); final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 9));
assertEquals(0, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_FRIDAY, SATURDAY)); assertEquals(0, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_FRIDAY, SATURDAY));
} }
@Test
public void testPastDaysOfWeekShouldReturn1Past1Saturdays() { public void testPastDaysOfWeekShouldReturn1Past1Saturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 7)); final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 7));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11)); final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_SUNDAY, SATURDAY)); assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_SUNDAY, SATURDAY));
} }
@Test
public void testPastDaysOfWeekShouldReturn2Past2Saturdays() { public void testPastDaysOfWeekShouldReturn2Past2Saturdays() {
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 8)); final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 8));
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 19)); final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 19));
assertEquals(2, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_MONDAY, SATURDAY)); assertEquals(2, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_MONDAY, SATURDAY));
} }
@Test
public void testPastDaysOfWeekShouldReturn1BeginningFromASaturday() { public void testPastDaysOfWeekShouldReturn1BeginningFromASaturday() {
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 10)); final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 10));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11)); final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_SATURDAY, A_SUNDAY, SATURDAY)); assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_SATURDAY, A_SUNDAY, SATURDAY));
} }
@Test
public void testPastDaysOfWeekShouldReturn1EndingAtASaturday() { public void testPastDaysOfWeekShouldReturn1EndingAtASaturday() {
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 8)); final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 8));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 10)); final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 10));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_SATURDAY, SATURDAY)); assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_SATURDAY, SATURDAY));
} }
private static Date d(int year, int month, int day) {
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day, 0, 0, 0);
return cal.getTime();
}
} }

View File

@ -18,17 +18,12 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import static java.util.Calendar.APRIL;
import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.MAY;
import static java.util.Calendar.NOVEMBER;
import static java.util.Calendar.OCTOBER;
import static java.util.Calendar.SEPTEMBER;
import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;
import java.text.SimpleDateFormat; import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -40,114 +35,140 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
import junit.framework.TestCase; public class TestWorkdayFunction {
/** private static final String STARTING_DATE = "2008/10/01";
* @author jfaenomoto@gmail.com private static final String FIRST_HOLIDAY = "2008/11/26";
*/ private static final String SECOND_HOLIDAY = "2008/12/04";
@SuppressWarnings("deprecation") // YK: heavily uses deprecated {@link java.util.Date(int year, int month, int date)} private static final String THIRD_HOLIDAY = "2009/01/21";
public class TestWorkdayFunction extends TestCase { private static final String RETROATIVE_HOLIDAY = "2008/09/29";
private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
private static final String STARTING_DATE = formatter.format(new Date(108, OCTOBER, 1));
private static final String FIRST_HOLIDAY = formatter.format(new Date(108, NOVEMBER, 26));
private static final String SECOND_HOLIDAY = formatter.format(new Date(108, DECEMBER, 4));
private static final String THIRD_HOLIDAY = formatter.format(new Date(109, JANUARY, 21));
private static final String RETROATIVE_HOLIDAY = formatter.format(new Date(108, SEPTEMBER, 29));
private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null); private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null);
@Test
public void testFailWhenNoArguments() { public void testFailWhenNoArguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[0], null)); ValueEval ve[] = new ValueEval[0];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
} }
@Test
public void testFailWhenLessThan2Arguments() { public void testFailWhenLessThan2Arguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[1], null)); ValueEval ve[] = new ValueEval[1];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
} }
@Test
public void testFailWhenMoreThan3Arguments() { public void testFailWhenMoreThan3Arguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[4], null)); ValueEval ve[] = new ValueEval[4];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
} }
@Test
public void testFailWhenArgumentsAreNotDatesNorNumbers() { public void testFailWhenArgumentsAreNotDatesNorNumbers() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate( ValueEval ve[] = { new StringEval("Potato"), new StringEval("Cucumber") };
new ValueEval[]{ new StringEval("Potato"), new StringEval("Cucumber") }, EC)); assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, EC));
} }
@Test
public void testReturnWorkdays() { public void testReturnWorkdays() {
assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30);
new StringEval(STARTING_DATE), new NumberEval(151) }, EC)).getNumberValue())); Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(151) };
Date actDate = DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue());
assertEquals(expDate, actDate);
} }
@Test
public void testReturnWorkdaysSpanningAWeekendSubtractingDays() { public void testReturnWorkdaysSpanningAWeekendSubtractingDays() {
String startDate = "2013/09/30"; Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 27);
int days = -1; Date expDate = expCal.getTime();
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ ValueEval ve[] = { new StringEval("2013/09/30"), new NumberEval(-1) };
stringEval, new NumberEval(days) }, EC)).getNumberValue(); double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41544.0, numberValue); assertEquals(41544.0, numberValue, 0);
Date date = DateUtil.getJavaDate(numberValue); Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/09/27", new Date(113, 8, 27), date); assertEquals(expDate, actDate);
} }
@Test
public void testReturnWorkdaysSpanningAWeekendAddingDays() { public void testReturnWorkdaysSpanningAWeekendAddingDays() {
String startDate = "2013/09/27"; Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 30);
int days = 1; Date expDate = expCal.getTime();
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ ValueEval ve[] = { new StringEval("2013/09/27"), new NumberEval(1) };
stringEval, new NumberEval(days) }, EC)).getNumberValue(); double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41547.0, numberValue); assertEquals(41547.0, numberValue, 0);
Date date = DateUtil.getJavaDate(numberValue); Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/09/30", new Date(113, 8, 30), date); assertEquals(expDate, actDate);
} }
@Test
public void testReturnWorkdaysWhenStartIsWeekendAddingDays() { public void testReturnWorkdaysWhenStartIsWeekendAddingDays() {
String startDate = "2013/10/06"; Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 7);
int days = 1; Date expDate = expCal.getTime();
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ ValueEval ve[] = { new StringEval("2013/10/06"), new NumberEval(1) };
stringEval, new NumberEval(days) }, EC)).getNumberValue(); double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41554.0, numberValue); assertEquals(41554.0, numberValue, 0);
Date date = DateUtil.getJavaDate(numberValue); Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/10/07", new Date(113, 9, 7), date); assertEquals(expDate, actDate);
} }
@Test
public void testReturnWorkdaysWhenStartIsWeekendSubtractingDays() { public void testReturnWorkdaysWhenStartIsWeekendSubtractingDays() {
String startDate = "2013/10/06"; Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 4);
int days = -1; Date expDate = expCal.getTime();
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ ValueEval ve[] = { new StringEval("2013/10/06"), new NumberEval(-1) };
stringEval, new NumberEval(days) }, EC)).getNumberValue(); double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41551.0, numberValue); assertEquals(41551.0, numberValue, 0);
Date date = DateUtil.getJavaDate(numberValue); Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/10/04", new Date(113, 9, 4), date); assertEquals(expDate, actDate);
} }
@Test
public void testReturnWorkdaysWithDaysTruncated() { public void testReturnWorkdaysWithDaysTruncated() {
assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30);
new StringEval(STARTING_DATE), new NumberEval(151.99999) }, EC)).getNumberValue())); Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(151.99999) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
} }
@Test
public void testReturnRetroativeWorkday() { public void testReturnRetroativeWorkday() {
assertEquals(new Date(108, SEPTEMBER, 23), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ Calendar expCal = LocaleUtil.getLocaleCalendar(2008, 8, 23);
new StringEval(STARTING_DATE), new NumberEval(-5), new StringEval(RETROATIVE_HOLIDAY) }, EC)) Date expDate = expCal.getTime();
.getNumberValue()));
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(-5), new StringEval(RETROATIVE_HOLIDAY) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
} }
@Test
public void testReturnNetworkdaysWithManyHolidays() { public void testReturnNetworkdaysWithManyHolidays() {
assertEquals(new Date(109, MAY, 5), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 4, 5);
new StringEval(STARTING_DATE), new NumberEval(151), Date expDate = expCal.getTime();
new MockAreaEval(FIRST_HOLIDAY, SECOND_HOLIDAY, THIRD_HOLIDAY) }, EC)).getNumberValue()));
ValueEval ve[] = {
new StringEval(STARTING_DATE), new NumberEval(151),
new MockAreaEval(FIRST_HOLIDAY, SECOND_HOLIDAY, THIRD_HOLIDAY) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
} }
private class MockAreaEval extends AreaEvalBase { private class MockAreaEval extends AreaEvalBase {

View File

@ -17,20 +17,21 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import java.util.Calendar; import static org.junit.Assert.assertEquals;
import java.util.GregorianCalendar;
import java.util.Locale;
import junit.framework.TestCase; import java.util.Calendar;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** /**
* Specific test cases for YearFracCalculator * Specific test cases for YearFracCalculator
*/ */
public final class TestYearFracCalculator extends TestCase { public final class TestYearFracCalculator {
@Test
public void testBasis1() { public void testBasis1() {
confirm(md(1999, 1, 1), md(1999, 4, 5), 1, 0.257534247); confirm(md(1999, 1, 1), md(1999, 4, 5), 1, 0.257534247);
confirm(md(1999, 4, 1), md(1999, 4, 5), 1, 0.010958904); confirm(md(1999, 4, 1), md(1999, 4, 5), 1, 0.010958904);
@ -59,10 +60,7 @@ public final class TestYearFracCalculator extends TestCase {
} }
private static double md(int year, int month, int day) { private static double md(int year, int month, int day) {
Calendar c = new GregorianCalendar(Locale.ROOT); Calendar c = LocaleUtil.getLocaleCalendar(year, month-1, day);
c.set(year, month-1, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
return DateUtil.getExcelDate(c.getTime()); return DateUtil.getExcelDate(c.getTime());
} }
} }

View File

@ -17,31 +17,29 @@
package org.apache.poi.ss.formula.atp; package org.apache.poi.ss.formula.atp;
import java.io.PrintStream; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator; import java.util.Iterator;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import junit.framework.ComparisonFailure;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** /**
* Tests YearFracCalculator using test-cases listed in a sample spreadsheet * Tests YearFracCalculator using test-cases listed in a sample spreadsheet
*
* @author Josh Micich
*/ */
public final class TestYearFracCalculatorFromSpreadsheet extends TestCase { public final class TestYearFracCalculatorFromSpreadsheet {
private static final class SS { private static final class SS {
@ -52,15 +50,14 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
public static final int EXPECTED_RESULT_COLUMN = 13; // "N" public static final int EXPECTED_RESULT_COLUMN = 13; // "N"
} }
public void testAll() { @Test
public void testAll() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls");
HSSFSheet sheet = wb.getSheetAt(0); HSSFSheet sheet = wb.getSheetAt(0);
HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb); HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb);
int nSuccess = 0; int nSuccess = 0;
int nFailures = 0; Iterator<Row> rowIterator = sheet.rowIterator();
int nUnexpectedErrors = 0;
Iterator rowIterator = sheet.rowIterator();
while(rowIterator.hasNext()) { while(rowIterator.hasNext()) {
HSSFRow row = (HSSFRow) rowIterator.next(); HSSFRow row = (HSSFRow) rowIterator.next();
@ -68,28 +65,16 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) { if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
continue; continue;
} }
try { processRow(row, cell, formulaEvaluator);
processRow(row, cell, formulaEvaluator); nSuccess++;
nSuccess++;
} catch (RuntimeException e) {
nUnexpectedErrors ++;
printShortStackTrace(System.err, e);
} catch (AssertionFailedError e) {
nFailures ++;
printShortStackTrace(System.err, e);
}
}
if (nUnexpectedErrors + nFailures > 0) {
String msg = nFailures + " failures(s) and " + nUnexpectedErrors
+ " unexpected errors(s) occurred. See stderr for details";
throw new AssertionFailedError(msg);
}
if (nSuccess < 1) {
throw new RuntimeException("No test sample cases found");
} }
assertTrue("No test sample cases found", nSuccess > 0);
wb.close();
} }
private static void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator) { private void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator)
throws EvaluationException {
double startDate = makeDate(row, SS.START_YEAR_COLUMN); double startDate = makeDate(row, SS.START_YEAR_COLUMN);
double endDate = makeDate(row, SS.END_YEAR_COLUMN); double endDate = makeDate(row, SS.END_YEAR_COLUMN);
@ -98,81 +83,33 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
double expectedValue = getDoubleCell(row, SS.EXPECTED_RESULT_COLUMN); double expectedValue = getDoubleCell(row, SS.EXPECTED_RESULT_COLUMN);
double actualValue; double actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
try {
actualValue = YearFracCalculator.calculate(startDate, endDate, basis); String loc = " - row " + (row.getRowNum()+1);
} catch (EvaluationException e) { assertEquals("Direct calculate failed"+loc, expectedValue, actualValue, 0);
throw new RuntimeException(e);
}
if (expectedValue != actualValue) {
throw new ComparisonFailure("Direct calculate failed - row " + (row.getRowNum()+1),
String.valueOf(expectedValue), String.valueOf(actualValue));
}
actualValue = formulaEvaluator.evaluate(cell).getNumberValue(); actualValue = formulaEvaluator.evaluate(cell).getNumberValue();
if (expectedValue != actualValue) { assertEquals("Formula evaluate failed"+loc, expectedValue, actualValue, 0);
throw new ComparisonFailure("Formula evaluate failed - row " + (row.getRowNum()+1),
String.valueOf(expectedValue), String.valueOf(actualValue));
}
} }
private static double makeDate(HSSFRow row, int yearColumn) { private static double makeDate(HSSFRow row, int yearColumn) {
int year = getIntCell(row, yearColumn + 0); int year = getIntCell(row, yearColumn + 0);
int month = getIntCell(row, yearColumn + 1); int month = getIntCell(row, yearColumn + 1);
int day = getIntCell(row, yearColumn + 2); int day = getIntCell(row, yearColumn + 2);
Calendar c = new GregorianCalendar(year, month-1, day, 0, 0, 0); Calendar c = LocaleUtil.getLocaleCalendar(year, month-1, day);
c.set(Calendar.MILLISECOND, 0);
return HSSFDateUtil.getExcelDate(c.getTime()); return HSSFDateUtil.getExcelDate(c.getTime());
} }
private static int getIntCell(HSSFRow row, int colIx) { private static int getIntCell(HSSFRow row, int colIx) {
double dVal = getDoubleCell(row, colIx); double dVal = getDoubleCell(row, colIx);
if (Math.floor(dVal) != dVal) { String msg = "Non integer value (" + dVal + ") cell found at column " + (char)('A' + colIx);
throw new RuntimeException("Non integer value (" + dVal assertEquals(msg, Math.floor(dVal), dVal, 0);
+ ") cell found at column " + (char)('A' + colIx));
}
return (int)dVal; return (int)dVal;
} }
private static double getDoubleCell(HSSFRow row, int colIx) { private static double getDoubleCell(HSSFRow row, int colIx) {
HSSFCell cell = row.getCell(colIx); HSSFCell cell = row.getCell(colIx);
if (cell == null) { assertNotNull("No cell found at column " + colIx, cell);
throw new RuntimeException("No cell found at column " + colIx);
}
double dVal = cell.getNumericCellValue(); double dVal = cell.getNumericCellValue();
return dVal; return dVal;
} }
/**
* Useful to keep output concise when expecting many failures to be reported by this test case
* TODO - refactor duplicates in other Test~FromSpreadsheet classes
*/
private static void printShortStackTrace(PrintStream ps, Throwable e) {
StackTraceElement[] stes = e.getStackTrace();
int startIx = 0;
// skip any top frames inside junit.framework.Assert
while(startIx<stes.length) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}
} }

View File

@ -21,8 +21,9 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.PrintStream; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
@ -33,14 +34,15 @@ import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogger; import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/** /**
* Tests formulas and operators as loaded from a test data spreadsheet.<p/> * Tests formulas and operators as loaded from a test data spreadsheet.<p/>
@ -49,248 +51,166 @@ import junit.framework.TestCase;
* exercised as well. Tests for bug fixes and specific/tricky behaviour can be found in the * exercised as well. Tests for bug fixes and specific/tricky behaviour can be found in the
* corresponding test class (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor, * corresponding test class (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor,
* where execution can be observed more easily. * where execution can be observed more easily.
*
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/ */
@RunWith(Parameterized.class)
public final class TestFormulasFromSpreadsheet { public final class TestFormulasFromSpreadsheet {
private static final POILogger logger = POILogFactory.getLogger(TestFormulasFromSpreadsheet.class);
private static final class Result { private static HSSFWorkbook workbook;
public static final int SOME_EVALUATIONS_FAILED = -1; private static Sheet sheet;
public static final int ALL_EVALUATIONS_SUCCEEDED = +1; private static HSSFFormulaEvaluator evaluator;
public static final int NO_EVALUATIONS_FOUND = 0; private static Locale userLocale;
}
/**
/**
* This class defines constants for navigating around the test data spreadsheet used for these tests. * This class defines constants for navigating around the test data spreadsheet used for these tests.
*/ */
private static final class SS { private static interface SS {
/** /**
* Name of the test spreadsheet (found in the standard test data folder) * Name of the test spreadsheet (found in the standard test data folder)
*/ */
public final static String FILENAME = "FormulaEvalTestData.xls"; String FILENAME = "FormulaEvalTestData.xls";
/** /**
* Row (zero-based) in the test spreadsheet where the operator examples start. * Row (zero-based) in the test spreadsheet where the operator examples start.
*/ */
public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23' int START_OPERATORS_ROW_INDEX = 22; // Row '23'
/** /**
* Row (zero-based) in the test spreadsheet where the function examples start. * Row (zero-based) in the test spreadsheet where the function examples start.
*/ */
public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96' int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/** /**
* Index of the column that contains the function names * Index of the column that contains the function names
*/ */
public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B' int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
/** /**
* Used to indicate when there are no more functions left * Used to indicate when there are no more functions left
*/ */
public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>"; String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
/** /**
* Index of the column where the test values start (for each function) * Index of the column where the test values start (for each function)
*/ */
public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D' short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
/** /**
* Each function takes 4 rows in the test spreadsheet * Each function takes 4 rows in the test spreadsheet
*/ */
public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4; int NUMBER_OF_ROWS_PER_FUNCTION = 4;
} }
private HSSFWorkbook workbook; @Parameter(value = 0)
private Sheet sheet; public String targetFunctionName;
// Note - multiple failures are aggregated before ending. @Parameter(value = 1)
// If one or more functions fail, a single AssertionFailedError is thrown at the end public int formulasRowIdx;
private int _functionFailureCount; @Parameter(value = 2)
private int _functionSuccessCount; public int expectedValuesRowIdx;
private int _evaluationFailureCount;
private int _evaluationSuccessCount;
private static final Cell getExpectedValueCell(Row row, int columnIndex) { @AfterClass
if (row == null) { public static void closeResource() throws Exception {
return null; LocaleUtil.setUserLocale(userLocale);
} workbook.close();
return row.getCell(columnIndex); }
}
@Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
// Function "Text" uses custom-formats which are locale specific
// can't set the locale on a per-testrun execution, as some settings have been
// already set, when we would try to change the locale by then
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) { workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
assertNotNull(msg + " - Bad setup data expected value is null", expected); sheet = workbook.getSheetAt( 0 );
assertNotNull(msg + " - actual value was null", actual); evaluator = new HSSFFormulaEvaluator(workbook);
List<Object[]> data = new ArrayList<Object[]>();
processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, "Text");
switch (expected.getCellType()) { return data;
case Cell.CELL_TYPE_BLANK: }
assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
break; /**
case Cell.CELL_TYPE_BOOLEAN: * @param startRowIndex row index in the spreadsheet where the first function/operator is found
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType()); * @param testFocusFunctionName name of a single function/operator to test alone.
assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue()); * Typically pass <code>null</code> to test all functions
break; */
case Cell.CELL_TYPE_ERROR: private static void processFunctionGroup(List<Object[]> data, int startRowIndex, String testFocusFunctionName) {
assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType()); for (int rowIndex = startRowIndex; true; rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION) {
assertEquals(msg, ErrorEval.getText(expected.getErrorCellValue()), ErrorEval.getText(actual.getErrorValue())); Row r = sheet.getRow(rowIndex);
break; String targetFunctionName = getTargetFunctionName(r);
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation assertNotNull("Test spreadsheet cell empty on row ("
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
break;
}
}
@Before
protected void setUp() {
if (workbook == null) {
workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
sheet = workbook.getSheetAt( 0 );
}
_functionFailureCount = 0;
_functionSuccessCount = 0;
_evaluationFailureCount = 0;
_evaluationSuccessCount = 0;
}
@Test
public void testFunctionsFromTestSpreadsheet() {
processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
// confirm results
String successMsg = "There were "
+ _evaluationSuccessCount + " successful evaluation(s) and "
+ _functionSuccessCount + " function(s) without error";
String msg = _functionFailureCount + " function(s) failed in "
+ _evaluationFailureCount + " evaluation(s). " + successMsg;
assertEquals(msg, _functionFailureCount, 0);
logger.log(POILogger.INFO, getClass().getName() + ": " + successMsg);
}
/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
Collection<String> funcs = FunctionEval.getSupportedFunctionNames();
int rowIndex = startRowIndex;
while (true) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
assertNotNull("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '" + (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'", targetFunctionName); + SS.FUNCTION_NAMES_END_SENTINEL + "'", targetFunctionName);
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) { if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list // found end of functions list
break; break;
} }
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) { if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
// expected results are on the row below // expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1); Row expectedValuesRow = sheet.getRow(rowIndex + 1);
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
assertNotNull("Missing expected values row for function '" assertNotNull("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")", expectedValuesRow); + targetFunctionName + " (row " + missingRowNum + ")", expectedValuesRow);
switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
default:
throw new RuntimeException("unexpected result");
case Result.NO_EVALUATIONS_FOUND: // do nothing
String uname = targetFunctionName.toUpperCase(Locale.ROOT);
if(startRowIndex >= SS.START_FUNCTIONS_ROW_INDEX &&
funcs.contains(uname)) {
logger.log(POILogger.WARN, uname + ": function is supported but missing test data");
}
break;
}
}
rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
}
}
/** data.add(new Object[]{targetFunctionName, rowIndex, rowIndex + 1});
* }
* @return a constant from the local Result class denoting whether there were any evaluation }
* cases, and whether they all succeeded. }
*/
private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName,
Row formulasRow, Row expectedValuesRow) {
int result = Result.NO_EVALUATIONS_FOUND; // so far @Test
short endcolnum = formulasRow.getLastCellNum(); public void processFunctionRow() {
Row formulasRow = sheet.getRow(formulasRowIdx);
Row expectedValuesRow = sheet.getRow(expectedValuesRowIdx);
// iterate across the row for all the evaluation cases short endcolnum = formulasRow.getLastCellNum();
for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
Cell c = formulasRow.getCell(colnum);
if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
continue;
}
CellValue actualValue = evaluator.evaluate(c); // iterate across the row for all the evaluation cases
for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
Cell c = formulasRow.getCell(colnum);
if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
continue;
}
Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum); CellValue actValue = evaluator.evaluate(c);
try { Cell expValue = (expectedValuesRow == null) ? null : expectedValuesRow.getCell(colnum);
confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
expectedValueCell, actualValue);
_evaluationSuccessCount ++;
if(result != Result.SOME_EVALUATIONS_FAILED) {
result = Result.ALL_EVALUATIONS_SUCCEEDED;
}
} catch (AssertionFailedError e) {
_evaluationFailureCount ++;
printShortStackTrace(System.err, e);
result = Result.SOME_EVALUATIONS_FAILED;
}
}
return result;
}
/** String msg = String.format(Locale.ROOT, "Function '%s': Formula: %s @ %d:%d"
* Useful to keep output concise when expecting many failures to be reported by this test case , targetFunctionName, c.getCellFormula(), formulasRow.getRowNum(), colnum);
*/
private static void printShortStackTrace(PrintStream ps, AssertionFailedError e) {
StackTraceElement[] stes = e.getStackTrace();
int startIx = 0; assertNotNull(msg + " - Bad setup data expected value is null", expValue);
// skip any top frames inside junit.framework.Assert assertNotNull(msg + " - actual value was null", actValue);
while(startIx<stes.length) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}
switch (expValue.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actValue.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actValue.getCellType());
assertEquals(msg, expValue.getBooleanCellValue(), actValue.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actValue.getCellType());
assertEquals(msg, ErrorEval.getText(expValue.getErrorCellValue()), ErrorEval.getText(actValue.getErrorValue()));
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actValue.getCellType());
TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actValue.getCellType());
assertEquals(msg, expValue.getRichStringCellValue().getString(), actValue.getStringValue());
break;
}
}
}
/** /**
* @return <code>null</code> if cell is missing, empty or blank * @return <code>null</code> if cell is missing, empty or blank
*/ */

View File

@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test; import org.junit.Test;
public final class TestDays360 { public final class TestDays360 {
@ -36,14 +37,13 @@ public final class TestDays360 {
* @param month 1-based * @param month 1-based
*/ */
private static Date makeDate(int year, int month, int day) { private static Date makeDate(int year, int month, int day) {
Calendar cal = Calendar.getInstance(Locale.ROOT); Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
cal.set(year, month-1, day, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime(); return cal.getTime();
} }
private static Date decrementDay(Date d) { private static Date decrementDay(Date d) {
Calendar c = (Calendar)d.clone(); Calendar c = LocaleUtil.getLocaleCalendar();
c.setTime(d);
c.add(Calendar.DAY_OF_MONTH, -1); c.add(Calendar.DAY_OF_MONTH, -1);
return c.getTime(); return c.getTime();
} }

View File

@ -17,22 +17,24 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.BlankEval; import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ErrorConstants; import org.apache.poi.ss.usermodel.ErrorConstants;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
public class TestEDate extends TestCase { public class TestEDate {
@Test
public void testEDateProperValues() { public void testEDateProperValues() {
// verify some border-case combinations of startDate and month-increase // verify some border-case combinations of startDate and month-increase
checkValue(1000, 0, 1000d); checkValue(1000, 0, 1000d);
@ -49,71 +51,79 @@ public class TestEDate extends TestCase {
private void checkValue(int startDate, int monthInc, double expectedResult) { private void checkValue(int startDate, int monthInc, double expectedResult) {
EDate eDate = new EDate(); EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(startDate), new NumberEval(monthInc)}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(startDate), new NumberEval(monthInc)}, null);
assertEquals(expectedResult, result.getNumberValue()); assertEquals(expectedResult, result.getNumberValue(), 0);
} }
@Test
public void testEDateInvalidValues() { public void testEDateInvalidValues() {
EDate eDate = new EDate(); EDate eDate = new EDate();
ErrorEval result = (ErrorEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000)}, null); ErrorEval result = (ErrorEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000)}, null);
assertEquals(ErrorConstants.ERROR_VALUE, result.getErrorCode()); assertEquals(ErrorConstants.ERROR_VALUE, result.getErrorCode(), 0);
} }
@Test
public void testEDateIncrease() { public void testEDateIncrease() {
EDate eDate = new EDate(); EDate eDate = new EDate();
Date startDate = new Date(); Date startDate = new Date();
int offset = 2; int offset = 2;
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue()); Date resultDate = DateUtil.getJavaDate(result.getNumberValue());
Calendar instance = Calendar.getInstance(); Calendar instance = LocaleUtil.getLocaleCalendar();
instance.setTime(startDate); instance.setTime(startDate);
instance.add(Calendar.MONTH, offset); instance.add(Calendar.MONTH, offset);
assertEquals(resultDate, instance.getTime()); assertEquals(resultDate, instance.getTime());
} }
@Test
public void testEDateDecrease() { public void testEDateDecrease() {
EDate eDate = new EDate(); EDate eDate = new EDate();
Date startDate = new Date(); Date startDate = new Date();
int offset = -2; int offset = -2;
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue()); Date resultDate = DateUtil.getJavaDate(result.getNumberValue());
Calendar instance = Calendar.getInstance(); Calendar instance = LocaleUtil.getLocaleCalendar();
instance.setTime(startDate); instance.setTime(startDate);
instance.add(Calendar.MONTH, offset); instance.add(Calendar.MONTH, offset);
assertEquals(resultDate, instance.getTime()); assertEquals(resultDate, instance.getTime());
} }
@Test
public void testBug56688() { public void testBug56688() {
EDate eDate = new EDate(); EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000), new RefEvalImplementation(new NumberEval(0))}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000), new RefEvalImplementation(new NumberEval(0))}, null);
assertEquals(1000d, result.getNumberValue()); assertEquals(1000d, result.getNumberValue(), 0);
} }
@Test
public void testRefEvalStartDate() { public void testRefEvalStartDate() {
EDate eDate = new EDate(); EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(new NumberEval(1000)), new NumberEval(0)}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(new NumberEval(1000)), new NumberEval(0)}, null);
assertEquals(1000d, result.getNumberValue()); assertEquals(1000d, result.getNumberValue(), 0);
} }
@Test
public void testEDateInvalidValueEval() { public void testEDateInvalidValueEval() {
ValueEval evaluate = new EDate().evaluate(new ValueEval[]{new ValueEval() {}, new NumberEval(0)}, null); ValueEval evaluate = new EDate().evaluate(new ValueEval[]{new ValueEval() {}, new NumberEval(0)}, null);
assertTrue(evaluate instanceof ErrorEval); assertTrue(evaluate instanceof ErrorEval);
assertEquals(ErrorEval.VALUE_INVALID, evaluate); assertEquals(ErrorEval.VALUE_INVALID, evaluate);
} }
@Test
public void testEDateBlankValueEval() { public void testEDateBlankValueEval() {
NumberEval evaluate = (NumberEval) new EDate().evaluate(new ValueEval[]{BlankEval.instance, new NumberEval(0)}, null); NumberEval evaluate = (NumberEval) new EDate().evaluate(new ValueEval[]{BlankEval.instance, new NumberEval(0)}, null);
assertEquals(-1.0d, evaluate.getNumberValue()); assertEquals(-1.0d, evaluate.getNumberValue(), 0);
} }
@Test
public void testEDateBlankRefValueEval() { public void testEDateBlankRefValueEval() {
EDate eDate = new EDate(); EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(BlankEval.instance), new NumberEval(0)}, null); NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(BlankEval.instance), new NumberEval(0)}, null);
assertEquals("0 startDate triggers BAD_DATE currently, thus -1.0!", assertEquals("0 startDate triggers BAD_DATE currently, thus -1.0!",
-1.0d, result.getNumberValue()); -1.0d, result.getNumberValue(), 0);
result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}, null); result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}, null);
assertEquals("Blank is handled as 0 otherwise", assertEquals("Blank is handled as 0 otherwise",
1.0d, result.getNumberValue()); 1.0d, result.getNumberValue(), 0);
} }
} }

View File

@ -17,12 +17,13 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.OperationEvaluationContext; import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.BlankEval; import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
@ -30,8 +31,10 @@ import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ErrorConstants; import org.apache.poi.ss.usermodel.ErrorConstants;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
public class TestEOMonth extends TestCase{ public class TestEOMonth {
private static final double BAD_DATE = -1.0; private static final double BAD_DATE = -1.0;
@ -47,6 +50,7 @@ public class TestEOMonth extends TestCase{
private final FreeRefFunction eOMonth = EOMonth.instance; private final FreeRefFunction eOMonth = EOMonth.instance;
private final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null); private final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null);
@Test
public void testEOMonthProperValues() { public void testEOMonthProperValues() {
// verify some border-case combinations of startDate and month-increase // verify some border-case combinations of startDate and month-increase
checkValue(DATE_1900_01_01, 0, DATE_1900_01_31); checkValue(DATE_1900_01_01, 0, DATE_1900_01_31);
@ -56,6 +60,7 @@ public class TestEOMonth extends TestCase{
checkValue(DATE_2034_06_09, 1, DATE_2034_07_31); checkValue(DATE_2034_06_09, 1, DATE_2034_07_31);
} }
@Test
public void testEOMonthBadDateValues() { public void testEOMonthBadDateValues() {
checkValue(0.0, -2, BAD_DATE); checkValue(0.0, -2, BAD_DATE);
checkValue(0.0, -3, BAD_DATE); checkValue(0.0, -3, BAD_DATE);
@ -63,74 +68,85 @@ public class TestEOMonth extends TestCase{
} }
private void checkValue(double startDate, int monthInc, double expectedResult) { private void checkValue(double startDate, int monthInc, double expectedResult) {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(startDate), new NumberEval(monthInc)}, ec); ValueEval ve[] = {new NumberEval(startDate), new NumberEval(monthInc)};
assertEquals(expectedResult, result.getNumberValue()); NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(expectedResult, result.getNumberValue(), 0);
} }
@Test
public void testEOMonthZeroDate() { public void testEOMonthZeroDate() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(0)}, ec); NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(0)}, ec);
assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue()); assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue(), 0);
result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(1)}, ec); result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(1)}, ec);
assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue()); assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue(), 0);
} }
@Test
public void testEOMonthInvalidArguments() { public void testEOMonthInvalidArguments() {
ValueEval result = eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26)}, ec); ValueEval result = eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26)}, ec);
assertTrue(result instanceof ErrorEval); assertTrue(result instanceof ErrorEval);
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode()); assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode(), 0);
result = eOMonth.evaluate(new ValueEval[] {new StringEval("a"), new StringEval("b")}, ec); result = eOMonth.evaluate(new ValueEval[] {new StringEval("a"), new StringEval("b")}, ec);
assertTrue(result instanceof ErrorEval); assertTrue(result instanceof ErrorEval);
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode()); assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode(), 0);
} }
public void testEOMonthIncrease() { @Test
checkOffset(new Date(), 2); public void checkOffset() {
} for (int offset=-12; offset<=12; offset++) {
Calendar cal = LocaleUtil.getLocaleCalendar();
public void testEOMonthDecrease() { Date startDate = cal.getTime();
checkOffset(new Date(), -2);
} cal.add(Calendar.MONTH, offset);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
private void checkOffset(Date startDate, int offset) { cal.clear(Calendar.HOUR);
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, ec); cal.set(Calendar.HOUR_OF_DAY, 0);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue()); cal.clear(Calendar.MINUTE);
Calendar instance = Calendar.getInstance(); cal.clear(Calendar.SECOND);
instance.setTime(startDate); cal.clear(Calendar.MILLISECOND);
instance.add(Calendar.MONTH, offset); Date expDate = cal.getTime();
instance.add(Calendar.MONTH, 1);
instance.set(Calendar.DAY_OF_MONTH, 1); ValueEval ve[] = {
instance.add(Calendar.DAY_OF_MONTH, -1); new NumberEval(DateUtil.getExcelDate(startDate)),
instance.set(Calendar.HOUR_OF_DAY, 0); new NumberEval(offset)
instance.set(Calendar.MINUTE, 0); };
instance.set(Calendar.SECOND, 0); NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
instance.set(Calendar.MILLISECOND, 0); Date actDate = DateUtil.getJavaDate(result.getNumberValue());
assertEquals(instance.getTime(), resultDate);
assertEquals(expDate, actDate);
}
} }
@Test
public void testBug56688() { public void testBug56688() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))}, ec); ValueEval ve[] = {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))};
assertEquals(DATE_1902_09_30, result.getNumberValue()); NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue(), 0);
} }
@Test
public void testRefEvalStartDate() { public void testRefEvalStartDate() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)}, ec); ValueEval ve[] = {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)};
assertEquals(DATE_1902_09_30, result.getNumberValue()); NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue(), 0);
} }
@Test
public void testEOMonthBlankValueEval() { public void testEOMonthBlankValueEval() {
NumberEval evaluate = (NumberEval) eOMonth.evaluate(new ValueEval[] {BlankEval.instance, new NumberEval(0)}, ec); NumberEval evaluate = (NumberEval) eOMonth.evaluate(new ValueEval[] {BlankEval.instance, new NumberEval(0)}, ec);
assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue()); assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue(), 0);
} }
@Test
public void testEOMonthBlankRefValueEval() { public void testEOMonthBlankRefValueEval() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)}, ec); ValueEval[] ve1 = {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)};
assertEquals("Blank is handled as 0", NumberEval result = (NumberEval) eOMonth.evaluate(ve1, ec);
DATE_1900_02_28, result.getNumberValue()); assertEquals("Blank is handled as 0", DATE_1900_02_28, result.getNumberValue(), 0);
result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}, ec); ValueEval[] ve2 = {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)};
assertEquals("Blank is handled as 0", result = (NumberEval) eOMonth.evaluate(ve2, ec);
DATE_1900_01_31, result.getNumberValue()); assertEquals("Blank is handled as 0", DATE_1900_01_31, result.getNumberValue(), 0);
} }
} }

View File

@ -17,21 +17,25 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import static org.junit.Assert.assertEquals;
import java.text.DateFormatSymbols;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.GregorianCalendar; import java.util.TimeZone;
import java.util.Locale;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
/** /**
* Test case for TEXT() * Test case for TEXT()
*/ */
public final class TestText extends TestCase { public final class TestText {
@Test
public void testTextWithStringFirstArg() { public void testTextWithStringFirstArg() {
ValueEval strArg = new StringEval("abc"); ValueEval strArg = new StringEval("abc");
ValueEval formatArg = new StringEval("abc"); ValueEval formatArg = new StringEval("abc");
@ -40,13 +44,14 @@ public final class TestText extends TestCase {
assertEquals(ErrorEval.VALUE_INVALID, result); assertEquals(ErrorEval.VALUE_INVALID, result);
} }
@Test
public void testTextWithDeciamlFormatSecondArg() { public void testTextWithDeciamlFormatSecondArg() {
ValueEval numArg = new NumberEval(321321.321); ValueEval numArg = new NumberEval(321321.321);
ValueEval formatArg = new StringEval("#,###.00000"); ValueEval formatArg = new StringEval("#,###.00000");
ValueEval[] args = { numArg, formatArg }; ValueEval[] args = { numArg, formatArg };
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1); ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
char groupSeparator = new DecimalFormatSymbols(Locale.getDefault()).getGroupingSeparator(); char groupSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getGroupingSeparator();
char decimalSeparator = new DecimalFormatSymbols(Locale.getDefault()).getDecimalSeparator(); char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
ValueEval testResult = new StringEval("321" + groupSeparator + "321" + decimalSeparator + "32100"); ValueEval testResult = new StringEval("321" + groupSeparator + "321" + decimalSeparator + "32100");
assertEquals(testResult.toString(), result.toString()); assertEquals(testResult.toString(), result.toString());
numArg = new NumberEval(321.321); numArg = new NumberEval(321.321);
@ -64,6 +69,7 @@ public final class TestText extends TestCase {
assertEquals(testResult.toString(), result.toString()); assertEquals(testResult.toString(), result.toString());
} }
@Test
public void testTextWithFractionFormatSecondArg() { public void testTextWithFractionFormatSecondArg() {
ValueEval numArg = new NumberEval(321.321); ValueEval numArg = new NumberEval(321.321);
ValueEval formatArg = new StringEval("# #/#"); ValueEval formatArg = new StringEval("# #/#");
@ -85,37 +91,47 @@ public final class TestText extends TestCase {
assertEquals(testResult.toString(), result.toString()); assertEquals(testResult.toString(), result.toString());
} }
@Test
public void testTextWithDateFormatSecondArg() { public void testTextWithDateFormatSecondArg() {
// Test with Java style M=Month TimeZone userTZ = LocaleUtil.getUserTimeZone();
ValueEval numArg = new NumberEval(321.321); LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss"); try {
ValueEval[] args = { numArg, formatArg }; // Test with Java style M=Month
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1); ValueEval numArg = new NumberEval(321.321);
ValueEval testResult = new StringEval("16:11:1900 07:42:14"); ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
assertEquals(testResult.toString(), result.toString()); ValueEval[] args = { numArg, formatArg };
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
// Excel also supports "m before h is month" ValueEval testResult = new StringEval("16:11:1900 07:42:14");
formatArg = new StringEval("dd:mm:yyyy hh:mm:ss"); assertEquals(testResult.toString(), result.toString());
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1); // Excel also supports "m before h is month"
testResult = new StringEval("16:11:1900 07:42:14"); formatArg = new StringEval("dd:mm:yyyy hh:mm:ss");
assertEquals(testResult.toString(), result.toString()); args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
// this line is intended to compute how "November" would look like in the current locale testResult = new StringEval("16:11:1900 07:42:14");
String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime()); assertEquals(testResult.toString(), result.toString());
// Again with Java style // this line is intended to compute how "November" would look like in the current locale
formatArg = new StringEval("MMMM dd, yyyy"); // update: now the locale will be (if not set otherwise) always Locale.getDefault() (see LocaleUtil)
args[1] = formatArg; DateFormatSymbols dfs = DateFormatSymbols.getInstance(LocaleUtil.getUserLocale());
result = TextFunction.TEXT.evaluate(args, -1, (short)-1); SimpleDateFormat sdf = new SimpleDateFormat("MMMM", dfs);
testResult = new StringEval(november + " 16, 1900"); String november = sdf.format(LocaleUtil.getLocaleCalendar(2015,10,1).getTime());
assertEquals(testResult.toString(), result.toString());
// Again with Java style
// And Excel style formatArg = new StringEval("MMMM dd, yyyy");
formatArg = new StringEval("mmmm dd, yyyy"); args[1] = formatArg;
args[1] = formatArg; result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
result = TextFunction.TEXT.evaluate(args, -1, (short)-1); testResult = new StringEval(november + " 16, 1900");
testResult = new StringEval(november + " 16, 1900"); assertEquals(testResult.toString(), result.toString());
assertEquals(testResult.toString(), result.toString());
// And Excel style
formatArg = new StringEval("mmmm dd, yyyy");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval(november + " 16, 1900");
assertEquals(testResult.toString(), result.toString());
} finally {
LocaleUtil.setUserTimeZone(userTZ);
}
} }
} }

View File

@ -17,9 +17,9 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import java.util.regex.Pattern; import static org.junit.Assert.assertEquals;
import junit.framework.TestCase; import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFCellStyle;
@ -28,13 +28,13 @@ import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Before;
import org.junit.Test;
/** /**
* Tests for {@link TimeFunc} * Tests for {@link TimeFunc}
*
* @author @author Steven Butler (sebutler @ gmail dot com)
*/ */
public final class TestTime extends TestCase { public final class TestTime {
private static final int SECONDS_PER_MINUTE = 60; private static final int SECONDS_PER_MINUTE = 60;
private static final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE; private static final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
@ -44,7 +44,8 @@ public final class TestTime extends TestCase {
private HSSFWorkbook wb; private HSSFWorkbook wb;
private HSSFDataFormatter form; private HSSFDataFormatter form;
private HSSFCellStyle style; private HSSFCellStyle style;
@Before
public void setUp() { public void setUp() {
wb = new HSSFWorkbook(); wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet"); HSSFSheet sheet = wb.createSheet("new sheet");
@ -58,11 +59,13 @@ public final class TestTime extends TestCase {
evaluator = new HSSFFormulaEvaluator(wb); evaluator = new HSSFFormulaEvaluator(wb);
} }
@Test
public void testSomeArgumentsMissing() { public void testSomeArgumentsMissing() {
confirm("00:00:00", "TIME(, 0, 0)"); confirm("00:00:00", "TIME(, 0, 0)");
confirm("12:00:00", "TIME(12, , )"); confirm("12:00:00", "TIME(12, , )");
} }
@Test
public void testValid() { public void testValid() {
confirm("00:00:01", 0, 0, 1); confirm("00:00:01", 0, 0, 1);
confirm("00:01:00", 0, 1, 0); confirm("00:01:00", 0, 1, 0);
@ -101,7 +104,6 @@ public final class TestTime extends TestCase {
} }
private void confirm(String expectedTimeStr, String formulaText) { private void confirm(String expectedTimeStr, String formulaText) {
// System.out.println("=" + formulaText);
String[] parts = Pattern.compile(":").split(expectedTimeStr); String[] parts = Pattern.compile(":").split(expectedTimeStr);
int expH = Integer.parseInt(parts[0]); int expH = Integer.parseInt(parts[0]);
int expM = Integer.parseInt(parts[1]); int expM = Integer.parseInt(parts[1]);

View File

@ -17,23 +17,31 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
import junit.framework.AssertionFailedError;
/** /**
* Common superclass for testing implementations of * Common superclass for testing implementations of
* {@link org.apache.poi.ss.usermodel.Cell} * {@link org.apache.poi.ss.usermodel.Cell}
*/ */
public abstract class BaseTestCell extends TestCase { public abstract class BaseTestCell {
protected final ITestDataProvider _testDataProvider; protected final ITestDataProvider _testDataProvider;
@ -44,6 +52,7 @@ public abstract class BaseTestCell extends TestCase {
_testDataProvider = testDataProvider; _testDataProvider = testDataProvider;
} }
@Test
public void testSetValues() { public void testSetValues() {
Workbook book = _testDataProvider.createWorkbook(); Workbook book = _testDataProvider.createWorkbook();
Sheet sheet = book.createSheet("test"); Sheet sheet = book.createSheet("test");
@ -80,7 +89,7 @@ public abstract class BaseTestCell extends TestCase {
assertProhibitedValueAccess(cell, Cell.CELL_TYPE_NUMERIC, Cell.CELL_TYPE_BOOLEAN, assertProhibitedValueAccess(cell, Cell.CELL_TYPE_NUMERIC, Cell.CELL_TYPE_BOOLEAN,
Cell.CELL_TYPE_FORMULA, Cell.CELL_TYPE_ERROR); Cell.CELL_TYPE_FORMULA, Cell.CELL_TYPE_ERROR);
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT); Calendar c = LocaleUtil.getLocaleCalendar();
c.setTimeInMillis(123456789); c.setTimeInMillis(123456789);
cell.setCellValue(c.getTime()); cell.setCellValue(c.getTime());
assertEquals(c.getTime().getTime(), cell.getDateCellValue().getTime()); assertEquals(c.getTime().getTime(), cell.getDateCellValue().getTime());
@ -132,6 +141,7 @@ public abstract class BaseTestCell extends TestCase {
/** /**
* test that Boolean and Error types (BoolErrRecord) are supported properly. * test that Boolean and Error types (BoolErrRecord) are supported properly.
*/ */
@Test
public void testBoolErr() { public void testBoolErr() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
@ -173,6 +183,7 @@ public abstract class BaseTestCell extends TestCase {
/** /**
* test that Cell Styles being applied to formulas remain intact * test that Cell Styles being applied to formulas remain intact
*/ */
@Test
public void testFormulaStyle() { public void testFormulaStyle() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
@ -214,6 +225,7 @@ public abstract class BaseTestCell extends TestCase {
} }
/**tests the toString() method of HSSFCell*/ /**tests the toString() method of HSSFCell*/
@Test
public void testToString() { public void testToString() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Row r = wb.createSheet("Sheet1").createRow(0); Row r = wb.createSheet("Sheet1").createRow(0);
@ -245,6 +257,7 @@ public abstract class BaseTestCell extends TestCase {
/** /**
* Test that setting cached formula result keeps the cell type * Test that setting cached formula result keeps the cell type
*/ */
@Test
public void testSetFormulaValue() { public void testSetFormulaValue() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet s = wb.createSheet(); Sheet s = wb.createSheet();
@ -278,7 +291,7 @@ public abstract class BaseTestCell extends TestCase {
return _testDataProvider.createWorkbook().createSheet("Sheet1").createRow(0).createCell(0); return _testDataProvider.createWorkbook().createSheet("Sheet1").createRow(0).createCell(0);
} }
@Test
public void testChangeTypeStringToBool() { public void testChangeTypeStringToBool() {
Cell cell = createACell(); Cell cell = createACell();
@ -305,6 +318,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("FALSE", cell.getRichStringCellValue().getString()); assertEquals("FALSE", cell.getRichStringCellValue().getString());
} }
@Test
public void testChangeTypeBoolToString() { public void testChangeTypeBoolToString() {
Cell cell = createACell(); Cell cell = createACell();
@ -321,6 +335,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("TRUE", cell.getRichStringCellValue().getString()); assertEquals("TRUE", cell.getRichStringCellValue().getString());
} }
@Test
public void testChangeTypeErrorToNumber() { public void testChangeTypeErrorToNumber() {
Cell cell = createACell(); Cell cell = createACell();
cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME); cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME);
@ -332,6 +347,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals(2.5, cell.getNumericCellValue(), 0.0); assertEquals(2.5, cell.getNumericCellValue(), 0.0);
} }
@Test
public void testChangeTypeErrorToBoolean() { public void testChangeTypeErrorToBoolean() {
Cell cell = createACell(); Cell cell = createACell();
cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME); cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME);
@ -353,6 +369,7 @@ public abstract class BaseTestCell extends TestCase {
* {@link FormulaEvaluator#evaluateInCell(Cell)} with a * {@link FormulaEvaluator#evaluateInCell(Cell)} with a
* string result type. * string result type.
*/ */
@Test
public void testConvertStringFormulaCell() { public void testConvertStringFormulaCell() {
Cell cellA1 = createACell(); Cell cellA1 = createACell();
cellA1.setCellFormula("\"abc\""); cellA1.setCellFormula("\"abc\"");
@ -371,10 +388,12 @@ public abstract class BaseTestCell extends TestCase {
} }
assertEquals("abc", cellA1.getStringCellValue()); assertEquals("abc", cellA1.getStringCellValue());
} }
/** /**
* similar to {@link #testConvertStringFormulaCell()} but checks at a * similar to {@link #testConvertStringFormulaCell()} but checks at a
* lower level that {#link {@link Cell#setCellType(int)} works properly * lower level that {#link {@link Cell#setCellType(int)} works properly
*/ */
@Test
public void testSetTypeStringOnFormulaCell() { public void testSetTypeStringOnFormulaCell() {
Cell cellA1 = createACell(); Cell cellA1 = createACell();
FormulaEvaluator fe = cellA1.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator(); FormulaEvaluator fe = cellA1.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
@ -418,6 +437,7 @@ public abstract class BaseTestCell extends TestCase {
/** /**
* Test for bug in convertCellValueToBoolean to make sure that formula results get converted * Test for bug in convertCellValueToBoolean to make sure that formula results get converted
*/ */
@Test
public void testChangeTypeFormulaToBoolean() { public void testChangeTypeFormulaToBoolean() {
Cell cell = createACell(); Cell cell = createACell();
cell.setCellFormula("1=1"); cell.setCellFormula("1=1");
@ -433,6 +453,7 @@ public abstract class BaseTestCell extends TestCase {
* Bug 40296: HSSFCell.setCellFormula throws * Bug 40296: HSSFCell.setCellFormula throws
* ClassCastException if cell is created using HSSFRow.createCell(short column, int type) * ClassCastException if cell is created using HSSFRow.createCell(short column, int type)
*/ */
@Test
public void test40296() { public void test40296() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet workSheet = wb.createSheet("Sheet1"); Sheet workSheet = wb.createSheet("Sheet1");
@ -470,6 +491,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("SUM(A1:B1)", cell.getCellFormula()); assertEquals("SUM(A1:B1)", cell.getCellFormula());
} }
@Test
public void testSetStringInFormulaCell_bug44606() { public void testSetStringInFormulaCell_bug44606() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0); Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@ -484,7 +506,8 @@ public abstract class BaseTestCell extends TestCase {
/** /**
* Make sure that cell.setCellType(Cell.CELL_TYPE_BLANK) preserves the cell style * Make sure that cell.setCellType(Cell.CELL_TYPE_BLANK) preserves the cell style
*/ */
public void testSetBlank_bug47028() { @Test
public void testSetBlank_bug47028() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0); Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@ -514,7 +537,8 @@ public abstract class BaseTestCell extends TestCase {
* </li> * </li>
* </ul> * </ul>
*/ */
public void testNanAndInfinity() { @Test
public void testNanAndInfinity() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet workSheet = wb.createSheet("Sheet1"); Sheet workSheet = wb.createSheet("Sheet1");
Row row = workSheet.createRow(0); Row row = workSheet.createRow(0);
@ -550,7 +574,8 @@ public abstract class BaseTestCell extends TestCase {
assertEquals(ErrorConstants.ERROR_DIV_0, cell2.getErrorCellValue()); assertEquals(ErrorConstants.ERROR_DIV_0, cell2.getErrorCellValue());
} }
public void testDefaultStyleProperties() { @Test
public void testDefaultStyleProperties() {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0); Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@ -584,7 +609,8 @@ public abstract class BaseTestCell extends TestCase {
assertFalse(style2.getHidden()); assertFalse(style2.getHidden());
} }
public void testBug55658SetNumericValue(){ @Test
public void testBug55658SetNumericValue(){
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet(); Sheet sh = wb.createSheet();
Row row = sh.createRow(0); Row row = sh.createRow(0);
@ -604,7 +630,8 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("24", wb.getSheetAt(0).getRow(0).getCell(1).getStringCellValue()); assertEquals("24", wb.getSheetAt(0).getRow(0).getCell(1).getStringCellValue());
} }
public void testRemoveHyperlink(){ @Test
public void testRemoveHyperlink(){
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet("test"); Sheet sh = wb.createSheet("test");
Row row = sh.createRow(0); Row row = sh.createRow(0);
@ -646,7 +673,8 @@ public abstract class BaseTestCell extends TestCase {
* an problem that cell could not return error value form formula cell). * an problem that cell could not return error value form formula cell).
* @throws IOException * @throws IOException
*/ */
public void testGetErrorCellValueFromFormulaCell() throws IOException { @Test
public void testGetErrorCellValueFromFormulaCell() throws IOException {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
try { try {
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();
@ -660,7 +688,8 @@ public abstract class BaseTestCell extends TestCase {
} }
} }
public void testSetRemoveStyle() throws Exception { @Test
public void testSetRemoveStyle() throws Exception {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0); Row row = sheet.createRow(0);
@ -699,6 +728,7 @@ public abstract class BaseTestCell extends TestCase {
wb.close(); wb.close();
} }
@Test
public void test57008() throws IOException { public void test57008() throws IOException {
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();
@ -740,6 +770,7 @@ public abstract class BaseTestCell extends TestCase {
* The maximum length of cell contents (text) is 32,767 characters. * The maximum length of cell contents (text) is 32,767 characters.
* @throws IOException * @throws IOException
*/ */
@Test
public void testMaxTextLength() throws IOException{ public void testMaxTextLength() throws IOException{
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet(); Sheet sheet = wb.createSheet();

View File

@ -17,15 +17,20 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Calendar;
import java.util.Locale;
import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.JvmBugs; import org.apache.poi.util.JvmBugs;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.Calendar;
/** /**
* Common superclass for testing automatic sizing of sheet columns * Common superclass for testing automatic sizing of sheet columns
* *
@ -35,12 +40,25 @@ public abstract class BaseTestSheetAutosizeColumn {
private final ITestDataProvider _testDataProvider; private final ITestDataProvider _testDataProvider;
private static Locale userLocale;
@BeforeClass
public static void initLocale() {
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
}
@AfterClass
public static void resetLocale() {
LocaleUtil.setUserLocale(userLocale);
}
protected BaseTestSheetAutosizeColumn(ITestDataProvider testDataProvider) { protected BaseTestSheetAutosizeColumn(ITestDataProvider testDataProvider) {
_testDataProvider = testDataProvider; _testDataProvider = testDataProvider;
} }
@Test @Test
public void numericCells(){ public void numericCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
DataFormat df = workbook.getCreationHelper().createDataFormat(); DataFormat df = workbook.getCreationHelper().createDataFormat();
@ -77,10 +95,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(5)); // 10.0000 and '10.0000' assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(5)); // 10.0000 and '10.0000'
workbook.close();
} }
@Test @Test
public void booleanCells(){ public void booleanCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
Sheet sheet = workbook.createSheet(); Sheet sheet = workbook.createSheet();
@ -106,10 +126,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertTrue(sheet.getColumnWidth(1) > sheet.getColumnWidth(0)); // 'true' is wider than '0' assertTrue(sheet.getColumnWidth(1) > sheet.getColumnWidth(0)); // 'true' is wider than '0'
assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width
workbook.close();
} }
@Test @Test
public void dateCells(){ public void dateCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
Sheet sheet = workbook.createSheet(); Sheet sheet = workbook.createSheet();
@ -124,8 +146,7 @@ public abstract class BaseTestSheetAutosizeColumn {
CellStyle style5 = workbook.createCellStyle(); //rotated text CellStyle style5 = workbook.createCellStyle(); //rotated text
style5.setDataFormat(df.getFormat("mmm/dd/yyyy")); style5.setDataFormat(df.getFormat("mmm/dd/yyyy"));
Calendar calendar = Calendar.getInstance(); Calendar calendar = LocaleUtil.getLocaleCalendar(2010, 0, 1); // Jan 1 2010
calendar.set(2010, 0, 1); // Jan 1 2010
Row row = sheet.createRow(0); Row row = sheet.createRow(0);
row.createCell(0).setCellValue(DateUtil.getJavaDate(0)); //default date row.createCell(0).setCellValue(DateUtil.getJavaDate(0)); //default date
@ -172,10 +193,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertTrue(sheet.getColumnWidth(5) > sheet.getColumnWidth(3)); // 'mmm/dd/yyyy' is wider than 'mmm' assertTrue(sheet.getColumnWidth(5) > sheet.getColumnWidth(3)); // 'mmm/dd/yyyy' is wider than 'mmm'
assertEquals(sheet.getColumnWidth(6), sheet.getColumnWidth(5)); // date formatted as 'mmm/dd/yyyy' assertEquals(sheet.getColumnWidth(6), sheet.getColumnWidth(5)); // date formatted as 'mmm/dd/yyyy'
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(7)); // date formula formatted as 'mmm' assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(7)); // date formula formatted as 'mmm'
workbook.close();
} }
@Test @Test
public void stringCells(){ public void stringCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
Sheet sheet = workbook.createSheet(); Sheet sheet = workbook.createSheet();
@ -205,10 +228,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(3)); assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(3));
boolean ignoreFontSizeX2 = JvmBugs.hasLineBreakMeasurerBug(); boolean ignoreFontSizeX2 = JvmBugs.hasLineBreakMeasurerBug();
assertTrue(ignoreFontSizeX2 || sheet.getColumnWidth(5) > sheet.getColumnWidth(4)); //larger font results in a wider column width assertTrue(ignoreFontSizeX2 || sheet.getColumnWidth(5) > sheet.getColumnWidth(4)); //larger font results in a wider column width
workbook.close();
} }
@Test @Test
public void rotatedText(){ public void rotatedText() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
Sheet sheet = workbook.createSheet(); Sheet sheet = workbook.createSheet();
@ -230,10 +255,12 @@ public abstract class BaseTestSheetAutosizeColumn {
int w1 = sheet.getColumnWidth(1); int w1 = sheet.getColumnWidth(1);
assertTrue(w0*5 < w1); // rotated text occupies at least five times less horizontal space than normal text assertTrue(w0*5 < w1); // rotated text occupies at least five times less horizontal space than normal text
workbook.close();
} }
@Test @Test
public void mergedCells(){ public void mergedCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook(); Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook); fixFonts(workbook);
Sheet sheet = workbook.createSheet(); Sheet sheet = workbook.createSheet();
@ -251,6 +278,8 @@ public abstract class BaseTestSheetAutosizeColumn {
sheet.autoSizeColumn(0, true); sheet.autoSizeColumn(0, true);
assertTrue(sheet.getColumnWidth(0) > defaulWidth); assertTrue(sheet.getColumnWidth(0) > defaulWidth);
workbook.close();
} }
@ -293,6 +322,8 @@ public abstract class BaseTestSheetAutosizeColumn {
Row r60708 = sheet.createRow(60708); Row r60708 = sheet.createRow(60708);
r60708.createCell(0).setCellValue("Near the end"); r60708.createCell(0).setCellValue("Near the end");
sheet.autoSizeColumn(0); sheet.autoSizeColumn(0);
workbook.close();
} }
// TODO should we have this stuff in the FormulaEvaluator? // TODO should we have this stuff in the FormulaEvaluator?

View File

@ -21,16 +21,22 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import junit.framework.TestCase;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.TestHSSFDataFormatter; import org.apache.poi.hssf.usermodel.TestHSSFDataFormatter;
import org.apache.poi.util.LocaleUtil;
import org.junit.Ignore;
import org.junit.Test;
/** /**
* Tests of {@link DataFormatter} * Tests of {@link DataFormatter}
@ -38,13 +44,14 @@ import org.apache.poi.hssf.usermodel.TestHSSFDataFormatter;
* See {@link TestHSSFDataFormatter} too for * See {@link TestHSSFDataFormatter} too for
* more tests. * more tests.
*/ */
public class TestDataFormatter extends TestCase { public class TestDataFormatter {
private static final double _15_MINUTES = 0.041666667; private static final double _15_MINUTES = 0.041666667;
/** /**
* Test that we use the specified locale when deciding * Test that we use the specified locale when deciding
* how to format normal numbers * how to format normal numbers
*/ */
@Test
public void testLocale() { public void testLocale() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
DataFormatter dfFR = new DataFormatter(Locale.FRENCH); DataFormatter dfFR = new DataFormatter(Locale.FRENCH);
@ -61,6 +68,7 @@ public class TestDataFormatter extends TestCase {
* a specific locale, but we should format things as if * a specific locale, but we should format things as if
* the locale (eg '[$-1010409]') isn't there * the locale (eg '[$-1010409]') isn't there
*/ */
@Test
public void testLocaleBasedFormats() { public void testLocaleBasedFormats() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -78,6 +86,7 @@ public class TestDataFormatter extends TestCase {
* Ensure that colours get correctly * Ensure that colours get correctly
* zapped from within the format strings * zapped from within the format strings
*/ */
@Test
public void testColours() { public void testColours() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -105,6 +114,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("[ab]12.34[x]", dfUS.formatRawCellContents(12.343, -1, "[ab]##.##[x]")); assertEquals("[ab]12.34[x]", dfUS.formatRawCellContents(12.343, -1, "[ab]##.##[x]"));
} }
@Test
public void testColoursAndBrackets() { public void testColoursAndBrackets() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -149,6 +159,7 @@ public class TestDataFormatter extends TestCase {
* and Excel differ, and workarounds are not * and Excel differ, and workarounds are not
* yet in place for all of these * yet in place for all of these
*/ */
@Test
public void testNegativeZero() { public void testNegativeZero() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -193,6 +204,7 @@ public class TestDataFormatter extends TestCase {
* Test that we correctly handle fractions in the * Test that we correctly handle fractions in the
* format string, eg # #/# * format string, eg # #/#
*/ */
@Test
public void testFractions() { public void testFractions() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -262,6 +274,7 @@ public class TestDataFormatter extends TestCase {
* and *x (fill to the column width with "x"s) are * and *x (fill to the column width with "x"s) are
* correctly ignored by us. * correctly ignored by us.
*/ */
@Test
public void testPaddingSpaces() { public void testPaddingSpaces() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
assertEquals("12.34", dfUS.formatRawCellContents(12.343, -1, "##.##_ ")); assertEquals("12.34", dfUS.formatRawCellContents(12.343, -1, "##.##_ "));
@ -278,6 +291,7 @@ public class TestDataFormatter extends TestCase {
/** /**
* DataFormatter is the CSV mode preserves spaces * DataFormatter is the CSV mode preserves spaces
*/ */
@Test
public void testPaddingSpacesCSV() { public void testPaddingSpacesCSV() {
DataFormatter dfUS = new DataFormatter(Locale.US, true); DataFormatter dfUS = new DataFormatter(Locale.US, true);
assertEquals("12.34 ", dfUS.formatRawCellContents(12.343, -1, "##.##_ ")); assertEquals("12.34 ", dfUS.formatRawCellContents(12.343, -1, "##.##_ "));
@ -311,12 +325,11 @@ public class TestDataFormatter extends TestCase {
* Test that the special Excel month format MMMMM * Test that the special Excel month format MMMMM
* gets turned into the first letter of the month * gets turned into the first letter of the month
*/ */
@Test
public void testMMMMM() { public void testMMMMM() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
Calendar c = Calendar.getInstance(); Calendar c = LocaleUtil.getLocaleCalendar(2010, 5, 1, 2, 0, 0);
c.set(Calendar.MILLISECOND, 0);
c.set(2010, 5, 1, 2, 0, 0);
assertEquals("2010-J-1 2:00:00", dfUS.formatRawCellContents( assertEquals("2010-J-1 2:00:00", dfUS.formatRawCellContents(
DateUtil.getExcelDate(c, false), -1, "YYYY-MMMMM-D h:mm:ss" DateUtil.getExcelDate(c, false), -1, "YYYY-MMMMM-D h:mm:ss"
@ -326,6 +339,7 @@ public class TestDataFormatter extends TestCase {
/** /**
* Tests that we do AM/PM handling properly * Tests that we do AM/PM handling properly
*/ */
@Test
public void testAMPM() { public void testAMPM() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -343,6 +357,7 @@ public class TestDataFormatter extends TestCase {
* Test that we can handle elapsed time, * Test that we can handle elapsed time,
* eg formatting 1 day 4 hours as 28 hours * eg formatting 1 day 4 hours as 28 hours
*/ */
@Test
public void testElapsedTime() { public void testElapsedTime() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -447,6 +462,7 @@ public class TestDataFormatter extends TestCase {
} }
} }
@Test
public void testDateWindowing() { public void testDateWindowing() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -455,6 +471,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("1904-01-01 00:00:00", dfUS.formatRawCellContents(0.0, -1, "yyyy-mm-dd hh:mm:ss", true)); assertEquals("1904-01-01 00:00:00", dfUS.formatRawCellContents(0.0, -1, "yyyy-mm-dd hh:mm:ss", true));
} }
@Test
public void testScientificNotation() { public void testScientificNotation() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -463,6 +480,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("0.00E+00", dfUS.formatRawCellContents(0.0, -1, "0.00E+00")); assertEquals("0.00E+00", dfUS.formatRawCellContents(0.0, -1, "0.00E+00"));
} }
@Test
public void testInvalidDate() { public void testInvalidDate() {
DataFormatter df1 = new DataFormatter(Locale.US); DataFormatter df1 = new DataFormatter(Locale.US);
assertEquals("-1.0", df1.formatRawCellContents(-1, -1, "mm/dd/yyyy")); assertEquals("-1.0", df1.formatRawCellContents(-1, -1, "mm/dd/yyyy"));
@ -472,6 +490,7 @@ public class TestDataFormatter extends TestCase {
df2.formatRawCellContents(-1, -1, "mm/dd/yyyy")); df2.formatRawCellContents(-1, -1, "mm/dd/yyyy"));
} }
@Test
public void testEscapes() { public void testEscapes() {
DataFormatter dfUS = new DataFormatter(Locale.US); DataFormatter dfUS = new DataFormatter(Locale.US);
@ -485,6 +504,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("1901/01/01", dfUS.formatRawCellContents(367.0, -1, "yyyy\\/mm\\/dd")); assertEquals("1901/01/01", dfUS.formatRawCellContents(367.0, -1, "yyyy\\/mm\\/dd"));
} }
@Test
public void testOther() { public void testOther() {
DataFormatter dfUS = new DataFormatter(Locale.US, true); DataFormatter dfUS = new DataFormatter(Locale.US, true);
@ -494,6 +514,7 @@ public class TestDataFormatter extends TestCase {
assertEquals(" $- ", dfUS.formatRawCellContents(0.0, -1, "_-$* #,##0.00_-;-$* #,##0.00_-;_-$* \"-\"??_-;_-@_-")); assertEquals(" $- ", dfUS.formatRawCellContents(0.0, -1, "_-$* #,##0.00_-;-$* #,##0.00_-;_-$* \"-\"??_-;_-@_-"));
} }
@Test
public void testErrors() throws IOException { public void testErrors() throws IOException {
DataFormatter dfUS = new DataFormatter(Locale.US, true); DataFormatter dfUS = new DataFormatter(Locale.US, true);
@ -519,6 +540,7 @@ public class TestDataFormatter extends TestCase {
* the start of a format string to format it differently, we * the start of a format string to format it differently, we
* should at least handle it as it if wasn't there * should at least handle it as it if wasn't there
*/ */
@Test
public void testDatesWithLocales() { public void testDatesWithLocales() {
DataFormatter dfUS = new DataFormatter(Locale.US, true); DataFormatter dfUS = new DataFormatter(Locale.US, true);
@ -543,7 +565,9 @@ public class TestDataFormatter extends TestCase {
/** /**
* TODO Fix these so that they work * TODO Fix these so that they work
*/ */
public void DISABLEDtestCustomFormats() { @Test
@Ignore
public void testCustomFormats() {
DataFormatter dfUS = new DataFormatter(Locale.US, true); DataFormatter dfUS = new DataFormatter(Locale.US, true);
String fmt; String fmt;
@ -560,6 +584,7 @@ public class TestDataFormatter extends TestCase {
/** /**
* ExcelStyleDateFormatter should work for Milliseconds too * ExcelStyleDateFormatter should work for Milliseconds too
*/ */
@Test
public void testExcelStyleDateFormatterStringOnMillis() { public void testExcelStyleDateFormatterStringOnMillis() {
// Test directly with the .000 style // Test directly with the .000 style
DateFormat formatter1 = new ExcelStyleDateFormatter("ss.000"); DateFormat formatter1 = new ExcelStyleDateFormatter("ss.000");
@ -589,7 +614,8 @@ public class TestDataFormatter extends TestCase {
assertEquals("01.010", dfUS.formatRawCellContents(0.0000116898, -1, "ss.000")); assertEquals("01.010", dfUS.formatRawCellContents(0.0000116898, -1, "ss.000"));
} }
public void testBug54786() { @Test
public void testBug54786() {
DataFormatter formatter = new DataFormatter(); DataFormatter formatter = new DataFormatter();
String format = "[h]\"\"h\"\" m\"\"m\"\""; String format = "[h]\"\"h\"\" m\"\"m\"\"";
assertTrue(DateUtil.isADateFormat(-1,format)); assertTrue(DateUtil.isADateFormat(-1,format));
@ -613,7 +639,8 @@ public class TestDataFormatter extends TestCase {
} }
} }
public void testIsADateFormat() { @Test
public void testIsADateFormat() {
// first check some cases that should not be a date, also call multiple times to ensure the cache is used // first check some cases that should not be a date, also call multiple times to ensure the cache is used
assertFalse(DateUtil.isADateFormat(-1, null)); assertFalse(DateUtil.isADateFormat(-1, null));
assertFalse(DateUtil.isADateFormat(-1, null)); assertFalse(DateUtil.isADateFormat(-1, null));

View File

@ -23,6 +23,7 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test; import org.junit.Test;
public class TestDateUtil { public class TestDateUtil {
@ -30,7 +31,7 @@ public class TestDateUtil {
@Test @Test
public void getJavaDate_InvalidValue() { public void getJavaDate_InvalidValue() {
double dateValue = -1; double dateValue = -1;
TimeZone tz = TimeZone.getDefault(); TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false; boolean use1904windowing = false;
boolean roundSeconds = false; boolean roundSeconds = false;
@ -44,13 +45,11 @@ public class TestDateUtil {
@Test @Test
public void getJavaDate_ValidValue() { public void getJavaDate_ValidValue() {
double dateValue = 0; double dateValue = 0;
TimeZone tz = TimeZone.getDefault(); TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false; boolean use1904windowing = false;
boolean roundSeconds = false; boolean roundSeconds = false;
Calendar calendar = Calendar.getInstance(tz); Calendar calendar = LocaleUtil.getLocaleCalendar(1900, 0, 0);
calendar.set(1900, 0, 0, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date date = calendar.getTime(); Date date = calendar.getTime();
assertEquals(date, DateUtil.getJavaDate(dateValue)); assertEquals(date, DateUtil.getJavaDate(dateValue));
@ -63,7 +62,7 @@ public class TestDateUtil {
@Test @Test
public void getJavaCalendar_InvalidValue() { public void getJavaCalendar_InvalidValue() {
double dateValue = -1; double dateValue = -1;
TimeZone tz = TimeZone.getDefault(); TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false; boolean use1904windowing = false;
boolean roundSeconds = false; boolean roundSeconds = false;
@ -76,17 +75,21 @@ public class TestDateUtil {
@Test @Test
public void getJavaCalendar_ValidValue() { public void getJavaCalendar_ValidValue() {
double dateValue = 0; double dateValue = 0;
TimeZone tz = TimeZone.getDefault(); TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false; boolean use1904windowing = false;
boolean roundSeconds = false; boolean roundSeconds = false;
Calendar calendar = Calendar.getInstance(tz); Calendar expCal = LocaleUtil.getLocaleCalendar(1900, 0, 0);
calendar.set(1900, 0, 0, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue)); Calendar actCal[] = {
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing)); DateUtil.getJavaCalendar(dateValue),
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing, tz)); DateUtil.getJavaCalendar(dateValue, use1904windowing),
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing, tz, roundSeconds)); DateUtil.getJavaCalendar(dateValue, use1904windowing, tz),
DateUtil.getJavaCalendar(dateValue, use1904windowing, tz, roundSeconds)
};
assertEquals(expCal, actCal[0]);
assertEquals(expCal, actCal[1]);
assertEquals(expCal, actCal[2]);
assertEquals(expCal, actCal[3]);
} }
} }

View File

@ -69,7 +69,7 @@ public final class TestDateFormatConverter extends TestCase {
Row row = sheet.createRow(rowNum++); Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(locale.toString()); row.createCell(0).setCellValue(locale.toString());
row.createCell(1).setCellValue(locale.getDisplayName()); row.createCell(1).setCellValue(locale.getDisplayName(Locale.ROOT));
DateFormat dateFormat; DateFormat dateFormat;
if( dates ) { if( dates ) {

View File

@ -134,7 +134,7 @@ public final class TestHexDump {
obj[17] = chrs.toString(); obj[17] = chrs.toString();
format.append("%18$s"+HexDump.EOL); format.append("%18$s"+HexDump.EOL);
String str = String.format(format.toString(), obj); String str = String.format(LocaleUtil.getUserLocale(), format.toString(), obj);
strExp.append(str); strExp.append(str);
} }
byte bytesExp[] = strExp.toString().getBytes(HexDump.UTF8); byte bytesExp[] = strExp.toString().getBytes(HexDump.UTF8);

View File

@ -144,7 +144,7 @@ public final class TestStringUtil extends TestCase {
} }
private static String fmt(double num, int minIntDigits, int maxFracDigitis) { private static String fmt(double num, int minIntDigits, int maxFracDigitis) {
NumberFormat nf = NumberFormat.getInstance(); NumberFormat nf = NumberFormat.getInstance(LocaleUtil.getUserLocale());
if (minIntDigits != -1) { if (minIntDigits != -1) {
nf.setMinimumIntegerDigits(minIntDigits); nf.setMinimumIntegerDigits(minIntDigits);