AI智慧社区--Excel表的导入导出

Excel表导入导出的环境配置

1.导入依赖

xml 复制代码
 <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>${easypoi.version}</version>
        </dependency>

2.配置Excel的导入导出以及文件上传的路径

yaml 复制代码
upload:
  face: D:/community/upload/face/
  excel: D:/community/upload/excel/
  urlPrefix: http://localhost:8181/

3.配置文件的导出以及上传的本地映射路径

java 复制代码
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表的导出

java 复制代码
@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);
    }
java 复制代码
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 对象作为参数,具体步骤如下:

  • 获取人员列表数据 :调用 personServicepersonList 方法,传入 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 保存文件
  • 使用 HSSFWorkbookwrite 方法将数据写入到文件输出流 fos 中。
  • 关闭文件输出流 fos
2.5 返回文件名

返回导出文件的名称 descfile

同时会将路径映射为本地路径

二、Excel表的导入

java 复制代码
 @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
  • 文件读取 :使用 POIFSFileSystemHSSFWorkbook 读取 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、所属楼栋、房号、姓名、性别、手机号码、居住性质、备注等。同时,将创建者设置为当前登录用户的用户名。
  • 数据保存 :调用 personServicesave 方法将 single 对象保存到数据库中。如果保存过程中出现异常,会打印异常堆栈信息。

5. 返回结果

  • 如果在数据处理过程中没有出现小区名称不存在的错误,最后返回成功结果,表明数据导入成功。
相关推荐
IT毕设实战小研2 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
一只爱撸猫的程序猿3 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋3 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
武昌库里写JAVA5 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
Pitayafruit6 小时前
Spring AI 进阶之路03:集成RAG构建高效知识库
spring boot·后端·llm
zru_96026 小时前
Spring Boot 单元测试:@SpyBean 使用教程
spring boot·单元测试·log4j
甄超锋7 小时前
Java Maven更换国内源
java·开发语言·spring boot·spring·spring cloud·tomcat·maven
还是鼠鼠8 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
舒一笑12 小时前
Started TttttApplication in 0.257 seconds (没有 Web 依赖导致 JVM 正常退出)
jvm·spring boot·后端
javadaydayup14 小时前
Apollo 凭什么能 “干掉” 本地配置?
spring boot·后端·spring