Web端Excel的导入导出Demo

发布于:2024-04-18 ⋅ 阅读:(29) ⋅ 点赞:(0)

📚简介:

      使用阿里巴巴开源组件Easy Excel对Excel的读取和写入。如需更详细查看官方文档,当前案例主要对Web端的数据导出,和Excel文件上传到服务端进行数据解析的Demo.其中主要的是工具类的用法。

工具类的主要用法:

  • web端接口导出
  • web接口导入
  • 本地文件读取
  • 本地文件导出

✨代码的构建:

Maven坐标

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--easyexcel导出-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>poi-ooxml-schemas</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
        <!--这个库提供了操作 Microsoft Office 格式文件的核心功能,包括读取和写入 ExcelWordPowerPoint 等文件格式的能力。-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!--这个库提供了对 OOXML 格式文件的读写能力,因此在处理 .xlsx 格式的 Excel 文件时需要导入这个库。-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>

项目结构:

在这里插入图片描述

EasyExcelUtils 工具代码我放到文章的末尾,其他工具类如果需要的话可以去Gitee上拉代码自行查看 项目Demo

解析类的Excel注解解释

@Data
public class UserInfo {
    /**
     * 姓名
     */
    @ExcelProperty(value = "姓名",index = 0)
    private String name;
    /**
     * 性别
     */
    @ExcelProperty(value ="性别",index = 1)
    private String sex;
    /**
     * 年龄
     */
    @ExcelProperty(value ="年龄",index = 2)
    private Integer age;
    /**
     * 忽略这个字段 ExcelIgnore添加后导出和导入都会过滤这个字段
     */
    //@ExcelIgnore()
    @ExcelProperty(value ="手机",index = 3)
    private String phone;
}
  • ExcelProperty index 指定写到第几列,默认根据成员变量排序(使用了index那读取的时候Excel中的文件必须和这个index对应,Excel默认第一个字段就是index=0)。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头
  • ExcelIgnore 添加后导出和导入都会过滤这个字段
  • DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat
  • NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat

ExcelProperty的属性介绍

在这里插入图片描述

💭Web端接口Excel操作

本次使用的是ApiPost工具模拟接口请求

🚀下载接口

代码

    @GetMapping("userInfo/excelExport")
    public ResultData userInfoExcelExport() {
        List<UserInfo> userInfoList = getUserInfoList();
        EasyExcelUtils.download("用户列表", userInfoList);
        return ResultData.success();
    }

    public List<UserInfo> getUserInfoList() {
        List<UserInfo> userInfoList = new ArrayList<>();
        List<String> sexStrList = Arrays.asList("男", "女");
        Random sexRandom = new Random();
        for (int i = 0; i < 10; i++) {
            UserInfo userInfo = new UserInfo();
            String sexStr = sexStrList.get(sexRandom.nextInt(sexStrList.size()));
            userInfo.setSex(sexStr);
            String name = UserBuildUtils.buildName(sexStr);
            userInfo.setName(name);
            userInfo.setAge(RandomUtils.nextInt(18, 35));
            userInfo.setPhone(UserBuildUtils.generatePhoneNumber());
            userInfoList.add(userInfo);
        }
        return userInfoList;
    }

效果

在这里插入图片描述

下载文件中打开

在这里插入图片描述

在这里插入图片描述

🚀导入读取数据接口

代码

    @PostMapping("userInfo/excelImport")
    public ResultData userInfoExcelImport(@RequestParam("file") MultipartFile file) throws IOException {
        //解析导入的excel文件成对象
        List<UserInfo> userInfoList = EasyExcelUtils.readExcel(UserInfo.class, file.getInputStream());
        //处理对象
        System.out.println(userInfoList);
        return ResultData.success();
    }

效果

本地文件用户列表1713077847559.xlsx文件中一共有100条用户数据,接下来使用工具请求导入接口完成Excel文件数的读取

在这里插入图片描述

请求接口:

在这里插入图片描述
在这里插入图片描述

🏡本地Excel文件操作

⚡导出数据

代码

       /**
     * Excel的导出
     */
    @Test
    void ExcelExport() {
        String outFile = System.getProperty("user.dir") + File.separatorChar + "file";

        List<UserInfo> userInfoList = new ArrayList<>();
        List<String> sexStrList = Arrays.asList("男","女");
        Random sexRandom = new Random();
        for (int i = 0; i < 100; i++) {
            UserInfo userInfo = new UserInfo();
            String sexStr = sexStrList.get(sexRandom.nextInt(sexStrList.size()));
            userInfo.setSex(sexStr);
            String name = UserBuildUtils.buildName(sexStr);
            userInfo.setName(name);
            userInfo.setAge(RandomUtils.nextInt(18, 35));
            userInfo.setPhone(UserBuildUtils.generatePhoneNumber());
            userInfoList.add(userInfo);
        }
        String outFileName = "用户列表" + System.currentTimeMillis() + ".xlsx";
        EasyExcelUtils.write(outFile, outFileName, UserInfo.class, userInfoList, "用户列表");
    }

效果:会在当前工程中的file文件夹中创建导出的Excel文件

在这里插入图片描述

🌈导入读取数据

代码

    /**
     * Excel导入
     */
    @Test
    void ExcelImport() {
        //Excel文件路径
        String filePath = System.getProperty("user.dir") + File.separatorChar + "file" + File.separatorChar
                + "readFile" + File.separatorChar + "用户列表1713077847559.xlsx";
        List<UserInfo> userInfoList = EasyExcelUtils.readExcel(UserInfo.class, filePath);
        System.out.println(userInfoList);
    }

效果: 指定需要读取的文件路径

在这里插入图片描述

EasyExcelUtils 工具类:


/**
 * @Author itmei
 * @Date 2024/4/13 20:49
 * @description:
 * @Title: EasyExcelUtils
 * @Package com.itmei.exceldemo.utils
 */
public class EasyExcelUtils {

    /**
     * 写文件
     *
     * @param outFileName 写的路径
     * @param clazz       用于获取类中的Excel注解
     * @param list        数据
     */
    public static void write(String outFileName, Class<?> clazz, List<?> list) {
        // 新版本会自动关闭流,不需要自己操作
        EasyExcel.write(outFileName, clazz).sheet().doWrite(list);
    }

    /**
     * 写文件
     *
     * @param outFileName 文件名称
     * @param clazz       用于获取类中的Excel注解
     * @param list        数据
     * @param sheetName   工作簿名称
     */
    public static void write(String outFileName, Class<?> clazz, List<?> list, String sheetName) {
        // 新版本会自动关闭流,不需要自己操作
        EasyExcel.write(outFileName, clazz).sheet(sheetName).doWrite(list);
    }

    /**
     * 写文件
     *
     * @param outFile     保存的文件位置(必须存在否则报错)
     * @param outFileName 文件名称
     * @param clazz       用于获取类中的Excel注解
     * @param list        数据
     * @param sheetName   工作簿名称
     */
    public static void write(String outFile, String outFileName, Class<?> clazz, List<?> list, String sheetName) {
        // 新版本会自动关闭流,不需要自己操作
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outFile + File.separatorChar + outFileName, clazz);
        excelWriterBuilder.sheet(sheetName).doWrite(list);
    }

    /**
     * 写文件
     *
     * @param outputStream 输出流
     * @param list         数据
     * @param sheetName    工作簿名称
     */
    public static void write(OutputStream outputStream, List<?> list, String sheetName) {
        Class<?> clazz = list.get(0).getClass();
        // sheetName为sheet的名字,默认写第一个sheet
        EasyExcel.write(outputStream, clazz).sheet(sheetName).doWrite(list);
    }

    /**
     * 文件下载,用于前端下载Excel
     *
     * @param sheetName 工作簿名称
     * @param list      数据
     * @throws IOException
     */
    public static void download(String sheetName, List<?> list) {
        HttpServletResponse response = HttpServletUtil.getResponse();
        try {
            Class<?> clazz = list.get(0).getClass();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(sheetName + "_" + DateUtils.format(new Date()), "UTF-8").replaceAll("\\+", "%20") + ".xlsx";
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            EasyExcel.write(response.getOutputStream(), clazz)
                    .autoCloseStream(false)
                    .sheet(sheetName)
                    .doWrite(list);
        } catch (Exception e) {
            handleException(response, e);
        }
    }

    private static void handleException(HttpServletResponse response, Exception e) {
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        Map<String, Object> map = MapUtils.newHashMap();
        map.put("status", "failure");
        map.put("message", "下载文件失败" + e.getMessage());
        try {
            response.getWriter().println(mapToJsonString(map));
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    /**
     * 将 Map 对象转换成 JSON 格式的字符串
     *
     * @param map
     * @return
     */
    public static String mapToJsonString(Map<String, Object> map) {
        StringBuilder json = new StringBuilder("{");
        boolean first = true;

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (!first) {
                json.append(",");
            }
            json.append("\"").append(entry.getKey()).append("\":");
            Object value = entry.getValue();
            if (value instanceof String) {
                json.append("\"").append(value).append("\"");
            } else {
                json.append(value);
            }
            first = false;
        }

        json.append("}");
        return json.toString();
    }

    /**
     * 读取Excel文件并且返回集合对象
     *
     * @param classT
     * @param filePath
     * @param <T>
     * @return
     */
    public static <T> List<T> readExcel(Class<T> classT, String filePath) {
        List<T> readAllList = new ArrayList<>();
        EasyExcel.read(filePath, classT, new ReadListener<T>() {
            @Override
            public void invoke(T data, AnalysisContext context) {
                //这个每一条数据解析都会来调用
                readAllList.add(data);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                //全部读取完成后会调用
            }
        }).sheet().doRead();
        return readAllList;
    }

    public static <T> List<T> readExcel(Class<T> classT, InputStream inputStream) {
        List<T> readAllList = new ArrayList<>();
        try {
            EasyExcel.read(inputStream, classT, new ReadListener<T>() {
                @Override
                public void invoke(T data, AnalysisContext context) {
                    // 这个每一条数据解析都会来调用
                    readAllList.add(data);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 全部读取完成后会调用
                    try {
                        inputStream.close(); // 关闭输入流
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
            // 处理异常情况,比如日志记录或者抛出自定义异常
        }
        return readAllList;
    }
}