git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@646405 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_0_3_BETA1
@@ -0,0 +1,117 @@ | |||
/* ==================================================================== | |||
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.hssf.eventusermodel; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.poi.hssf.record.CellValueRecordInterface; | |||
import org.apache.poi.hssf.record.ExtendedFormatRecord; | |||
import org.apache.poi.hssf.record.FormatRecord; | |||
import org.apache.poi.hssf.record.Record; | |||
import org.apache.poi.hssf.usermodel.HSSFDataFormat; | |||
/** | |||
* A proxy HSSFListener that keeps track of the document | |||
* formatting records, and provides an easy way to look | |||
* up the format strings used by cells from their ids. | |||
*/ | |||
public class FormatTrackingHSSFListener implements HSSFListener { | |||
private HSSFListener childListener; | |||
private Map customFormatRecords = new Hashtable(); | |||
private List xfRecords = new ArrayList(); | |||
public FormatTrackingHSSFListener(HSSFListener childListener) { | |||
this.childListener = childListener; | |||
} | |||
/** | |||
* Process this record ourselves, and then | |||
* pass it on to our child listener | |||
*/ | |||
public void processRecord(Record record) { | |||
// Handle it ourselves | |||
processRecordInternally(record); | |||
// Now pass on to our child | |||
childListener.processRecord(record); | |||
} | |||
/** | |||
* Process the record ourselves, but do not | |||
* pass it on to the child Listener. | |||
* @param record | |||
*/ | |||
public void processRecordInternally(Record record) { | |||
if(record instanceof FormatRecord) { | |||
FormatRecord fr = (FormatRecord) record; | |||
customFormatRecords.put(new Integer(fr.getIndexCode()), fr); | |||
} | |||
if(record instanceof ExtendedFormatRecord) { | |||
ExtendedFormatRecord xr = (ExtendedFormatRecord) record; | |||
xfRecords.add(xr); | |||
} | |||
} | |||
/** | |||
* Returns the format string, eg $##.##, for the | |||
* given number format index. | |||
*/ | |||
public String getFormatString(int formatIndex) { | |||
String format = null; | |||
if(formatIndex >= HSSFDataFormat.getNumberOfBuiltinBuiltinFormats()) { | |||
FormatRecord tfr = (FormatRecord)customFormatRecords.get(new Integer(formatIndex)); | |||
if(tfr == null) { | |||
System.err.println("Requested format at index " + formatIndex + ", but it wasn't found"); | |||
} else { | |||
format = tfr.getFormatString(); | |||
} | |||
} else { | |||
format = HSSFDataFormat.getBuiltinFormat((short)formatIndex); | |||
} | |||
return format; | |||
} | |||
/** | |||
* Returns the format string, eg $##.##, used | |||
* by your cell | |||
*/ | |||
public String getFormatString(CellValueRecordInterface cell) { | |||
int formatIndex = getFormatIndex(cell); | |||
if(formatIndex == -1) { | |||
// Not found | |||
return null; | |||
} | |||
return getFormatString(formatIndex); | |||
} | |||
/** | |||
* Returns the index of the format string, used by your cell, | |||
* or -1 if none found | |||
*/ | |||
public int getFormatIndex(CellValueRecordInterface cell) { | |||
ExtendedFormatRecord xfr = (ExtendedFormatRecord) | |||
xfRecords.get(cell.getXFIndex()); | |||
if(xfr == null) { | |||
System.err.println("Cell " + cell.getRow() + "," + cell.getColumn() + " uses XF with index " + cell.getXFIndex() + ", but we don't have that"); | |||
return -1; | |||
} | |||
return xfr.getFormatIndex(); | |||
} | |||
} |
@@ -29,6 +29,7 @@ import java.util.Hashtable; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener; | |||
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; | |||
import org.apache.poi.hssf.eventusermodel.HSSFListener; | |||
import org.apache.poi.hssf.eventusermodel.HSSFRequest; | |||
@@ -70,8 +71,7 @@ public class XLS2CSVmra implements HSSFListener { | |||
// Records we pick up as we process | |||
private SSTRecord sstRecord; | |||
private Map customFormatRecords = new Hashtable(); | |||
private List xfRecords = new ArrayList(); | |||
private FormatTrackingHSSFListener formatListener; | |||
/** | |||
* Creates a new XLS -> CSV converter | |||
@@ -104,9 +104,11 @@ public class XLS2CSVmra implements HSSFListener { | |||
*/ | |||
public void process() throws IOException { | |||
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this); | |||
formatListener = new FormatTrackingHSSFListener(listener); | |||
HSSFEventFactory factory = new HSSFEventFactory(); | |||
HSSFRequest request = new HSSFRequest(); | |||
request.addListenerForAllRecords(listener); | |||
request.addListenerForAllRecords(formatListener); | |||
factory.processWorkbookEvents(request, fs); | |||
} | |||
@@ -125,14 +127,6 @@ public class XLS2CSVmra implements HSSFListener { | |||
case SSTRecord.sid: | |||
sstRecord = (SSTRecord) record; | |||
break; | |||
case FormatRecord.sid: | |||
FormatRecord fr = (FormatRecord) record; | |||
customFormatRecords.put(new Integer(fr.getIndexCode()), fr); | |||
break; | |||
case ExtendedFormatRecord.sid: | |||
ExtendedFormatRecord xr = (ExtendedFormatRecord) record; | |||
xfRecords.add(xr); | |||
break; | |||
case BlankRecord.sid: | |||
BlankRecord brec = (BlankRecord) record; | |||
@@ -259,41 +253,32 @@ public class XLS2CSVmra implements HSSFListener { | |||
*/ | |||
private String formatNumberDateCell(CellValueRecordInterface cell, double value) { | |||
// Get the built in format, if there is one | |||
ExtendedFormatRecord xfr = (ExtendedFormatRecord) | |||
xfRecords.get(cell.getXFIndex()); | |||
if(xfr == null) { | |||
System.err.println("Cell " + cell.getRow() + "," + cell.getColumn() + " uses XF with index " + cell.getXFIndex() + ", but we don't have that"); | |||
int formatIndex = formatListener.getFormatIndex(cell); | |||
String formatString = formatListener.getFormatString(cell); | |||
if(formatString == null) { | |||
return Double.toString(value); | |||
} else { | |||
int formatIndex = xfr.getFormatIndex(); | |||
String format; | |||
if(formatIndex >= HSSFDataFormat.getNumberOfBuiltinBuiltinFormats()) { | |||
FormatRecord tfr = (FormatRecord)customFormatRecords.get(new Integer(formatIndex)); | |||
format = tfr.getFormatString(); | |||
} else { | |||
format = HSSFDataFormat.getBuiltinFormat(xfr.getFormatIndex()); | |||
} | |||
// Is it a date? | |||
if(HSSFDateUtil.isADateFormat(formatIndex,format) && | |||
if(HSSFDateUtil.isADateFormat(formatIndex,formatString) && | |||
HSSFDateUtil.isValidExcelDate(value)) { | |||
// Java wants M not m for month | |||
format = format.replace('m','M'); | |||
formatString = formatString.replace('m','M'); | |||
// Change \- into -, if it's there | |||
format = format.replaceAll("\\\\-","-"); | |||
formatString = formatString.replaceAll("\\\\-","-"); | |||
// Format as a date | |||
Date d = HSSFDateUtil.getJavaDate(value, false); | |||
DateFormat df = new SimpleDateFormat(format); | |||
DateFormat df = new SimpleDateFormat(formatString); | |||
return df.format(d); | |||
} else { | |||
if(format == "General") { | |||
if(formatString == "General") { | |||
// Some sort of wierd default | |||
return Double.toString(value); | |||
} | |||
// Format as a number | |||
DecimalFormat df = new DecimalFormat(format); | |||
DecimalFormat df = new DecimalFormat(formatString); | |||
return df.format(value); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
/* ==================================================================== | |||
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.hssf.eventusermodel; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.hssf.HSSFTestDataSamples; | |||
import org.apache.poi.hssf.record.Record; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
/** | |||
* Tests for FormatTrackingHSSFListener | |||
*/ | |||
public final class TestFormatTrackingHSSFListener extends TestCase { | |||
private FormatTrackingHSSFListener listener; | |||
public void setUp() { | |||
HSSFRequest req = new HSSFRequest(); | |||
MockHSSFListener mockListen = new MockHSSFListener(); | |||
listener = new FormatTrackingHSSFListener(mockListen); | |||
req.addListenerForAllRecords(listener); | |||
HSSFEventFactory factory = new HSSFEventFactory(); | |||
try { | |||
InputStream is = HSSFTestDataSamples.openSampleFileStream("MissingBits.xls"); | |||
POIFSFileSystem fs = new POIFSFileSystem(is); | |||
factory.processWorkbookEvents(req, fs); | |||
} catch (IOException e) { | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
public void testFormats() throws Exception { | |||
assertEquals("_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)", listener.getFormatString(41)); | |||
assertEquals("_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)", listener.getFormatString(42)); | |||
assertEquals("_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)", listener.getFormatString(43)); | |||
} | |||
private static final class MockHSSFListener implements HSSFListener { | |||
public MockHSSFListener() {} | |||
private final List _records = new ArrayList(); | |||
public void processRecord(Record record) { | |||
_records.add(record); | |||
} | |||
} | |||
} |