当前位置: 首页 > article >正文

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 对象作为参数,具体步骤如下:

  • 获取人员列表数据:调用 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表的导入

 @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. 返回结果

  • 如果在数据处理过程中没有出现小区名称不存在的错误,最后返回成功结果,表明数据导入成功。

在这里插入图片描述


http://www.kler.cn/a/530060.html

相关文章:

  • 一文了解DeepSeek
  • 标准IO与文件IO 进程与线程
  • python学opencv|读取图像(五十二)使用cv.matchTemplate()函数实现最佳图像匹配
  • OpenEuler学习笔记(十四):在OpenEuler上搭建.NET运行环境
  • Two Divisors ( Educational Codeforces Round 89 (Rated for Div. 2) )
  • Shell特殊状态变量以及常用内置变量总结
  • < 自用文儿 使用 acme 获取网站证书 > ACME 脚本 script: acme.sh 获得证书 觉得比 certbot 方便
  • 深入理解计算机系统:揭开计算机科学的神秘面纱
  • MFC程序设计(六)消息和控件
  • Spring Boot 实例解析:配置文件占位符
  • DeepSeek R1 本地部署安装包下载 及 本地部署教程
  • 【机器学习与数据挖掘实战】案例11:基于灰色预测和SVR的企业所得税预测分析
  • 【LeetCode 刷题】回溯算法-子集问题
  • CTFSHOW-WEB入门-命令执行54-70
  • 初步认识操作系统(Operator System)
  • 2025_2_2 C语言中字符串库函数,结构体,结构体内存对齐
  • RocketMQ中的NameServer主要数据结构
  • 网站快速收录:利用网站作者信息提升权重
  • ROS-SLAM
  • DeepSeek-R1模型1.5b、7b、8b、14b、32b、70b和671b有啥区别?
  • 25.2.2学习内容
  • C++11新特性之范围for循环
  • 使用 HTTP::Server::Simple 实现轻量级 HTTP 服务器
  • kamailio-kamctl monitor解释
  • 面经--C语言——sizeof和strlen,数组和链表,#include <>和 #include ““ #define 和typedef 内存对齐概述
  • Pluto固件编译笔记