|
我今天发现代码里面有个这样的问题,就是POI事件解析Excel的时候,空单元格会被忽略,请问下知道的筒子,这种情况怎么处理,注意是事件读取,附代码 package com.its.fedex.msg.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import com.its.fedex.msg.exception.ExcelParseException;
import com.its.fedex.msg.service.IRowHandler;
public class Excel2007Reader extends DefaultHandler
{
/**
* 共享字符串表
*/
private SharedStringsTable sst;
/**
* 上一次的内容
*/
private String lastContents;
/**
* 字符串标识
*/
private boolean nextIsString;
/**
* 工作表索引
*/
private int sheetIndex = -1;
/**
* 行集合
*/
private List<String> rowlist = new ArrayList<String>();
/**
* 当前行
*/
private int curRow = 0;
/**
* 当前列
*/
private int curCol = 0;
/**
* T元素标识
*/
private boolean isTElement;
/**
* Excel数据逻辑处理
*/
private IRowHandler rowHandler;
/**
* 异常信息,如果为空则表示没有异常
*/
private String exceptionMessage;
/**
* 单元格数据类型,默认为字符串类型
*/
private CellDataType nextDataType = CellDataType.SSTINDEX;
private final DataFormatter formatter = new DataFormatter();
private short formatIndex;
private String formatString;
/**
* 单元格
*/
private StylesTable stylesTable;
public void setRowReader(IRowHandler rowHandler)
{
this.rowHandler = rowHandler;
}
/**
* 遍历工作簿中所有的电子表格
*
* @param filename
* @throws IOException
* @throws OpenXML4JException
* @throws SAXException
* @throws Exception
*/
public void process(String filename) throws IOException, OpenXML4JException, SAXException
{
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader xssfReader = new XSSFReader(pkg);
stylesTable = xssfReader.getStylesTable();
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XMLReader parser = this.fetchSheetParser(sst);
Iterator<InputStream> sheets = xssfReader.getSheetsData();
while (sheets.hasNext())
{
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException
{
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
return parser;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
{
// c => 单元格
if ("c".equals(name))
{
// 设定单元格类型
this.setNextDataType(attributes);
}
// 当元素为t时
if ("t".equals(name))
{
isTElement = true;
}
else
{
isTElement = false;
}
// 置空
lastContents = "";
}
/**
* 单元格中的数据可能的数据类型
*/
enum CellDataType
{
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
}
/**
* 处理数据类型
*
* @param attributes
*/
public void setNextDataType(Attributes attributes)
{
nextDataType = CellDataType.NUMBER;
formatIndex = -1;
formatString = null;
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
if ("b".equals(cellType))
{
nextDataType = CellDataType.BOOL;
}
else if ("e".equals(cellType))
{
nextDataType = CellDataType.ERROR;
}
else if ("inlineStr".equals(cellType))
{
nextDataType = CellDataType.INLINESTR;
}
else if ("s".equals(cellType))
{
nextDataType = CellDataType.SSTINDEX;
}
else if ("str".equals(cellType))
{
nextDataType = CellDataType.FORMULA;
}
if (cellStyleStr != null)
{
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
formatIndex = style.getDataFormat();
formatString = style.getDataFormatString();
if ("m/d/yy" == formatString)
{
nextDataType = CellDataType.DATE;
formatString = "yyyy-MM-dd hh:mm:ss.SSS";
}
if (formatString == null)
{
nextDataType = CellDataType.NULL;
formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
}
}
}
/**
* 对解析出来的数据进行类型处理
*
* @param value
* 单元格的值(这时候是一串数字)
* @param thisStr
* 一个空字符串
* @return
*/
@SuppressWarnings("deprecation")
public String getDataValue(String value, String thisStr)
{
switch (nextDataType)
{
// 这几个的顺序不能随便交换,交换了很可能会导致数据错误
case BOOL:
char first = value.charAt(0);
thisStr = first == ""0"" ? "FALSE" : "TRUE";
break;
case ERROR:
thisStr = ""ERROR:" + value.toString() + """"";
break;
case FORMULA:
thisStr = """"" + value.toString() + """"";
break;
case INLINESTR:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
thisStr = rtsi.toString();
rtsi = null;
break;
case SSTINDEX:
String sstIndex = value.toString();
try
{
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sst.getEntryAt(idx));
thisStr = rtss.toString();
rtss = null;
}
catch (NumberFormatException ex)
{
thisStr = value.toString();
}
break;
case NUMBER:
if (formatString != null)
{
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString)
.trim();
}
else
{
thisStr = value;
}
thisStr = thisStr.replace("_", "").trim();
break;
case DATE:
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);
// 对日期字符串作特殊处理
thisStr = thisStr.replace(" ", "T");
break;
default:
thisStr = " ";
break;
}
return thisStr;
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException
{
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
if (nextIsString)
{
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
}
// t元素也包含字符串
if (isTElement)
{
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
String value = lastContents.trim();
rowlist.add(curCol, value);
curCol++;
isTElement = false;
}
else if ("v".equals(name))
{
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
String value = this.getDataValue(lastContents.trim(), "");
rowlist.add(curCol, value);
curCol++;
}
else
{
// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row"))
{
try
{
rowHandler.getRows(curRow, rowlist);
}
catch (ExcelParseException e)
{
exceptionMessage = e.getMessage();
}
rowlist.clear();
curRow++;
curCol = 0;
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
// 得到单元格内容的值
lastContents += new String(ch, start, length);
}
/**
* @return the exceptionMessage
*/
public String getExceptionMessage()
{
return exceptionMessage;
}
}
|
|
|
#1 |
没人知道啊,擦
|
|
#2 |
100分给我 我告诉你
|
|
20分
#3 |
private List<Map> parseworkbookVoucher(HSSFWorkbook workbook){
//存放凭证主表
List<Map> VoucherList=new ArrayList<Map>();
int columnNum = 0;
Sheet sheet = workbook.getSheetAt(0);
if(sheet.getRow(0)!=null){
columnNum = sheet.getRow(0).getLastCellNum()-sheet.getRow(0).getFirstCellNum();
}
Row rowkey=sheet.getRow(0);
if(columnNum>1){
for (int j = 2; j <= sheet.getLastRowNum(); j++) {
Row row=sheet.getRow(j);
Map<String, Object> Vouchermap =new HashMap<String, Object>();
for(int i=0;i<columnNum;i++){
Cell cell = row.getCell(i, Row.CREATE_NULL_AS_BLANK);
Cell cellkey = rowkey.getCell(i);
switch(cell.getCellType()){
case Cell.CELL_TYPE_BLANK:
Vouchermap.put(cellkey.getStringCellValue().trim(), "");
break;
case Cell.CELL_TYPE_BOOLEAN:
Vouchermap.put(cellkey.getStringCellValue().trim(), "");
break;
case Cell.CELL_TYPE_NUMERIC:
if(DateUtil.isCellDateFormatted(cell)){
//System.out.println("日期:"+cell.getDateCellValue());
Vouchermap.put(cellkey.getStringCellValue().trim(), dateformate(cell.getDateCellValue()));
}else{
cell.setCellType(Cell.CELL_TYPE_STRING);
//System.out.println("*********"+cellkey.getStringCellValue());
//System.out.println("*********"+cell.getStringCellValue());
//DecimalFormat df = new DecimalFormat("###0.00");
Vouchermap.put(cellkey.getStringCellValue().trim(), cell.getStringCellValue());
}
break;
case Cell.CELL_TYPE_STRING:
Vouchermap.put(cellkey.getStringCellValue().trim(), cell.getStringCellValue());
break;
case Cell.CELL_TYPE_ERROR:
Vouchermap.put(cellkey.getStringCellValue().trim(), "");
break;
}
}
//Vouchermap.put("Table", "Co_Relationdetails1");
if(null!=Vouchermap.get("cOrgnID")&&!Vouchermap.get("cOrgnID").equals("")){
VoucherList.add(Vouchermap);
}
}
}
for (int m = 0; m < VoucherList.size(); m++) {
System.out.println(VoucherList.size());
Map map=VoucherList.get(m);
System.out.println("模板数据:"+map);
}
return VoucherList;
}
换一个遍历方式,楼主的遍历可能涉及到一些迭代器,其中可能进行了一些处理,具体细节不太了解 |
|
#4 |
回复楼:
我也很想100分都给你,可是你的做法是基于UserModel解析的,我用的是事件解析,因为数据量比较大,没办法
|
|
#5 |
楼主能否说下事件解析Excel是什么意思?
基于事件?what? |
|
#6 |
回复楼:
Event,就是一个先把Excel弄成DOM树的结构,然后用SAX解析,你那种UserModle的解析方式是另外一种常用的方式,但是碰上数据量比较大的情况,就会内存溢出,参看这个博客http://blog.csdn.net/goodkuang2012/article/details/7350985
|
|
10分
#7 |
单元格是否为空,可以根据
cell.getCellType() == HSSFCell.CELL_TYPE_BLANK 来判断 |
|
#8 |
回复楼:
没有Cell对象
|
|
70分
#9 |
poi好久没用了都忘了,应该是有Cell对象的,poi操作的对象不就是sheet row cell 这样的
|
|
#10 |
回复楼:
那是前面说的UserModel的解析方式,那种方式的确有,操作简便,就是很容易内存溢出
|
|
#11 |
昨天自己解决了,结贴
attributes.getValue(“r”); |
|
#12 |
attributes.getValue(“r”); 在什么地方判断啊? 我也遇到空格的问题了
|
|
#13 |
请问,这个问题怎么解决啊
|
|
#14 |
这个能读excel中的“真空”值吗?
|
|
#15 |
回复11楼: 怎么解决的? |
|
#16 |
回复15楼: 我已解决,有问题问我 |
|
#17 |
DefaultHandle接口里面仔细找下,有一个方法就可以满足你。加油,另外03頒的也支持时间驱动。
|
|
#18 |
回复15楼: 请问这个空单元格问题是怎么解决的啊 |
|
#19 |
attributes.getValue(“r”);
nmb 装 解决就说 孩子啊哪里装nmb 楼主wcnm |
|
#20 |
刚才我调试了一下,attributes.getValue(“r”);是获取单元格的坐标例如A1,B1,D1,把这些跟读取出来的数值绑定一下,哪个没绑定就给他设为一个控制就行了,哈哈
|
|
#21 |
@wujiangqing123
具体如何处理,是否可以的供一下代吗 |