Title

使用 hutool包进行excel导入导出

依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.6</version>
</dependency>
<!--Export as Excel-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.1</version>
</dependency>

导入

/**
 * excel导入
 */
@PostMapping("/upload")
@ApiOperation("excel导入")
public Result upload(@RequestParam("file") MultipartFile file) throws IOException {
    // 通过文件获取输入流
    InputStream in = file.getInputStream();
    // 借助hutool读取
    ExcelReader reader = ExcelUtil.getReader(in);
    List<List<Object>> list = reader.read(1); // 从第二行开始读
    // 创建一个List集合
    List<User> users = CollUtil.newArrayList();
    List<List<Object>> data = new ArrayList<>(0);
    // 遍历
    for (List<Object> row : list) {
        User user = new User();
        // 转换成字符串
        user.setUsername(row.get(0).toString());
        user.setPassword(row.get(1).toString());
        user.setNickname(row.get(2).toString());
        user.setEmail(row.get(3).toString());
        user.setPhone(row.get(4).toString());
        user.setAddress(row.get(5).toString());
        // 遍历完一个添加一个
        users.add(user);
        data.add(row);
    }
    // 调用mapper添加到数据库
    boolean flag = userService.addAll(users);

    // 输出到本地文件
    ExcelWriter writer = ExcelUtil.getWriter(new File("C:\\Users\\zg\\Downloads\\export.xlsx"));
    writer.writeHeadRow(Arrays.asList("账号", "密码", "用户名称", "邮箱", "电话"));
    for (List<Object> row : data) {
        // 写入整行
        writer.writeRow(row);
    }
    // 关闭流
    writer.flush();
    writer.close();
    return flag ? Result.ok() : Result.failed();
}

使用 List<List<Object>> list = reader.read(1); 导入时候,excel 如果有多个相邻都为空的会识别成一个空的问题

解决:使用 reader.readAll(); 方法

List<Map<String, Object>> maps = reader.readAll();
map读取为:{姓名=李四, 年龄=null, 性别=null}

使用实体类,表头和字段名一致即可
List<User> list = reader.readAll(User.class);

导出

设置样式

官网自定义样式

ExcelWriter writer = ...;

// 定义单元格背景⾊
StyleSet style = writer.getStyleSet();
// 第⼆个参数表⽰是否也设置头部单元格背景
style.setBackgroundColor(IndexedColors.RED, false);
//设置内容字体
Font font = writer.createFont();
font.setBold(true);
font.setColor(Font.COLOR_RED); 
font.setItalic(true); 
//第⼆个参数表⽰是否忽略头部样式
writer.getStyleSet().setFont(font, true);

以上⾃定义样式是针对单元格集合的,划分为:
头部样式 headCellStyle
普通单元格样式 cellStyle
数字单元格样式 cellStyleForNumber
⽇期单元格样式 cellStyleForDate

有时候我们只需要修改单个单元格样式,其他单元格样式采⽤默认样式,参考如下:

@GetMapping("downloadExampleExcel")
    public Response downloadExampleExcel(HttpServletResponse response) {
        logger.info("downloadExampleExcel response start。。。");
        List<Title> titles = titleService.selectTitles();
        ExcelWriter writer = ExcelUtil.getWriter();
        for (int i = 0, j = 0; i < titles.size(); i++) {
            Title title = titles.get(i);
            writeCell(writer, j ++, title.getFieldDescC(), title.getRequiredFlag());
        }
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + "⽂件名" + ".xls");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (Exception e) {
            log.error("downloadExampleExcel response exception", e);
            return ResponseHelper.buildFail(e.getMessage());
        } finally {
            writer.close();
            if (out != null) {
                IoUtil.close(out);
            }
            logger.info("downloadExampleExcel response end。。。");
        }
        return ResponseHelper.buildOk();
    }
    /**
     * 输⼊标题到excel
     * @param writer excel对象
     * @param column 当前列位置
     * @param cellValue 标题内容
     * @param requiredFlag 是否标红
     */
    private void writeCell(ExcelWriter writer, int column, String cellValue, String requiredFlag){
        // 根据x,y轴设置单元格内容
        writer.writeCellValue(column , 0, cellValue);
        Font font = writer.createFont();
        font.setColor(Font.COLOR_RED);
        if (Constants.NUMBER_TWO.equals(requiredFlag)){
            // 根据x,y轴获取当前单元格样式 x 列数,从 0 开始    y 行数,从 0 开始 (包括标题栏)
            CellStyle cellStyle = writer.createCellStyle(column, 0);
            // 内容⽔平居中
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            // 内容垂直居中
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            // 设置边框
            cellStyle.setBorderBottom(BorderStyle.THIN);
            cellStyle.setBorderLeft(BorderStyle.THIN);
            cellStyle.setBorderRight(BorderStyle.THIN);
            // 字体颜⾊标红
            cellStyle.setFont(font);
        }
    }

效果:

由于 autoSizeColumnAll() 自动设置列宽方法只对数字、字母生效,对中文不生效

针对中文设置列宽

        ExcelWriter writer = ExcelUtil.getWriter(true);
        //写数据 writer.write(data, true);
        StyleSet style = writer.getStyleSet();
        Font font = writer.createFont();
        font.setColor(IndexedColors.VIOLET.index);
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        //重点,设置中文字体
        font.setFontName("宋体");
        style.getHeadCellStyle().setFont(font);
        int columnCount = writer.getColumnCount();
        for (int i = 0; i < columnCount; ++i) {
            double width = SheetUtil.getColumnWidth(writer.getSheet(), i, false);
            if (width != -1.0D) {
                width *= 256.0D;
                //此处可以适当调整,调整列空白处宽度
                width += 220D;
                writer.setColumnWidth(i, Math.toIntExact(Math.round(width / 256D)));
            }
        }

默认导出

/**
 * 文件导出 excel
 */
public void exportFile(HttpServletResponse response) throws IOException {
    ExcelWriter writer = ExcelUtil.getWriter();
    String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    // 设置表名
    String excelName="导出文件"+time+".xls";
    // 设置表头
    List<Object> header= CollectionUtil.newArrayList("编号","姓名","年龄","生日","性别");
    // 使用 mybatis-plus 快速查询数据
    Collection<UserEntity> userList = userMapper.selectList(new QueryWrapper<UserEntity>());
    // 输出数据设置
    List<List<Object>> rows=userList.stream().map(a->{
        List<Object> list=new ArrayList<>(0);
        list.add(a.getId());
        list.add(a.getUsername());
        list.add(a.getAge());
        list.add(a.getBirth());
        list.add(a.getGender());
        return list;
    }).collect(Collectors.toList());
    // 数据导出
    writer.writeHeadRow(header).write(rows==null?new ArrayList<List<Object>>():rows);
    response.setContentType("application/vnd.ms-excel;charset=utf-8");
    response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(excelName, "utf-8"));
    ServletOutputStream out = response.getOutputStream();
    // 关闭连接
    writer.flush(out).close();
}

自定义导出

  • 工具类
package com.zl.util;

import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.SheetUtil;

/**
 * hutool excel 工具类
 */
public class LocalExcelUtil {
    /**
     * 设置 excel 单元格颜色
     * @param writer ExcelWriter
     * @param x 列
     * @param y 行
     * @param color 颜色
     */
    public static void setColor(ExcelWriter writer,int x,int y,short color){
        Font font = writer.createFont();
        font.setColor(color);
        CellStyle cellStyle = writer.createCellStyle(x, y);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setFont(font);
    }

    /**
     * 设置 excel 自动列宽
     * @param writer ExcelWriter
     * @param fontName 字体
     * @param bold 加粗
     * @param fontColor 字体颜色
     */
    public static void setAuthColWidth(ExcelWriter writer,String fontName,Boolean bold,short fontColor){
        writer.autoSizeColumnAll();
        StyleSet style = writer.getStyleSet();
        Font font = writer.createFont();
        font.setColor(fontColor);
        // 加粗
        font.setBold(bold);
        font.setFontHeightInPoints((short) 12);
        //重点,设置中文字体
        font.setFontName(fontName);
        style.getHeadCellStyle().setFont(font);
        int columnCount = writer.getColumnCount();
        for (int i = 0; i < columnCount; ++i) {
            double width = SheetUtil.getColumnWidth(writer.getSheet(), i, false);
            if (width != -1.0D) {
                width *= 256.0D;
                //此处可以适当调整,调整列空白处宽度
                width += 220D;
                writer.setColumnWidth(i, Math.toIntExact(Math.round(width / 256D)));
            }
        }
    }
}
  • 导出
    /**
     * 导出数据
     * @param queryUserVO 查询参数
     * @param response 响应
     */
    @Override
    public void exportUserInfo(QueryUserVO queryUserVO, HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter();
        StyleSet styleSet=writer.getStyleSet();
        // 第二个参数表示是否也设置头部单元格背景
        styleSet.setBackgroundColor(IndexedColors.WHITE,true);
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd %T"));
        // 设置表名
        String excelName="用户数据"+time+".xls";
        String titleName="用户数据";
        // 查询数据
        QueryWrapper<UserEntity> queryWrapper=new QueryWrapper<>();
        Object[] prams={queryUserVO.getStartTime(),queryUserVO.getEndTime()};
        queryWrapper.apply("DATE_FORMAT(birth,'%Y-%m-%d %T') BETWEEN {0} and {1}",prams);
        queryWrapper.orderByAsc("birth");
        List<UserEntity> data = list(queryWrapper);
        // 查询性别 0 女  1 男
        queryWrapper.eq("gender",queryUserVO.getGender());
        switch (queryUserVO.getGender()){
            case 0:
                titleName= titleName+"(女)";
                break;
            case 1:
                titleName= titleName+"(男)";
                break;
        }
        // 设置表头
        List<Object> header= CollectionUtil.newArrayList("姓名","性别","年龄","生日");
        writer.merge(header.size()-1, titleName);
        writer.writeHeadRow(header);
        // 数据导出
        IntStream.range(0,data.size()).forEach(i->{
            // x 表示列 y 表示行
            writer.writeCellValue(0,i+2,data.get(i).getUsername());
            writer.writeCellValue(1,i+2,data.get(i).getGender());
            writer.writeCellValue(2,i+2,data.get(i).getAge());
            // 当年龄大于55岁时显示红色
            if(data.get(i).getAge()>55){
                LocalExcelUtil.setColor(writer,2,i+2,Font.COLOR_RED);
            }
            writer.writeCellValue(3,i+2,new SimpleDateFormat("yyyy/MM/dd").format(data.get(i).getBirth()));
        });
        // 设置默认列宽
        LocalExcelUtil.setAuthColWidth(writer,"宋体",false,IndexedColors.BLACK.index);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(excelName, "utf-8"));
        ServletOutputStream out = response.getOutputStream();
        // 关闭连接
        writer.flush(out).close();
    }

根据业务相应的改动就行


参考链接:

https://wenku.baidu.com/view/547d8a39b4360b4c2e3f5727a5e9856a561226ff.html

posted @ 2022-05-26 18:42  快乐小洋人  阅读(3814)  评论(0编辑  收藏  举报