视频链接-我是学习之星我为狂神打call~
【狂神说Java】POI及EasyExcel一小时搞定通俗易懂
想给项目添加一个表格导入导出功能吗?
“xxx管理系统”没有导入导出功能逼格不够了?
想简单入手下 how to 用java 生成excel又找不到合适的教程?
come on !这篇文章简单介绍下如何用java操作excel,主要涉及到POI和easyExcel这两个
文章目录
- 1.POI和easyExcel介绍
- 是什么?
- 有什么用?
- 2.POI-excel-写
- excel 基本写入操作
- 03版本xls
- 07版本xlsx
- 大量数据写入
- 大文件写HSSF
- 大文件写XSSF
- 大文件写SXSSF
- 3.POI-excel-读
- 03/07版本
- 03版本代码示例
- 07版本代码示例
- 读取不同类型的数据(难点★)
- 计算公式(了解即可)
- 4.EasyExcel相关的操作
- 导入依赖
- 写入测试
- 1.DemoData.java
- 2.测试写入数据
- 最终的结果
1.POI和easyExcel介绍
是什么?
我们经常需要将项目中的表格数据或者文档数据进行导入或者导出操作,这个如果自己从零开始做还比较麻烦。比如我之前就职的公司都是自己做的组件,但是很不好用,BUG 太多。关于表格导入导出,市面上比较知名的开源就是 Apache 的POI 和 阿里巴巴的 EasyExcel了。EasyExcel 也是对 POI 的改进和封装, 更加好用。
有什么用?
1、将用户的信息导出为 excel 表格。
2、将 Excel 表中的信息录入到网站数据库。
开发中经常会涉及到 excel 的 处理,如导出 Excel ,导入 Excel 到数据库中。
操作 Excel 目前比较流行的就是 Apache POI 和阿里巴巴的 EasyExcel。
Apache POI
结构:
EasyExcel
EasyExcel 是阿里巴巴开源的一个 excel处理框架,以使用简单、节省内存著称。
EasyExcel 能大大减少内存占用的主要原因是在解析 Excel 时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
下面是 EasyExcel 和 POI 在解析Excel 时的对比图。
2.POI-excel-写
excel 基本写入操作
万物皆对象:工作簿是个对象,其中包含工作表;工作表是个对象,其中包含行,列对象。。
03版本xls
@Testpublic void testWriteTest03() throws Exception {// 1.创建一个工作簿Workbook workbook =new HSSFWorkbook();// 2.创建一个工作表Sheet sheet = workbook.createSheet("学生统计表");// 3.创建一个行(1,1)Row row1 =sheet.createRow(0);// 4.创建一个单元格 (1,2)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("入学时间");//( 2,2)Cell cell22 =row2.createCell(1);String time = new DateTime().toString("yyyy-MM-dd");cell22.setCellValue(time);// 生成一张表(IO流) 03 版本使用的就是 xls结尾!FileOutputStream fileOutputStream = new FileOutputStream(PATH + "学生统计表03.xls");workbook.write(fileOutputStream);// 关闭流fileOutputStream.close();System.out.println("学生统计表03表格生成完毕");}
07版本xlsx
@Testpublic void testWriteTest07() throws Exception {// 1.创建一个工作簿 07Workbook workbook =new XSSFWorkbook();// 2.创建一个工作表Sheet sheet = workbook.createSheet("学生统计表");// 3.创建一个行(1,1)Row row1 =sheet.createRow(0);// 4.创建一个单元格 (1,2)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("入学时间");//( 2,2)Cell cell22 =row2.createCell(1);String time = new DateTime().toString("yyyy-MM-dd");cell22.setCellValue(time);// 生成一张表(IO流) 03 版本使用的就是 xlsx结尾!FileOutputStream fileOutputStream = new FileOutputStream(PATH + "学生统计表07.xlsx");workbook.write(fileOutputStream);// 关闭流fileOutputStream.close();System.out.println("学生统计表07表格生成完毕");}
大量数据写入
PS:xls文件有行数限制(65536行)。
03版本xls对应的是HSSF格式,07版本xlsx对应的是XSSF格式
注意:03版本xls写的行数超过65536会报错异常:
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
大文件写HSSF
@Testpublic void testWrite03BigData() throws Exception {// 时间long begin = System.currentTimeMillis();// 创建一个簿Workbook workbook = new HSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNum = 0; rowNum < 65535; 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 outputStream = new FileOutputStream(PATH + "testWrite03BigData.xls");workbook.write(outputStream);// 关闭流outputStream.close();long end = System.currentTimeMillis();System.out.println((double)(end-begin)/1000);}
大文件写XSSF
// 耗时较久!!@Testpublic void testWrite07BigData() throws Exception {// 时间long begin = System.currentTimeMillis();// 创建一个簿Workbook workbook = new XSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNum = 0; rowNum < 200000; 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 outputStream = new FileOutputStream(PATH + "testWrite07BigData.xlsx");workbook.write(outputStream);// 关闭流outputStream.close();long end = System.currentTimeMillis();System.out.println((double)(end-begin)/1000);}
大文件写SXSSF
@Testpublic void testWrite07BigDataSecond() throws Exception {// 时间long begin = System.currentTimeMillis();// 创建一个簿Workbook workbook = new SXSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNum = 0; rowNum < 200000; 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 outputStream = new FileOutputStream(PATH + "testWrite07BigDataSecond.xlsx");workbook.write(outputStream);// 关闭流outputStream.close();// 清除临时文件!((SXSSFWorkbook)workbook).dispose();long end = System.currentTimeMillis();System.out.println((double)(end-begin)/1000);}
3.POI-excel-读
03/07版本
03版本代码示例
String PATH = "C:\\Users\\Administrator\\Desktop\\poi-easyExcel\\";@Testpublic void testReadTest03() throws Exception {// 获取文件流FileInputStream inputStream = new FileInputStream(PATH + "poi学生统计表03.xls");// 1.创建一个工作簿, excel 能操作的它都能操作Workbook workbook = new HSSFWorkbook(inputStream);// 2.得到表Sheet sheet = workbook.getSheetAt(0);// 3.得到行Row row = sheet.getRow(0);// 4.得到列Cell cell = row.getCell(1);// 输出(0,0)// 读取值的时候一定要注意判断类型,否则会读取失败System.out.println(cell.getStringCellValue());}
07版本代码示例
@Testpublic void testReadTest07() throws Exception {// 获取文件流FileInputStream inputStream = new FileInputStream(PATH + "poi学生统计表07.xlsx");// 1.创建一个工作簿, excel 能操作的它都能操作Workbook workbook = new XSSFWorkbook(inputStream);// 2.得到表Sheet sheet = workbook.getSheetAt(0);// 3.得到行Row row = sheet.getRow(0);// 4.得到列Cell cell = row.getCell(1);// 输出(0,0)// 读取值的时候一定要注意判断类型,否则会读取失败System.out.println(cell.getStringCellValue());}
注意获取值的类型即可
读取不同类型的数据(难点★)
@Testpublic void testCellType() throws Exception {// 获取文件流FileInputStream inputStream = new FileInputStream(PATH + "明细表.xls");// 1.创建一个工作簿, excel 能操作的它都能操作Workbook workbook = new HSSFWorkbook(inputStream);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) {int cellType = cell.getCellType();String cellValue = cell.getStringCellValue();System.out.print(cellValue + " | ");}}System.out.println();}// 获取表中的内容int rowCount = sheet.getPhysicalNumberOfRows();for (int rowNum = 1; rowNum < rowCount; rowNum++) {Row rowData = sheet.getRow(rowNum);if (rowData != null) {// 读取列int cellCount = rowTitle.getPhysicalNumberOfCells();for (int cellNum = 0; cellNum < cellCount; cellNum++) {System.out.print("[" + (rowNum + 1) + "-" + (cellNum + 1)+"]");Cell cell = rowData.getCell(cellNum);// 匹配数据的类型if (cell!=null){int cellType = cell.getCellType();String cellValue="";switch (cellType){case Cell.CELL_TYPE_STRING: // 字符串System.out.print("[String]");cellValue=cell.getStringCellValue();break;case Cell.CELL_TYPE_NUMERIC: //数字System.out.print("[numeric]");if (HSSFDateUtil.isCellDateFormatted(cell)){ //日期System.out.print("[日期]");Date date = cell.getDateCellValue();cellValue = new DateTime(date).toString();}else {// 不是日期格式,防止数字过长System.out.print("[转换为字符串输出]");cell.setCellType(Cell.CELL_TYPE_STRING);cellValue = cell.toString();}break;default:System.out.print("[数据类型错误!]");break;}System.out.println(cellValue);}}}}// 关闭流inputStream.close();}
注意类型转换!!
计算公式(了解即可)
@Testpublic void testWrite07BigDataSecond() throws Exception {// 时间long begin = System.currentTimeMillis();// 创建一个簿Workbook workbook = new SXSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNum = 0; rowNum < 200000; 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 outputStream = new FileOutputStream(PATH + "testWrite07BigDataSecond.xlsx");workbook.write(outputStream);// 关闭流outputStream.close();// 清除临时文件!((SXSSFWorkbook)workbook).dispose();long end = System.currentTimeMillis();System.out.println((double)(end-begin)/1000);}
4.EasyExcel相关的操作
EasyExcel官方示例
导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>1.1.2-beat1</version>
</dependency>
写入测试
对象
@Data
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;
}
1.DemoData.java
/*** 最简单的写* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 直接写即可*/
@Test
public void simpleWrite() {// 写法1String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 上面那个fileName不一定非得按人家的格式写,只要能保证该文件能确定一个文件就可以了// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可/*他这个默认是xlsx格式的,第一个参数是文件名(绝对路径),第二个参数是哪个模板,比如上面定义的DemoData对象sheet("模板") 是说生成的工作簿(fileName)中含有一个叫“模板”的表doWrite中的参数 data()返回的就是需要写入的数据!*/EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}
PS:我这里的data()是这样写的
private List<DemoData> data() {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);}return list;}
2.测试写入数据
@Test测试下吧
最终的结果
如案例图所示