首先需求是前端传入对象list,指定后端配置的Excel导出实体类package地址(根据需求可脱离前端根据业务需求定义接口直接调工具类方法即可,传参数方式由指向地址改为Excel导出实体类Class对象)并且以application/vnd.ms-excel类型的回执返回给前端download(实现逻辑简单不喜勿喷,希望得到各路神仙的指点OwO)。讲一下实现思路首先后端拿到list和实体类映射地址或者类Class定义文件输出流定义两个方法一个作为创建列头和数据,另一个作为导出操作(这一步操作是由Lambda表达式写入提交)直接写入到流中返回给前端。
1.引入maven poi依赖以及其他应用到的依赖2.结构目录org.apache.poi poi org.apache.poi poi-ooxml org.springframework.boot spring-boot-starter-web
annotations:字段型自定义注解(列头/日期格式/字典式数字替换文字/列头宽度……后期拓展字段交给你们OwO)
as:函数接口/自定义接口/定义接口实现
entity:Excel导出行数据转换实体
model:Excel导出实体类
uitls:Excel导出工具类
package 这个你们放你们自己的包吧;
import java.lang.annotation.*;
@documented
@Target({ElementType.FIELD}) //注解应用类型(应用到方法的注解,还有类的可以自己试试)
@Retention(RetentionPolicy.RUNTIME) // 注解的类型
public @interface Excel {
String name() default "";
String format() default "yyyy/MM/dd";
String[] filterText() default {};
int width() default 30;
String func() default "";
}
4.自定义一个消费型函数式接口
这里着重讲一下含义所谓消费,其实就是将数据提交到接口里由方法重写由Lambda表达式的方式处理数据优化代码避免性能浪费
package 这个你们放你们自己的包吧; @FunctionalInterface public interface ExportConsumer5.定义数据转换类实体{ public abstract void accept(ByteArrayOutputStream fileOut, Workbook wk, List list) throws Exception; }
这里是对list的属性的一些定义因为要对list里的数据标记那些要日期格式化那些要文字替换下文在注释里有详解
package 这个你们放你们自己的包吧;
public class FieldExcel {
private String[] fieldArr;
private String fieldName;
private String fieldType;
private String fieldFormat;
public String[] getFieldArr() {
return fieldArr;
}
public void setFieldArr(String[] fieldArr) {
this.fieldArr = fieldArr;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldType() {
return fieldType;
}
public void setFieldType(String fieldType) {
this.fieldType = fieldType;
}
public String getFieldFormat() {
return fieldFormat;
}
public void setFieldFormat(String fieldFormat) {
this.fieldFormat = fieldFormat;
}
public FieldExcel() {
this.fieldArr = new String[]{};
this.fieldName = "null_flag";
}
}
6.导出列头实体类(这个类里的属性根据业务需求制作)
主要需要看Excel注解
package 这个你们放你们自己的包吧;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import 这个你们放你们自己的包吧.CfmRepairCodeEnum;
import 这个你们放你们自己的包吧.annotations.Excel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
@Component
public class FitMentExcelModel implements Serializable {
private static final long serialVersionUID = 1L;
private Long cfmRepairId;
@Excel(name = "装店装修单R单单号")
private String cfmRepairCode;
@Excel(name = "申请日期")
private LocalDateTime applyTime;
@Excel(name = "申请人")
private String applyName;
@Excel(name = "申请人电话")
private String applyMobile;
@Excel(name = "城市经理名称")
private String cityManager;
@Excel(name = "城市经理电话")
private String cityManagerPhone;
@Excel(name = "装修负责人")
private String repairLeader;
@Excel(name = "负责人电话")
private String leaderPhone;
@Excel(name = "省份")
private String province;
@Excel(name = "城市")
private String city;
@Excel(name = "区")
private String area;
@Excel(name = "店面名称")
private String storeName;
@Excel(name = "店面类别")
private String storeType;
@Excel(name = "店面类型")
private String storeCategory;
@Excel(name = "店面性质")
private String storeProperty;
@Excel(name = "店面面积")
private BigDecimal storeArea;
@Excel(name = "店面所属商圈")
private String storeBusinessArea;
@Excel(name = "地级/县级", filterText = {"1:地级", "2:县级"})
private String cityLevel;
@Excel(name = "老店历史装修时间")
private LocalDate decorateDate;
@Excel(name = "装修性质")
private String repairLevelName;
@Excel(name = "装修模式")
private String repairModelName;
@Excel(name = "预计开业时间")
private LocalDate openDate;
@Excel(name = "店面专区备注")
private String storeTeamRemark;
@Excel(name = "店面专区面积")
private BigDecimal storeTeamArea;
@Excel(name = "开始设计时间")
private LocalDate designingDate;
@Excel(name = "设计完成时间")
private LocalDate designFinishDate;
@Excel(name = "设计周期")
private Integer designCycle;
@Excel(name = "铺地砖日期")
private LocalDate brickDate;
@Excel(name = "木工日期")
private LocalDate woodDate;
@Excel(name = "油工日期")
private LocalDate oilDate;
@Excel(name = "安装样品日期")
private LocalDate installDate;
@Excel(name = "软装摆场日期")
private LocalDate softDate;
@Excel(name = "暂不装修时间")
private LocalDate notRepairDate;
@Excel(name = "暂不装修原因")
private String notRepairReason;
@Excel(name = "不装修时间")
private LocalDate noRepairDate;
@Excel(name = "不装修原因")
private String noRepairReason;
@Excel(name = "装修完成时间")
private LocalDate repairFinishDate;
@Excel(name = "装修周期")
private Integer repairCycle;
@Excel(name = "验收完成时间")
private LocalDate checkDate;
@Excel(name = "验收周期")
private Integer checkCycle;
@Excel(name = "验收状态", filterText = {"0:不合格", "1:合格", "2:无验收"})
private Integer checkState;
@Excel(name = "装修单状态", filterText = "${getEnumRepairSate}")
private Integer repairState;
@Excel(name = "状态")
private String state;
@Excel(name = "支付时间")
private LocalDateTime payTime;
@Excel(name = "支付单号")
private String cfmPayCode;
@Excel(name = "设计费金额(分)")
private Long sumDesignCost;
@Excel(name = "支付方式")
private String payMethod;
@Excel(name = "评价状态", filterText = {"0:未评价", "1:已评价"})
private Integer evaluateState;
@Excel(name = "评价信息-图纸设计")
private BigDecimal evaluateDesign;
@Excel(name = "评价信息-装修效果")
private BigDecimal evaluateRepair;
@Excel(name = "评价信息-服务沟通")
private BigDecimal evaluateCommunication;
@Excel(name = "评价内容")
private String evaluateContent;
@Excel(name = "设计师负责人名称")
private String responseName;
@Excel(name = "设计师名称")
private String designName;
@Excel(name = "表单备注")
private String formRemark;
@Excel(name = "备注")
private String remark;
private String storeId;
private String storeCode;
private Long applyId;
@Bean
public List
7.导出工具类(创建列头和数据以及提交写入流方法)都在注释里了
package 这个你们放你们自己的包吧;
import com.alibaba.fastjson.JSONObject;
import 这个你们放你们自己的包吧;
import 这个你们放你们自己的包吧;
import 这个你们放你们自己的包吧;
import 这个你们放你们自己的包吧;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.WorkbookUtil;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
public class ExportUtils {
public static ResponseEntity exportExcel(ByteArrayOutputStream fileOut,
Workbook wb,
List listData,
String fileName,
ExportConsumer> consumer) {
HttpHeaders headers = new HttpHeaders();
try {
consumer.accept(fileOut, wb, listData); // 函数接口数据配置
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 配置请求头类型
headers.setContentDispositionFormData("attachment", new String((fileName + ".xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); //配置表单信息,字符转换
return new ResponseEntity<>(fileOut.toByteArray(), headers, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
public static Workbook createCell(Workbook wb, List data, Class> className) {
try {
String safeName = WorkbookUtil.createSafeSheetName("sheet1");
Sheet sheet = wb.createSheet(safeName); // 创建工作空间
//第一行标题
Row title = sheet.createRow(0);
List
8.自定义接口调用
到了这一步这个方法已经注入到spring的管辖范围内了,就可以根据业务需求处理list然后导出啦!
package 这个你们放你们自己的包吧;
import 这个你们放你们自己的包吧;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.List;
@Service
public class OrdCfmExport implements IOrdCfmExport {
@Override
public ResponseEntity exportFitment(List list, String className){
try {
ByteArrayOutputStream fileout = new ByteArrayOutputStream();
Workbook wb = new HSSFWorkbook();
Class> aClass = Class.forName(className); // 反射加载类实体
return ExportUtils.exportExcel(
fileout,
wb,
list,
"",
(out, workbook, data) -> ExportUtils.createCell(
wb,
data,
aClass).write(fileout));
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Override
public ResponseEntity exportFitment(List list, Class> className) {
try {
ByteArrayOutputStream fileout = new ByteArrayOutputStream();
Workbook wb = new HSSFWorkbook();
Class> aClass = className; // 反射加载类实体
return ExportUtils.exportExcel(
fileout,
wb,
list,
"",
(out, workbook, data) -> ExportUtils.createCell(
wb,
data,
aClass).write(fileout));
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
9.最后贴一下vue代码
export() {
let that = this
let params = {}
params.data = that.exportBatchWrapper
params.baseUrl = that.url.baseUrlExport
framework.save(that.url.data.saveExport, params, 'EXPORT_POST').then((res) => {
let blob = new Blob([res.data], { type: 'application/vnd.ms-excel' })
// 其他浏览器
let link = document.createElement('a') // 创建a标签
link.style.display = 'none'
let objectUrl = URL.createObjectURL(blob)
link.href = objectUrl
link.click()
URL.revokeObjectURL(objectUrl)
}).catch((e) => {
that.$message.error('导出失败,内部服务器错误!')
})
}
save: function (url, params, method) {
if (method === 'GET') {
return http.get(url, params.data, null, params.baseUrl)
} else if (method === 'POST') {
return http.post(url, params.data, null, params.baseUrl)
} else if (method === 'EXPORT_POST') {
return http.post(url, params.data, { responseType: 'blob' }, params.baseUrl)
}
}
export function post(url, data, config, baseUrl) {
let options = { url: url, data: data, method: 'post' }
let opt = config ? Object.assign(config, options) : options
if (baseUrl === '' || baseUrl === null || baseUrl === undefined) {
axios = new HttpRequest(getbaseUrl())
return axios.request(opt)
} else {
if (nodeEnv === 'production') {
axios = new HttpRequest(getbaseUrl() + baseUrl)
} else {
axios = new HttpRequest(baseUrl)
}
return axios.request(opt)
}
}
axios配置这里不做展示了,相信到这里就已经能明白了。后期如果有代码技术上的问题请后台联系我发起技术讨论大家相互学习。最后希望大家学无止境,欲穷千里目,更上一层楼。谢谢



