前言
- Excel文件的导入导出功能,在项目中可以说是一个极其常见的功能了,使用到这技术的业务场景也非常多,例如:客户信息的导入导出,运营数据的导入导出,订单数据的导入导出等等。
- 而POI在就针对这方面的工具包,是Apche基介下的一个孵化项目,先一言不合就上官网吧:http://poi.apache.org/
集成 Poi
Poi 对 Excel 抽象出来的对象
刚才简单的说过了Excel文件相关的情况,但是那是在电脑中使用Excel需要用到的东西,如果要通过 SpringBoot 导入导入 Excel 文件,就要通过类和方法来进行。是吧这很面向对象,也符合我们dao的数据操控写入写出。
1.什么是 Poi
根据官方的介绍以及一些Excel方面的资料。
1.通过 office Excel软件或者 wps 常用的Excel格式有两种:
xls 和 xlsx两种格式
2.上图中的两个文件都是Excel文件,在一个Excel文件中包含若干张表,而本身Excel又是一个工作簿,对应Api中的workbook或者sheets这样的英文概念。默认创建的是有3个,可以自定义增加和删除以及修改对应工作表名字
3.一张表中可以分为很多行 row ,每行又分为很多单元格 cell
2.Poi 对 Excel 抽象出来的对象
如果要通过 SpringBoot 导入导入 Excel 文件,就要通过类和方法来进行。
于是在 Poi 中对以上提到的所有的名词都做了一定的封装。对应关系如下:
Excel中的概念 | Poi对应的对象 |
---|---|
Excel 文件 | HSSFWorkbook (xls)XSSFWorkbook(xlsx) |
Excel 的工作表 | HSSFSheet |
Excel 的行 | HSSFRow |
Excel 中的单元格 | HSSFCell |
Excel 字体 | HSSFFont |
Excel 单元格样式 | HSSFCellStyle |
Excel 颜色 | HSSFColor |
合并单元格 | CellRangeAddress |
3.案例整合
首先创建springboot项目,相信在学习整合poi的你,不会连工程都不会创建,略过。讲讲案例吧,使用springboot通过单元测试把我们要的对象导出在excel表格,自定义命名以及保存路径,为了演示效果,我将存放在桌面。
项目结构非常简单:
整合需要poi的pom依赖:
<!--poi依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14</version>
</dependency>
编写User类:
package com.tho.domain;
import java.io.Serializable;
public class User implements Serializable {
private Integer userId;
private String userName;
private String userAge;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAge() {
return userAge;
}
public void setUserAge(String userAge) {
this.userAge = userAge;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userAge='" + userAge + '\'' +
'}';
}
}
编写测试类:
package com.tho;
import com.tho.domain.User;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileOutputStream;
import java.io.IOException;
@SpringBootTest
class BootPoiApplicationTests {
@Test
void contextLoads() {
}
/**
* 导出数据
*/
@Test
public void test2() throws IOException {
// 0.准备数据
User user = new User();
user.setUserId(1);
user.setUserName("zhangsan");
user.setUserAge("20");
String[] titles = {"编号", "名字", "年龄"};
/**
* 先写入 标题栏数据
*/
// 1.创建文件对象 创建HSSFWorkbook只能够写出为xls格式的Excel
// 要写出 xlsx 需要创建为 XSSFWorkbook 两种Api基本使用方式一样
HSSFWorkbook workbook = new HSSFWorkbook();
//2.创建表对象
HSSFSheet sheet = workbook.createSheet("users");
//3.创建标题栏(第一行) 参数为行下标 行下标从0开始
HSSFRow titleRow = sheet.createRow(0);
//4.在标题栏中写入数据
for (int i = 0; i < titles.length; i++) {
// 创建单元格
HSSFCell cell = titleRow.createCell(i);
cell.setCellValue(titles[i]);
}
/**
* 写入用户数据
*/
// 5 创建行 如果是用户数据的集合 需要遍历
HSSFRow row = sheet.createRow(1);
//6 将用户数据写入到行中
row.createCell(0).setCellValue(user.getUserId());
row.createCell(1).setCellValue(user.getUserName());
row.createCell(2).setCellValue(user.getUserAge());
//文件保存到本地 参数为要写出的位置
workbook.write(new FileOutputStream("C:\\Users\\HaSee\\Desktop\\zhangsan.xls"));
}
}
测试:
导入:
/**
* 文件导入 实际上就是文件导出反向操作
*/
@Test
public void importTest() throws Exception {
// 1..通过流读取Excel文件
FileInputStream inputStream = new FileInputStream("C:\\Users\\HaSee\\Desktop\\zhangsan.xls");
// 2.通过poi解析流 HSSFWorkbook 处理流得到的对象中 就封装了Excel文件所有的数据
HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
// 3.从文件中获取表对象 getSheetAt通过下标获取
HSSFSheet sheet = workbook.getSheetAt(0);
// 4.从表中获取到行数据 从第二行开始 到 最后一行 getLastRowNum() 获取最后一行的下标
int lastRowNum = sheet.getLastRowNum();
for (int i = 1; i <= lastRowNum; i++) {
//通过下标获取行
HSSFRow row = sheet.getRow(i);
// 从行中获取数据
/**
* getNumericCellValue() 获取数字
* getStringCellValue 获取String
*/
double id = row.getCell(0).getNumericCellValue();
String name = row.getCell(1).getStringCellValue();
String age = row.getCell(2).getStringCellValue();
// 封装到对象中
User user = new User();
user.setUserId((int) id);
user.setUserName(name);
user.setUserAge(age);
//将对象添加数据库
System.out.println(user);
}
}
ok整合完成!
值得注意的是
:
本案例我们如果插入行的集合需要使用循环遍历完成,同时初始值应该为1,因为0是给标题使用的。其次我们导出的路径时,在实际中,通常需要对操作系统进行判断,还有\
在java中是转义符的意思而使用\\
才能得到正常的windows的路径。