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;
    }
}
相关推荐
破z晓14 小时前
javascript 导出excel表
开发语言·javascript·excel
Am-Chestnuts18 小时前
豆包多轮回答中的表格导出 Excel:编号、日期与长数字检查
excel
hPw0eKIqD1 天前
使用二次封装的Excel COM 组件操作Excel\WPS ET中的区域、行和列
excel·wps
冰心孤城2 天前
Excel: xls与xlsx格式转换排坑指南
java·前端·excel
金豆呀2 天前
WPS批量提取Word文档内容生成固定格式Excel表格
word·excel·wps
Access开发易登软件2 天前
Access 怎么做前后端分离?用 Web API 读写 SQL Server
前端·数据库·人工智能·microsoft·excel·access
红莲凪是3 天前
使用二次封装的Excel COM 组件操作Excel\WPS ET IExcelRange 高级应用
python·excel·wps
用户298698530143 天前
如何使用免费工具在线将 Excel 转换为 XML 格式
人工智能·后端·excel
开开心心就好3 天前
内存清理工具定时自动清理开机自启动
java·开发语言·elasticsearch·ocr·excel·音视频·big data
开开心心就好3 天前
电脑内存优化工具一键释放内存超简单
java·开发语言·macos·arcgis·ocr·excel·音视频