目前操作 Excel 比较流行的就是 Apache POI 和阿里巴巴的 easyExcel。
Apache POI 是用 Java 编写的免费开源的跨平台的 Java API,Apache POI 提供 API 给 Java 程序对 Microsoft Office 格式文档读和写的常用功能。POI 为 “Poor Obfuscation Implementation” 的首字母缩写,意为“简洁版的模糊实现”。其常用的结构如下:
HSSF -- 提供读写 03 版本的 Excel 常用功能。
XSSF -- 提供读写 07 版本的 Excel 常用功能。
HWPF -- 提供读写 Word 格式的常用功能
HSLF -- 提供读写 ppt 格式的常用功能。
HDGF -- 提供读写 visio 格式的常用功能
easyExcel 是阿里巴巴开源的一个 excel 处理框架,以使用简单、节省内存著称。easyExcel 能大大减少占用内存的主要原因是在解析 Excel 时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
easyExcel 官网地址:https://github.com/alibaba/easyexcel
常用的 excel 文档有两种结尾形式,分别为 xls 和 xlsx,其中以 xls 结尾的文档属于 03 版本的,它里面最多可以存储 65536 行数据。而以 xlsx 结尾的文档属于 07 版本的,它理论上可以存储无限行数据,这就是两者之前的区别。
org.apache.poi
poi
3.9
org.apache.poi
poi-ooxml
3.9
joda-time
joda-time
2.10.1
junit
junit
4.12
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 org.junit.Test;
import java.io.FileOutputStream;
public class ExcelWriteTest {
String PATH ="F:\\idea_home\\poi-excel\\";
@Test
public void testWrite03() throws Exception {
// 1、创建一个工作簿
Workbook workbook = new HSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet("我是 sheet1 页");
// 3、创建一行
Row row1 = sheet.createRow(0);
// 4、创建一个单元格
Cell cell11 = row1.createCell(0);
cell11.setCellValue("我是第一行第一个单元格");
Cell cell12 = row1.createCell(1);
cell12.setCellValue("我是第一行第二个单元格");
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("我是第二行第一个单元格");
Cell cell22 = row2.createCell(1);
String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
// 03 版本的使用 xls 结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"统计表03类型.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("Excel03 写入完成了");
}
}
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 org.junit.Test;
import java.io.FileOutputStream;
public class ExcelWriteTest {
String PATH ="F:\\idea_home\\poi-excel\\";
@Test
public void testWrite07() throws Exception {
// 1、创建一个工作簿
Workbook workbook = new XSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet("我是 sheet1 页");
// 3、创建一行
Row row1 = sheet.createRow(0);
// 4、创建一个单元格
Cell cell11 = row1.createCell(0);
cell11.setCellValue("我是第一行第一个单元格");
Cell cell12 = row1.createCell(1);
cell12.setCellValue("我是第一行第二个单元格");
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("我是第二行第一个单元格");
Cell cell22 = row2.createCell(1);
String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
// 07 版本的使用 xlsx 结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"统计表07类型.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("Excel07 写入完成了");
}
}
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.junit.Test;
import java.io.FileOutputStream;
public class ExcelWriteTest {
String PATH ="F:\\idea_home\\poi-excel\\";
@Test
public void testWrite03BigData() throws Exception {
long begin = System.currentTimeMillis();
// 1、创建一个工作簿
Workbook workbook = new HSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet();
// 3、写入数据
for(int rowNum =0;rowNum<65537;rowNum++){
Row row = sheet.createRow(rowNum);
for(int cellNum=0;cellNum<10;cellNum++){
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"统计表03大数据类型.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
}
缺点:最多只能处理 65536 行,否则会抛出异常。
优点:写入过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快。将 65537 改成65536 再次执行程序,结果如下,可以看到 1.692s 就完成了写入操作,速度还是很快的。
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.junit.Test;
import java.io.FileOutputStream;
public class ExcelWriteTest {
String PATH ="F:\\idea_home\\poi-excel\\";
@Test
public void testWrite07BigData() throws Exception {
long begin = System.currentTimeMillis();
// 1、创建一个工作簿
Workbook workbook = new XSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet();
// 3、写入数据
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);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"统计表07大数据类型.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
}
缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条。
优点:可以写较大的数据量,如20万条。
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 org.junit.Test;
import java.io.FileOutputStream;
public class ExcelWriteTest {
String PATH ="F:\\idea_home\\poi-excel\\";
@Test
public void testWrite07BigDataS() throws Exception {
long begin = System.currentTimeMillis();
// 1、创建一个工作簿
Workbook workbook = new SXSSFWorkbook();
// 2、创建一个工作表
Sheet sheet = workbook.createSheet();
// 3、写入数据
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);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH+"统计表07大数据类型优化.xlsx");
workbook.write(fileOutputStream);
// 清除产生的临时文件
((SXSSFWorkbook)workbook).dispose();
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
}
优点:可以写非常大的数据量,如 100万 条甚至更多条,数据速度快,占用更少的内存。
需要注意的是:代码在过程中会产生临时文件,需要清理临时文件。默认有 100 条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件。如果想自定义内存中数据的数量,可以使用 new SXSSFWorkbook(数量) 。
SXSSFWorkbook 来至官方的解释:实现 “BigGridDemo” 策略的流式 XSSFWorkbook 版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。请注意,仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释……仍然只存储在内存中,因此如果广泛使用,可能需要大量内存。