POI是什么
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
版本差异
poi 有两个版本:03版本和07版本,引入的依赖各不相同,也有细微的差距
03年创建的表格是 .xls
后缀、07年版本是.xlsx
版本。两个版本的差异体现在内容大小上。
以下是两个两个版本的依赖:
org.apache.poi
poi
3.17
org.apache.poi
poi-ooxml
3.17
使用流程
该工具很好的体现了面向对象的思想。把 Excel 里的内容对象化。
里面的对象大致分四个:
Excel的对象
Sheet 对象
行对象
单元格对象
03版本
写
按照上面的对象流程来书写代码。因为是写操作,所以需要手动创建该对象
public void writeExcel(){
String path = "E:\\";
// 创建一个Excel对象
Workbook workbook = new HSSFWorkbook();
// 创建一个工作薄
Sheet sheet = workbook.createSheet();
// 创建一行 0代表Excel的第一行
Row row = sheet.createRow(0);
// 创建单元格
Cell cell = row.createCell(0);
// 给单元格书写内容
cell.setCellValue("张三");
// 内容写完后输出到硬盘上
// 这里要自己指定后缀 务必遵循 03 使用xls 否则无法打开
try (FileOutputStream fos = new FileOutputStream(path+"excel03.xls")) {
// 注意! 这里是用excel对象来进行写入。
workbook.write(fos);
System.out.println("输出完毕");
workbook.close();
}catch (Exception e){
e.printStackTrace();
}
}
读
读操作,所以先从本地读取Excel
public void readExcel() throw Exception{
// 读取excel
FileInputStream fis = new FileInputStream("E:\\excel03.xls");
// 将流读入 WorkBook 中
Workbook workbook = new HSSFWorkbook(fis);
// 获取第一页 sheet || 通过 getSheet 读取,参数是 sheet 的名字
Sheet sheet0 = workbook.getSheetAt(0);
// 获取第一行
Row row = sheet0.getRow(0);
// 获取第一个单元格
Cell cell = row.getCell(0);
// 读取不比写入,这里有一点问题,因为读取出来的数据可能是 数字、字符串、时间格式 所以需要额外判断 稍后在07版本写判断该数据什么格式
System.out.println(cell.getStringCellValue());
// 别忘记关流了
workbook.close();
fis.close();
}
07版本
03和07的书写差异并不大。实现类、后缀名不同。
写
流程基本一样,注意 实现类,文件后缀名即可
public void writeExcel07(){
String path = "E:\\";
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("李四");
// 后缀名 xlsx
try (FileOutputStream fos = new FileOutputStream(path+"excel07.xlsx")) {
workbook.write(fos);
System.out.println("输出完毕");
workbook.close();
}catch (Exception e){
e.printStackTrace();
}
}
读
读取流程一样
public void readExcel() throws Exception(){
FileInputStream fis = new FileInputStream("E:\\excel07.xlsx");
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
System.out.println(cell.getStringCellValue());
workbook.close();
fis.close();
}
超级写
超级写和普通写的区别:速度!速度!
实现方式变为new SXSSFWorkbook()
,且需要显示的清除文件缓存。
public void superWriteExcel(){
String path = "E:\\";
// 接口无清除方法,所以不采用接口申明
SXSSFWorkbook workbook = new SXSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("李四");
try (FileOutputStream fos = new FileOutputStream(path+"excel07.xlsx")) {
workbook.write(fos);
System.out.println("输出完毕");
workbook.close();
// 清除临时文件 这里清除
workbook.dispose();
}catch (Exception e){
e.printStackTrace();
}
}
读取时候数据类型的判断
以下代码是正常读取一个excel所做的操作
public void read()throws Exception{
FileInputStream fis = new FileInputStream("E:\\excel07.xlsx");
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
// 获取第一行 一般是表头
Row rowTitle = sheet.getRow(0);
// 单元格是否为空
if (rowTitle != null) {
// 一行中单元格数量
int titleCellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < titleCellCount; cellNum++) {
Cell cell = rowTitle.getCell(cellNum);
String cellValue = cell.getStringCellValue();
System.out.print(cellValue + " |");
}
System.out.println();
// 获取一共有多少行
int rowCount = sheet.getPhysicalNumberOfRows();
// 这里从第二行开始读取 因为第一行是表头
for (int i = 1; i < rowCount; i++) {
Row rowDate = sheet.getRow(i);
if (rowDate != null) {
int cellCount = rowDate.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
Cell cellDate = rowDate.getCell(cellNum);
String cellValue = "";
if (cellDate != null) {
switch (cellDate.getCellTypeEnum()) {
case STRING:
cellValue = cellDate.getStringCellValue();
break;
case BOOLEAN:
cellValue = String.valueOf(cellDate.getBooleanCellValue());
break;
case NUMERIC:
if ("General".equals(cellDate.getCellStyle().getDataFormatString())) {
cellValue = cellDate.toString();
} else if ("m/d/yy".equals(cellDate.getCellStyle().getDataFormatString())) {
// 用的时间格式化工具,无视之
cellValue = new DateTime(cellDate.getDateCellValue()).toString("yyyy-MM-dd");
} else {
cellValue = cellDate.toString();
}
break;
case BLANK:
break;
}
}
System.out.print(cellValue + "|");
}
}
}
}
fis.close();
}
以上就是POI的基本读写了。
一些其他问题
读取多少行有两个方法:
假设现在在excel 第1行有数据 第10行有数据 2-9无数据
sheet.getLastRowNum()
:读取的是最后一行有数据的行数,n-1 10-1 九行
sheet.getPhysicalNumberOfRows()
:读取有数据的行数, n-m 10-8 两行
读取一行有多少列的两个方法:
假设现在excel第一行 第1列有数据 第10列有数据
row.getLastCellNum()
:读取是最后一列有数据的数字,n(非n-1)
row.getPhysicalNumberOfCells()
:读取有数据的行数,n-m 10-8 两列
PS:注意虽然方法名都是Last 但是行读取的不是n-1模式而是直接取n
读取问题
上面的读有03版本和07版本,写的时候也是分开写的,那么有一个通用读取方法吗?
必然是有的采用工厂读取。
2003/2007/2010 都是可以处理的
Workbook workbook = WorkbookFactory.create(fis);
写入问题
当excel 执行write 后,创建的 workbook对象则被清空,此时读取设置好的数据会出现空指向异常。
使用注意
poi使用采用的一口气读取进内存,所以读取过大的excel非常容易出现OOM
所以还有另外一个软件阿里出的:EasyExcel