一、Apache POI
基本介绍
Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。Apache POI 提供Java操作Excel解决方案(适用于Excel97-2008)。
功能结构
- HSSF - 提供读写Microsoft Excel XLS格式档案的功能。 (Excel 03 版本,行数最多 65536行,文件以 .xls 结尾)
- XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。(Excel 07 版本,行数没有限制,文件以 .xlsx 结尾)
- HWPF - 提供读写Microsoft Word DOC格式档案的功能。
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
- HDGF - 提供读Microsoft Visio格式档案的功能。
- HPBF - 提供读Microsoft Publisher格式档案的功能。
- HSMF - 提供读Microsoft Outlook格式档案的功能。
Excel 03 版本写操作
public static final String PATH = "D:\\gitProject\\excel-poi\\";
/**
* 测试 Excel 03 版本写操作
*/
@Test
public void write03versionTest() {
// 1. 创建工作簿
Workbook workbook = new HSSFWorkbook();
// 2. 创建工作表
Sheet sheet = workbook.createSheet("注册用户统计表");
// 3. 创建第一行
Row row = sheet.createRow(0);
// 4. 创建单元格
Cell cell1 = row.createCell(0);
cell1.setCellValue("用户编号");
Cell cell2 = row.createCell(1);
cell2.setCellValue("用户姓名");
Cell time = row.createCell(2);
time.setCellValue("注册时间");
// 5. 创建第二行
Row row1 = sheet.createRow(1);
Cell cell3 = row1.createCell(0);
cell3.setCellValue("001");
Cell cell4 = row1.createCell(1);
cell4.setCellValue("张三");
Cell time1 = row1.createCell(2);
String str1 = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
time1.setCellValue(str1);
try {
// 6. 生成一张表(IO流),03 版本是以 .xls 结尾
FileOutputStream stream = new FileOutputStream(PATH + "注册用户统计表.xls");
// 7. 输出
workbook.write(stream);
// 用try-catch 捕获异常,会自动关闭stream流
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("生成注册用户统计表结束!!!");
}
Excel 07 版本写操作
public static final String PATH = "D:\\gitProject\\excel-poi\\";
/**
* 测试 Excel 07 版本写操作
*/
@Test
public void write07versionTest() {
// 1. 创建工作簿
Workbook workbook = new XSSFWorkbook();
// 2. 创建工作表
Sheet sheet = workbook.createSheet("注册用户统计表");
// 3. 创建第一行
Row row = sheet.createRow(0);
// 4. 创建单元格
Cell cell1 = row.createCell(0);
cell1.setCellValue("用户编号");
Cell cell2 = row.createCell(1);
cell2.setCellValue("用户姓名");
Cell time = row.createCell(2);
time.setCellValue("注册时间");
// 5. 创建第二行
Row row1 = sheet.createRow(1);
Cell cell3 = row1.createCell(0);
cell3.setCellValue("001");
Cell cell4 = row1.createCell(1);
cell4.setCellValue("张三");
Cell time1 = row1.createCell(2);
String str1 = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
time1.setCellValue(str1);
try {
// 6. 生成一张表(IO流),07 版本是以 .xlsx 结尾
FileOutputStream stream = new FileOutputStream(PATH + "注册用户统计表.xlsx");
// 7. 输出
workbook.write(stream);
// 用try-catch 捕获异常,会自动关闭stream流
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("生成注册用户统计表结束!!!");
}
数据批量导入
大文件写HSSF | |
缺点 | 最多只能处理65536行数据,超出会抛异常 |
优点 | 速度快,过程中写入缓存,不操作磁盘,最后一次性写入磁盘 |
大文件写XSSF | |
缺点 | 写数据时速度非常慢,非常耗内存,会发生内存溢出,如100万条数据 |
优点 | 可以写较大的数据量,如20万条数据 |
大文件写SXSSF | |
缺点 | 过程中会产生临时文件,需要清理临时文件 |
优点 | 可以写非常大的数据量,如100万条数据甚至更多,写数据速度非常快,占用内存更少 |
批量导入数据代码 03 版本
/**
* 测试 Excel 03 版本大数据写操作
*/
@Test
public void write03versionBigDataTest() {
long start = System.currentTimeMillis();
// 创建工作簿
Workbook workbook = new HSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet("03版本大数据写入表");
// 创建单元格
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
FileOutputStream stream = null;
try {
// 生成表
stream = new FileOutputStream(PATH + "03版本大数据写入表.xls");
// 写入
workbook.write(stream);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("03版本大数据写入表完成!!!");
System.out.println("耗时时间:{}" + ((double) System.currentTimeMillis() - start) / 1000 + "秒");
}
批量导入数据代码 07 版本
/**
* 测试 Excel 07 版本大数据写操作
*/
@Test
public void write07versionBigDataTest() {
long start = System.currentTimeMillis();
// 创建工作簿
Workbook workbook = new XSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet("07版本大数据写入表");
// 创建单元格
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
FileOutputStream stream = null;
try {
// 生成表
stream = new FileOutputStream(PATH + "07版本大数据写入表.xlsx");
// 写入
workbook.write(stream);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("03版本大数据写入表完成!!!");
System.out.println("耗时时间:{}" + ((double) System.currentTimeMillis() - start) / 1000 + "秒");
}
批量导入数据代码 07 版本升级版本
/**
* 测试 Excel 07 版本升级版大数据写操作
*/
@Test
public void write07SversionBigDataTest() {
long start = System.currentTimeMillis();
// 创建工作簿
Workbook workbook = new SXSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet("07升级版本大数据写入表");
// 创建单元格
for (int rowNum = 0; rowNum < 100000; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
FileOutputStream stream = null;
try {
// 生成表
stream = new FileOutputStream(PATH + "07升级版本大数据写入表.xlsx");
// 写入
workbook.write(stream);
//清除临时文件
((SXSSFWorkbook) workbook).dispose();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("03版本大数据写入表完成!!!");
System.out.println("耗时时间:{}" + ((double) System.currentTimeMillis() - start) / 1000 + "秒");
}
二、easyExcel
官网:null
https://easyexcel.opensource.alibaba.com/docs/current/
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String name;
/**
* 学生性别
*/
@ExcelProperty(value = "学生性别")
private String gender;
/**
* 学生出生日期
*/
@ExcelProperty(value = "学生出生日期")
@DateTimeFormat("yyyy-MM-dd")
private String birthday;
/**
* id
*/
@ExcelIgnore
private String id;
调用EasyExcel的API读取的`Excel`文件的测试类StudentReadDemo
package com.zc.listener;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.zc.pojo.Bill;
import com.zc.pojo.Student;
import java.io.File;
/**
* @Classname StudentReadDemo
* @Description TODO
* @Version 1.0.0
* @Date 2022/7/9 15:01
* @Created by 海贼王
*/
public class StudentReadDemo {
public static final String HOUZHUI = "xlsx";
public static void main(String[] args) throws Exception {
// 获取当前项目路径
String path = System.getProperty("user.dir") + File.separator;
// 获取文件名称
String fileName = path + "票据模板.xlsx";
String substring = fileName.substring(fileName.lastIndexOf(".") + 1);
if (!HOUZHUI.equals(substring)) {
throw new Exception("请使用新票据模板填写");
}
System.out.println(substring);
// 读取文件,读取完之后会自动关闭
/*
pathName 文件路径;"d:\\杭州黑马在线202003班学员信息.xls"
head 每行数据对应的实体;Student.class
readListener 读监听器,每读一样就会调用一次该监听器的invoke方法
sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0
*/
// 封装工作簿对象
ExcelReaderBuilder workBook = EasyExcel.read(fileName, Bill.class, new StudentReadListener());
// 封装工作表
ExcelReaderSheetBuilder sheet1 = workBook.sheet(0);
// 读取
sheet1.doRead();
}
}
读取Excel的监听器,用于处理读取产生的数据
package com.zc.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zc.pojo.Bill;
import com.zc.pojo.Student;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
@Slf4j
public class StudentReadListener extends AnalysisEventListener<Bill> {
// 每读一样,会调用该invoke方法一次
@Override
public void invoke(Bill data, AnalysisContext context) {
System.out.println("data = " + data);
System.out.println("插入数据库成功!");
}
// 全部读完之后,会调用该方法
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO......
}
}