前言
一、需求分析
1. 两个方式
导出excel有两个方式,前端导出
和 后端导出
- 前端导出excel:就用
vue+XLSX
(npm 包) - 后端导出excel:就用
vue+POI
(maven 包)
2. 对比分析
- 前端导出excel 相对来说简单一点,XLSX是前端 npm 包,但是如果数据量大的话,会卡顿,处理时间慢;当数据量多的时候 使用后端导出会好一点
- 后端导出excel 相对来说麻烦一点,但是时间短、速度快;具体操作都放在后端,也节省了前端的操作。用户效果好。
二、方式1:vue+XLSX
1. 安装 XLSX
npm install xlsx file-saver --save
2. XLSX 两个方法比较
- 这个
XLSX 方法一
和下面的XLSX 方法二
都是使用的XLSX
模块的 方法,只是获取数据的方式和 导出excel的方式有点不一样。 - 相比之下,还是
XLSX 方法一
会好一点,可以自定义导出的字段。
3. XLSX 方法一:
a. 按钮事件
<el-button size="small" type="primary" @click="exportSelect()">导出选中</el-button>
<el-button size="small" type="primary" @click="exportAllExcel">导出全部</el-button>
其实 上面的 二方法 可以做成一个方法,但是为了明确好分析,我写成了二个方法。
b. js 方法:导出选中 exportSelect()
exportSelect() {
// 导出选中
this.$confirm("是否确认导出当前所有参赛人员数据?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then((response) => {
// this.selectdata 是复选框的 数据列表
if (this.selectdata.length <= 0) {
this.$message.info('请选择数据!');
return false;
}
let tableData = [
['序号', '赛区名称', '参赛人', '手机号', '收件地址', "邮箱", "录入时间", "状态"]//导出表头
] // 表格表头
this.selectdata.forEach((item, index) => {
let rowData = []
//导出内容的字段
rowData = [
index + 1,
item.matchAreaName,
item.userName,
item.userPhone,
item.receiveAddress,
item.createTime,
item.dataFlag === 0 ? '待审核': '审核通过',
]
tableData.push(rowData)
})
let workSheet = XLSX.utils.aoa_to_sheet(tableData);
let bookNew = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(bookNew, workSheet, '作品名称') // 工作簿名称
let name = '参赛人员选中' + this.timeFormat() + '.xlsx'
XLSX.writeFile(bookNew, name) // 保存的文件名
})
},
timeFormat() {
let time = new Date();
let year = time.getFullYear();
let month = time.getMonth() + 1;
let date = time.getDate();
let hours = time.getHours();
let minutes = time.getMinutes();
let seconds = time.getSeconds();
return year + '-' + this.addZero(month) + '-' + this.addZero(date) + ' ' + this.addZero(hours) + ':' + this.addZero(minutes) + ':' + this.addZero(seconds);
},
addZero(num) {
return num < 10 ? '0' + num : num
},
c. js 方法:导出全部 exportAllExcel
// 导出 所有
exportAllExcel() {
this.$confirm("是否确认导出全部参赛人员数据?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(response => {
// 获取用户列表
let arr = [];
let parameter = {
pageNo: 1,
pageSize: 1000
}
getMatchUserInfoList(parameter).then(res => {
this.loading = false;
if (res.data.code != "1") {
this.$message({
type: 'info',
message: res.data.message
})
} else {
arr = res.data.data;
console.log('----------:', JSON.stringify(arr))
this.exportList(arr);
}
}).catch(err => {
this.$message.warning("系统问题,请稍后重试!")
})
},
exportList(arr){
let tableData = [
['序号', '赛区名称', '参赛人', '手机号', '收件地址', "邮箱", "录入时间", "审核状态", "是否发送豆子"]//导出表头
] // 表格表头
arr.forEach((item, index) => {
let rowData = []
//导出内容的字段
rowData = [
index + 1,
item.matchAreaName,
item.userName,
item.userPhone,
item.receiveAddress,
item.email,
item.createTime,
item.dataFlag === 0 ? '待审核': '审核通过',
item.sendFlag === 1 ? '否': '是',
]
tableData.push(rowData)
})
let workSheet = XLSX.utils.aoa_to_sheet(tableData);
let bookNew = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(bookNew, workSheet, '作品名称') // 工作簿名称
let name = '全部参赛人员' + this.timeFormat() + '.xlsx'
XLSX.writeFile(bookNew, name) // 保存的文件名
},
4. XLSX 方法二:
a. 按钮事件
<el-button size="small" type="primary" @click="exportExcel">导出当前页</el-button>
b. js 方法:导出当前页 exportExcel
这里是
// 导出当前页
exportExcel() {
this.$confirm("是否确认导出当前所有参赛人员数据?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then((response) => {
const wb = XLSX.utils.table_to_book(
document.querySelector("#el-table")
);
const wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
try {
FileSaver.saveAs(
new Blob([wbout], {type: "application/octet-stream"}),
"参赛人员数据.xlsx"
);
} catch (e) {
if (typeof console !== "undefined") console.log(e, wbout);
}
});
},
二、方式2:vue+POI
这个方式也就是后端生成excel,与前端没有多大的关系,后端写好的 excel
就直接write
到 response
里面了。
先直接放上前端代码。
1. 前端代码
a、按钮事件
<el-button size="small" type="primary" @click="exportAllExcel">导出全部</el-button>
b、网络请求封装
// 导出全部
export function exportExcelForMatchUser(data) {
return fetch({
url: '/xfx/matchUser/web/exportExcelForMatchUser',
method: 'post',
timeout: '120000',
responseType: 'blob',
data
});
}
c、js方法:导出全部 exportAllExcel
// 导出 所有
exportAllExcel() {
this.$confirm("是否确认导出全部参赛人员数据?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(response => {
exportExcelForMatchUser().then(response => {
const data = "参赛人员web.xlsx";
console.log('1111111111111111111111111', JSON.stringify(response))
let blob = new Blob([response.data], {type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8"});
console.log('333333333333333333333333', JSON.stringify(blob))
// for IE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, data);
} else {
console.log('chrome go here ')
let downloadElement = document.createElement('a');
let href = window.URL.createObjectURL(blob); // 创建下载的链接
downloadElement.href = href;
downloadElement.download = data; // 下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); // 点击下载
document.body.removeChild(downloadElement); // 下载完成移除元素
window.URL.revokeObjectURL(href); // 释放掉blob对象
}
}).catch(err => {
console.log(err)
this.loading = false;
this.$message.warning("对不起,下载失败");
});
})
},
2. 后端代码(IMPORTANT)
a、maven 依赖
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.14</version>
</dependency>
<!--这个不属于 poi ,就是一个工具类-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
b、controller 控制器层
/**
* @return com.zheng.ucenter.common.constant.UcenterResult
* @Author fengfanli
* @Description //TODO 导出全部
* @Date 17:40 2021/5/17
* @Param [param, request]
**/
@RequestMapping(value = "/web/exportExcelForMatchUser", method = RequestMethod.POST)
public UcenterResult exportExcelForMatchUser(HttpServletResponse response) {
try {
MatchUserModel model = new MatchUserModel();
model.setStart(0);
model.setPageSize(10000);
List<MatchUserModel> allMatchUserModels = matchUserService.getAllMatchUserModels(model);
// 导出 代码
List<MatchUserResp> result = new ArrayList<>(allMatchUserModels.size());
for (MatchUserModel matchUserModel : allMatchUserModels) {
MatchUserResp resp = new MatchUserResp();
BeanUtils.copyProperties(matchUserModel, resp);
resp.setCreateTime(DateHander.dateToStr1(matchUserModel.getCreateTime()));
result.add(resp);
}
if (result.size()!=0){
ExportExcel exportExcel = new ExportExcel("参赛人员", MatchUserResp.class, 1);
exportExcel.setDataList(result);
String fileName = "MATCH_USER_" + DateHander.dateToStrD(new Date()) + (new Random().nextInt(100 - 10) + 10) + ".xlsx";
exportExcel.write(response, fileName);
}
return new UcenterResult(UcenterResultConstant.SUCCESS);
} catch (Exception e) {
logger.error("MatchUserController exportExcelForMatchUser error:", e);
}
return new UcenterResult(UcenterResultConstant.FAILED);
}
重点就是其中的五行:
c、POJO类MatchUserResp类
这里使用到了自定义的 注解类
import java.io.Serializable;
import java.util.Date;
/**
* @ClassName MatchUserResp
* @Description TODO
* @Author admin
* @Date 2021/5/14 15:36
* @Version 1.0
*/
public class MatchUserResp implements Serializable {
@ExcelField(title = "序号", align = 1, sort = 1)
private Integer id;
private Long matchMainId;
private Long userId;
@ExcelField(title = "是否发送豆子(2:发送,1:未发送)", align = 1, sort = 2)
private Long sendFlag;
@ExcelField(title = "比赛名称", align = 1, sort = 3)
private String matchName;
@ExcelField(title = "用户名", align = 1, sort = 4)
private String userName;
@ExcelField(title = "手机号", align = 1, sort = 5)
private String userPhone;
private String userWxHead;
@ExcelField(title = "收件地址", align = 1, sort = 6)
private String receiveAddress;
@ExcelField(title = "邮箱", align = 1, sort = 7)
private String email;
private Long matchAreaCodeId;
@ExcelField(title = "赛区名称", align = 1, sort = 8)
private String matchAreaName;
@ExcelField(title = "备注", align = 1, sort = 9)
private String remark;
private Integer createUserId;
private String createUserName;
@ExcelField(title = "创建时间", align = 1, sort = 10)
private String createTime;
private Integer dataFlag;
private Integer useFlag;
private String timeStamp;
public Long getSendFlag() {
return sendFlag;
}
public void setSendFlag(Long sendFlag) {
this.sendFlag = sendFlag;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Long getMatchMainId() {
return matchMainId;
}
public void setMatchMainId(Long matchMainId) {
this.matchMainId = matchMainId;
}
public String getMatchName() {
return matchName;
}
public void setMatchName(String matchName) {
this.matchName = matchName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
public String getUserWxHead() {
return userWxHead;
}
public void setUserWxHead(String userWxHead) {
this.userWxHead = userWxHead;
}
public String getReceiveAddress() {
return receiveAddress;
}
public void setReceiveAddress(String receiveAddress) {
this.receiveAddress = receiveAddress;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Long getMatchAreaCodeId() {
return matchAreaCodeId;
}
public void setMatchAreaCodeId(Long matchAreaCodeId) {
this.matchAreaCodeId = matchAreaCodeId;
}
public String getMatchAreaName() {
return matchAreaName;
}
public void setMatchAreaName(String matchAreaName) {
this.matchAreaName = matchAreaName;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Integer getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Integer createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public Integer getDataFlag() {
return dataFlag;
}
public void setDataFlag(Integer dataFlag) {
this.dataFlag = dataFlag;
}
public Integer getUseFlag() {
return useFlag;
}
public void setUseFlag(Integer useFlag) {
this.useFlag = useFlag;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
}
c、其余的工具类
我都上传至GitHub了,可以直接拿过来用。
3. 总结
到此 后端导出excel结束了。