POI-Excel
常用信息
- 将用户信息导出为excel表格(例如是导出数据:数据库信息)
- 将excel表中的信息录入网站数据库(例如是导入数据:题库)
开发中经常会用到excel的处理,例如导入、导出excel
操作Excel目前比较流行的就是 Apache POI 和阿里巴巴的 easyExcel
Apache POI(会比较麻烦一些)
官网:Apache POI - the Java API for Microsoft Documents
百度简介:
Apache POI [1] 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对[Microsoft Office](https://baike.baidu.com/item/Microsoft Office)格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
结构:
easyExcel(alibaba)
官网:https://github.com/alibaba/easyexce or EasyExcel · 语雀 (yuque.com)
EasyExcel 是阿里巴巴开源的一个excel处理框架,以使用简单,节约内存著称
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
文件解压文件读取通过文件形式
POI-Excel写
创建项目
-
创建一个新项目
-
引入pom依赖
<!--导入依赖--> <dependencies> <!--03--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> </dependency> <!--07--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> </dependency> <!--日期格式化工具--> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.1</version> </dependency> <!--test--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
-
科普:
03版本的execl和07版本的execl有什么区别了?
-
03与07版本的区别:
03版本
@Test public void test03() throws IOException { //创建一个工作簿 Workbook workbook = new HSSFWorkbook(); //创建一个工作表 Sheet sheet = workbook.createSheet("李凯的工作表"); //创建行 Row row = sheet.createRow(0); //创建单元格子((0,0) Cell cell = row.createCell(0); /*添加内容*/ cell.setCellValue("今天花费"); //(0,1) Cell cell1 = row.createCell(1); cell.setCellValue("20"); /*1,0*/ final Row row1 = sheet.createRow(1); final Cell cell2 = row1.createCell(0); cell2.setCellValue("统计时间"); final String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss:sss"); final Cell cell3 = row1.createCell(1); /*放入时间*/ cell3.setCellValue(time); /*生成一张表 03版本使用xls结尾*/ FileOutputStream fileOutputStream = new FileOutputStream(PATH + "李凯的日出消费表.xls"); workbook.write(fileOutputStream); //关闭流 fileOutputStream.close(); workbook.close(); System.out.println("生成完毕"); }
07版本
public void test07() throws IOException { //创建一个工作簿 Workbook workbook = new XSSFWorkbook(); //创建一个工作表 Sheet sheet = workbook.createSheet("李凯的工作表"); //创建行 Row row = sheet.createRow(0); //创建单元格子((0,0) Cell cell = row.createCell(0); /*添加内容*/ cell.setCellValue("今天花费"); //(0,1) Cell cell1 = row.createCell(1); cell1.setCellValue("20"); /*1,0*/ Row row1 = sheet.createRow(1); Cell cell2 = row1.createCell(0); cell2.setCellValue("统计时间"); final String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss:sss"); final Cell cell3 = row1.createCell(1); /*放入时间*/ cell3.setCellValue(time); /*生成一张表 03版本使用xls结尾*/ FileOutputStream fileOutputStream = new FileOutputStream(PATH + "李凯的日出消费表.xlsx"); workbook.write(fileOutputStream); //关闭流 fileOutputStream.close(); workbook.close(); System.out.println("生成完毕"); }
区别:
-
对象的区别
03版本:
Workbook workbook = new HSSFWorkbook();
07版本:
Workbook workbook = new XSSFWorkbook();
-
后缀名的区别
03 07 xls xlsx
-
-
03版本的大文件写入
缺点:最多只可以写入65536行
,否则会抛出异常
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快
时间:
正确代码:
public void test03BigData() throws IOException {
// 时间差:
final long begin = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建表
final Sheet sheet = workbook.createSheet();
//写入数据
for (int rowNum = 0;rowNum<65536;rowNum++){
final Row row = sheet.createRow(rowNum);
for (int cellNum = 0;cellNum<10;cellNum++){
final Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
final long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
报错代码:
public void test03BigData() throws IOException {
// 时间差:
final long begin = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建表
final Sheet sheet = workbook.createSheet();
//写入数据
for (int rowNum = 0;rowNum<65537;rowNum++){
final Row row = sheet.createRow(rowNum);
for (int cellNum = 0;cellNum<10;cellNum++){
final Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
final long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
-
07版本的大文件写入
缺点:写数据时数据速度非常慢,非常消耗内存,也会发生溢出,如100w条数据
优点:可以写比较大的数据量,如20w条数据
时间:
可以发现哪怕多了一条数据,时间就多了将进4倍
代码:
public void test07BigData() throws IOException { // 时间差: final long begin = System.currentTimeMillis(); //创建一个工作簿 Workbook workbook = new XSSFWorkbook(); //创建表 final Sheet sheet = workbook.createSheet(); //写入数据 for (int rowNum = 0;rowNum<65537;rowNum++){ final Row row = sheet.createRow(rowNum); for (int cellNum = 0;cellNum<10;cellNum++){ final Cell cell = row.createCell(cellNum); cell.setCellValue(cellNum); } } System.out.println("over"); final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xlsx"); workbook.write(fileOutputStream); fileOutputStream.close(); final long end = System.currentTimeMillis(); System.out.println((double)(end-begin)/1000); }
-
07版本的大数据写SXSSF
优点
:可以写非常大的数据量,例如100w条数据甚至更多条,相对于07版本的XSSF,他的读写数据更快,占用内存更少注意
:过程中会产生临时文件,需要清理临时文件默认的时100条记录被保存在内存中,如果超过这个数量,则最前面的数据将会写入到临时文件当中。
如果要想自定义内存中的数据的数量,则可以通过
new SXXSFWorkbook(数量)
时间:
代码:
public void test07BigDataS() throws IOException { // 时间差: final long begin = System.currentTimeMillis(); //创建一个工作簿 Workbook workbook = new SXSSFWorkbook(); //创建表 final Sheet sheet = workbook.createSheet(); //写入数据 for (int rowNum = 0;rowNum<65537;rowNum++){ final Row row = sheet.createRow(rowNum); for (int cellNum = 0;cellNum<10;cellNum++){ final Cell cell = row.createCell(cellNum); cell.setCellValue(cellNum); } } System.out.println("over"); final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xlsx"); workbook.write(fileOutputStream); fileOutputStream.close(); /*清除临时文件*/ ((SXSSFWorkbook)workbook).dispose(); final long end = System.currentTimeMillis(); System.out.println((double)(end-begin)/1000); }
POI-Excel读
07/03版本
@Test
public void test03() throws IOException {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xls");
//创建一个工作簿.使用excel能完成的操作这里都可以完成
Workbook workbook = new HSSFWorkbook(fileInputStream);
//获取表
final Sheet sheetAt = workbook.getSheetAt(0);
/*获取行*/
final Row row = sheetAt.getRow(0);
final int RowNum = sheetAt.getLastRowNum();
/*获取列*/
final Cell cell = row.getCell(0);
final String stringCellValue = cell.getStringCellValue();
System.out.println(stringCellValue);
System.out.println(RowNum);
fileInputStream.close();
}
07版本:
@Test
public void test03() throws IOException {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xlsx");
//创建一个工作簿.使用excel能完成的操作这里都可以完成
Workbook workbook = new XSSFWorkbook(fileInputStream);
//获取表
final Sheet sheetAt = workbook.getSheetAt(0);
/*获取行*/
final Row row = sheetAt.getRow(0);
final int RowNum = sheetAt.getLastRowNum();
/*获取列*/
final Cell cell = row.getCell(0);
final String stringCellValue = cell.getStringCellValue();
System.out.println(stringCellValue);
System.out.println(RowNum);
fileInputStream.close();
}
读取不同的数据类型
重点:数据转换类型!
@Test
public void test07Demo() throws IOException {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xlsx");
//创建一个工作簿.使用excel能完成的操作这里都可以完成
Workbook workbook = new XSSFWorkbook(fileInputStream);
//获取表
Sheet sheetAt = workbook.getSheetAt(0);
/*获取行数*/
Row row = sheetAt.getRow(0);
if (row!=null){
/*获取所有的行数*/
final int physicalNumberOfCells = row.getPhysicalNumberOfCells();
for (int CellNum = 0; CellNum < physicalNumberOfCells; CellNum++) {
final Cell cell = row.getCell(CellNum);
if (cell!=null){
/*获取行的类型*/
CellType cellType = cell.getCellType();
String stringCellValue = cell.getStringCellValue();
System.out.print(stringCellValue+" ");
}
}
System.out.println();
}
//获取表中的数据(列数)
int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
for (int RowNum = 1; RowNum < physicalNumberOfRows; RowNum++) {
final Row row1 = sheetAt.getRow(RowNum);
if (row1!=null){
//读取列
final int physicalNumberOfCells = row1.getPhysicalNumberOfCells();
for (int cellNumber = 0; cellNumber < physicalNumberOfCells; cellNumber++) {
final Cell cell = row1.getCell(cellNumber);
//匹配列的数据类型
if (cell!=null){
CellType cellType = cell.getCellType();
String cellValue = "";
/*判断类型*/
switch (cellType){
case STRING:
System.out.println("字符串");
cellValue= cell.getStringCellValue();
break;
case BOOLEAN:
System.out.println("布尔类型");
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case BLANK:
System.out.println("为空");
break;
case NUMERIC: //数字(日期和普通数字)
if (HSSFDateUtil.isCellDateFormatted(cell)){ //日期
System.out.println("日期类型");
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM-dd");
}else {
System.out.println("数字");
cellValue = String.valueOf(cell.getNumericCellValue());
}
break;
case ERROR:
System.out.println("数组类型错误");
break;
}
System.out.println(cellValue);
}
}
}
}
fileInputStream.close();
}
计算公式:
@Test
public void testFormula() throws IOException {
FileInputStream fileInputStream = new FileInputStream(PATH + "Documents测试.xlsx");
Workbook workbook= new XSSFWorkbook(fileInputStream);
Sheet sheetAt = workbook.getSheetAt(0);
Row row = sheetAt.getRow(4);
Cell cell = row.getCell(0);
//拿到计算公式 eval
FormulaEvaluator xssfFormulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
//输出单元格的内容
CellType cellType = cell.getCellType();
switch (cellType){
case FORMULA: //公式
String cellFormula = cell.getCellFormula();
System.out.println(cellFormula);
//计算
CellValue evaluate = xssfFormulaEvaluator.evaluate(cell);
String CellValue = evaluate.formatAsString();
System.out.println(CellValue);
break;
}
}