POI
今天向大家介绍一个轻量级的自动化处理Microsoft Office格式文件的Java组件POI。
在工作中打交道最多的就是Excel数据表了,遇到一些重复性的而又不得不做的事务的时候POI组件就可以根据你的想法完成各种各样的任务。
进入正题,首先向大家介绍一下POI中对Excel操作常用的两个类分别是
HSSFWorkbook Hw = new HSSFWorkbook();
XSSFWorkbook Xw = new XSSFWorkbook();
以上两个对象的区别就是随着Excel的发展来划分的,众所周知Excel有代表性的版本分别是03版本和07版本,这两个版本最显著的区别就是03版本所容纳的数据行只有65536行,而07版本则是可以容纳无限数据的。
以上各两个对象也是为了兼容新版和旧版Excel来划分的,HSSFWorkbook适用于旧版,XSSFWorkbook适用于新版。在使用过程中没有区别,只是对象名称不同。
Maven中的POI依赖
<!-- 03版本的POI依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<!-- 07版本的POI依赖-->
<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>
POI写操作
这个操作过程可以使用流水账来形容,顺滑的逻辑思想,下面来简单的过一遍吧
-
创建对Excel的操作对象,工作簿
Workbook Work = new XSSFWorkbook(); //面向接口编程,对象变了,接口不变
-
创建工作表
有了工作簿之后,使用工作簿对象创建工作表
Sheet sheet = Work.createSheet();
-
创建第一行数据
使用上面的工作表对象,调用创建数据行方法
方法内的参数就是Excel中的行数,索引为0,表示常规工作表中的第一行
Row row = sheet.createRow(0);
-
创建第一列数据
使用上面的第一行对象,调用创建第一列数据的方法
方法内的参数为0,就表示创建了第一行中的第一列的数据
Cell cell = row.createCell(0);
执行完上述操作之后,就相当于选中了一个工作表中的第一行中的第一列数据,接下来就可以往当前选中的单元格填充数据了!
-
填充字符串格式的数据
cell.setCellValue("卡特琳娜")
之后就可将,创建的Excel表输出到本地来查看我们的执行结果啦
-
输出Excel文档
//FileOutputStream中参数就是当前本地输出的地址 FileOutputStream fileOutputStream = new FileOutputStream(PATH+"mmd.xlsx"); //调用work工作簿对象,就可以将文件输出到本地 Work.write(fileOutputStream);
POI读操作
既然要读取本地的Excel文件,那么就要存在本地文件并且创建文件的输入流
-
创建本地文件输入流,并转交给工作簿操作对象
//创建文件的数据流 FileInputStream file = new FileInputStream(PATH + "07.xlsx"); //将文件流引入POI操作对象 Workbook Work = new XSSFWorkbook(file);
-
获取工作表
现在已经有了工作簿的操作对象,现在我们就要选择工作簿中具体的工作表来进行下一步操作,这里介绍两种方法。
Sheet sheet1 = Work.getSheetAt(0); //根据索引选择第一张工作表 Sheet sheet2 = Work.getSheet("one"); //根据工作表的名称选择工作表
-
获取第一行
将指针定位到第一行
Row row = sheet1.getRow(0); //获取第一行
-
获取具体的单元格
使用定位到上一行的对象,定位具体的第N列数据
Cell cell = row.getCell(0); //获取第一行中第一列的数据
-
获取单元格数据
cell.getStringCellValue() //获取String的值
-
以工作表对象为基点,获取工作表中有效行的总行数(自动化读取数据的时候使用)
//获取工作表中可用的数据总行数,说白了就是有多少有效数据行,就返回多大的数字 int Lines = sheet.getPhysicalNumberOfRows();
-
以行对象为基点,获取行单位下有效列的总列数
//这个跟上面内个方法没啥大区别,这个是获取当前选中行中有效的数据列数 int Cells = line.getPhysicalNumberOfCells();
到这里其实已经掌握了怎样从Excel中读数据和写数据,其实向Excel中写数据好说,读数据这里有一个很显著的坑,那就是你永远不知道你选择的单元格中的数据类型是啥,所以上面演示的读数据是读出来的String类型的数据。
接下来就补充一下在读数据的时候,为了应对各种情况进行的安全性判断吧。
/*
int CELL_TYPE_NUMERIC = 0; 数字类型(普通数字,日期)
int CELL_TYPE_STRING = 1; 字符串类型
int CELL_TYPE_FORMULA = 2; 公式类型
int CELL_TYPE_BLANK = 3; 空白类型
int CELL_TYPE_BOOLEAN = 4; Boolean类型
int CELL_TYPE_ERROR = 5; 错误类型
*/
实例演示
个人演示的实例,贴在这里,需要者自取,已经封装为工具类,可以直接使用!!!
/**
* 该方法为自动适配单元格中的各种类型,进行读取Excel中的数据并显示在控制台中
* 可以进一步进化,封装为工具类使用
* @throws Exception
*/
public static void AutoRead07() throws Exception{
//创建文件的数据流(本地实际存在的文件)
FileInputStream file = new FileInputStream(PATH + "07.xlsx");
//将文件流引入POI操作对象
Workbook Work = new XSSFWorkbook(file);
//跟上边一样都是先获取位于工作簿中的第一个工作表
Sheet sheet = Work.getSheetAt(0);
//获取工作表中可用的数据总行数,说白了就是有多少有效数据行,就返回多大的数字
int Lines = sheet.getPhysicalNumberOfRows();
for (int i = 0; i < Lines; i++) {
//选中第 N 行
Row line = sheet.getRow(i);
//这个跟上面内个方法没啥大区别,这个是获取当前选中行中有效的数据列数
int Cells = line.getPhysicalNumberOfCells();
for (int j = 0; j < Cells; j++) {
//获取具体的列
Cell cell = line.getCell(j);
//接下来就是打印了,首先经过我们以上的操作,已经定位到了具体单元格,就差获取单元格中的数据了,但是我们并不知道单元格中的数据类型,所以我们不能直接获取
//不同类型返回不同的值
if(cell != null){
int cellType = cell.getCellType();
/*
int CELL_TYPE_NUMERIC = 0; 数字类型(普通数字,日期)
int CELL_TYPE_STRING = 1; 字符串类型
int CELL_TYPE_FORMULA = 2; 公式类型
int CELL_TYPE_BLANK = 3; 空白类型
int CELL_TYPE_BOOLEAN = 4; Boolean类型
int CELL_TYPE_ERROR = 5; 错误类型
*/
String Cellvalue = "";
switch (cellType){
case Cell.CELL_TYPE_NUMERIC: //数字类型(普通数字,日期)
//HSSFDateUtil.isCellDateFormatted为判断当前数字是否为日期
if(HSSFDateUtil.isCellDateFormatted(cell)){
Date dateCellValue = cell.getDateCellValue();
Cellvalue = new DateTime(dateCellValue).toString("YYYY-MM-dd");
}else{
Cellvalue = String.valueOf(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_STRING:
Cellvalue = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_FORMULA:
Cellvalue = cell.getCellFormula();
break;
case Cell.CELL_TYPE_BOOLEAN:
Cellvalue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
Cellvalue = String.valueOf(cell.getErrorCellValue());
break;
}
System.out.print(Cellvalue+" | ");
}
}
//显示完一行之后自动回车一下
System.out.println();
}
}