文章目录
一、POI是什么?
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
操作Excel目前表流行的就是Apache POI和阿里巴巴的easyExcel
Apache POI介绍
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
EasyExcel介绍
EasyExcel是阿里巴巴开源的一个excel,以使用简单,节省内存著称。 EasyExcel能大大减少占用内存的原因在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
二、常用信息
1.将用户信息导出为excel表格(导出数据…)
2.将Excel表中的信息录入到网站数据库(习题上传…)
开发中经常设计到excel的处理,如导出导入Excel到数据库中
三、导出Excel表具体操作
1.POI-Excel写
1.创建项目
建立一个空项目POItest.

2.导入pom依赖
代码如下(示例):
<!--导入依赖-->
<dependencies>
<!--java万物皆对象 -->
<!--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>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<!--test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!---->
</dependencies>
3.在com.yang包下建立一个ExcelWriteTest测试类
//写 测试类
public class ExcelWriteTest {
String PATH="E:\\IDEA Workspace\\POItest\\";
}
4.生成一个工作薄
03版本:
@Test
public void testWrite03() throws Exception {
//1.创造一个工作簿
Workbook workbook=new HSSFWorkbook();//03版本HSSF
//2.创建一个工作表
Sheet sheet=workbook.createSheet("Java学习人数统计表");
//3.创建一个行
Row row1=sheet.createRow(0);//零代表第一行
//4.创建一个单元格
Cell cell11=row1.createCell(0);//表格中第一行的第一个数据
cell11.setCellValue("今日新增学习人数");
Cell cell12=row1.createCell(0);//表格中第一行的第二个数据
cell12.setCellValue("666");
//第二行(2.1)
Row row2=sheet.createRow(1);
Cell cell21=row2.createCell(0);//表格中第二行的第一个数据
cell21.setCellValue("统计时间");
//(2.2)
Cell cell22=row1.createCell(1);//表格中第一行的第一个数据
String time= new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
//生成一张表(IO流) 03版本就是使用xls结尾! 07版本是使用xlsx!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "Java学习人数统计表03.xls");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("Java学习人数统计表03 生成完毕!");
}
07版本:
@Test
public void testWrite07() throws Exception {
//1.创造一个工作簿
Workbook workbook=new XSSFWorkbook();//07版本XSSF
//2.创建一个工作表
Sheet sheet=workbook.createSheet("Java学习人数统计表");
//3.创建一个行
Row row1=sheet.createRow(0);//零代表第一行
//4.创建一个单元格
Cell cell11=row1.createCell(0);//表格中第一行的第一个数据
cell11.setCellValue("今日新增学习人数");
Cell cell12=row1.createCell(0);//表格中第一行的第二个数据
cell12.setCellValue("666");
//第二行(2.1)
Row row2=sheet.createRow(1);
Cell cell21=row2.createCell(0);//表格中第二行的第一个数据
cell21.setCellValue("统计时间");
//(2.2)
Cell cell22=row1.createCell(1);//表格中第一行的第一个数据
String time= new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
//生成一张表(IO流) 03版本就是使用xls结尾! 07版本是使用xlsx!
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "Java学习人数统计表07.xlsx");
//输出
workbook.write(fileOutputStream);
//关闭流
fileOutputStream.close();
System.out.println("Java学习人数统计表07 生成完毕!");
}
2.大文件写数据
数据行数<=65536行 03版本比07版本运行快,>65536以后只有07版本能操作添加数据
03版本(HSSF):
@Test
public void testWrite03bigDate() throws IOException {
//时间
long begin = System.currentTimeMillis();
//1.创建一个薄
Workbook workbook = new HSSFWorkbook();//03版本HSSF
//2.创建一个工作表
Sheet sheet = workbook.createSheet();
//3.写入数据
for(int rowNum = 0; rowNum < 65536; rowNum++){
//行数需要小于65536,03版本的最大行数为65536 超过汇报异常
Row row =sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10 ; cellNum++){
//添加的单元格数值在0与10之间
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("添加完毕!!!");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite03bigDate.xls");
//03版本就是使用xls结尾! 07版本是使用xlsx!
workbook.write(outputStream);
outputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
缺点:最多只能处理 65536行,否则会抛出异常
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快。
07版本(XSSF):
@Test
public void testWrite07bigDate() throws IOException {
//时间
long begin = System.currentTimeMillis();
//1.创建一个薄
Workbook workbook = new XSSFWorkbook();//07版本XSSF
//2.创建一个工作表
Sheet sheet = workbook.createSheet();
//3.写入数据
for(int rowNum = 0; rowNum < 65536; rowNum++){
//行数需要小于65536,03版本的最大行数为65536 超过汇报异常
//07版可以大于65536,循环设为65536是为了比较同行数 二者处理数据的速度
Row row =sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10 ; cellNum++){
//添加的单元格数值在0与10之间
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("添加完毕!!!");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite07bigDate.xlsx");
//03版本就是使用xls结尾! 07版本是使用xlsx!
workbook.write(outputStream);
outputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条
优点:可以写比较大数据量,如20万条
注意:注意对象的一个区别,文件后缀!
3.大文件写SXSSF
public void testWrite07bigDateS() throws IOException {
//时间
long begin = System.currentTimeMillis();
//1.创建一个薄
Workbook workbook = new XSSFWorkbook();//超级版本用SXSSF
//2.创建一个工作表
Sheet sheet = workbook.createSheet();
//3.写入数据
for(int rowNum = 0; rowNum < 65536; rowNum++){
//行数需要小于65536,03版本的最大行数为65536 超过汇报异常
Row row =sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10 ; cellNum++){
//添加的单元格数值在0与10之间
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("添加完毕!!!");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite07bigDateS.xlsx");
//03版本就是使用xls结尾! 07版本是使用xlsx!
workbook.write(outputStream);
outputStream.close();
//清除临时文件!
((SXSSFWorkbook) workbook).dispose();
long end = System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
优点:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存
注意:过程中产生临时文件,需要清理临时文件
默认有100条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件,如果想自定义内存中数据的数量,可以使用new SXSSFWorkbock(数量)
SXSSFWorkbock官方的解释:实现策略的流式SXSSFWorkbock版本,这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。
请注意,仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释…仍然只储存在内存中,因此如果广泛使用,可能需要大量内存。
四、读Excel表具体操作
1.在com.yang包下再建立一个ExcelReadTest测试类
03版本(读取):
public class ExcelReadTest {
String PATH="E:\\IDEA Workspace\\POItest\\";
@Test
public void testRead03() throws Exception {
//获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "Java学习人数统计表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(0);
System.out.println(cell.getStringCellValue());
inputStream.close();
}
}
效果演示:
07版本(读取):
public void testRead07() throws Exception {
//获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "Java学习人数统计表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);
//getStringCellValue 字符串 读取值的时候要注意类型!
//System.out.println(cell.getStringCellValue());
System.out.println(cell.getNumericCellValue());
inputStream.close();
}
注意:1.地址PATH=“E:\IDEA Workspace\POItest\”,将会放在POItest下 如果后面不加\就会放到上一次层地址IDEA Workspace下。2.注意获取值的类型。
难点:读取不同类型的数据
新建一张有数据的表(例:明细表)

获取表头数据(以03版演示)
@Test
public void testCellType() throws IOException {
//获取文件流
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.println("["+(rowNum+1)+"-"+(cellNum+1)+"]");
Cell cell = rowData.getCell(cellNum);
//匹配列的数据类型
if (cell!=null){
int cellType = cell.getCellType();
String cellValue="";
switch (cellType){
case HSSFCell.CELL_TYPE_STRING://字符串类型
System.out.print("[String]");
cellValue = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_BOOLEAN://布尔
System.out.print("[BOOLEAN]");
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK://空
System.out.print("[BLANK]");
break;
case HSSFCell.CELL_TYPE_NUMERIC://数字(日期,普通数字)
System.out.print("[NUMERIC]");
if (HSSFDateUtil.isCellInternalDateFormatted(cell)){
//日期
System.out.print("[日期]");
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM-dd");
}else{
//不是日期格式,防止数字过长!
System.out.println("[转换为字符串输出]");
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cellValue = cell.toString();
}
break;
case HSSFCell.CELL_TYPE_ERROR://错误
System.out.print("[数据类型错误]");
break;
}
System.out.println(cellValue);
}
}
}
}
inputStream.close();
}
}
效果演示

总结
以上就是今天要讲关于POI导出和读取的内容,本文仅仅简单介绍了POI具体操作,和对于不同类型的数据读取的难点,感谢观看!
这篇博客介绍了Apache POI和EasyExcel在Java中处理Excel文件的用途,包括导出和读取操作。内容涵盖POI的创建工作簿、大文件写入策略以及EasyExcel的内存效率优势。还详细讲解了读取不同类型数据的难点和解决办法。

6705

被折叠的 条评论
为什么被折叠?



