POI、EasyExcel操作Excel
2022-01-10 本文已影响0人
WebGiser
项目结构
image.pngpom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.geovis</groupId>
<artifactId>excel-util</artifactId>
<version>1.0-SNAPSHOT</version>
<name>excel-util</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- easyexcel内部已经包含了poi依赖,不能同时引入 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<!--
<!– poi-xsl 03版 –>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.1.0</version>
</dependency>
<!– poi-xsl 07版 –>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.1.0</version>
</dependency>
-->
<!-- joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
</dependencies>
</project>
EasyExcel
EasyExcel 读取 Excel
DemoData2.java
package com.geovis.easyExcel;
import lombok.Data;
import java.util.Date;
@Data
public class DemoData2 {
private String string;
private Date date;
private Double doubleData;
}
DemoDAO.java
package com.geovis.easyExcel;
import java.util.List;
/**
* 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
**/
public class DemoDAO {
public void save(List<DemoData2> list) {
// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
}
}
DemoData2Listener.java
package com.geovis.easyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoData2Listener extends AnalysisEventListener<DemoData2> {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoData2Listener.class);
// 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
private static final int BATCH_COUNT = 5;
List<DemoData2> list = new ArrayList<DemoData2>();
// 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
private DemoDAO demoDAO;
public DemoData2Listener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
demoDAO = new DemoDAO();
}
public DemoData2Listener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
/**
* 这个每一条数据解析都会来调用
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(DemoData2 data, AnalysisContext context) {
System.out.println(JSON.toJSONString(data));
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
demoDAO.save(list);
LOGGER.info("存储数据库成功!");
}
}
EasyExcelRead.java
package com.geovis.easyExcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
public class EasyExcelRead {
public static void main(String[] args) {
String fileName = "D:/temp/easy.xlsx";
EasyExcel.read(fileName, DemoData2.class, new DemoData2Listener()).sheet().doRead();
// ExcelReader excelReader = EasyExcel.read(fileName, DemoData2.class, new DemoData2Listener()).build();
// ReadSheet readSheet = EasyExcel.readSheet(0).build();
// excelReader.read(readSheet);
// excelReader.finish();
}
}
EasyExcel 写入 Excel
DemoData.java
package com.geovis.easyExcel;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class DemoData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
/**
* 忽略这个字段
*/
@ExcelIgnore
private String ignore;
}
EasyExcelWrite.java
package com.geovis.easyExcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyExcelWrite {
public static void main(String[] args) {
// 创建示例数据
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
String fileName = "D:/temp/easy.xlsx";
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(list);
// ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// excelWriter.write(list, writeSheet);
// excelWriter.finish();
}
}
POI
POI 03版 读取 Excel
PoiExcelRead03.java
package com.geovis.poi;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileInputStream;
// poi读取03版excel
public class PoiExcelRead03 {
static String path = "D:/temp/poi-03.xls";
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream(path);
Workbook workbook = new HSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
System.out.println(cell.getStringCellValue());
fis.close();
}
}
POI 03版 读取大数据量的 Excel
PoiExcelWriteBigData03.java
package com.geovis.poi;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import java.io.FileOutputStream;
// poi写入03版excel,最多只能处理65536行,否则会抛出异常
public class PoiExcelWriteBigData03 {
static String path = "D:/temp";
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("员工统计表");
for (int i = 0; i < 65536; i++) {
Row row = sheet.createRow(i);
for (int j = 0; j < 10; j++) {
Cell cell = row.createCell(j);
cell.setCellValue(i+","+j);
}
}
// 生成文件
FileOutputStream fos = new FileOutputStream(path + "/poi-bigdata-03.xls");
workbook.write(fos);
fos.close();
System.out.println("文件生成完毕!");
long end = System.currentTimeMillis();
System.out.println((double)(end-start)/1000);
}
}
POI 03版 写入 Excel
PoiExcelWrite03.java
package com.geovis.poi;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import java.io.FileOutputStream;
// poi写入03版excel,最多只能处理65536行,否则会抛出异常
public class PoiExcelWrite03 {
static String path = "D:/temp";
public static void main(String[] args) throws Exception {
// 1、创建一个工作簿
Workbook workbook = new HSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet("员工统计表");
// 3、创建一个行
Row row1 = sheet.createRow(0);
// 4、创建一个单元格
Cell cell11 = row1.createCell(0);
cell11.setCellValue("名字");
Cell cell12 = row1.createCell(1);
cell12.setCellValue("年龄");
Cell cell13 = row1.createCell(2);
cell13.setCellValue("生日");
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("张三");
Cell cell22 = row2.createCell(1);
cell22.setCellValue(20);
Cell cell23 = row2.createCell(2);
cell23.setCellValue(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
// 第二行
Row row3 = sheet.createRow(2);
Cell cell31 = row3.createCell(0);
cell31.setCellValue("李四");
Cell cell32 = row3.createCell(1);
cell32.setCellValue(30);
Cell cell33 = row3.createCell(2);
cell33.setCellValue(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
// 生成文件
FileOutputStream fos = new FileOutputStream(path + "/poi-03.xls");
workbook.write(fos);
fos.close();
System.out.println("文件生成完毕!");
}
}
POI 07版 读取 Excel
PoiExcelRead07.java
package com.geovis.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
// poi读取07版excel
public class PoiExcelRead07 {
static String path = "D:/temp/poi-07.xlsx";
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream(path);
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
System.out.println(cell.getStringCellValue());
fis.close();
}
}
POI 07版读取完整的 Excel
ReadExcel07.java
package com.geovis.poi;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import java.io.FileInputStream;
import java.util.Date;
// poi完整读取07版excel
public class ReadExcel07 {
static String path = "D:/temp/test.xlsx";
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream(path);
Workbook workbook = new XSSFWorkbook(fis);
// 读取title表头
Sheet sheet = workbook.getSheetAt(0);
Row rowTitle = sheet.getRow(0);
int cellNum = rowTitle.getPhysicalNumberOfCells();
for (int i = 0; i < cellNum; i++) {
Cell cell = rowTitle.getCell(i);
if(cell != null){
String cellValue = cell.getStringCellValue();
System.out.print(cellValue + " | ");
}
}
System.out.println();
// 读取数据内容
int rowNum = sheet.getPhysicalNumberOfRows();
for (int i = 1; i < rowNum; i++) {
Row row = sheet.getRow(i);
if (row != null) {
for (int j = 0; j < cellNum; j++) {
Cell cell = row.getCell(j);
if(cell != null){
CellType cellType = cell.getCellType();
String cellVal = "";
switch (cellType){
// 字符串
case STRING:
System.out.print("[字符串]");
cellVal = cell.getStringCellValue();
break;
// 布尔
case BOOLEAN:
System.out.print("[布尔]");
cellVal = String.valueOf(cell.getBooleanCellValue());
break;
// 数值
case NUMERIC:
System.out.print("[数值]");
if(HSSFDateUtil.isCellDateFormatted(cell)){
// 日期
System.out.print("[日期]");
Date date = cell.getDateCellValue();
cellVal = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");
}else{
// 数字
System.out.print("[数字]");
cellVal = String.valueOf(cell.getNumericCellValue());
}
break;
// 空
case BLANK:
System.out.print("[空]");
break;
// 公式
case FORMULA:
System.out.print("[公式]");
XSSFFormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
String formula = cell.getCellFormula();
System.out.println("公式为:"+formula);
CellValue value = formulaEvaluator.evaluate(cell);
cellVal = value.formatAsString();
break;
// 错误
case ERROR:
System.out.print("[错误]");
break;
}
System.out.println(cellVal);
}
}
}
System.out.println("********************************");
}
fis.close();
}
}
POI 07版写入 Excel
PoiExcelWrite07.java
package com.geovis.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import java.io.FileOutputStream;
// poi写入07版excel,数据量大时,可能内存溢出
public class PoiExcelWrite07 {
static String path = "D:/temp";
public static void main(String[] args) throws Exception {
// 1、创建一个工作簿
Workbook workbook = new XSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet("员工统计表");
// 3、创建一个行
Row row1 = sheet.createRow(0);
// 4、创建一个单元格
Cell cell11 = row1.createCell(0);
cell11.setCellValue("名字");
Cell cell12 = row1.createCell(1);
cell12.setCellValue("年龄");
Cell cell13 = row1.createCell(2);
cell13.setCellValue("生日");
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("张三");
Cell cell22 = row2.createCell(1);
cell22.setCellValue(20);
Cell cell23 = row2.createCell(2);
cell23.setCellValue(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
// 第二行
Row row3 = sheet.createRow(2);
Cell cell31 = row3.createCell(0);
cell31.setCellValue("李四");
Cell cell32 = row3.createCell(1);
cell32.setCellValue(30);
Cell cell33 = row3.createCell(2);
cell33.setCellValue(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
// 生成文件
FileOutputStream fos = new FileOutputStream(path + "/poi-07.xlsx");
workbook.write(fos);
fos.close();
System.out.println("文件生成完毕!");
}
}
POI 07版写入大数据量的 Excel
PoiExcelWriteBigData07.java
package com.geovis.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
// poi写入07版excel,耗时较长。数据量大时,可能内存溢出
public class PoiExcelWriteBigData07 {
static String path = "D:/temp";
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("员工统计表");
for (int i = 0; i < 100000; i++) {
Row row = sheet.createRow(i);
for (int j = 0; j < 10; j++) {
Cell cell = row.createCell(j);
cell.setCellValue(i+","+j);
}
}
// 生成文件
FileOutputStream fos = new FileOutputStream(path + "/poi-bigdata-07.xlsx");
workbook.write(fos);
fos.close();
System.out.println("文件生成完毕!");
long end = System.currentTimeMillis();
System.out.println((double)(end-start)/1000);
}
}
POI 07版写入大数据量的 Excel(优化)
PoiExcelWriteBigDataS07.java
package com.geovis.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
// 使用 SXSSFWorkbook 代替 XSSFWorkbook,会加快速度
// SXSSFWorkbook 默认每次读取100万行数据到内存中
public class PoiExcelWriteBigDataS07 {
static String path = "D:/temp";
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
Workbook workbook = new SXSSFWorkbook();
Sheet sheet = workbook.createSheet("员工统计表");
for (int i = 0; i < 100000; i++) {
Row row = sheet.createRow(i);
for (int j = 0; j < 10; j++) {
Cell cell = row.createCell(j);
cell.setCellValue(i+","+j);
}
}
// 生成文件
FileOutputStream fos = new FileOutputStream(path + "/poi-bigdatas-07.xlsx");
workbook.write(fos);
fos.close();
// 清除临时文件
((SXSSFWorkbook)workbook).dispose();
System.out.println("文件生成完毕!");
long end = System.currentTimeMillis();
System.out.println((double)(end-start)/1000);
}
}