excel2007是通过sax解析xml来做的,这种方法支持度的数据量比较大,没内存溢出问题,现在有个问题,就是,如果某个<c>标签没有<v>子标签的话,解析出来的某一行的数据就会错列,有什么解决方法吗?row r="1" x14ac:dyDescent="0.2" thickBot="1" ht="14.25" spans="1:8"><c r="A1" t="s" s="12"><v>0</v></c><c r="B1" t="s" s="13"><v>1</v></c><c r="C1" t="s" s="13"><v>2</v></c><c r="D1" t="s" s="13"><v>3</v></c><c r="E1" t="s" s="13"><v>4</v></c><c r="F1" t="s" s="13"><v>5</v></c><c r="G1" t="s" s="13"><v>6</v></c></row>public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser = XMLReaderFactory
.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
return parser;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => 单元格
if (name.equals("c")) {
// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
String cellType = attributes.getValue("t");
curCell = attributes.getValue("r");
while(!curCell.equals(nextCell)){
generateNextCell();
rowlist.add("");
}
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}else if("row".equals(name)){
row = Integer.parseInt( attributes.getValue("r"));
}
// 置空
lastContents = "";
}
//生成下一列的坐标 ,但使用起来没用
private void generateNextCell() {
int length = curCell.length();
if(length == 2){
char c = (char) (nextCell.charAt(0));
if(c == 'Z'){
nextCell = "AA" +row;
}else{
nextCell = (char)(c+1)+"" + row ;
}
}
if(length>=3){
char pc = nextCell.charAt(0);
char c = (char) (nextCell.charAt(1));
if(c <= 'Z' && c >= 'A'){
if(c == 'Z'){
nextCell = (char)(pc + 1)+""+'A'+""+row;
}else{
nextCell = pc+""+(char)(c+1)+"" + row;
}
}else{
if(pc == 'Z'){
nextCell = "AA" + row;
}else{
nextCell = (char)(pc + 1) + "" + row;
}
}
}
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
if (nextIsString) {
try {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
.toString();
} catch (Exception e) {
}
}
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
if (name.equals("v")) {
String value = lastContents.trim();
if(value != null && value.contains("'")){
value = value.replace("'", "");
}
// value = value==null || value.equals("") ? " " : value;
rowlist.add(value);
//curCol++;
}else if("c".equals(name)){
generateNextCell();
} else {
// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row")) {
optRow(sheetIndex, curRow, rowlist);
rowlist.clear();
curRow++;
curCol = 0;
nextCell = 'A'+""+(row+1);
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
// 得到单元格内容的值
lastContents += new String(ch, start, length);
}
XMLReader parser = XMLReaderFactory
.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
return parser;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => 单元格
if (name.equals("c")) {
// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
String cellType = attributes.getValue("t");
curCell = attributes.getValue("r");
while(!curCell.equals(nextCell)){
generateNextCell();
rowlist.add("");
}
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}else if("row".equals(name)){
row = Integer.parseInt( attributes.getValue("r"));
}
// 置空
lastContents = "";
}
//生成下一列的坐标 ,但使用起来没用
private void generateNextCell() {
int length = curCell.length();
if(length == 2){
char c = (char) (nextCell.charAt(0));
if(c == 'Z'){
nextCell = "AA" +row;
}else{
nextCell = (char)(c+1)+"" + row ;
}
}
if(length>=3){
char pc = nextCell.charAt(0);
char c = (char) (nextCell.charAt(1));
if(c <= 'Z' && c >= 'A'){
if(c == 'Z'){
nextCell = (char)(pc + 1)+""+'A'+""+row;
}else{
nextCell = pc+""+(char)(c+1)+"" + row;
}
}else{
if(pc == 'Z'){
nextCell = "AA" + row;
}else{
nextCell = (char)(pc + 1) + "" + row;
}
}
}
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
if (nextIsString) {
try {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
.toString();
} catch (Exception e) {
}
}
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
if (name.equals("v")) {
String value = lastContents.trim();
if(value != null && value.contains("'")){
value = value.replace("'", "");
}
// value = value==null || value.equals("") ? " " : value;
rowlist.add(value);
//curCol++;
}else if("c".equals(name)){
generateNextCell();
} else {
// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row")) {
optRow(sheetIndex, curRow, rowlist);
rowlist.clear();
curRow++;
curCol = 0;
nextCell = 'A'+""+(row+1);
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
// 得到单元格内容的值
lastContents += new String(ch, start, length);
}
解决方案 »
- 在项目中如何用junit写单元测试用例?
- struts2 xml中 执行一个action里的多个action方法?
- null !=str 和 str !=null 两者有什么区别?
- tomcat配置,显示jsp页面列表
- tomcat热部署
- FCKeditor使用问题!!!!
- 两个java web项目的通信
- 我的怎么不行?有j2ee这个应用程序?
- Hibernate中@ManyToOne与@OneToMany注解查询结果用gson序列化出现循环引用问题
- 【求助】MyBatis使用连接查询语句报错
- mybaits 连接sql sever 2008数据库问题,sa用户用studio可以登录,但是用程序里面去无法连接
- 下面这段代码不知可不可行?
用POI库吧。
http://www.apache.org/dyn/closer.cgi/poi/release/bin/poi-bin-3.8-20120326.zip例子。
http://zcw-java.iteye.com/blog/1405682
http://blog.csdn.net/huangli2009/article/details/6333812