Fix bug #45365 - Handle more excel number formatting rules in FormatTrackingHSSFListener / XLS2CSVmra
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@675671 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f6730d9a3a
commit
81f9610e04
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45365 - Handle more excel number formatting rules in FormatTrackingHSSFListener / XLS2CSVmra</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
|
<action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>
|
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45348 - Tweaks to RVA formula logic</action>
|
<action dev="POI-DEVELOPERS" type="fix">45348 - Tweaks to RVA formula logic</action>
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45365 - Handle more excel number formatting rules in FormatTrackingHSSFListener / XLS2CSVmra</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
|
<action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>
|
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45348 - Tweaks to RVA formula logic</action>
|
<action dev="POI-DEVELOPERS" type="fix">45348 - Tweaks to RVA formula logic</action>
|
||||||
|
@ -20,10 +20,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
|
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
|
||||||
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
|
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
|
||||||
@ -37,7 +33,6 @@ import org.apache.poi.hssf.model.FormulaParser;
|
|||||||
import org.apache.poi.hssf.record.BOFRecord;
|
import org.apache.poi.hssf.record.BOFRecord;
|
||||||
import org.apache.poi.hssf.record.BlankRecord;
|
import org.apache.poi.hssf.record.BlankRecord;
|
||||||
import org.apache.poi.hssf.record.BoolErrRecord;
|
import org.apache.poi.hssf.record.BoolErrRecord;
|
||||||
import org.apache.poi.hssf.record.CellValueRecordInterface;
|
|
||||||
import org.apache.poi.hssf.record.FormulaRecord;
|
import org.apache.poi.hssf.record.FormulaRecord;
|
||||||
import org.apache.poi.hssf.record.LabelRecord;
|
import org.apache.poi.hssf.record.LabelRecord;
|
||||||
import org.apache.poi.hssf.record.LabelSSTRecord;
|
import org.apache.poi.hssf.record.LabelSSTRecord;
|
||||||
@ -47,7 +42,6 @@ import org.apache.poi.hssf.record.RKRecord;
|
|||||||
import org.apache.poi.hssf.record.Record;
|
import org.apache.poi.hssf.record.Record;
|
||||||
import org.apache.poi.hssf.record.SSTRecord;
|
import org.apache.poi.hssf.record.SSTRecord;
|
||||||
import org.apache.poi.hssf.record.StringRecord;
|
import org.apache.poi.hssf.record.StringRecord;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
|
|
||||||
@ -180,7 +174,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
nextRow = frec.getRow();
|
nextRow = frec.getRow();
|
||||||
nextColumn = frec.getColumn();
|
nextColumn = frec.getColumn();
|
||||||
} else {
|
} else {
|
||||||
thisStr = formatNumberDateCell(frec, frec.getValue());
|
thisStr = formatListener.formatNumberDateCell(frec);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
thisStr = '"' +
|
thisStr = '"' +
|
||||||
@ -231,7 +225,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
thisColumn = numrec.getColumn();
|
thisColumn = numrec.getColumn();
|
||||||
|
|
||||||
// Format
|
// Format
|
||||||
thisStr = formatNumberDateCell(numrec, numrec.getValue());
|
thisStr = formatListener.formatNumberDateCell(numrec);
|
||||||
break;
|
break;
|
||||||
case RKRecord.sid:
|
case RKRecord.sid:
|
||||||
RKRecord rkrec = (RKRecord) record;
|
RKRecord rkrec = (RKRecord) record;
|
||||||
@ -290,44 +284,6 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a number or date cell, be that a real number, or the
|
|
||||||
* answer to a formula
|
|
||||||
*/
|
|
||||||
private String formatNumberDateCell(CellValueRecordInterface cell, double value) {
|
|
||||||
// Get the built in format, if there is one
|
|
||||||
int formatIndex = formatListener.getFormatIndex(cell);
|
|
||||||
String formatString = formatListener.getFormatString(cell);
|
|
||||||
|
|
||||||
if(formatString == null) {
|
|
||||||
return Double.toString(value);
|
|
||||||
} else {
|
|
||||||
// Is it a date?
|
|
||||||
if(HSSFDateUtil.isADateFormat(formatIndex,formatString) &&
|
|
||||||
HSSFDateUtil.isValidExcelDate(value)) {
|
|
||||||
// Java wants M not m for month
|
|
||||||
formatString = formatString.replace('m','M');
|
|
||||||
// Change \- into -, if it's there
|
|
||||||
formatString = formatString.replaceAll("\\\\-","-");
|
|
||||||
|
|
||||||
// Format as a date
|
|
||||||
Date d = HSSFDateUtil.getJavaDate(value, false);
|
|
||||||
DateFormat df = new SimpleDateFormat(formatString);
|
|
||||||
return df.format(d);
|
|
||||||
} else {
|
|
||||||
if(formatString == "General") {
|
|
||||||
// Some sort of wierd default
|
|
||||||
return Double.toString(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format as a number
|
|
||||||
DecimalFormat df = new DecimalFormat(formatString);
|
|
||||||
return df.format(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if(args.length < 1) {
|
if(args.length < 1) {
|
||||||
System.err.println("Use:");
|
System.err.println("Use:");
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.hssf.eventusermodel;
|
package org.apache.poi.hssf.eventusermodel;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -24,8 +28,11 @@ import java.util.Map;
|
|||||||
import org.apache.poi.hssf.record.CellValueRecordInterface;
|
import org.apache.poi.hssf.record.CellValueRecordInterface;
|
||||||
import org.apache.poi.hssf.record.ExtendedFormatRecord;
|
import org.apache.poi.hssf.record.ExtendedFormatRecord;
|
||||||
import org.apache.poi.hssf.record.FormatRecord;
|
import org.apache.poi.hssf.record.FormatRecord;
|
||||||
|
import org.apache.poi.hssf.record.FormulaRecord;
|
||||||
|
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.HSSFDateUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A proxy HSSFListener that keeps track of the document
|
* A proxy HSSFListener that keeps track of the document
|
||||||
@ -69,6 +76,61 @@ public class FormatTrackingHSSFListener implements HSSFListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given numeric of date Cell's contents
|
||||||
|
* as a String, in as close as we can to the way
|
||||||
|
* that Excel would do so.
|
||||||
|
* Uses the various format records to manage this.
|
||||||
|
*
|
||||||
|
* TODO - move this to a central class in such a
|
||||||
|
* way that hssf.usermodel can make use of it too
|
||||||
|
*/
|
||||||
|
public String formatNumberDateCell(CellValueRecordInterface cell) {
|
||||||
|
double value;
|
||||||
|
if(cell instanceof NumberRecord) {
|
||||||
|
value = ((NumberRecord)cell).getValue();
|
||||||
|
} else if(cell instanceof FormulaRecord) {
|
||||||
|
value = ((FormulaRecord)cell).getValue();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported CellValue Record passed in " + cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the built in format, if there is one
|
||||||
|
int formatIndex = getFormatIndex(cell);
|
||||||
|
String formatString = getFormatString(cell);
|
||||||
|
|
||||||
|
if(formatString == null) {
|
||||||
|
return Double.toString(value);
|
||||||
|
} else {
|
||||||
|
// Is it a date?
|
||||||
|
if(HSSFDateUtil.isADateFormat(formatIndex,formatString) &&
|
||||||
|
HSSFDateUtil.isValidExcelDate(value)) {
|
||||||
|
// Java wants M not m for month
|
||||||
|
formatString = formatString.replace('m','M');
|
||||||
|
// Change \- into -, if it's there
|
||||||
|
formatString = formatString.replaceAll("\\\\-","-");
|
||||||
|
|
||||||
|
// Format as a date
|
||||||
|
Date d = HSSFDateUtil.getJavaDate(value, false);
|
||||||
|
DateFormat df = new SimpleDateFormat(formatString);
|
||||||
|
return df.format(d);
|
||||||
|
} else {
|
||||||
|
if(formatString == "General") {
|
||||||
|
// Some sort of wierd default
|
||||||
|
return Double.toString(value);
|
||||||
|
}
|
||||||
|
if(formatString == "0.00E+00") {
|
||||||
|
// This seems to mean output as a normal double
|
||||||
|
return Double.toString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format as a number
|
||||||
|
DecimalFormat df = new DecimalFormat(formatString);
|
||||||
|
return df.format(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format string, eg $##.##, for the
|
* Returns the format string, eg $##.##, for the
|
||||||
* given number format index.
|
* given number format index.
|
||||||
|
BIN
src/testcases/org/apache/poi/hssf/data/45365.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45365.xls
Normal file
Binary file not shown.
@ -24,6 +24,9 @@ import java.util.List;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
|
import org.apache.poi.hssf.record.CellValueRecordInterface;
|
||||||
|
import org.apache.poi.hssf.record.FormulaRecord;
|
||||||
|
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.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
/**
|
/**
|
||||||
@ -31,16 +34,17 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|||||||
*/
|
*/
|
||||||
public final class TestFormatTrackingHSSFListener extends TestCase {
|
public final class TestFormatTrackingHSSFListener extends TestCase {
|
||||||
private FormatTrackingHSSFListener listener;
|
private FormatTrackingHSSFListener listener;
|
||||||
|
private MockHSSFListener mockListen;
|
||||||
|
|
||||||
public void setUp() {
|
private void processFile(String filename) throws Exception {
|
||||||
HSSFRequest req = new HSSFRequest();
|
HSSFRequest req = new HSSFRequest();
|
||||||
MockHSSFListener mockListen = new MockHSSFListener();
|
mockListen = new MockHSSFListener();
|
||||||
listener = new FormatTrackingHSSFListener(mockListen);
|
listener = new FormatTrackingHSSFListener(mockListen);
|
||||||
req.addListenerForAllRecords(listener);
|
req.addListenerForAllRecords(listener);
|
||||||
|
|
||||||
HSSFEventFactory factory = new HSSFEventFactory();
|
HSSFEventFactory factory = new HSSFEventFactory();
|
||||||
try {
|
try {
|
||||||
InputStream is = HSSFTestDataSamples.openSampleFileStream("MissingBits.xls");
|
InputStream is = HSSFTestDataSamples.openSampleFileStream(filename);
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
POIFSFileSystem fs = new POIFSFileSystem(is);
|
||||||
factory.processWorkbookEvents(req, fs);
|
factory.processWorkbookEvents(req, fs);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -49,11 +53,42 @@ public final class TestFormatTrackingHSSFListener extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFormats() throws Exception {
|
public void testFormats() throws Exception {
|
||||||
|
processFile("MissingBits.xls");
|
||||||
|
|
||||||
assertEquals("_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)", listener.getFormatString(41));
|
assertEquals("_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)", listener.getFormatString(41));
|
||||||
assertEquals("_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)", listener.getFormatString(42));
|
assertEquals("_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)", listener.getFormatString(42));
|
||||||
assertEquals("_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)", listener.getFormatString(43));
|
assertEquals("_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)", listener.getFormatString(43));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that all number and formula records can be
|
||||||
|
* turned into strings without problems
|
||||||
|
*/
|
||||||
|
public void testTurnToString() throws Exception {
|
||||||
|
processFile("45365.xls");
|
||||||
|
|
||||||
|
for(int i=0; i<mockListen._records.size(); i++) {
|
||||||
|
Record r = (Record)mockListen._records.get(i);
|
||||||
|
CellValueRecordInterface cvr = null;
|
||||||
|
|
||||||
|
if(r instanceof NumberRecord) {
|
||||||
|
cvr = (CellValueRecordInterface)r;
|
||||||
|
}
|
||||||
|
if(r instanceof FormulaRecord) {
|
||||||
|
cvr = (CellValueRecordInterface)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cvr != null) {
|
||||||
|
// Should always give us a string
|
||||||
|
String s = listener.formatNumberDateCell(cvr);
|
||||||
|
assertNotNull(s);
|
||||||
|
assertTrue(s.length() > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - test some specific format strings
|
||||||
|
}
|
||||||
|
|
||||||
private static final class MockHSSFListener implements HSSFListener {
|
private static final class MockHSSFListener implements HSSFListener {
|
||||||
public MockHSSFListener() {}
|
public MockHSSFListener() {}
|
||||||
private final List _records = new ArrayList();
|
private final List _records = new ArrayList();
|
||||||
|
Loading…
Reference in New Issue
Block a user