在工作的开发过过程中,我们总会遇到将数据导出到excel的需求,和导入excel到数据库,下面会讲解当今比较流行的两个工具实现Java操作excel:
使用poi会相对比较原生,相较于easyExcel比较复杂(easyExcel读写的时候可以做到一行代码就可以搞定,相当优雅)
针对上图的基本功能的 1 ,2,workbook的实现类有三个接口。其中SXSSFWorkbook操作excel07版XSSF的升级,速度比XSSF更快。具体下面有写。
都入相关依赖
<!--xls 03-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<!--xlsx 07版本-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<!-- 测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
03版本写excel
@Test
public void writeExcel03() throws IOException {
String path = "E:\\excel\\";
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet("sheet01");
//创建行
Row row01 = sheet.createRow(0);//行从0开始,第一行
//创建一个单元格
Cell cell01 = row01.createCell(0);//列也是从0开始
//设置单元格中的内容
cell01.setCellValue("码农");
Cell cell02 = row01.createCell(1);
cell02.setCellValue("IT民工");
FileOutputStream outputStream = new FileOutputStream(path + "码农.xls");
//工作簿通过流写出
workbook.write(outputStream);
outputStream.close();
System.out.println(">>>>>>>>excel 03 write finish");
}
07版本:跟03版本基本一样,只是工作簿的对象不同(03-HSSFWorkbook;07-XSSFWorkbook),和文件后缀的不同
@Test
public void writeExcel07() throws IOException {
String path = "E:\\excel\\";
//创建一个工作簿
Workbook workbook = new XSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet("sheet01");
//创建行
Row row01 = sheet.createRow(0);//行从0开始,第一行
//创建一个单元格
Cell cell01 = row01.createCell(0);//列也是从0开始
//设置单元格中的内容
cell01.setCellValue("码农");
Cell cell02 = row01.createCell(1);
cell02.setCellValue("IT民工");
FileOutputStream outputStream = new FileOutputStream(path + "07码农.xlsx");
//工作簿通过流写出
workbook.write(outputStream);
outputStream.close();
System.out.println(">>>>>>>>excel 07 write finish");
}
下面例子用时 2秒
@Test
public void bigDatawriteExcel03() throws IOException {
String path = "E:\\excel\\";
long beginTime = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet("sheet01");
//创建行
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(j);
}
}
FileOutputStream outputStream = new FileOutputStream(path + "bigData03码农.xls");
//工作簿通过流写出
workbook.write(outputStream);
outputStream.close();
long endTime = System.currentTimeMillis();
System.out.println("用时" + ((endTime-beginTime) / 1000) + " 秒" );
}
下面例子用时 7秒.
虽然它比03的用时长,但是它比03可以写更多的数据,比如超过6553行的数据都可以,而03的超过6553行就会报错
@Test
public void bigDatawriteExcel07() throws IOException {
String path = "E:\\excel\\";
long beginTime = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new XSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet("sheet01");
//创建行
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(j);
}
}
FileOutputStream outputStream = new FileOutputStream(path + "bigData07码农.xlsx");
//工作簿通过流写出
workbook.write(outputStream);
outputStream.close();
long endTime = System.currentTimeMillis();
System.out.println("用时" + ((endTime-beginTime) / 1000) + " 秒" );
}
@Test
public void bigDatawriteExcelS07() throws IOException {
String path = "E:\\excel\\";
long beginTime = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new SXSSFWorkbook();
//创建一个工作表
Sheet sheet = workbook.createSheet("sheet01");
//创建行
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(j);
}
}
FileOutputStream outputStream = new FileOutputStream(path + "bigData07码农S.xlsx");
//工作簿通过流写出
workbook.write(outputStream);
outputStream.close();
long endTime = System.currentTimeMillis();
System.out.println("用时" + ((endTime-beginTime) / 1000) + " 秒" );
}
controller中
package com.qhy.test;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
/**
* @author qiuhongyu
* @date 2022/3/24 14:09
*/
@Api(tags = "数据导出demo")
@RestController
@RequestMapping("/export")
public class ExportExcelController {
@Autowired
private ExportExcelService exportExcelService;
@PostMapping("excelTest")
public void exportExcel() {
ServletRequestAttributes servletRequestAttributes
= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = servletRequestAttributes.getResponse();
exportExcelService.exportExcel(response);
}
}
service中
package com.qhy.test;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
/**
* @author qiuhongyu
* @date 2022/3/24 14:13
*/
@Service
public class ExportExcelService {
@Value("{export_excel_template}")
private String exportExcelTemplate;
public void exportExcel(HttpServletResponse response) {
//获取导出的模板
ClassPathResource classPathResource = new ClassPathResource(exportExcelTemplate);
try (InputStream inputStream = classPathResource.getInputStream();
ServletOutputStream outputStream = response.getOutputStream()) {
//获取工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
//获取工作表
Sheet sheet = workbook.getSheet("sheetTest");
//TODO (从数据库中查出要导出的数据)此处将相关数据写入到excel(在这还可以设置单元格的格式,背景颜色等)
//设置导出的excel的文件名
String excelName = java.net.URLEncoder.encode("demo导出Excel", "UTF-8");
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//如果是xlsx格式的,那么ContenType就设置成下面的这种
// response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + excelName + ".xls");
workbook.write(outputStream);
}catch (Exception e) {
}
}
}
工具类
package com.qhy.test;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
/**
* @author qiuhongyu
* @date 2022/3/24 14:22
*/
public class ExportExcelUtil {
/**
* 获取列
*
* @param row
* @param index
* @return
*/
public static Cell createOrGetCell(Row row, int index) {
Cell cell = row.getCell(index);
if (cell == null) {
cell = row.createCell(index);
}
return cell;
}
/**
* 获取行
*
* @param sheet
* @param index
* @return
*/
public static Row createOrGetRow(Sheet sheet, int index) {
Row row = sheet.getRow(index);
if (row == null) {
row = sheet.createRow(index);
}
return row;
}
/**
* 设置单元格样式-百分比
*
* @param book
* @return
*/
public static CellStyle revertPercent(Workbook book) {
CellStyle style = book.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(book.createDataFormat().getFormat("0.0%"));
return style;
}
/**
* 设置单元格样式-小数
*
* @param book
* @return
*/
public static CellStyle keepPoint(Workbook book) {
CellStyle style = book.createCellStyle();
style.setDataFormat(book.createDataFormat().getFormat("#0.000"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
/**
* 设置单元格样式-整数
*
* @param book
* @return
*/
public static CellStyle keepInteger(Workbook book) {
CellStyle style = book.createCellStyle();
style.setDataFormat(book.createDataFormat().getFormat("###0"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
/**
* 设置单元格样式-字符串,数字科学计数法
*
* @param book
* @return
*/
public static CellStyle strStyle(Workbook book) {
CellStyle style = book.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(book.createDataFormat().getFormat("#,##0"));
return style;
}
/**
* 设置单元格的样式(字体,背景颜色等)
* @param book
* @param red
* @param green
* @param blue
* @param horizontalAlignment
* @param fontName
* @param boldOrNOt
* @param cellStyle
* @return
*/
public static CellStyle cellStyleForntColor(HSSFWorkbook book,
int red,
int green,
int blue,
HorizontalAlignment horizontalAlignment,
String fontName,
Boolean boldOrNOt,
CellStyle cellStyle) {
CellStyle style;
if (cellStyle != null) {
style = cellStyle;
} else {
style = book.createCellStyle();
}
style.setAlignment(horizontalAlignment);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font font = book.createFont();
font.setFontName(fontName);
font.setFontHeightInPoints((short) 10);
font.setBold(boldOrNOt);
style.setFont(font);
HSSFPalette palette = book.getCustomPalette();
// String color = "#C9DBFF";
// String r = color.substring(1, 3);
// String g = color.substring(3, 5);
// String b = color.substring(5, 7);
// int rc = Integer.parseInt(r, 16);
// int gc = Integer.parseInt(g, 16);
// int bc = Integer.parseInt(b, 16);
// HSSFColor hssfColor = palette.findSimilarColor(201, 219, 255);
HSSFColor hssfColor = palette.findSimilarColor(red, green, blue);
style.setFillForegroundColor(hssfColor.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
public static CellStyle xssfCellStyleForntColor(Workbook book,
int red,
int green,
int blue,
HorizontalAlignment horizontalAlignment,
String fontName,
Boolean boldOrNOt,
XSSFCellStyle cellStyle) {
XSSFCellStyle style;
if (cellStyle != null) {
style = cellStyle;
} else {
style = (XSSFCellStyle) book.createCellStyle();
}
style.setAlignment(horizontalAlignment);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font font = book.createFont();
font.setFontName(fontName);
font.setFontHeightInPoints((short) 10);
font.setBold(boldOrNOt);
style.setFont(font);
// 1.行背景色
// style.setFillForegroundColor(IndexedColors.BLUE.getIndex());
//自定义
style.setFillForegroundColor(new XSSFColor(new java.awt.Color(red, green, blue)));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
// 自适应宽度(中文支持)
public static void setSizeColumn(HSSFSheet sheet, int size) {
for (int columnNum = 0; columnNum < size; columnNum++) {
int columnWidth = sheet.getColumnWidth(columnNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
HSSFRow currentRow;
//当前行未被使用过
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(columnNum) != null) {
HSSFCell currentCell = currentRow.getCell(columnNum);
if (currentCell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue().getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
sheet.setColumnWidth(columnNum, columnWidth * 256);
}
}
}
获取列的值的时候,每个单元格都有不同的类型,所以我们在获取的时候,根据类型取获取里面的值,不同类型的获取有不同的方法,如String类型获取的方法为getStringCellValue()。所以读取的时候一定要注意读取的类型,否则会读取失败。(读取不同的数据类型,下面有写,工作中这一块相对比较麻烦)
@Test
public void readExcel07() throws IOException {
String path = "E:\\excel\\";
//获取文件流
FileInputStream inputStream = new FileInputStream(path + "07码农.xlsx");
//获取一个工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 得到表
Sheet sheet = workbook.getSheetAt(0);
//得到行
Row row = sheet.getRow(0);
// 得到列
Cell cell = row.getCell(0);
//getStringCellValue 获取的是字符串类型的
String stringCellValue = cell.getStringCellValue();
System.out.println(stringCellValue);
inputStream.close();
}
@Test
public void readExcel07() throws IOException {
String path = "E:\\excel\\";
//获取文件流
FileInputStream inputStream = new FileInputStream(path + "07码农.xlsx");
//获取一个工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 得到表
Sheet sheet = workbook.getSheetAt(0);
//得到行
Row row = sheet.getRow(0);
// 得到列
Cell cell = row.getCell(0);
//getStringCellValue 获取的是字符串类型的
String stringCellValue = cell.getStringCellValue();
System.out.println(stringCellValue);
inputStream.close();
}
如:excel中有葛总各样不同类型的数据,有字符串类型的,有时间类型的,有小数等
代码实现:不同的数据类型的读取都已经写好,有需要的直接拿来用即可
@Test
public void testCellType() throws IOException {
String path = "E:\\excel\\";
//获取文件流
FileInputStream inputStream = new FileInputStream(path + "03码农.xls");
//获取一个工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
// 得到表
Sheet sheet = workbook.getSheetAt(0);
//得到行(获取标题:也就是第一行中的内容)
Row rowTitle = sheet.getRow(0);
//getPhysicalNumberOfCells()方法:获取这行中有多少个列
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
//获取列
Cell cell = rowTitle.getCell(cellNum);
if (cell != null) {
//获取类型
CellStyle cellStyle = cell.getCellStyle();
}
}
//获取表中内容
//获取表的行数
int rowCount = sheet.getPhysicalNumberOfRows();
for (int rowNum = 0; rowNum < rowCount; rowNum++) {
Row row = sheet.getRow(rowNum);
if (row != null) {
// 读取列
int cellCount2 = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount2; cellNum++) {
Cell cell = row.getCell(cellNum);
//匹配列的数据类型
if (cell != null) {
int cellType = cell.getCellType();
String cellValue = "";
switch (cellType) {
//字符串类型
case HSSFCell.CELL_TYPE_STRING:
cellValue = cell.getStringCellValue();
break;
//布尔类型
case HSSFCell.CELL_TYPE_BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
//空类型
case HSSFCell.CELL_TYPE_BLANK:
//空就不需要读取了
break;
//数字类型(数字又分为 -日期数字,普通数字)
case HSSFCell.CELL_TYPE_NUMERIC:
//判断是不是日期类型
if (HSSFDateUtil.isCellDateFormatted(cell)) {
//日期,就要转换成日期对应的格式
Date dateCellValue = cell.getDateCellValue();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
cellValue = simpleDateFormat.format(dateCellValue);
} else {
//不是日期格式,防止数字过长,转换成科学计数法
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cellValue = cell.toString();
}
break;
//数据类型错误
case HSSFCell.CELL_TYPE_ERROR:
//错误也不需要写了
break;
}
System.out.println(cellValue);
}
}
}
}
inputStream.close();
}
导入相关依赖(这里使用了比较新的版本3.0.5)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
package com.qhy.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.junit.Test;
import java.util.Date;
import java.util.List;
/**
* @author qiuhongyu
* @date 2021/12/4 23:00
*/
public class EasyExcelTest {
private List<DemoData> data() {
List<DemoData> list = ListUtils.newArrayList();
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;
}
@Test
public void simpleWrite() {
// 写法1 JDK8+
// since: 3.0.0-beta1
String fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, DemoData.class)
.sheet("模板")
.doWrite(() -> {
// 分页查询数据
return data();
});
// 写法2
fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
// 写法3
fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel.write(fileName, DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
}
创建一个实体,用于接受读取的数据
@Getter
@Setter
@EqualsAndHashCode
public class DemoData {
private String string;
private Date date;
private Double doubleData;
}
创建一个监听器
package com.qhy.easyexcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {
/**
* 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 100;
/**
* 缓存的数据
*/
private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(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;
}
/**
* 这个每一条数据解析都会来调用(即:核心方法,读取数据会调用invoke方法)
* DemoData 读取的类型
* AnalysisContext 分析上下文
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
System.out.printf( JSON.toJSONString(data));
cachedDataList.add(data);
/* 达到BATCH_COUNT了,需条要去存储一次数据库,防止数据几万数据在内存,容易OOM
即:如果数据>=5条就会保存到数据库(这一步是将读取出来的内容保存到数据库,如果没有这样的需求就不用做持久化的操作)
*/
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
log.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", cachedDataList.size());
demoDAO.save(cachedDataList);
log.info("存储数据库成功!");
}
}
编写一个测试方法进行读取的操作
/**
* 最简单的读 (个人推荐写法3,一行代码搞定)
*
* 1. 创建excel对应的实体对象 参照{@link DemoData}
*
* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
*
* 3. 直接读即可
*/
Logger log = LoggerFactory.getLogger(EasyExcelTest.class);
@Test
public void simpleRead() {
// 写法1:JDK8+ ,不用额外写一个DemoDataListener
// since: 3.0.0-beta1
String fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>(dataList -> {
for (DemoData demoData : dataList) {
log.info("读取到一条数据{}", JSON.toJSONString(demoData));
}
})).sheet().doRead();
// 写法2:
// 匿名内部类 不用额外写一个DemoDataListener
fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, DemoData.class, new ReadListener<DemoData>() {
/**
* 单次缓存的数据量
*/
public static final int BATCH_COUNT = 100;
/**
*临时存储
*/
private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
@Override
public void invoke(DemoData data, AnalysisContext context) {
cachedDataList.add(data);
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
saveData();
}
/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", cachedDataList.size());
log.info("存储数据库成功!");
}
}).sheet().doRead();
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
// 写法3:
fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
// 写法4:
fileName ="D:\\easyexcel\\" + "码畜easyExcel" + ".xlsx";
// 一个文件一个reader
ExcelReader excelReader = null;
try {
excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
// 构建一个sheet 这里可以指定名字或者no
ReadSheet readSheet = EasyExcel.readSheet(0).build();
// 读取一个sheet
excelReader.read(readSheet);
} finally {
if (excelReader != null) {
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
}
}
}