EasyExcel--导入和导出Excel的方法

原文网址:EasyExcel--导入和导出Excel的方法_IT利刃出鞘的博客-CSDN博客

简介

本文介绍SpringBoot整合EasyExcel导入和导出Excel的方法。

使用

Excel导入

实体类

java 复制代码
@Data
public class OrderImportBO {
    @ExcelProperty("订单号")
    @NotBlank(message = "订单号不能为空")
    private String scOrderPoolId;

    @ExcelProperty("金额")
    private String amount;
}

Controller

java 复制代码
@PostMapping("importOrder")
public void importOrder(@RequestPart MultipartFile file) {
    List<OrderImportBO> orderImportBOList = ExcelUtil.importExcel(file, OrderImportBO.class);
}

Excel导出

实体类

java 复制代码
@Data
public class OrderExportBO {
    @ExcelProperty("订单号")
    @NotBlank(message = "订单号不能为空")
    private String scOrderPoolId;

    @ExcelProperty("金额")
    private String amount;
}

Service

java 复制代码
List<OrderExportVO> exportVOS = new ArrayList();
ExcelUtil.exportExcel(exportVOS, OrderExportVO.class);

详细代码

依赖

EasyExcel

XML 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.11</version>
</dependency>

整个pom.xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.knife</groupId>
    <artifactId>demo_EasyExcel_SpringBoot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo_EasyExcel_SpringBoot</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>easyexcel</artifactId>
			<version>2.2.11</version>
		</dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.0.RELEASE</version>
            </plugin>
        </plugins>
    </build>

</project>

Excel配置

字符串转换器

java 复制代码
package com.knife.excel.handler;


import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

public class StringConverter implements Converter<String> {

    @Override
    public Class supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 将excel对象转成Java对象,这里读的时候会调用
     */
    @Override
    public String convertToJavaData(CellData cellData, 
ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return cellData.getStringValue().trim();
    }

    /**
     * 将Java对象转成String对象,写出的时候调用
     */
    @Override
    public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData(value);
    }
}

writeHandler

java 复制代码
package com.knife.excel.halper;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelHandler extends AbstractColumnWidthStyleStrategy {

    private static final int MAX_COLUMN_WIDTH = 255;
    
    //因为在自动列宽的过程中,有些设置地方让列宽显得紧凑,所以做出了个判断
    private static final int COLUMN_WIDTH = 20;
    
    private  Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);

    public ExcelHandler() {
    }

    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
        if (needSetWidth) {
            Map<Integer, Integer> maxColumnWidthMap = (Map)CACHE.get(writeSheetHolder.getSheetNo());
            if (maxColumnWidthMap == null) {
                maxColumnWidthMap = new HashMap(16);
                CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
            }

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > MAX_COLUMN_WIDTH) {
                    columnWidth = MAX_COLUMN_WIDTH;
                }else {
                    if(columnWidth<COLUMN_WIDTH){
                        columnWidth =columnWidth*2;
                    }
                }

                Integer maxColumnWidth = (Integer)((Map)maxColumnWidthMap).get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    ((Map)maxColumnWidthMap).put(cell.getColumnIndex(), columnWidth);
                    writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(),  columnWidth* 256);
                }
            }
        }
    }

    private  Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
        if (isHead) {
            return cell.getStringCellValue().getBytes().length;
        } else {
            CellData cellData = (CellData)cellDataList.get(0);
            CellDataTypeEnum type = cellData.getType();
            if (type == null) {
                return -1;
            } else {
                switch(type) {
                    case STRING:
                        return cellData.getStringValue().getBytes().length;
                    case BOOLEAN:
                        return cellData.getBooleanValue().toString().getBytes().length;
                    case NUMBER:
                        return cellData.getNumberValue().toString().getBytes().length;
                    default:
                        return -1;
                }
            }
        }
    }
    public static HorizontalCellStyleStrategy getStyleStrategy(){
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为灰色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short)11);
        // 字体样式
        headWriteFont.setFontName("Arial Unicode MS");
        headWriteFont.setColor(IndexedColors.WHITE.getIndex());
        headWriteCellStyle.setWriteFont(headWriteFont);
        //自动换行
        headWriteCellStyle.setWrapped(false);
        // 水平对齐方式
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直对齐方式
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        // contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);
        // 背景白色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short)11);
        // 字体样式
        contentWriteFont.setFontName("宋体");
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //是否换行
        contentWriteCellStyle.setWrapped(false);
        //  垂直对齐方式
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
}

数据校验

java 复制代码
package com.bondex.oms.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.knife.util.BeanHelper;
import com.knife.util.ValidateUtil;

public class ExcelValidateListener<T> extends AnalysisEventListener<T> {
    @Override
    public void invoke(T bo, AnalysisContext analysisContext) {
        // 如果是空行,不处理
        if (BeanHelper.allFieldAreNull(bo)) {
            return;
        }

        int row = analysisContext.readRowHolder().getRowIndex() + 1;
        try {
            // 校验输入字段
            ValidateUtil.validate(bo);
        } catch (Exception e) {
            throw new RuntimeException("第[" + row + "]行数据校验失败:" + e.getMessage());
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

Bean工具

java 复制代码
package com.knife.util;

import org.springframework.beans.BeanUtils;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.util.CollectionUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class BeanHelper {
    public static <T> List<T> convert(List<?> sources, Class<T> target) {
        if (CollectionUtils.isEmpty(sources)) {
            return new ArrayList<>();
        }

        List<T> targets = new LinkedList<>();
        for (Object source : sources) {
            T t = null;
            try {
                t = target.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            BeanUtils.copyProperties(source, t);
            targets.add(t);
        }

        return targets;
    }

    public static <T> T convert(Object source, Class<T> target) {
        if (source == null) {
            return null;
        }

        T t;
        try {
            t = target.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        BeanUtils.copyProperties(source, t);
        return t;
    }

    public static boolean allFieldAreNull(Object o) {
        Class<?> aClass = o.getClass();

        PropertyDescriptor[] beanProperties = ReflectUtils.getBeanProperties(aClass);
        for (PropertyDescriptor beanProperty : beanProperties) {
            Method readMethod = beanProperty.getReadMethod();
            try {
                Object value = readMethod.invoke(o);
                if (value != null) {
                    return false;
                }
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

        return true;
    }
}

Excel工具类

java 复制代码
package com.bondex.oms.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.knife.entity.UserDTO;
import com.knife.util.UserDtoUtils;
import com.knife.excel.helper.ExcelHandler;
import com.knife.excel.helper.ExcelValidateListener;
import com.knife.excel.helper.HeadRowListener;
import com.knife.excel.helper.StringConverter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

public class ExcelUtil {
    public static <T> void exportExcel(List<T> dataList,
                                       Class<T> tClass) {

        ServletRequestAttributes servletRequestAttributes =
                (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();

        Assert.notNull(servletRequestAttributes, "RequestAttributes不能为null");

        HttpServletResponse response = servletRequestAttributes.getResponse();

        Assert.notNull(response, "Response不能为null");

        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        String fileName = "测试文件.xlsx";
        try {
            // 必须要转一下,否则中文文件名会乱码
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        // 通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");

        // 输出流到浏览器下载
        EasyExcel.write(out)
                .needHead(true)
                .head(tClass)
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(true)
                .registerWriteHandler(new ExcelHandler())
                .registerWriteHandler(ExcelHandler.getStyleStrategy())
                .sheet(0, "Sheet1")
                .doWrite(dataList);
    }

    public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass) {
        return importExcel(file, tClass, 1, null);
    }

    public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass, String sheet) {
        return importExcel(file, tClass, 1, sheet);
    }

    public static <T> List<T> importExcel(MultipartFile file,
                                          Class<T> tClass,
                                          Integer headRowNumber,
                                          String sheet) {
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<T> list = null;

        list = EasyExcel.read(inputStream)
                .registerConverter(new StringConverter())
                .registerReadListener(new ExcelValidateListener<T>())
                .head(tClass)
                // 可以指定sheet名字,不指定或null则表示第1个
                .sheet(sheet)
                .headRowNumber(headRowNumber)
                .doReadSync();

        list.removeIf(BeanHelper::allFieldAreNull);

        return list;
    }
}
相关推荐
慧都小妮子11 小时前
标签打印如何减少手工抄数?用Bartender 直连 Excel 批量打印
excel·bartender·条码打印·标签打印软件·数据驱动打印·工业打印机
SunnyDays101120 小时前
Java 设置 Excel 数据验证:整数、日期、文本长度、下拉列表和时间
java·excel·数据验证·下拉列表
Metaphor69220 小时前
使用 Python 设置 Excel 行列自适应 【代码示例】
python·excel
用户0332126663672 天前
使用 Python 设置 Excel 行列自适应 【代码示例】
python·excel
企业数字化笔记2 天前
固定资产Excel批量导入怎么防重复?资产编码、重复检查和错误回执
java·后端·excel
CORNERSTONE3652 天前
低代码开发有哪些应用场景?
低代码·excel·erp·mes·企业数字化
小葱炖豆腐2 天前
python绘制excel折线图
python·excel·numpy·pandas·matplotlib
cspttty3 天前
2026年财务分析岗JD中的Excel、SQL、BI与业务分析要求
大数据·sql·excel
cspttty3 天前
HR数字化校招准备路线:Excel、SQL、BI和AI工具怎么学
人工智能·sql·excel
鲲穹AI种草4 天前
Excel 表格批量处理与数据整理,多款表格工具能力客观记录
excel·表格处理