Poi介绍
Poi是由apache公司提供的Java编写的免费开源跨平台的Java API,提供让Java程序对Microsoft Office档案读和写的功能。也是目前针对Excel读写比较常用的实现方案。
poi分为2003版(.xls文件)和2007版(.xlsx文件),本次只介绍07版Excel的基础操作
导入相关的jar
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
Poi包结构:
HSSF —— 读写 Microsoft Excel xls(07版本之前的Excel)
XSSF —— 读写 Microsoft Excel OOXML XLSX(07版本之后的Excel)
HWPF —— 读写 Word
HSLF —— 读写 PowerPoint(PPT)
其实我们主要用的就是XSSF
读取Excel
Poi如何读取操作表格?其实在Poi内部封装了一些对象
XSSFWorkbook:工作簿
XSSFSheet:工作表
Row:行
Cell:单元格
具体使用
那这里我做了一个简答的表格来模仿,如何将表格中的数据读取出来,并且放入到实体类中,后续用于写入数据库
首先创建一个product的实体类
/**
* 此类型用户测试poi读取Excel表格功能
* 将读取的数据,存入到当前Product类型的属性中
* Excel中的每一条数据为一个Product实列
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Product {
private Integer id;
private String name;
private Double price;
private Integer count;
}
然后创建具体的测试类来读取表格中的数据
/**
* 利用Poi读取excel表格数据
*/
public class ReadDemo {
public static void main(String[] args) {
try {
List<Product> products = read("D:\JAVA_\a.xlsx");
for (Product product : products) {
System.out.println(product);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<Product> read(String path) throws Exception{
//最后输出的实体类的集合
List<Product> products = new ArrayList<>();
// 1. 创建输入流
FileInputStream fip = new FileInputStream(path);
// 2. 在输入流中获取工作簿(excel表格)
XSSFWorkbook workbook = new XSSFWorkbook(fip);
// 3. 在目标工作簿中获取目标工作表 0:表示第一个工作表
Sheet sheet = workbook.getSheetAt(0);
// 4. 获取工作表的行数(有数据的)
int rowNum = sheet.getPhysicalNumberOfRows();
// 除去第一行,有效数据从第二行开始
for (int i = 1; i < rowNum; i++) {
// 5. 获取除第一行以外的所有行
Row row = sheet.getRow(i);
if(row!=null){
//用于保存每一行数据的集合
List<String> list = new ArrayList<>();
for (Cell cell : row) {
if(cell!=null){
// 6. 把一行中所有的数据转化为String,方便数据处理
cell.setCellType(Cell.CELL_TYPE_STRING);
// 7. 获取所有单元格的数据
String value = cell.getStringCellValue();
if(value !=null && !value.equals("")){
// 8. 将每一个单元格的数据放入到list集合中
list.add(value);
}
}
}
// 9. 把获取的每一行数据封装成product对象
if(list.size()>0){
Product product = new Product(Integer.parseInt(list.get(0)), list.get(1), Double.parseDouble(list.get(2)), Integer.parseInt(list.get(3)));
// 将product对象放入products对象中
products.add(product);
}
}
}
return products;
}
}
测试
当遇到实体类中对象数据较多时 用list封装就比较麻烦,此时可以采用Map来封装数据,但是第一列的数据要与实体类中的属性值相对应
/**
* 解析表格的工具类
*/
public class ExcelUtil {
/**
* 解析表格的方法(通用)
* @param stream 文件的输入流
* @param clazz 实体类类型
* @param <T> 任何数据类型
* @return 解析表格的数据
*/
public static <T>List<T> readExcel (FileInputStream stream,Class<T> clazz) throws Exception {
List<T> result = new ArrayList<>();
//从输入流中获取工作簿
XSSFWorkbook workbook = new XSSFWorkbook(stream);
//在工作簿中获取目标工作表
Sheet sheet = workbook.getSheetAt(0);
//获取工作表中的行数
int rowNums = sheet.getPhysicalNumberOfRows();
//获取第一行数据,因为Excel表格中第一行数据包含对应要映射的属性
Row row = sheet.getRow(0);
//遍历第一行的数据,遍历出的数据就是所需要新增数据的所有属性,并且把这些数据放入到key集合中
List<String> key = new ArrayList<>();
// 遍历第一行数据,遍历出所有需要新增的属性,并把这些属性放入key中
for (Cell cell : row) {
cell.setCellType(Cell.CELL_TYPE_STRING);
key.add(cell.getStringCellValue());
}
// 遍历所有的正式数据,但是要跳过第二行标题数据,所以下标要从2开始;
for(int i=2;i<rowNums;i++){
// 获取所有行
row = sheet.getRow(i);
if(row!=null){
// 遍历所有单元格中的数据,并且把key和value(单元格的数据),放入到excelMap中映射
//计数器用于映射数据使用
int count = 0;
//用于保存每条数据的Map,并且在Map中建立属性与对应关系的映射关系
Map<String,String> excelMap = new HashMap<>();
for (Cell cell : row) {
if(cell != null){
cell.setCellType(Cell.CELL_TYPE_STRING);
//获取每个单元格的数据
String value = cell.getStringCellValue();
if(value!=null && !value.equals("")){
// 将每个单元格的数据,存储到集合中
excelMap.put(key.get(count),value);
count++;
}
}
}
//创建对应的实体类类型
T t =clazz.newInstance();
/**
* Spring 提供的BeanMap,它可以通过反射的形式把Map中的数据映射到实体类中
*/
BeanMap beanMap = BeanMap.create(t);
beanMap.putAll(excelMap);
result.add(t);
}
}
return result;
}
}