AI智慧社区--Excel表的导入导出
Excel表导入导出的环境配置
1.导入依赖
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>${easypoi.version}</version>
</dependency>
2.配置Excel的导入导出以及文件上传的路径
upload:
face: D:/community/upload/face/
excel: D:/community/upload/excel/
urlPrefix: http://localhost:8181/
3.配置文件的导出以及上传的本地映射路径
package com.southwind.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Value("${upload.face}")
String face;
@Value("${upload.excel}")
String excel;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 假设前端要访问的faceUrl为 http://localhost:8181/community/upload/face/+生成的文件名
* 会被映射为 D:/community/upload/face/+生成的文件名
*/
registry.addResourceHandler("/community/upload/face/**").addResourceLocations("file:"+face);
registry.addResourceHandler("/community/upload/excel/**").addResourceLocations("file:"+excel);
}
}
一、Excel表的导出
@GetMapping("/exportExcel")
public Result exportExcel(PersonListForm personListForm){
//获取用户的列表,拿到要导出的数据
PageVO pageVO = this.personService.personList(personListForm);
//只需要list数据,进行导出
List list = pageVO.getList();
//path:D:/community/upload/excel/
String path = excel;
//导入文件
path = ExcelUtil.ExpPersonInfo(list,path);
return Result.ok().put("data", path);
}
package com.southwind.util;
import com.southwind.vo.PersonVO;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.BorderStyle;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ExcelUtil {
public static String ExpPersonInfo(List<PersonVO> info, String path){
// // 声明 POIFSFileSystem 对象,用于处理 Excel 文件的输入流
POIFSFileSystem fs = null;
//从第二行开始写
int headRow = 2;
//目标文件名称
String descfile = null;
try {
//复制文件
//文件路径:D:/community/upload/excel/personInfo.xls
String srcfile = path + "personInfo.xls";
//编辑导入文件的文件名
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String dateStr = format.format(date);
descfile = dateStr + ".xls";
try {
///文件的输入流,用于读取模板文件
FileInputStream fis = new FileInputStream(srcfile);
//文件的输出流,用于写入新文件
FileOutputStream fos = new FileOutputStream(path+descfile);
byte [] buffer = new byte[1024*4];
//如果缓冲区中还有内容,继续写
while(fis.read(buffer) != -1){
fos.write(buffer);
}
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
//写数据
fs = new POIFSFileSystem(new FileInputStream(path + descfile));
FileOutputStream fos = new FileOutputStream(path + descfile);
//创建 HSSFWorkbook 对象,用于操作 Excel 文件
HSSFWorkbook wb1 = new HSSFWorkbook(fs);
//获取第一个工作表
HSSFSheet sheet = wb1.getSheetAt(0);
//获取人员信息列表的大小
int size = info.size();
int col = 0;
//创建一个单元格样式对象
HSSFCellStyle style = wb1.createCellStyle();
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
for(int i = 0;i < size;i++){
col = 0;
PersonVO p = info.get(i);
HSSFRow row = sheet.createRow(i+headRow);
HSSFCell cell = null;
//写入居民ID
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getPersonId());
//写入小区名称
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getCommunityName());
//居住的楼栋
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getTermName());
//房号
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getHouseNo());
//用户名
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getUserName());
//性别
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getSex());
//手机号
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getMobile());
//居住类型
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getPersonType());
//备注
cell = row.createCell(col++);
cell.setCellStyle(style);
cell.setCellValue(p.getRemark());
}
wb1.write(fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return descfile;
}
}
Excel表的导出流程
1. 控制器层接收请求
在控制器中,定义了一个 @GetMapping
注解的方法 exportExcel
,用于处理 /exportExcel
的 GET 请求,接收一个 PersonListForm
对象作为参数,具体步骤如下:
-
获取人员列表数据:调用
personService
的personList
方法,传入personListForm
参数,获取包含人员信息的分页对象PageVO
。 -
提取数据列表:从
PageVO
对象中提取出人员信息列表list
,该列表将用于后续的 Excel 导出。 -
指定文件保存路径:定义一个字符串
path
,用于指定 Excel 文件的保存路径,这里的excel
变量应该是在配置文件中定义的路径字符串。 -
调用导出工具类方法:调用
ExcelUtil
工具类的ExpPersonInfo
方法,将人员信息列表list
和保存路径path
作为参数传入,执行具体的导出操作。 -
返回结果:将导出文件的路径封装在
Result
对象中返回给客户端。
2. 工具类实现 Excel 导出
ExcelUtil
工具类中的 ExpPersonInfo
方法实现了具体的 Excel 导出逻辑,步骤如下:
2.1 初始化变量
- 声明
POIFSFileSystem
对象fs
,用于处理 Excel 文件的输入流。 - 定义
headRow
变量,指定数据从 Excel 文件的第二行开始写入。 - 定义
descfile
变量,用于存储导出文件的名称。
2.2 复制模板文件
- 指定模板文件路径:拼接模板文件的完整路径
srcfile
,模板文件名为personInfo.xls
。 - 生成导出文件名:使用当前时间生成一个唯一的文件名
descfile
,格式为yyyyMMddHHmmss.xls
。 - 复制文件:通过
FileInputStream
读取模板文件,通过FileOutputStream
将模板文件内容复制到新文件中。
2.3 写入数据
- 创建工作簿和工作表:使用
POIFSFileSystem
读取新文件,创建HSSFWorkbook
对象wb1
来操作 Excel 文件,并获取第一个工作表sheet
。 - 获取数据列表大小:获取人员信息列表
info
的大小,用于循环写入数据。 - 创建单元格样式:创建一个
HSSFCellStyle
对象style
,设置单元格的边框样式为细边框。 - 循环写入数据:遍历人员信息列表
info
,为每一条记录创建一行HSSFRow
,并在该行中创建多个单元格HSSFCell
,将人员信息的各个字段(如居民 ID、小区名称、房号等)写入对应的单元格中,并设置单元格的样式。
2.4 保存文件
- 使用
HSSFWorkbook
的write
方法将数据写入到文件输出流fos
中。 - 关闭文件输出流
fos
。
2.5 返回文件名
返回导出文件的名称 descfile
。
同时会将路径映射为本地路径
二、Excel表的导入
@LogAnnotation("导入数据")
@PostMapping("/parsefile/{fileName}")
public Result parsefile(@PathVariable("fileName") String fileName,HttpSession session){
//获取用户信息
User user = (User) session.getAttribute("user");
//用于处理输入流的
POIFSFileSystem fs = null;
//用于处理Excel的
HSSFWorkbook wb = null;
try {
//basePath:D:/community/upload/excel/用户名
String basePath = excel + fileName;
fs = new POIFSFileSystem(new FileInputStream(basePath));
wb = new HSSFWorkbook(fs);
} catch (Exception e) {
e.printStackTrace();
}
HSSFSheet sheet = wb.getSheetAt(0);
Object[][] data = null;
int r = sheet.getLastRowNum()+1;
int c = sheet.getRow(0).getLastCellNum();
int headRow = 2;
data = new Object[r - headRow][c];
for (int i = headRow; i < r; i++) {
HSSFRow row = sheet.getRow(i);
for (int j = 0; j < c; j++) {
HSSFCell cell = null;
try {
cell = row.getCell(j);
try {
cell = row.getCell(j);
DataFormatter dataFormater = new DataFormatter();
String a = dataFormater.formatCellValue(cell);
data[i - headRow][j] = a;
} catch (Exception e) {
data[i-headRow][j] = "";
if(j==0){
try {
double d = cell.getNumericCellValue();
data[i - headRow][j] = (int)d + "";
}catch(Exception ex){
data[i-headRow][j] = "";
}
}
}
} catch (Exception e) {
System.out.println("i="+i+";j="+j+":"+e.getMessage());
}
}
}
int row = data.length;
int col = 0;
String errinfo = "";
headRow = 3;
String[] stitle={"ID","小区名称","所属楼栋","房号","姓名","性别","手机号码","居住性质","状态","备注"};
errinfo = "";
for (int i = 0; i < row; i++) {
Person single = new Person();
single.setPersonId(0);
single.setState(1);
single.setFaceUrl("");
try {
col=1;
String communityName = data[i][col++].toString();
QueryWrapper<Community> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("community_name", communityName);
Community community = this.communityService.getOne(queryWrapper);
if( community == null){
errinfo += "Excel文件第" + (i + headRow) + "行小区名称不存在!";
return Result.ok().put("status", "fail").put("data", errinfo);
}
single.setCommunityId(community.getCommunityId());
single.setTermName(data[i][col++].toString());
single.setHouseNo(data[i][col++].toString());
single.setUserName(data[i][col++].toString());
single.setSex(data[i][col++].toString());
single.setMobile(data[i][col++].toString());
single.setPersonType(data[i][col++].toString());
single.setRemark(data[i][col++].toString());
single.setCreater(user.getUsername());
this.personService.save(single);
} catch (Exception e) {
e.printStackTrace();
}
}
return Result.ok().put("status", "success").put("data","数据导入完成!");
}
Excel表的导入流程
1. 接收请求并获取用户信息
- 请求映射:使用
@PostMapping("/parsefile/{fileName}")
注解,表明该方法处理/parsefile/{fileName}
路径的 POST 请求,{fileName}
作为路径变量传入。 - 获取用户信息:从
HttpSession
中获取当前登录用户的信息,存储在User
对象user
中,后续用于记录数据的创建者。
2. 读取 Excel 文件
- 文件路径拼接:将全局变量
excel
和传入的文件名fileName
拼接成完整的文件路径basePath
。 - 文件读取:使用
POIFSFileSystem
和HSSFWorkbook
读取 Excel 文件。如果读取过程中出现异常,会打印异常堆栈信息。
3. 解析 Excel 数据到二维数组
- 获取工作表:从
HSSFWorkbook
中获取第一个工作表sheet
。 - 计算行列数:获取工作表的最后一行索引
r
和第一行的最后一个单元格索引c
,用于确定数据的范围。 - 数据初始化:由于数据从第三行(索引为 2)开始,所以
headRow
设为 2,创建一个二维数组data
用于存储解析后的数据。 - 遍历单元格:使用双重循环遍历工作表中的每一个单元格,从第三行开始。对于每个单元格,使用
DataFormatter
格式化其值并存储到data
数组中。如果单元格为空或出现异常,将该位置的值设为空字符串。对于第一列(索引为 0),如果单元格是数值类型,将其转换为整数后再转换为字符串存储。
4. 处理解析后的数据并保存到数据库
- 数据遍历:遍历
data
数组中的每一行数据。 - 对象初始化:创建一个
Person
对象single
,并初始化一些默认值,如personId
设为 0,state
设为 1,faceUrl
设为空字符串。 - 小区名称验证:从
data
数组中获取小区名称,使用QueryWrapper
查询数据库中是否存在该小区。如果不存在,将错误信息添加到errinfo
中,并返回失败结果。 - 数据赋值:如果小区名称验证通过,将解析后的数据依次设置到
single
对象中,包括小区 ID、所属楼栋、房号、姓名、性别、手机号码、居住性质、备注等。同时,将创建者设置为当前登录用户的用户名。 - 数据保存:调用
personService
的save
方法将single
对象保存到数据库中。如果保存过程中出现异常,会打印异常堆栈信息。
5. 返回结果
- 如果在数据处理过程中没有出现小区名称不存在的错误,最后返回成功结果,表明数据导入成功。