Java使用EasyExcel导出数据到Excel文件,以及调用接口下载文件

2023-10-29

1.引入EasyExcel 依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.2</version>
</dependency>

2.引入读写工具类: (原工具类地址)

package com.yangjie.testDemo1.util;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.handler.WriteHandler;
import org.apache.poi.ss.formula.functions.T;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Author:         yangjie
 * Datetime:       2022年11月16日 10:57
 * Description:    注:如果方法中无以下参数,则使用默认值
 * Integer sheetNo       默认0读取第一张sheet
 * Integer headRowNum    默认1不读取首行,从第二行开始读取
 * 返回值return:List<Map<Integer,String>>: Integer:列数  String:列数对应的value
 */
public class EasyExcelUtil {

    /**
     * 同步无模型读(默认读取sheet0,从第2行开始读)
     *
     * @param filePath excel文件的绝对路径
     */
    public static List<Map<Integer, String>> syncRead(String filePath) {
        return EasyExcelFactory.read(filePath).sheet().doReadSync();
    }

    /**
     * 同步无模型读(自定义读取sheetX,从第2行开始读)
     *
     * @param filePath excel文件的绝对路径
     * @param sheetNo  sheet页号,从0开始
     */
    public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).doReadSync();
    }

    /**
     * 同步无模型读(指定sheet和表头占的行数)
     *
     * @param filePath
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }

    /**
     * 同步无模型读(指定sheet和表头占的行数)
     *
     * @param inputStream
     * @param sheetNo     sheet页号,从0开始
     * @param headRowNum  表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<Map<Integer, String>> syncRead(InputStream inputStream, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }

    /**
     * 同步无模型读(指定sheet和表头占的行数)
     *
     * @param file
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<Map<Integer, String>> syncRead(File file, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }
//====================================================无JAVA模型读取excel数据===============================================================

//====================================================将excel数据同步到JAVA模型属性里===============================================================

    /**
     * 同步按模型读(默认读取sheet0,从第2行开始读)
     *
     * @param filePath
     * @param clazz    模型的类类型(excel数据会按该类型转换成对象)
     */
    public static List<T> syncReadModel(String filePath, Class clazz) {
        return EasyExcelFactory.read(filePath).sheet().head(clazz).doReadSync();
    }

    /**
     * 同步按模型读(默认表头占一行,从第2行开始读)
     *
     * @param filePath
     * @param clazz    模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo  sheet页号,从0开始
     */
    public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读(指定sheet和表头占的行数)
     *
     * @param inputStream
     * @param clazz       模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo     sheet页号,从0开始
     * @param headRowNum  表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<T> syncReadModel(InputStream inputStream, Class clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读(指定sheet和表头占的行数)
     *
     * @param file
     * @param clazz      模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<T> syncReadModel(File file, Class clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读(指定sheet和表头占的行数)
     *
     * @param filePath
     * @param clazz      模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }

    /**
     * 异步无模型读(默认读取sheet0,从第2行开始读)
     *
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param filePath      表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener) {
        EasyExcelFactory.read(filePath, excelListener).sheet().doRead();
    }

    /**
     * 异步无模型读(默认表头占一行,从第2行开始读)
     *
     * @param filePath      表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param sheetNo       sheet页号,从0开始
     */
    public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener, Integer sheetNo) {
        EasyExcelFactory.read(filePath, excelListener).sheet(sheetNo).doRead();
    }

    /**
     * 异步无模型读(指定sheet和表头占的行数)
     *
     * @param inputStream
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncRead(InputStream inputStream, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(inputStream, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步无模型读(指定sheet和表头占的行数)
     *
     * @param file
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncRead(File file, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(file, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步无模型读(指定sheet和表头占的行数)
     *
     * @param filePath
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return
     */
    public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(filePath, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步按模型读取(默认读取sheet0,从第2行开始读)
     *
     * @param filePath
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     */
    public static void asyncReadModel(String filePath, AnalysisEventListener<T> excelListener, Class clazz) {
        EasyExcelFactory.read(filePath, clazz, excelListener).sheet().doRead();
    }

    /**
     * 异步按模型读取(默认表头占一行,从第2行开始读)
     *
     * @param filePath
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo       sheet页号,从0开始
     */
    public static void asyncReadModel(String filePath, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo) {
        EasyExcelFactory.read(filePath, clazz, excelListener).sheet(sheetNo).doRead();
    }

    /**
     * 异步按模型读取
     *
     * @param inputStream
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncReadModel(InputStream inputStream, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(inputStream, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步按模型读取
     *
     * @param file
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncReadModel(File file, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(file, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步按模型读取
     *
     * @param filePath
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncReadModel(String filePath, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(filePath, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 无模板写文件
     *
     * @param filePath
     * @param head     表头数据
     * @param data     表内容数据
     */
    public static void write(String filePath, List<List<String>> head, List<List<Object>> data) {
        EasyExcel.write(filePath).head(head).sheet().doWrite(data);
    }

    /**
     * 无模板写文件
     *
     * @param filePath
     * @param head      表头数据
     * @param data      表内容数据
     * @param sheetNo   sheet页号,从0开始
     * @param sheetName sheet名称
     */
    public static void write(String filePath, List<List<String>> head, List<List<Object>> data, Integer sheetNo, String sheetName) {
        EasyExcel.write(filePath).head(head).sheet(sheetNo, sheetName).doWrite(data);
    }

    /**
     * 根据excel模板文件写入文件
     *
     * @param filePath
     * @param templateFileName
     * @param headClazz
     * @param data
     */
    public static void writeTemplate(String filePath, String templateFileName, Class headClazz, List data) {
        EasyExcel.write(filePath, headClazz).withTemplate(templateFileName).sheet().doWrite(data);
    }

    /**
     * 根据excel模板文件写入文件
     *
     * @param filePath
     * @param templateFileName
     * @param data
     */
    public static void writeTemplate(String filePath, String templateFileName, List data) {
        EasyExcel.write(filePath).withTemplate(templateFileName).sheet().doWrite(data);
    }

    /**
     * 按模板写文件
     *
     * @param filePath
     * @param headClazz 表头模板
     * @param data      数据
     */
    public static void write(String filePath, Class headClazz, List data) {
        EasyExcel.write(filePath, headClazz).sheet().doWrite(data);
    }

    /**
     * 按模板写文件
     *
     * @param filePath
     * @param headClazz 表头模板
     * @param data      数据
     * @param sheetNo   sheet页号,从0开始
     * @param sheetName sheet名称
     */
    public static void write(String filePath, Class headClazz, List data, Integer sheetNo, String sheetName) {
        EasyExcel.write(filePath, headClazz).sheet(sheetNo, sheetName).doWrite(data);
    }

    /**
     * 按模板写文件
     *
     * @param filePath
     * @param headClazz    表头模板
     * @param data         数据
     * @param writeHandler 自定义的处理器,比如设置table样式,设置超链接、单元格下拉框等等功能都可以通过这个实现(需要注册多个则自己通过链式去调用)
     * @param sheetNo      sheet页号,从0开始
     * @param sheetName    sheet名称
     */
    public static void write(String filePath, Class headClazz, List data, WriteHandler writeHandler, Integer sheetNo, String sheetName) {
        EasyExcel.write(filePath, headClazz).registerWriteHandler(writeHandler).sheet(sheetNo, sheetName).doWrite(data);
    }

    /**
     * 按模板写文件(包含某些字段)
     *
     * @param filePath
     * @param headClazz   表头模板
     * @param data        数据
     * @param includeCols 包含字段集合,根据字段名称显示
     * @param sheetNo     sheet页号,从0开始
     * @param sheetName   sheet名称
     */
    public static void writeInclude(String filePath, Class headClazz, List data, Set<String> includeCols, Integer sheetNo, String sheetName) {
        EasyExcel.write(filePath, headClazz).includeColumnFiledNames(includeCols).sheet(sheetNo, sheetName).doWrite(data);
    }

    /**
     * 按模板写文件(排除某些字段)
     *
     * @param filePath
     * @param headClazz   表头模板
     * @param data        数据
     * @param excludeCols 过滤排除的字段,根据字段名称过滤
     * @param sheetNo     sheet页号,从0开始
     * @param sheetName   sheet名称
     */
    public static void writeExclude(String filePath, Class headClazz, List data, Set<String> excludeCols, Integer sheetNo, String sheetName) {
        EasyExcel.write(filePath, headClazz).excludeColumnFiledNames(excludeCols).sheet(sheetNo, sheetName).doWrite(data);
    }

    /**
     * 多个sheet页的数据链式写入
     * ExcelUtil.writeWithSheets(outputStream)
     * .writeModel(ExcelModel.class, excelModelList, "sheetName1")
     * .write(headData, data,"sheetName2")
     * .finish();
     *
     * @param outputStream
     */
    public static EasyExcelWriterFactory writeWithSheets(OutputStream outputStream) {
        EasyExcelWriterFactory excelWriter = new EasyExcelWriterFactory(outputStream);
        return excelWriter;
    }

    /**
     * 多个sheet页的数据链式写入
     * ExcelUtil.writeWithSheets(file)
     * .writeModel(ExcelModel.class, excelModelList, "sheetName1")
     * .write(headData, data,"sheetName2")
     * .finish();
     *
     * @param file
     */
    public static EasyExcelWriterFactory writeWithSheets(File file) {
        EasyExcelWriterFactory excelWriter = new EasyExcelWriterFactory(file);
        return excelWriter;
    }

    /**
     * 多个sheet页的数据链式写入
     * ExcelUtil.writeWithSheets(filePath)
     * .writeModel(ExcelModel.class, excelModelList, "sheetName1")
     * .write(headData, data,"sheetName2")
     * .finish();
     *
     * @param filePath
     */
    public static EasyExcelWriterFactory writeWithSheets(String filePath) {
        EasyExcelWriterFactory excelWriter = new EasyExcelWriterFactory(filePath);
        return excelWriter;
    }

    /**
     * 多个sheet页的数据链式写入(失败了会返回一个有部分数据的Excel)
     * ExcelUtil.writeWithSheets(response, exportFileName)
     * .writeModel(ExcelModel.class, excelModelList, "sheetName1")
     * .write(headData, data,"sheetName2")
     * .finish();
     *
     * @param response
     * @param exportFileName 导出的文件名称
     */
    public static EasyExcelWriterFactory writeWithSheetsWeb(HttpServletResponse response, String exportFileName) throws IOException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码
        String fileName = URLEncoder.encode(exportFileName, "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcelWriterFactory excelWriter = new EasyExcelWriterFactory(response.getOutputStream());
        return excelWriter;
    }
}

3.引入自定义写入类,此类是原作者封装一个类方便使用链式调用的方式方便添加多sheet(这里下面生成时会用到这个链式调用)

package com.yangjie.testDemo1.util;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;

import java.io.File;
import java.io.OutputStream;
import java.util.List;

/**
 * Author:         YangJie
 * Datetime:       2022年11月16日 10:59
 * Description:    链式添加sheet表
 */
public class EasyExcelWriterFactory {

    private int sheetNo = 0;
    private ExcelWriter excelWriter = null;

    public EasyExcelWriterFactory(OutputStream outputStream) {
        excelWriter = EasyExcel.write(outputStream).build();
    }

    public EasyExcelWriterFactory(File file) {
        excelWriter = EasyExcel.write(file).build();
    }

    public EasyExcelWriterFactory(String filePath) {
        excelWriter = EasyExcel.write(filePath).build();
    }

    /**
     * 链式模板表头写入
     *
     * @param headClazz 表头格式
     * @param data      数据 List<ExcelModel> 或者List<List<Object>>
     * @return
     */
    public EasyExcelWriterFactory writeModel(Class headClazz, List data, String sheetName) {
        excelWriter.write(data, EasyExcel.writerSheet(this.sheetNo++, sheetName).head(headClazz).build());
        return this;
    }

    /**
     * 链式自定义表头写入
     *
     * @param head
     * @param data      数据 List<ExcelModel> 或者List<List<Object>>
     * @param sheetName
     * @return
     */
    public EasyExcelWriterFactory write(List<List<String>> head, List data, String sheetName) {
        excelWriter.write(data, EasyExcel.writerSheet(this.sheetNo++, sheetName).head(head).build());
        return this;
    }

    /**
     * 使用此类结束后,一定要关闭流
     */
    public void finish() {
        excelWriter.finish();
    }
}

4.下载ExcelUtil 工具类

package com.yangjie.testDemo1.util;



import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @className com.yq.common.utils.ExcelUtil
 * @author: yangjie
 * @description: ExcelUtil
 */
@Slf4j
public class ExcelUtil {
    /**
     * 下载Excel
     *
     * @param response 请求response
     * @param fileName 下载文件名称 xxx.xlsx
     * @param filePath 下载文件路径 D://xxx/xxx
     */
    public static void downExcel(HttpServletResponse response, String fileName, String filePath) {
        // path是指想要下载的文件的路径
        File file = new File(filePath);
        ExcelUtil.downExcel(response,fileName,file);
    }


    /**
     * 下载Excel
     *
     * @param response 请求response
     * @param fileName 下载文件名称 xxx.xlsx
     * @param file 下载文件流
     */
    public static void downExcel(HttpServletResponse response, String fileName, File file) {
        FileInputStream fileInputStream = null;
        InputStream fis = null;
        OutputStream outputStream = null;
        try {
            // 将文件写入输入流
            fileInputStream = new FileInputStream(file);
            fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            // 解决跨域问题,这句话是关键,对任意的域都可以,如果需要安全,可以设置成安前的域名
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.setHeader("FileName", URLEncoder.encode(fileName, "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "FileName");
            response.setCharacterEncoding("UTF-8");
            //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
            //attachment表示以附件方式下载   inline表示在线打开   "Content-Disposition: inline; filename=文件名.mp3"
            // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // 告知浏览器文件的大小
            response.addHeader("Content-Length", "" + file.length());
            outputStream = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            outputStream.write(buffer);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件下载异常,{}", e);
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

5.创建实体类(这里的

@ExcelProperty(value = "品种", index = 0)
value对应 Excel中最上方显示名称 index:代表在第几列

)

package com.yangjie.testDemo1.entity;

import com.alibaba.excel.annotation.ExcelProperty;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * @author YangJie
 * @date 2022年11月16日 13:49
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExportMyRequirementsInformationVo implements Serializable {

    private static final long serialVersionUID = -2986024804753822180L;

    @ExcelProperty(value = "品种", index = 0)
    private String spuName;

    @ExcelProperty(value = "企业名称", index = 1)
    private String customerEnterpriseName;

    @ExcelProperty(value = "需求量 (吨)", index = 2)
    private BigDecimal requirementWeight;

    @ExcelProperty(value = "品种需求占比", index = 3)
    private String proportionOfDemand;

    @ExcelProperty(value = "品牌偏好", index = 4)
    private String brand;

    @ExcelProperty(value = "竞争对手", index = 5)
    private String competitorName;

}

6:写入和下载文件  访问该请求地址浏览器可直接下载

(这里造的数据和输出的不一样是 因为我偷懒了)

/**
     * 导出我的需求信息
     *
     * @author YangJie
     * @date 2022/11/16 14:25
     */
    @GetMapping("/exportMyRequirementsInformation")
    public void exportMyRequirementsInformation(HttpServletResponse response) {
        List<ExportMyRequirementsInformationVo> exportMyRequirementsInformationVoList = new ArrayList<>();

        //造数据
        for (int i = 0; i < 10; i++) {
            ExportMyRequirementsInformationVo exportMyRequirementsInformationVo = new ExportMyRequirementsInformationVo();
            exportMyRequirementsInformationVo.setRequirementWeight(BigDecimal.ONE);
            exportMyRequirementsInformationVo.setBrand("数据" + i);
            exportMyRequirementsInformationVo.setCompetitorName("Name" + i);
            exportMyRequirementsInformationVo.setSpuName("产品" + i);
            exportMyRequirementsInformationVoList.add(exportMyRequirementsInformationVo);
        }

        //文件名称  注意这里一定要拼接文件格式 不然文件下载下来会是txt文件
        String fileName = "我的Excel" + ".xlsx";
        //文件存储路径
        String tempPath = "/Users/yangjie/Desktop/testDemo/src/main/resources" + "/";
        //导出/写入 文件路径
        String filePath = tempPath + fileName;
        EasyExcelWriterFactory res = EasyExcelUtil.writeWithSheets(filePath)
                .writeModel(ExportMyRequirementsInformationVo.class, exportMyRequirementsInformationVoList, "我的需求信息");
        res.finish();

        //下载 
        ExcelUtil.downExcel(response,fileName,filePath);
    }

解决: 想要实现循环 多sheet问题

 

 

1.因为在 EasyExcelWriterFactory 中我们封装了链式调用

我们就可以用循环的形式来添加多个sheet

1.1 因为第一个sheet和后面的格式不一样 可以单独为第一个sheet设置一个实体类

        EasyExcelWriterFactory res = null;
        for (Long spuId : spuIdSet) {
            if (res == null) {
               //判断循环当前是否是第一个sheet 如果是就用单独创建的类
                res = EasyExcelUtil.writeWithSheets(filePath)
                        .writeModel(ExportSummaryOfRequirementsVo.class, exportSummaryOfRequirementsVoList, "需求总览");
            }
            List<ExampleExportRequirementStatisticsVo> exampleExportRequirementStatisticsVoResultList =
                    exampleExportRequirementStatisticsVoMap.get(spuId);
//因为这边需求是用产品名称来为sheet命名 
            String spuName = exampleExportRequirementStatisticsVoResultList.get(0).getSpuName();
//循环中 链式调用创建多sheet
            res = res.writeModel(ExampleExportRequirementStatisticsVo.class, exampleExportRequirementStatisticsVoResultList, spuName);
        }
        res.finish();
//下载
ExcelUtil.downExcel(response,statisticalFileName,filePath);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java使用EasyExcel导出数据到Excel文件,以及调用接口下载文件 的相关文章

  • 如何在spring mvc中从控制器名称+操作名称获取映射的URL?

    是否有现有的解决方案可以从 Spring MVC3 中的 控制器名称 操作名称 获取映射的 URL 例如 asp net mvc 或 Rails 中的 UrlHelper 我觉得非常有用 thx 也许 你想要这样的东西 in your Co
  • 在文本文件中搜索单词并返回其频率

    如何在包含单词文本的文本文件中搜索特定单词并返回其频率或出现次数 使用扫描仪 String text Question how to search for a particular word in a text file containin
  • 记录骆驼路线

    我的项目中有几个 Camel 上下文 如果可能的话 我想以逆向工程方式记录路线 因为我们希望保持与上下文相关的文档最新 最好的方法是什么 我们倾向于预先实际设计路线 并使用来自EIP book http www eaipatterns co
  • 如何让spring为JdbcMetadataStore创建相应的schema?

    我想使用此处描述的 jdbc 元数据存储 https docs spring io spring integration docs 5 2 0 BUILD SNAPSHOT reference html jdbc html jdbc met
  • 如何获取 WebElement 的父级[重复]

    这个问题在这里已经有答案了 我试过了 private WebElement getParent final WebElement webElement return webElement findElement By xpath 但我得到
  • Java 8 中函数式接口的使用

    这是来自的后续问题Java 8 中的 双冒号 运算符 https stackoverflow com questions 20001427 double colon operator in java 8其中 Java 允许您使用以下方式引用
  • 列表应该如何转换为具体的实现?

    假设我正在使用一个我不知道源代码的库 它有一个返回列表的方法 如下所示 public List
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • 在 Spring Boot Actuator 健康检查 API 中启用日志记录

    我正在使用 Spring boot Actuator APIproject https imobilenumbertracker com 拥有一个健康检查端点 并通过以下方式启用它 management endpoints web base
  • Android Studio 将音乐文件读取为文本文件,如何恢复它?

    gameAlert mp3是我的声音文件 运行应用程序时 它询问我该文件不与任何文件类型关联 请定义关联 我选择TextFile错误地 现在我的音乐文件被读取为文本文件 我如何将其转换回music file protected void o
  • 如何配置 WebService 返回 ArrayList 而不是 Array?

    我有一个在 jax ws 上实现的 java Web 服务 此 Web 服务返回用户的通用列表 它运行得很好 Stateless name AdminToolSessionEJB RemoteBinding jndiBinding Admi
  • 对象锁定私有类成员 - 最佳实践? (爪哇)

    I asked 类似的问题 https stackoverflow com questions 10548066 multiple object locks in java前几天 但对回复不满意 主要是因为我提供的代码存在一些人们关注的问题
  • 如何在 Quartz 调度程序中每 25 秒运行一次?

    我正在使用 Java 的 Quartz Scheduling API 你能帮我使用 cron 表达式每 25 秒运行一次吗 这只是一个延迟 它不必总是从第 0 秒开始 例如 序列如下 0 00 0 25 0 50 1 15 1 40 2 0
  • JVM:是否可以操作帧堆栈?

    假设我需要执行N同一线程中的任务 这些任务有时可能需要来自外部存储的一些值 我事先不知道哪个任务可能需要这样的值以及何时 获取速度要快得多M价值观是一次性的而不是相同的M值在M查询外部存储 注意我不能指望任务本身进行合作 它们只不过是 ja
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • Hibernate 和可序列化实体

    有谁知道是否有一个框架能够从实体类中剥离 Hibernate 集合以使它们可序列化 我查看了 BeanLib 但它似乎只进行实体的深层复制 而不允许我为实体类中的集合类型指定实现映射 BeanLib 目前不适用于 Hibernate 3 5
  • 嵌入式 Jetty - 以编程方式添加基于表单的身份验证

    有没有一种方法可以按如下方式以编程方式添加基于表单的身份验证 我用的是我自己的LdapLoginModule 最初我使用基本身份验证并且工作正常 但现在我想在登录页面上进行更多控制 例如显示徽标等 有没有好的样品 我正在使用嵌入式 jett
  • JAXB - 列表<可序列化>?

    我使用 xjc 制作了一些课程 public class MyType XmlElementRefs XmlElementRef name MyInnerType type JAXBElement class required false
  • 如何使用 php 将 *.xlsb 转换为数组或 *.csv

    我正在尝试转换 xlsb文件到php array or csv文件 或至少 xls 我尝试使用PHPExcel 但看起来它无法识别该文件中的内容 我注意到 你可以重命名 xlsb文件到 zip文件 然后使用命令行解压缩unzip zip 之

随机推荐

  • 并行编程OpenCL-矩阵相加

    并行编程OpenCL 矩阵相加 1 host端代码 include
  • springboot之mybatis进阶

    springboot之mybatis进阶 简介 CRUD标签 select insert update delete resultMap sql片段 动态sql if choose when otherwise where 和set for
  • 关于使用SSM框架搭建的项目的运行方法

    目录 运行环境配置 1 安装 IDEA 开发工具 中文版设置 JDK直接下载 2 安装 MYSQL 数据库 2 1 下载安装 2 2 配置环境变量 2 4 安装 MySQL 2 4 进入 MySQL 2 5 常见问题 3 安装Tomcat
  • java日期之间的比较【项目日常】

    一 String类中提供了compareTo方法 原理是将字符串转成char 从char 0 开始进行比较 如果两值不相等 则返回相减的结果 一般将结果与0相比 进行判断 并不关心返回的具体值 String s1 2022 09 22 St
  • 蓝桥杯每日练习2

    文章目录 一 Fibonacci斐波那契数列 1 题目 2 样例 3 解析 4 Python代码 二 求圆的面积 1 题目 2 样例 3 解析 4 Python代码 三 N以内累加求和 1 题目 2 样例 3 解析 4 Python代码 四
  • 分布式文件系统 - FastDFS 在UBUNTU下安装

    分布式文件系统 FastDFS 在 CentOS 下配置安装部署 按照该博主的介绍 大部分安装操作正常 只是在创建软连接的时候报错 所以只好用笨办法启动和关闭 启动tracker usr bin fdfs trackerd etc fdfs
  • Python 实现不平衡采样

    本文将基于不平衡数据 使用Python进行反欺诈模型数据分析实战 模拟分类预测模型中因变量分类出现不平衡时该如何解决 具体的案例应用场景除反欺诈外 还有客户违约和疾病检测等 只要是因变量中各分类占比悬殊 就可对其使用一定的采样方法 以达到除
  • python命令行操作:Click包

    0 前言 在Python开发和测试过程中主要有两种模式可以选择 脚本模式 命令行模式 在代码的开发和调试过程中使用脚本模式还是很方便的 尤其接触pycharm eclipse这类强大的IDE 或者配合vs code这种综合的文本编辑器 但是
  • 【MySQL】——数据库的基本查询练习

    个人主页 努力学习的少年 版权 本文由 努力学习的少年 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 基本查询 基本查询只在一张数据表中进行查询 接下来的题目都会在下面这张表进行
  • Java多线程——线程池

    一 ThreadPoolExecutor接口 之前提到过Executors所提供的四种线程池 即 Scheduled Single Fixed Cached 如果这几种线程池不能完全满足你的需求 那么通过ThreadPoolExecutor
  • [4G&5G专题-97]:MAC层- 调度 - 上行调度的原理、过程与算法

    目录 第1章 调度概述 1 1 调度概述 1 2 无线资源调度的分类 第2章 上行调度的整体架构与过程 2 1 上行需要调度的信道 2 2 上行数据发送过程 2 3 上行调度架构 2 4 上行调度的输入信息 2 5 上行调度的步骤与过程 2
  • 【客户案例】云联壹云帮助华北电力大学搭建 AI 训练平台

    客户介绍 华北电力大学是教育部直属全国重点大学 是国家 211 工程 和 985 工程优势学科创新平台 重点建设大学 2017 年 学校进入国家 双一流 建设高校行列 重点建设能源电力科学与工程学科群 全面开启了建设世界一流学科和高水平研究
  • 如何制作属于自己的图片马

    前言 图片马是指代码写入后不破坏图片为前提 图片仍可正常打开 详细过程 自定义一个新的文件夹 文件夹里放入三个文件 一张自己喜欢的图片 自定义php代码文件 批处理文件 super png 用文本编辑器打开也没php代码
  • 深度学习基础知识

    深度学习入门者必看 25个你一定要知道的概念如果你还不了解深度学习有多么强大 不妨就从这篇文章开始 https mp weixin qq com s biz MzIzNjc1NzUzMw mid 2247485927 idx 1 sn 60
  • vue diff 双端比较算法

    文章目录 双端指针 比较策略 命中策略四 命中策略二 命中策略三 命中策略一 未命中四种策略 遍历旧节点列表 新增情况一 新增情况二 删除节点 双端比较的优势 双端指针 使用四个变量 oldStartIdx oldEndIdx newSta
  • 微信小程序页面跳转三种方式

    为了不让用户在使用小程序时造成困扰 微信小程序规定页面路径只能是五层 请尽量避免多层级的交互方式 页面跳转的话就涉及到了多个页面层级 第一种 wx navigateTo OBJECT 保留当前页面 跳转到应用内的某个页面 使用wx navi
  • powershell 自动补全

    我在zsh中使用智能提示 zsh autosuggestions已经习惯了 而在windows中的终端默认没有智能提示 很起来不舒服 那么有没有什么替代呢 安装powershell 7 3 我的windows 10默认安装的是powersh
  • CSDN 改变字体颜色

    将字体改变为红色 font color 900 我是编程ID font 设置字体颜色和字号 font face 华文行楷 color red size 5 本字体是华文行楷 红色 5号大小 font 更多字体参见 https blog cs
  • vue+element+table+render+slot

    前言 最新又回忆并且整理下之前的资料 在这里共享下把 主要是element ui框架里面对table的使用 因为element ui不可以像我们iview框架一样可以直接的在表头里面写render函数 我这里把element ui的tabl
  • Java使用EasyExcel导出数据到Excel文件,以及调用接口下载文件

    1 引入EasyExcel 依赖