Vue+SpringBoot导出Excel,自定义要导出的表格的列
Vue+SpringBoot导出Excel,自定义要导出的表格的列前言一、Vue弹出层?1.数据展示2.导出弹出层3.弹出层界面二、后端API1.控制类2.实现逻辑总结前言之前一篇博客介绍了使用POI来完成报表的导出,默认都是导出所有数据列,但是我们有时候可能需要导出某些指定的列,搭配我前端使用的Vue和ElementUI,然后便做出来个可以自定义导出列的功能一、Vue弹出层?1.数据展示首先我们
·
前言
之前一篇博客介绍了使用POI来完成报表的导出,默认都是导出所有数据列,但是我们有时候可能需要导出某些指定的列,搭配我前端使用的Vue和ElementUI,然后便做出来个可以自定义导出列的功能
一、Vue弹出层?
1.数据展示
首先我们来看一下我们要导出的数据,先看一下所有的列
看一下data中的数据,有用户名和日期搜索
// el
ifLoading: false,
exportShow: false,
userDataList: [],
rangeTime: '',
searchData: {
total: 0,
pageNum: 1,
pageSize: 5,
userAccount: '',
},
columnTitle: [],
下面可以看到prop,label这些属性就是我们一会儿需要获取到的数据
<el-table :data="userDataList" border style="width: 100%;" class="el-table01" v-loading="ifLoading" ref="userDataListRef">
<el-table-column prop="index" :label="$t('serialNo')" align="center"></el-table-column>
<el-table-column prop="userAccount" :label="$t('account')" align="center"></el-table-column>
<el-table-column prop="userName" :label="$t('userName')" align="center"></el-table-column>
<el-table-column prop="userSex" :label="$t('userSex')" align="center">
<template slot-scope="scope">
<span v-if="scope.row.userSex == 0">{{$t('womanText')}}</span>
<span v-if="scope.row.userSex == 1">{{$t('manText')}}</span>
</template>
</el-table-column>
<el-table-column prop="userIslogin" :label="$t('isLogin')" align="center">
<template slot-scope="scope">
<span v-if="scope.row.userIslogin == 0">{{$t('offline')}}</span>
<span v-if="scope.row.userIslogin == 1" style="color: #357ae8;font-weight: bold;">{{$t('online')}}</span>
</template>
</el-table-column>
<el-table-column prop="userBirthday" :label="$t('birthday')" align="center"></el-table-column>
<el-table-column prop="userCreateTime" :label="$t('createTime')" align="center"></el-table-column>
</el-table>
2.导出弹出层
在这里我使用了el-popover,弹出层组件都想试一下嘛,其实这个的确没有其他的好用
<div class="btnBox">
<el-button size="medium" :loading="ifLoading" type="primary" @click="queryMainData()">{{ $t('search') }}</el-button>
<el-popover
placement="bottom"
width="320"
:offset="-100"
v-model="exportShow">
<h2>{{ $t('pleaseSelectEx') }}</h2>
<div class="excel-title-cls">
<el-row>
<el-col v-for="ct in columnTitle" :key="ct.prop" :span="10">
<span v-if="ct.prop != 'index'">
<el-checkbox class="btn-check" v-model="ct.checked" border>{{ct.label}}</el-checkbox>
</span>
<span v-else>
<el-checkbox class="btn-check" v-model="ct.checked" disabled border>{{ct.label}}</el-checkbox>
</span>
</el-col>
</el-row>
</div>
<div style="text-align: right; margin: 0">
<el-button type="primary" @click="exportData('check')">{{ $t('exportSome') }}</el-button>
<el-button class="btn-all" @click="exportData('all')">{{ $t('exportAll') }}</el-button>
<el-button type="error" plain @click="exportShow = false">{{ $t('close') }}</el-button>
</div>
<el-button slot="reference" size="medium" type="success" @click="exportOpen">{{ $t('export') }}</el-button>
</el-popover>
</div>
获取所有列方法
我们在打开弹出层时获取所有的列,并循环遍历到弹出层中
exportOpen(){
this.columnTitle = []
this.$refs.userDataListRef.$children.forEach(obj => {
if (obj.label != undefined){
// 每个列我们自己设置3个属性,label:显示的文本,prop:英文编码,checked:选中状态
let columnChild = {'label':obj.label,'checked':false,'prop':obj.prop}
// 存到columnTitle数组中
this.columnTitle.push(columnChild)
}
})
},
导出部分和导出全部的方法
根据参数 all 或者 check来判断全导出还是部分导出
exportData(type) {
// 日期搜索框
this.searchData.startDatetime = ''
this.searchData.endDatetime = ''
if (this.rangeTime && this.rangeTime.length) {
this.searchData.startDatetime = this.rangeTime[0]
this.searchData.endDatetime = this.rangeTime[1]
}
let s = this.searchData
// 遍历所有列数组,将序号去除,如果选中将数据加入新的数组
let columnTitleNew = []
this.columnTitle.forEach((item)=>{
if (type === 'all'){
if (item.prop != 'index'){
columnTitleNew.push(item)
}
} else if (type === 'check'){
if (item.checked){
columnTitleNew.push(item)
}
}
})
if (columnTitleNew.length == 0){
this.$message({type: 'error',message: '请选择要导出的列'})
return
} else {
// 传递新的数组给后端,调用后端导出接口,这里需要对格式进行转换防止URL无法识别部分编码
this.exportShow = false
var url = 'http://localhost:8089/api/reportExport/userList'
var href = url + '?userAccount=' + s.userAccount + '&startDatetime=' + s.startDatetime + '&endDatetime=' + s.endDatetime + '&columnTitle=' + encodeURI(JSON.stringify(columnTitleNew))
window.open(href)
}
},
3.弹出层界面
二、后端API
1.控制类
我们需要传递分页,模糊搜索,导出的列这些参数
@GetMapping("/reportExport/userList")
@ApiOperation(value="用户信息导出" , notes ="用户信息自定义列导出" , response = Result.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "userAccount", value = "用户账号", required = true, dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "startDatetime", value = "开始时间yyyy-MM-dd格式", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "endDatetime", value = "结束时间yyyy-MM-dd格式", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "pageNum", value = "数据页数量", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "pageSize", value = "数据页编号,从1开始", required = false, dataType = "Integer", paramType = "query"),
})
public Object prodTest(HttpServletResponse response,
@RequestParam(required = false) String userAccount,
@RequestParam(required = false) String startDatetime,
@RequestParam(required = false) String endDatetime,
@RequestParam(required = false) String columnTitle) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
String fileName = DateUtils.format(new Date(),"yyyyMMddHHmmss") +"-USER.xls";
String headStr = "attachment; filename=" + fileName;
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", headStr);
reportService.exportUserList(response.getOutputStream(), userAccount, startDatetime, endDatetime, columnTitle);
return null;
}
2.实现逻辑
来看一下Impl中的具体实现
@Override
public void exportUserList(OutputStream out, String userAccount, String startDatetime, String endDatetime, String columnTitle) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
List<SysUser> list = userMapper.queryUserList(userAccount, startDatetime, endDatetime);
List<Object[]> dataList = new ArrayList<Object[]>();
// 把需要展示的列json数据转为List
List<Map<String, Object>> cols = JsonUtils.jsonStringToList1(columnTitle);
// 设置Excel列标题
String[] rowsName = new String[cols.size()+1];
rowsName[0] = "序号";
for (int i = 0; i < cols.size(); i++) {
rowsName[i+1] = cols.get(i).get("label").toString();
}
// 设置Excel行数据
for (SysUser p : list) {
Object[] objs = new Object[cols.size()+1];
objs[0] = "";
for (int j = 0; j < cols.size(); j++) {
String prop = cols.get(j).get("prop").toString();
if (prop.equals("userCreateTime")) {
objs[j + 1] = new DateTime(invokeGetMethod(SysUser.class, prop, p)).toString(DateUtils.DATE_PATTERN[3]);
} else if (prop.equals("userBirthday")){
objs[j + 1] = new DateTime(invokeGetMethod(SysUser.class, prop, p)).toString(DateUtils.DATE_PATTERN[5]);
} else if (prop.equals("userSex")) {
String userSex = invokeGetMethod(SysUser.class, prop, p).toString();
if (userSex.equals("0")) {
objs[j + 1] = "女";
} else if (userSex.equals("1")) {
objs[j + 1] = "男";
} else {
objs[j + 1] = "未知";
}
} else if (prop.equals("userIslogin")) {
String userLogin = invokeGetMethod(SysUser.class, prop, p).toString();
if (userLogin.equals("1")) {
objs[j + 1] = "在线";
} else {
objs[j + 1] = "离线";
}
} else {
objs[j + 1] = invokeGetMethod(SysUser.class, prop, p);
}
}
dataList.add(objs);
}
String title = "用户信息报表";
ExportExcel ex = new ExportExcel(title, rowsName, dataList);
try {
ex.export(out);
} catch (Exception e) {
e.printStackTrace();
}
out.flush();
out.close();
}
以上我们需要调用自定义的反射辅助类,根据实体类属性来调用实体类get方法
package cn.liu783.vueappjava.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectUtils {
/**
* 拼接属性,调用目标Class的get方法
*
* @param c 属性所属实体类
* @param filedName 需要调用的属性名
* @param obj 实体类实例
* @return 返回get方法结果
*/
public static Object invokeGetMethod(Class<?> c, String filedName, Object obj) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
String methodName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
Class<?>[] nullClasses = null;
Method method = c.getMethod(methodName, nullClasses);
Object[] nullObjects = null;
return method.invoke(obj, nullObjects);
}
}
3.所需工具类
json字符串传为List
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Json转换类
*/
public class JsonUtil {
// 使用jackson进行json转换
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
return OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param beanType 对象中的object类型
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
*/
public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String listToJson(List<Object> list) throws JsonParseException, JsonMappingException, IOException{
String comment_json = OBJECT_MAPPER.writeValueAsString(list);
return comment_json;
}
public static String mapToJson(Map<String,Object> map) throws JsonParseException, JsonMappingException, IOException{
String comment_json = OBJECT_MAPPER.writeValueAsString(map);
return comment_json;
}
public static Map<String,Object> jsonStringToMap(String jsonString) throws Exception{
Map<String,Object> map = OBJECT_MAPPER.readValue(jsonString, Map.class);
return map;
}
public static String listToJson1(List<Map<String, Object>> targetList) throws JsonParseException, JsonMappingException, IOException{
String comment_json = OBJECT_MAPPER.writeValueAsString(targetList);
return comment_json;
}
@SuppressWarnings("unchecked")
public static List<Map<String, Object>> jsonStringToList1(String jsonString) throws JsonParseException, JsonMappingException, IOException{
List<Map<String, Object>> commodityOrderInfoList=new ArrayList<Map<String, Object>>();
if(!jsonString.equals("")){
JavaType javaType = getCollectionType(ArrayList.class, Object.class);
commodityOrderInfoList = (List<Map<String, Object>>)OBJECT_MAPPER.readValue(jsonString, javaType);
}
return commodityOrderInfoList;
}
}
导出的工具类大家可以我的这篇文章
总结
然后我们选中用户名,性别,创建日期这几列来测试一下
教程写的很仓促,大家琢磨一下就都懂了,加油陌生人!
更多推荐
已为社区贡献5条内容
所有评论(0)