一、基于POI操作EXCEL文件
org.apache.poi
poi
4.1.2
org.apache.poi
poi-ooxml
4.1.2
org.apache.poi
poi-ooxml-schemas
4.1.2
xerces
xercesImpl
2.12.0
EXCEL文件读操作示例如下:
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.*;
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.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.platform.utils.date.DateFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
public class PoiExcelFileReader {
private Logger LOG = LoggerFactory.getLogger(PoiExcelFileReader.class);
enum XssfDataType {
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
}
public static final SimpleDateFormat SDF = DateFormatter.TIME.get();
public static final DecimalFormat DF = new DecimalFormat("0");
public static final int ERROR = 0;
public static final int BOOLEAN = 1;
public static final int NUMBER = 2;
public static final int STRING = 3;
public static final int DATE = 4;
public static final String DATE_FORMAT_STR1 = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT_STR2 = "yyyy/MM/dd HH:mm:ss";
private boolean isExcel2007 = true;
private InputStream inputStream = null;
private InputStream sheetInputStream = null;
private InputSource sheetInputSource = null;
private XMLReader xmlReader = null;
private List rowDataList = new ArrayList();
// 批量处理
private Consumer> consumer = null;
// 批量处理的阀值
private Integer threshold = null;
// 跳过表头的行数
private Integer skipHeadLineCount = 0;
public PoiExcelFileReader(InputStream in, String suffix, Consumer> consumer, int threshold) {
this(in, suffix, consumer, threshold, 0);
}
public PoiExcelFileReader(InputStream in, String suffix, Consumer> consumer, int threshold,
int skipHeadLineCount) {
this.inputStream = in;
this.isExcel2007 = "xls".equals(suffix.toLowerCase()) ? false : true;
this.consumer = consumer;
this.threshold = threshold;
this.skipHeadLineCount = skipHeadLineCount;
}
public void parse() {
if (isExcel2007) {
try {
init(OPCPackage.open(inputStream));
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
parseExcel2007();
} else {
parseExcel2003(inputStream);
}
}
public List getRowDataList() {
return this.rowDataList;
}
/** 初始化将Excel转换为XML */
private void init(OPCPackage pkg) throws IOException, OpenXML4JException, SAXException{
XSSFReader xssfReader = new XSSFReader(pkg);
SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();
StylesTable stylesTable = xssfReader.getStylesTable();
sheetInputStream = xssfReader.getSheet(getSheetId(xssfReader.getWorkbookData()));
sheetInputSource = new InputSource(sheetInputStream);
xmlReader = getXmlReader(sharedStringsTable, stylesTable);
}
private XMLReader getXmlReader(SharedStringsTable sharedStringsTable, StylesTable stylesTable) throws SAXException {
XMLReader xmlReader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
ContentHandler contentHandler = new CustomHandler(sharedStringsTable, stylesTable);
xmlReader.setContentHandler(contentHandler);
return xmlReader;
}
private void parseExcel2007(){
try {
xmlReader.parse(sheetInputSource);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
} finally{
if(sheetInputStream != null){
try {
sheetInputStream.close();
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}
}
}
}
private String getSheetId(InputStream workbookDataInputStream) {
String sheetId = "rId1";
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(workbookDataInputStream));
String line = null;
loop:
while (null != (line = br.readLine())) {
if (line.startsWith(" iterator = rootElement.getChildren().iterator();
while (iterator.hasNext()) {
Element element = iterator.next();
if (!"sheets".equals(element.getName())) continue;
List children = element.getChildren();
for (int i = 0, iLen = children.size(); i < iLen; i++) {
Element subElement = children.get(i);
for (Attribute attribute : subElement.getAttributes()) {
if ("id".equals(attribute.getName())) {
sheetId = attribute.getValue();
break loop;
}
}
}
}
} catch (JDOMException e) {
LOG.error(e.getMessage(), e);
} finally {
try {
if (null != in) in.close();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
}
}
} catch (IOException e) {
LOG.error(e.getMessage(), e);
} finally {
try {
if (null != workbookDataInputStream) workbookDataInputStream.close();
if (null != br) br.close();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
return sheetId;
}
private class CustomHandler extends DefaultHandler {
// 映射字符串
private SharedStringsTable sharedStringsTable = null;
// 单元格样式
private StylesTable stylesTable = null;
// 读取值
private String readValue = null;
// 单元格类型
private XssfDataType dataType = null;
// 一行中数据文本
private String[] rowStrings = null;
// 一行中数据类型
private int[] rowTypes = null;
// 当前行索引
private int rowIndex = 0;
// 当前列索引
private int columnIndex;
private short formatIndex = -1;
private CustomHandler(SharedStringsTable sharedStringsTable,StylesTable stylesTable) {
this.sharedStringsTable = sharedStringsTable;
this.stylesTable = stylesTable;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 单元格
if (qName.equals("c")) {
this.columnIndex = getColumnIndex(attributes);
String cellType = attributes.getValue("t");
String cellStyle = attributes.getValue("s");
this.dataType = XssfDataType.NUMBER;
if ("b".equals(cellType)) {
this.dataType = XssfDataType.BOOL;
} else if ("e".equals(cellType)) {
this.dataType = XssfDataType.ERROR;
} else if ("inlineStr".equals(cellType)) {
this.dataType = XssfDataType.INLINESTR;
} else if ("s".equals(cellType)) {
this.dataType = XssfDataType.SSTINDEX;
} else if ("str".equals(cellType)) {
this.dataType = XssfDataType.FORMULA;
} else if (cellStyle != null) {
int styleIndex = Integer.parseInt(cellStyle);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
this.formatIndex = style.getDataFormat();
}
} else if (qName.equals("row")) {
rowIndex++;
// 获取该行的单元格数 初始化数组
int columnNumber = getColumnNumber(attributes);
this.rowStrings = new String[columnNumber];
this.rowTypes = new int[columnNumber];
}
readValue = "";
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// 单元格的值
if (qName.equals("v")) {
switch (this.dataType) {
case BOOL: {
rowStrings[columnIndex] = readValue.charAt(0) == '0' ? "FALSE" : "TRUE";
rowTypes[columnIndex] = BOOLEAN;
break;
}
case ERROR: {
rowStrings[columnIndex] = "ERROR:" + readValue.toString();
rowTypes[columnIndex] = ERROR;
break;
}
case INLINESTR: {
rowStrings[columnIndex] = new XSSFRichTextString(readValue).getString();
rowTypes[columnIndex] = STRING;
break;
}
case SSTINDEX: {
rowStrings[columnIndex] = sharedStringsTable.getItemAt(Integer.parseInt(readValue)).getString();
rowTypes[columnIndex] = STRING;
break;
}
case FORMULA: {
rowStrings[columnIndex] = readValue;
rowTypes[columnIndex] = STRING;
break;
}
case NUMBER: {
// 判断是否是日期格式
if (formatIndex != -1 && DateUtil.isADateFormat(formatIndex, readValue)) {
Date date = DateUtil.getJavaDate(Double.parseDouble(readValue));
if (null != date) {
rowStrings[columnIndex] = DateFormatUtils.format(date, DATE_FORMAT_STR1);
} else {
rowStrings[columnIndex] = readValue;
}
rowTypes[columnIndex] = DATE;
formatIndex = -1;
} else {
rowStrings[columnIndex] = readValue;
rowTypes[columnIndex] = NUMBER;
}
break;
}
default : break;
}
} else if (qName.equals("row")) {
// 当解析的一行的末尾时输出数组中的数据
if (rowIndex > skipHeadLineCount) {
// 过滤空行
boolean isValid = false;
for (int i = 0, len = rowStrings.length; i < len; i++) {
if (StringUtils.isNotBlank(rowStrings[i])) {
isValid = true;
break;
}
}
if (isValid) {
rowDataList.add(new PoiExcelRow(rowIndex, rowTypes, rowStrings));
if (null != threshold && rowDataList.size() > threshold) {
consumer.accept(rowDataList);
rowDataList.clear();
}
}
}
}
}
/**
* 如果单元格类型是字符串、INLINESTR、数字、日期,readValue则是索引值
* 如果单元格类型是布尔值、错误、公式,readValue则是内容值
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
readValue += new String(ch, start, length);
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
if (rowDataList.size() > 0) {
consumer.accept(rowDataList);
rowDataList.clear();
}
}
private int getColumnIndex(Attributes attributes) {
String attributeValue = attributes.getValue("r");
int columnIndex = -1;
for (int i = 0, len = attributeValue.length(); i < len; ++i) {
if (Character.isDigit(attributeValue.charAt(i))) break;
columnIndex = (columnIndex + 1) * 26 + attributeValue.charAt(i) - 'A';
}
return columnIndex;
}
private int getColumnNumber(Attributes attrubuts){
String spans = attrubuts.getValue("spans");
return StringUtils.isBlank(spans) ? -1 : Integer.parseInt(spans.substring(spans.indexOf(":") + 1));
}
}
private void parseExcel2003(InputStream in) {
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(in);
Sheet sheet = workbook.getSheetAt(0);
int lastCellNum = sheet.getRow(0).getPhysicalNumberOfCells();
for (int i = skipHeadLineCount, iLen = sheet.getLastRowNum(); i <= iLen; i++) {
Row row = sheet.getRow(i);
String[] rowStrings = new String[lastCellNum];
for (int j = 0, jLen = lastCellNum; j < jLen; j++) {
Cell cell = row.getCell(j);
if (null == cell) continue;
Object cellValue = null;
switch (cell.getCellType()) {
case BOOLEAN: cellValue = cell.getBooleanCellValue(); break;
case ERROR: cellValue = cell.getErrorCellValue(); break;
case FORMULA: cellValue = cell.getCellFormula(); break;
case NUMERIC: cellValue = DF.format(cell.getNumericCellValue()); break;
default: cellValue = cell.getStringCellValue(); break;
}
rowStrings[j] = String.valueOf(cellValue);
}
rowDataList.add(new PoiExcelRow(i, null, rowStrings));
if (null != threshold && rowDataList.size() > threshold) {
consumer.accept(rowDataList);
rowDataList.clear();
}
}
if (rowDataList.size() > 0) {
consumer.accept(rowDataList);
rowDataList.clear();
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
} finally {
try {
if (null != in) in.close();
if (null != workbook) workbook.close();
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}
}
}
}
EXCEL文件写操作示例如下:
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.List;
public class PoiExcelFileWriter {
private static Logger LOG = LoggerFactory.getLogger(PoiExcelFileWriter.class);
/**
* 操作Excel2003以前(包括2003)的版本,扩展名是.xls。导出的行数至多为65535行
* */
public static void writeHSSFWorkbook(List headerList, List> resultList, OutputStream outputStream) {
HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
HSSFSheet hssfSheet = hssfWorkbook.createSheet("sheet1");
HSSFRow hssfRow = null;
boolean isBlankHeader = null == headerList || headerList.isEmpty();
if (!isBlankHeader) {
hssfRow = hssfSheet.createRow(0);
for (int i = 0, len = headerList.size(); i < len; i++) {
HSSFCell hssfCell = hssfRow.createCell(i);
hssfCell.setCellValue(headerList.get(i));
}
}
for (int i = 0, iLen = resultList.size(); i < iLen; i++) {
hssfRow = hssfSheet.createRow(isBlankHeader ? i : i + 1);
List
二、基于EASYEXCEL操作EXCEL文件
com.alibaba
easyexcel
2.2.3
EXCEL文件读写操作示例如下:
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EasyExcelFileUtils {
private static Logger LOG = LoggerFactory.getLogger(EasyExcelFileUtils.class);
public static void read(InputStream in, int threshold, List headerFieldList, List
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
public class EventListenerUtils {
/**
* 批量监听
* @param
* @param consumer 批量消费
* @param threshold 批量阀值
* @return
*/
public static AnalysisEventListener getListener(Consumer> consumer, int threshold) {
return new AnalysisEventListener() {
private List ts = new ArrayList();
@Override
public void invoke(T t, AnalysisContext context) {
ts.add(t);
if (ts.size() == threshold) {
consumer.accept(ts);
ts.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (ts.size() > 0) {
consumer.accept(ts);
ts.clear();
}
}
};
}
/**
* 批量监听
* @param
* @param headConsumer 表头消费
* @param consumer 批量消费
* @param threshold 批量阀值
* @return
*/
public static AnalysisEventListener getListener(Consumer headConsumer, Consumer> consumer, int threshold) {
return new AnalysisEventListener() {
private List ts = new ArrayList();
@Override
public void invoke(T t, AnalysisContext context) {
if (context.readRowHolder().getRowIndex() == 0) {
headConsumer.accept(t);
} else {
ts.add(t);
if (ts.size() == threshold) {
consumer.accept(ts);
ts.clear();
}
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (ts.size() > 0) {
consumer.accept(ts);
ts.clear();
}
}
};
}
/**
* 限制数量的监听
* @param
* @param headConsumer 表头消费
* @param consumer 消费
* @param threshold 限制阀值
* @return
*/
public static AnalysisEventListener getLimitListener(Consumer headConsumer, Consumer> consumer, int threshold) {
return new AnalysisEventListener() {
private List ts = new ArrayList();
@Override
public void invoke(T t, AnalysisContext context) {
if (context.readRowHolder().getRowIndex() == 0) {
headConsumer.accept(t);
} else {
if (ts.size() < threshold) {
ts.add(t);
}
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (ts.size() > 0) {
consumer.accept(ts);
ts.clear();
}
}
};
}
}