初识poi和easyExcel
1. 聊聊POI和EasyExcel
2. Excel基本写操作
- 导入依赖
org.apache.poi
poi
3.10-FINAL
org.apache.poi
poi-ooxml
3.10-FINAL
junit
junit
4.12
joda-time
joda-time
2.10.5
ExcelWriteTest.java
package top.gujiakai;
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.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelWriteTest {
String PATH="D:\\project\\Java\\Excel\\Kai-poi";
@Test
public void testWrite03() throws IOException {
//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("我爱你");
//第二行
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);
//生成一张表(IOl流) 03版本就是使用xls结尾!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "蔡伟粉丝统计03.xls");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("蔡伟粉丝统计表03 生成完毕!");
}
@Test
public void testWrite07() throws IOException {
//1.创建一个工作簿
XSSFWorkbook 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("我不爱你");
//第二行
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);
//生成一张表(IOl流) 07版本就是使用xlsx结尾!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "蔡伟粉丝统计07.xlsx");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("蔡伟粉丝统计表07 生成完毕!");
}
}
3. 大数据量的写入
ExcelWriteTest.java
package top.gujiakai;
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.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelWriteTest {
String PATH="D:\\project\\Java\\Excel\\Kai-poi";
@Test
public void testWrite03() throws IOException {
//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("我爱你");
//第二行
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);
//生成一张表(IOl流) 03版本就是使用xls结尾!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "蔡伟粉丝统计03.xls");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("蔡伟粉丝统计表03 生成完毕!");
}
@Test
public void testWrite07() throws IOException {
//1.创建一个工作簿
XSSFWorkbook 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("我不爱你");
//第二行
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);
//生成一张表(IOl流) 07版本就是使用xlsx结尾!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "蔡伟粉丝统计07.xlsx");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("蔡伟粉丝统计表07 生成完毕!");
}
@Test
public void testWrite03BigData() throws IOException {
//开始时间
long begin=System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet();
//写入数据
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);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "testWrite03BigData.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
//结束事件
long end=System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
//耗时较长,缓存
@Test
public void testWrite07BigData() throws IOException {
//开始时间
long begin=System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new XSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet();
//写入数据
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 + "testWrite07BigData.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
//结束事件
long end=System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
@Test
public void testWrite07BigDataS() throws IOException {
//开始时间
long begin=System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new SXSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet();
//写入数据
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 + "testWrite07BigDataS.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
//清除临时文件
((SXSSFWorkbook) workbook).dispose();
//结束事件
long end=System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
}
4. Excel基本读取及注意
ExcelReadTest.java
package top.gujiakai;
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.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExcelReadTest{
String PATH="D:\\project\\Java\\Excel\\";
@Test
public void testRead03() throws IOException {
//1.获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "Kai-poi蔡伟粉丝统计03.xls");
//2.获取工作簿
Workbook workbook = new HSSFWorkbook(fileInputStream);
//3.获取表
Sheet sheet = workbook.getSheetAt(0);
//4.得到行
Row row = sheet.getRow(0);
//5.得到列
Cell cell = row.getCell(1);
//读取值的时候,要注意类型!
System.out.println(cell.getStringCellValue());
fileInputStream.close();
}
@Test
public void testRead07() throws IOException {
//1.获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "Kai-poi蔡伟粉丝统计07.xlsx");
//2.获取工作簿
Workbook workbook = new XSSFWorkbook(fileInputStream);
//3.获取表
Sheet sheet = workbook.getSheetAt(0);
//4.得到行
Row row = sheet.getRow(0);
//5.得到列
Cell cell = row.getCell(1);
//读取值的时候,要注意类型!
System.out.println(cell.getStringCellValue());
fileInputStream.close();
}
}
5. 难点-读取不同类型的数据
ExcelReadTest.java
package top.gujiakai;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelReadTest {
String PATH = "D:\\project\\Java\\Excel\\";
@Test
public void testRead03() throws IOException {
//1.获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "Kai-poi蔡伟粉丝统计03.xls");
//2.获取工作簿
Workbook workbook = new HSSFWorkbook(fileInputStream);
//3.获取表
Sheet sheet = workbook.getSheetAt(0);
//4.得到行
Row row = sheet.getRow(0);
//5.得到列
Cell cell = row.getCell(1);
//读取值的时候,要注意类型!
System.out.println(cell.getStringCellValue());
fileInputStream.close();
}
@Test
public void testRead07() throws IOException {
//1.获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "Kai-poi蔡伟粉丝统计07.xlsx");
//2.获取工作簿
Workbook workbook = new XSSFWorkbook(fileInputStream);
//3.获取表
Sheet sheet = workbook.getSheetAt(0);
//4.得到行
Row row = sheet.getRow(0);
//5.得到列
Cell cell = row.getCell(1);
//读取值的时候,要注意类型!
System.out.println(cell.getStringCellValue());
fileInputStream.close();
}
@Test
public void testCellType() throws IOException {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "明细表.xls");
//获取一个工作簿
Workbook workbook = new HSSFWorkbook(fileInputStream);
Sheet sheet = workbook.getSheetAt(0);
//获取标题内容
Row rowTitle = sheet.getRow(0);
if (rowTitle != null) {
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
Cell cell = rowTitle.getCell(cellNum);
if (cell != null) {
CellType cellType = cell.getCellType();
String cellValue = cell.getStringCellValue();
System.out.print(cellValue + " | ");
}
}
System.out.println();
}
//...读取值的时候,一定要注意类型。
}
}
6. 了解-计算公式
@Test
public void testFormula() throws IOException {
FileInputStream fileInputStream = new FileInputStream(PATH + "公式.xlsx");
Workbook workbook = new XSSFWorkbook(fileInputStream);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(4);
Cell cell = row.getCell(0);
//拿到计算公式
XSSFFormulaEvaluator FormulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
//输出单元格的内容
CellType cellType = cell.getCellType();
// switch(cellType){
// case Cell.CELL_:
// }
String cellFormula = cell.getCellFormula();
System.out.println(cellFormula);
//计算
CellValue evaluate = FormulaEvaluator.evaluate(cell);
String s = evaluate.formatAsString();
System.out.println(s);
}
7. EasyExcel使用
- 导入依赖
com.alibaba
easyexcel
3.0.1
DemoData.java
package easy;
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;
}
EasyTest.java
package easy;
import com.alibaba.excel.EasyExcel;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyTest {
String PATH="D:\\project\\Java\\Excel\\Kai-poi";
private List data() {
List list = new ArrayList();
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);
}
return list;
}
//根据list,写入Excel。
@Test
public void simpleWrite() {
String fileName = PATH+"EasyTest.xlsx";
// 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
//write(fileName,格式类)
//sheet(声明)
//doWrite(数据)
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}
/**
* 最简单的读
* 1. 创建excel对应的实体对象 参照{@link DemoData}
*
2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
*
3. 直接读即可
*/
@Test
public void simpleRead() {
String fileName = PATH+"EasyTest.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}
}
DemoDAO.java
package easy;
import java.util.List;
/**
* 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
**/
public class DemoDAO {
public void save(List list) {
//持久化操作
// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
}
}
DemoDataListener.java
package easy;
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 DemoDataListener extends AnalysisEventListener {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 3000;
/**
* 缓存的数据
*/
private List list = new ArrayList<>(BATCH_COUNT);
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
private DemoDAO demoDAO;
public DemoDataListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
demoDAO = new DemoDAO();
}
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param demoDAO
*/
public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
//读取数据会执行invoke方法
//DemoData类型
//AnalysisContext分析器
@Override
public void invoke(DemoData data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
System.out.println(JSON.toJSONString(data));
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list = new ArrayList<>(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
demoDAO.save(list);
LOGGER.info("存储数据库成功!");
}
}