使用VUE+SpringBoot+EasyExcel 整合导入导出demo

本文详细介绍了如何使用EasyExcel进行Excel的导出与导入操作,包括实体类注解配置、动态表头设置、数据宽度自适应处理以及前端Vue的调用方法。示例代码涵盖了从添加依赖到实际业务处理的完整流程,适用于Java后端开发者进行Excel交互的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导出示例:

后台:

1、引入依赖:需要引入easyExcel的依赖,但是我在使用过程中发现也是需要poi的依赖,不然会报错,就同时引入了。

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>4.0.1</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
   <version>4.0.1</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>easyexcel</artifactId>
  <version>2.1.6</version>
</dependency>

2、实体类定义导出字段及Title:@ExcelProperty

@Setter
@Getter
public class TradingRecord {

    @ExcelProperty({"沃联之家VGM对账清单", "账单创建时间","ID"})
    private String uuid;

    @ExcelProperty({"沃联之家VGM对账清单", "账单创建时间","关联业务编号"})
    private String referenceNo;

    @ExcelProperty({"沃联之家VGM对账清单", "账单创建时间","金额"})
    private Double changeTicket;

    @ExcelProperty({"沃联之家VGM对账清单", "账单创建时间","交易时间"})
    private Date recordDate;

    @ExcelProperty({"沃联之家VGM对账清单", "账单总金额","交易说明"})
    private String remark;

}

3、直接调用

public void writeTradingRecord(HttpServletResponse   response,AppreciationServiceRequest appreciationServiceRequest) throws IOException {
        List<TradingRecord> list = new ArrayList<TradingRecord>();
        String name = "VGM对账清单.xlsx";
        // 导出时候会出现中文无法识别问题,需要转码
        String fileName = new String(name.getBytes("gb2312"),"ISO8859-1");
        response.setContentType("application/vnd.ms-excel;chartset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=" + fileName);
        //调用工具类
        ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build();
        WriteSheet sheet = EasyExcel.writerSheet(0,"sheet").head(TradingRecord.class).build();
        writer.write(list,sheet);
        writer.finish(); // 使用完毕之后要关闭
    }

也支持动态复杂表头:

public void writeTradingRecord(HttpServletResponse   response,AppreciationServiceRequest appreciationServiceRequest) throws IOException {
        List<TradingRecord> list = new ArrayList<TradingRecord>();
        String name = "VGM对账清单.xlsx";
        // 导出时候会出现中文无法识别问题,需要转码
        String fileName = new String(name.getBytes("gb2312"),"ISO8859-1");
        response.setContentType("application/vnd.ms-excel;chartset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=" + fileName);
        //调用工具类
        // 自定义动态Title
        List<List<String>> headTitles = Lists.newArrayList();
        // 第一行表头
        String basicInfo = "沃联之家VGM对账清单";
        // 第二行表头
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String createDate = "账单创建时间: " + sdf.format(new Date());
        String amount1 = "账单总金额: ¥" + df2.format(amount);
        // 第三行表头
        headTitles.add( Lists.newArrayList(basicInfo , createDate,"ID"));
        headTitles.add( Lists.newArrayList(basicInfo , createDate,"关联业务编号"));
        headTitles.add( Lists.newArrayList(basicInfo , createDate,"金额"));
        headTitles.add( Lists.newArrayList(basicInfo , createDate,"交易时间"));
        headTitles.add( Lists.newArrayList(basicInfo , amount1,"交易说明"));
        ExcelWriter writer = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new CustomCellWriteHandler()).build();
        WriteSheet sheet = EasyExcel.writerSheet(0,"sheet").head(headTitles).build();
        writer.write(list,sheet);
        writer.finish();
    }

若想使导出的表格宽度自适应:添加宽度自适应工具类,并在使用时.registerWriteHandler。如:EasyExcel.write(response.getOutputStream()).registerWriteHandler(new CustomCellWriteHandler()).build();

package com.walltech.oms.util;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;

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

/**
 * Excel 导出列宽度自适应
 * @author phli
 */
public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {

    private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>();

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

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > 255) {
                    columnWidth = 255;
                }

                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    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 = 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;
                }
            }
        }
    }
}

4、VUE端:在使用过程中,发现不能直接使用axios直接调用,会报错,需要使用window.localtion调用。

5、导出示例:

----导出end-----

 

导入示例:

1、VUE:使用element的el-upload

            <el-upload
              class="upload-demo"
              name="file"
              :action="url"
              :with-credentials="true" 
              :on-change="handleChange"
              :file-list="fileList"
              :limit="1"
              :on-exceed="handleExceed"
              :on-preview="handlePreview"
              accept=".xlsx"
              :auto-upload="false"
              >
              <el-button size="mini" style="border-radius:25px;">
                <i class="el-icon-upload2"/>点击上传</el-button>
              <div slot="tip" class="el-upload__tip">一次只能上传一个文件,文件大小不可超过20M</div>
            </el-upload>

2、传参调用后台:

    importExcel () {
      let self = this
      if (self.fileList.length <= 0) {
        self.$message("请选择要导入的文件!")
      }
      let formData = new FormData();
      let file = this.fileList[0]
      formData.append('file', file.raw)
      self.importLoding = true
      axios.post('/appreciation/import', formData).then(res => {
        self.$message('导入成功')
        self.importDialog = false
        self.fetchVgmList(1)
        self.fileList = []
        self.importLoding = false
      }).catch (err=> {
        self.importLoding = false
      })
    }

3、后台处理:

EasyExcel.read(file.getInputStream(), TradingRecord.class,
     new ImportTradingListener(appreciationService)).sheet().doRead();

4、添加监听,处理excel表格内容:

package com.walltech.oms.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.walltech.oms.pojo.excelModel.TradingRecord;
import com.walltech.oms.service.AppreciationService;

import java.util.ArrayList;
import java.util.List;

/**
 * 监听:交易记录导入获取UUID
 * @author phli
 */
public class ImportTradingListener extends AnalysisEventListener<TradingRecord> {

    /**
     * 每隔1000条存储数据库,然后清理list,方便内存回收
     */
    private static final Integer BATCH_COUNT = 1000;

    List<String> list = new ArrayList<>();

    private AppreciationService appreciationService;

    public ImportTradingListener(AppreciationService appreciationService){
        this.appreciationService = appreciationService;
    }

    @Override
    public void invoke(TradingRecord tradingRecord, AnalysisContext analysisContext) {
        list.add(tradingRecord.getUuid());
        if (list.size() >= BATCH_COUNT) {
            list.clear(); //保证doAfterAllAnalysed方法执行数据为不重复数据
        }
    }

    //这里是数据全部读完之后走  为保证数据不够批量最小值也能存进数据库
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这个方法便是拿到excel的数据之后,进行修改数据库的操作。
        appreciationService.updateWriteOffState(list);
    }
}

------导入END------

 

<think>嗯,用户想用Spring BootVue3结合Element Plus、Print.js以及TypeScript来实现后端导出Excel数据的功能。首先,我需要确定前后端各自的职责。后端负责生成Excel文件,前端负责触发下载操作,可能需要处理请求和展示按钮。 首先,后端部分。Spring Boot导出Excel常用的库有Apache POI和EasyExcel。考虑到EasyExcel操作更简便,性能也不错,可能更适合。用户需要在pom.xml中添加EasyExcel的依赖。然后,创建一个Controller层的方法,处理导出请求。这里要注意设置响应头,确保浏览器能识别为Excel文件,比如Content-Type和Content-Disposition。示例代码中,用户可能需要模拟数据,所以需要构建一个数据对象,比如ProductDTO,并填充示例数据。使用EasyExcel的write方法将数据写入输出流。 然后是前端部分。Vue3配合Element Plus,需要一个按钮来触发导出操作。使用Element Plus的<el-button>组件,绑定点击事件。在事件处理中,发送GET或POST请求到后端的导出接口。这里需要注意,请求可能需要处理blob类型的响应,因为后端返回的是文件流。使用axios时,设置responseType为'blob'是关键,否则可能无法正确接收文件数据。 接下来,处理响应数据。前端接收到blob后,需要创建一个URL对象,并利用a标签的download属性来触发下载。或者,可以使用FileSaver.js库的saveAs方法,但用户提到用Print.js,不过Print.js主要用于打印,可能不太适合处理Excel下载,这里可能需要澄清。不过根据示例代码,用户可能只是需要基本的下载功能,所以直接使用a标签的方式即可。 另外,需要处理可能的错误情况,比如后端返回错误信息时,前端应该用Element Plus的ElMessage提示用户。例如,检查响应中的code字段,如果不是200则显示错误信息。 前后端交互的细节需要注意跨域问题。如果前端和后端分开部署,需要在Spring Boot中配置CORS,允许前端的域名访问。或者在Controller方法上添加@CrossOrigin注解。 关于TypeScript的部分,前端代码需要定义接口,比如响应数据的结构,以及请求的参数。示例中的res.data.code和res.data.data需要符合定义的接口,以利用TypeScript的类型检查。 可能还需要考虑后端生成Excel的性能,如果数据量较大,使用EasyExcel的分页查询和写入,避免内存溢出。但示例中数据量小,直接写入即可。 最后,验证整个流程是否正确。从点击按钮,发送请求,后端生成Excel,前端接收并下载文件,是否每个步骤都无误。同时,处理异常情况,比如网络错误或后端处理失败时的反馈。 总结来说,步骤分为后端生成Excel文件并提供下载接口,前端发送请求并处理文件下载。需要注意依赖的引入、响应类型设置、错误处理以及跨域配置。</think>### 分步实现方案 #### 一、后端实现(Spring Boot) 1. **添加依赖** ```xml <!-- Apache POI 或 EasyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency> ``` 2. **编写导出接口** ```java @RestController @RequestMapping("/api/export") public class ExcelExportController { @GetMapping("/excel") public void exportExcel(HttpServletResponse response) throws IOException { // 设置响应头 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=export_data.xlsx"); // 模拟数据(需替换为业务数据) List<ProductDTO> dataList = Collections.singletonList(new ProductDTO("手机", 2999.00)); // 使用EasyExcel写入数据流 EasyExcel.write(response.getOutputStream(), ProductDTO.class) .sheet("商品数据") .doWrite(dataList); } } ``` #### 二、前端实现(Vue3 + Element Plus) 1. **安装依赖** ```bash npm install print-js @types/print-js ``` 2. **封装导出请求** ```typescript // utils/request.ts import axios from 'axios'; const service = axios.create({ baseURL: 'http://localhost:8080', timeout: 5000 }); // 拦截器可添加Token等逻辑 export default service; ``` 3. **组件实现** ```vue <template> <el-button @click="handleExport">导出Excel</el-button> </template> <script setup lang="ts"> import { ElMessage } from 'element-plus'; import request from '../utils/request'; const handleExport = async () => { try { const response = await request({ url: '/api/export/excel', method: 'GET', responseType: 'blob' // 关键参数 }); // 创建下载链接 const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'export_data.xlsx'); document.body.appendChild(link); link.click(); document.body.removeChild(link); ElMessage.success('导出成功'); } catch (error) { ElMessage.error('导出失败:' + error.message); } }; </script> ``` #### 三、关键配置说明 1. **跨域处理**:在Spring Boot的`application.yml`中添加CORS配置[^1] ```yaml spring: application: name: export-demo mvc: pathmatch: matching-strategy: ant_path_matcher ``` 2. **数据模型定义**:前后端DTO需保持一致 ```java // ProductDTO.java @Data public class ProductDTO { @ExcelProperty("商品名称") private String productName; @ExcelProperty("价格") private Double price; } ``` ###
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值