POI事件模型处理execl导入功能(只支持07版本的execl)
由于通过new XSSFWorkbook 这种方式导入导致生产环境端口宕机、通过dump文件和javacore文件分析是导入功能导致的。
解决办法:自己通过网上写的工具类,不知道是否存在bug。
package com.yygx.impexptemplate.utils; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.beans.factory.annotation.Autowired;
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; public class ExcelReaderParse extends DefaultHandler { private List<String> rowData = new ArrayList<String>();
private List<String[]> sheetData = new ArrayList<String[]>();
private Map<Integer, Object> map = new HashMap<Integer, Object>();
private String lastContents;
private SharedStringsTable sst;
private boolean nextIsString;
private Integer limit = 0;
// 定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等
private String preRef = null, ref = null;
// 定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
private String maxRef = null;
private int curRow = 0;
private int maxlimit = 0;
private List<String[]> sheetNames ; private int titleRow = 2; public int getSheetRow() {
return titleRow;
} public void setSheetRow(int sheetRow) {
this.titleRow = sheetRow;
} public List<String[]> getSheetNames() {
return sheetNames;
} public void setSheetNames(List<String[]> sheetNames) {
this.sheetNames = sheetNames;
} public Map<Integer, Object> getMap() {
return map;
} public void setMap(Map<Integer, Object> map) {
this.map = map;
} /**
* 读取所有工作簿的入口方法
*
* @param path
* @throws Exception
*/
@Autowired
public void process(InputStream inputStream) {
OPCPackage pkg = null;
InputStream sheet = null;
try {
pkg = OPCPackage.open(inputStream);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable(); XMLReader parser = fetchSheetParser(sst); // Iterator<InputStream> sheets = r.getSheetsData();
SheetIterator sheets = (SheetIterator) r.getSheetsData();
String sheetName = null;
int sheetNum = 0;
while (sheets.hasNext()) {
sheet = sheets.next();
if(sheetNum == 0){
sheetName = sheets.getSheetName();
}
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close(); map.put(sheetNum, this.sheetData);
this.sheetData = new ArrayList<String[]>();
sheetNum++;
curRow = 0;
}
List<String[]> list = new ArrayList<String[]>();
list.add(new String[]{sheetName});
this.setSheetNames(list);
} catch (InvalidFormatException e) {
throw new RuntimeException(e.getMessage());
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
} catch (OpenXML4JException e) {
throw new RuntimeException(e.getMessage());
} catch (SAXException e) {
throw new RuntimeException(e.getMessage());
} finally {
try {
pkg.close();
sheet.close();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e.getMessage());
}
}
} /**
* 读取第一个工作簿的入口方法
*
* @param path
* @throws RuntimeException
*/
private void readOneSheet(String path) throws RuntimeException {
// TODO Auto-generated method stub
OPCPackage pkg = null;
InputStream sheet = null;
try {
pkg = OPCPackage.open(path);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
sheet = r.getSheet("rId1");
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
map.put(0, this.sheetData);
this.sheetData.clear();
} catch (InvalidFormatException e) {
throw new RuntimeException(e.getMessage());
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
} catch (OpenXML4JException e) {
throw new RuntimeException(e.getMessage());
} catch (SAXException e) {
throw new RuntimeException(e.getMessage());
} finally {
try {
pkg.close();
sheet.close();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e.getMessage());
}
}
} private XMLReader fetchSheetParser(SharedStringsTable sst)
throws RuntimeException {
// TODO Auto-generated method stub
XMLReader parser;
try {
parser = XMLReaderFactory
.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
return parser;
} catch (SAXException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e.getMessage());
} } public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => 单元格
if (name.equals("c")) {
// 前一个单元格的位置
if (preRef == null) {
preRef = attributes.getValue("r");
} else {
preRef = ref;
}
// 当前单元格的位置
ref = attributes.getValue("r"); // 如果下一个元素是 SST 的索引,则将nextIsString标记为true
String cellType = attributes.getValue("t");
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// 置空
lastContents = "";
} 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();
nextIsString = false;
} catch (Exception e) {
e.printStackTrace();
}
} // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
if (name.equals("v")) {
String value = lastContents.trim();
// if (value.equals("销售与客服支撑")) {
// System.out.println();
// } // 补全单元格之间的空单元格
if (!ref.equals(preRef)) {
int len = countNullCell(ref, preRef);
for (int i = 0; i < len; i++) {
rowData.add(limit, "");
limit++;
}
} else if (ref.equals(preRef) && limit == 0 && !ref.contains("A")) {
int len = letterToNum(ref);
for(int i=0;i<len-1;i++){
rowData.add(limit,"");
limit++;
}
} rowData.add(limit, value);
limit++;
} else if (name.equals("row")) {
// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
// System.out.println(rowData);
if(curRow == titleRow) {
maxlimit = limit;
}else if(curRow == 0) {
maxlimit = limit;
}
if (limit != maxlimit) {
int len = maxlimit - limit;
for (int i = 0; i < len; i++) {
rowData.add(limit, "");
limit++;
}
}
sheetData.add(rowData.toArray(new String[limit]));
rowData.clear();
limit = 0;
curRow++;
preRef = null;
ref = null;
}
} /**
* 计算两个单元格之间的单元格数目(同一行)
*
* @param ref
* @param preRef
* @return
*/
public int countNullCell(String ref, String preRef) {
// excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
String xfd = ref.replaceAll("\\d+", "");
String xfd_1 = preRef.replaceAll("\\d+", ""); xfd = fillChar(xfd, 3, '@', true);
xfd_1 = fillChar(xfd_1, 3, '@', true); char[] letter = xfd.toCharArray();
char[] letter_1 = xfd_1.toCharArray();
int res = (letter[0] - letter_1[0]) * 26 * 26
+ (letter[1] - letter_1[1]) * 26 + (letter[2] - letter_1[2]);
return res - 1;
} /**
* 字符串的填充
*
* @param str
* @param len
* @param let
* @param isPre
* @return
*/
String fillChar(String str, int len, char let, boolean isPre) {
int len_1 = str.length();
if (len_1 < len) {
if (isPre) {
for (int i = 0; i < (len - len_1); i++) {
str = let + str;
}
} else {
for (int i = 0; i < (len - len_1); i++) {
str = str + let;
}
}
}
return str;
} public void characters(char[] ch, int start, int length)
throws SAXException {
// 得到单元格内容的值
lastContents += new String(ch, start, length);
} // 将字母转换成数字
public int letterToNum(String input) { StringBuffer sb = new StringBuffer();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if ((c <= 'z' && c >= 'a') || (c <= 'Z' && c >= 'A')) {
sb.append(c);
}
} StringBuilder builder = new StringBuilder();
for (byte b : sb.toString().toLowerCase().getBytes()) {
builder.append(b - 96);
}
return Integer.valueOf(builder.toString());
}
}
POI事件模型处理execl导入功能(只支持07版本的execl)的更多相关文章
- 让C# Excel导入导出,支持不同版本的Office
问题:最近在项目中遇到,不同客户机安装不同Office版本,在导出Excel时,发生错误. 找不到Excel Com组件,错误信息如下. 未能加载文件或程序集“Microsoft.Office.Int ...
- JXL读取Excel(只支持xls版本)——(二)
注意:jxl是不支持xlsx后缀的excel的.因此建议用POI读取excel. Jar包 同一一样 Java代码 package JXL; import java.io.File; import j ...
- 让C# Excel导入导出,支持不同版本的Office(转)
问题:最近在项目中遇到,不同客户机安装不同Office版本,在导出Excel时,发生错误. 找不到Excel Com组件,错误信息如下. 未能加载文件或程序集“Microsoft.Office.Int ...
- JXL导出Excel(只支持xls版本)——(一)
注意: 导出的后缀是xls可以直接打开,如果导出的后缀是xlsx打开报错,需要手动将名字改为xls才可以打开.也就是JXL不可以导出xlsx的excel. Jar包
- javascript 事件传播与事件冒泡,W3C事件模型
说实话笔者在才工作的时候就听说了什么"事件冒泡",弄了很久才弄个大概,当时理解意思是子级dom元素和父级dom元素都绑定了相同类型的事件,这时如果子级事件触发了父级也会触发,然后这 ...
- [JS学习笔记]浅谈Javascript事件模型
DOM0级事件模型 element.on[type] = function(){} 兼容性:全部支持 lay1 lay2 lay3 e.target:直接触发事件的元素[IE8及以下不支持tage ...
- 同时绑定onpropertychange 和 oninput 事件,实时检测 input、textarea输入改变事件,支持低版本IE,支持复制粘贴
实时检测 input.textarea输入改变事件,支持低版本IE,支持复制粘贴 检测input.textarea输入改变事件有以下几种: 1.onkeyup/onkeydown 捕获用户键盘输入事件 ...
- java中poi解析excel(兼容07版本以上及以下:.xls和.xlsx格式)
package com.genersoft.cbms.ysbz.ExcelDr.cmd; import com.genersoft.cbms.ysbz.ExcelDr.dao.ExcelDrDao; ...
- ExtJS框架基础:事件模型及其常用功能
前言 工作中用ExtJS有一段时间了,Ext丰富的UI组件大大的提高了开发B/S应用的效率.虽然近期工作中天天都用到ExtJS,但很少对ExtJS框架原理性的东西进行过深入学习,这两天花了些时间学习了 ...
随机推荐
- day 69 权限的设置
1.权限控制 1). 表结构的设置 2). 流程 1.登录 get: 通过中间件的白名单 re 获取到登录页面 post: 通过中间件的白名单,认证成功,保存权限信息, --ORM 去空的权限 去重 ...
- [Leetcode 392]判断子序列 Is Subsequence
[思路] 判断s是否为t的子串,所以length(s)<=length(t).于是两个指针,一次循环. 将s.t转换为数组p1.p2. i为过程中s的匹配长度. i=0空串,单独讨论返回true ...
- sass和scss的区别
页面引入的时候还是引入的css文件 因为sass和scss都是一种css的预处理工具 目的最后都是生成css文件 sass不带{}和:是基于Ruby 写出来的,严格的缩进方式来控制 scss带这两个 ...
- intelij idea常用设置
1.genneral设置 2.自动导包 3.设置显示行号和方法分隔符 4.忽略大小写提示代码 比如:输入str会让其提示String 5.去掉单行显示类,让idea多行显示,容易找到类 6.设置字体及 ...
- python笔记1-基础概念、python安装使用配置
Python 1.基础概念 一.什么是python? python是一种面向对象.解释型的计算机语言,它的特点是语法简洁.优雅.简单易学.在1989诞生,Guido(龟叔)开发.这里的python并不 ...
- Effective Java通用设计
将局部变量作用域最小化 将变量一开始就声明在头是十分不明智的选择,局部变量最好是在初始使用的时候才声明,而且尽量给定一个值,好处有三,一是容易读程序,二在对应的语句块使用,可以节省开销,三因为在对应的 ...
- 多点触控 TouchAction
#TouchAction #TouchAction方法是appium自已定义的新方法 # * 短按 (press) * 释放 (release) * 移动到 (moveTo) * 点击 (tap) * ...
- JavaWeb:动作标识
动作标识 一.包含文件标识<jsp:include> 1.介绍 用于向当前页面中包含其他文件.被包含的文件可以是动态文件,也可以是静态文件 2.语法格式 <jsp:include p ...
- 分类算法的R语言实现案例
最近在读<R语言与网站分析>,书中对分类.聚类算法的讲解通俗易懂,和数据挖掘理论一起看的话,有很好的参照效果. 然而,这么好的讲解,作者居然没提供对应的数据集.手痒之余,我自己动手整理了一 ...
- scrapy中自动补全url
url = "https:" + url 或者url = response.urljoin(url) #这里代表的是自动补全url