問題:
這是今年在項目中遇到的一個需求,並且之前有個博客園的伙伴也問到過,當時很忙,沒仔細去思考過,現在工作輕松一點了,寫個總結,當是一個小筆記吧
思路及原理:
之前的導出我們在頁面中設置了兩個el-table標簽,table1用來展示數據,另外一個table2負責導出數據(隱藏)。要導出指定的列,我們可以做的地方就在於控制隱藏的table2的列是否存在,這里我們使用v-if來控制,因為v-show僅僅是把元素的display屬性設置為none,列依然存在,導出的時候還是導出全部列數據,所以使用v-if
效果展示:
這是表格顯示的數據,有很多列的內容,下面先導出全都內容
導出指定列數據:這里我隨便勾選四個列導出
基本的效果就是上面這樣的了,全部數據那里的塗黑的部分是一些信息數據,隱藏一些不影響啥的,下面就直接放代碼了。
1、安裝插件並引入
import FileSaver from 'file-saver' import XLSX from 'xlsx'
2、因為使用的地方比較多,所以我將導出功能封裝成一個組件,方便引用,代碼如下
HTML部分:
<div class="excel-export-page"> <el-table v-show="false" id="exportTable" border height="300" :data="tableData"> <template v-for="(item, index) in exportFeild.tableCol"> <el-table-column v-if="item.checked" :key="index" :property="item.property" :label="item.colName" /> </template> </el-table> <div class="export-dialog"> <div style="display: flex;justify-content: space-between;align-items: center;"> <span>頁碼</span> <div style="display: flex;align-items: center;"> <div> <el-input v-model="pageStart" style="width: 80px;" @change="pagesChange" /> </div> <!-- ~ <div> <el-input v-model="pageEnd" style="width: 50px;" /> </div> --> <span style="padding: 0 20px;">所有頁</span> <el-checkbox v-model="getMore" @change="exprotAll" /> </div> </div> <div style="color: blue;">聯機下載最大記錄數為1000 <span style="color: red;">(導出最大量數據請在空閑時操作)</span> </div> <div class="export-clomon-choice"> <div v-for="(item, index) in exportFeild.tableCol" :key="index" class="export-row-style"> <el-checkbox v-model="item.checked">{{ item.colName }}</el-checkbox> </div> </div> <div class="export-btn-style"> <el-button type="primary" size="mini" icon="el-icon-download" @click="getExportDt">導出</el-button> </div> </div> </div>
CSS部分:
<style lang="scss" scoped> .excel-export-page { width: 100%; padding: 20px; } .export-dialog { width: 100%; } .export-clomon-choice { height: 150px; border: 1px solid #AECAF0; overflow-y: scroll; margin-top: 2px; .export-row-style { border-top: 1px solid #ededed; padding-left: 10px; } } .export-btn-style { padding: 10px; display: flex; justify-content: center; } </style>
JS部分:
<script> import { postRequest } from '@/api/httpRequest.js' import FileSaver from 'file-saver' import XLSX from 'xlsx' import Vue from 'vue' export default { props: { exportFeild: { type: Object, default() { return {} } } }, data() { return { dict: Vue.filter('dict'), // 獲取到全局字典過濾器方法 tableData: [], getMore: false, pageStart: 1, maxPage: 0 } }, watch: { 'exportFeild.currentPage': { handler: function(newVal, oldVal) { this.pageStart = newVal }, deep: true } }, mounted() { this.pageStart = this.exportFeild.currentPage }, methods: { // 是否導出最大量 exprotAll(val) { if (val) { this.pageStart = 1 } else { this.pageStart = parseInt(this.exportFeild.qryParams.nextPage) } }, // 頁碼輸入改變事件 pagesChange(val) { if (this.getMore) { const totalPg = Math.ceil(this.exportFeild.total / 1000) if (this.pageStart > totalPg) { this.pageStart = totalPg } } else { const totals = Math.ceil(this.exportFeild.total / this.exportFeild.pageSize) if (this.pageStart > totals) { this.pageStart = totals } } }, // 導出數據到Excel表 exportExcel(id) { /* generate workbook object from table */ var xlsxParam = { raw: true } // 導出的內容只做解析,不進行格式轉換 var wb = XLSX.utils.table_to_book(document.querySelector(id), xlsxParam) /* get binary string as output */ var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' }) try { FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.exportFeild.exportFileName) } catch (e) { if (typeof console !== 'undefined') { console.log(e, wbout) } } return wbout }, // 獲取導出的數據,與展示的表格數據不一定是一致的 getExportDt() { if (!this.getMore) { // 如果不是導出全部,則頁碼跟每頁條數跟列表頁一致 this.exportFeild.qryParams.nextPage = String(this.pageStart) this.exportFeild.qryParams.everyPage = String(this.exportFeild.pageSize) } else { // 導出全部數據,可輸入頁碼,讓用戶可選 this.exportFeild.qryParams.nextPage = String(this.pageStart) this.exportFeild.qryParams.everyPage = '1000' } // 這里是我們是獲取表格數據的請求方法,根據自己的項目請求方法切換一下就行 postRequest(this.exportFeild.qryParams, this.exportFeild.ck).then(response => { if (response.rspCode === '0000') { if (response.body.resultList) { this.tableData = response.body.resultList this.exportFeild.tableCol.forEach(item => { if (item.dictionaryFlag) { this.tableData.forEach(item2 => { const feildAttr = item.property.includes('.') if (!feildAttr) { item2[item.property] = this.dict(item2[item.property], item.dictionaryStr) } else { // 如果字段是drftInf.drftAttr這樣的,這樣進行賦值 const part1 = item.property.split('.')[0] const part2 = item.property.split('.')[1] item2[part1][part2] = this.dict(item2[part1][part2], item.dictionaryStr) } // item2[item.property] = this.dict(item2[item.property], item.dictionaryStr) }) } }) setTimeout(() => { this.exportExcel('#exportTable') }, 500) } } else { this.tableData = [] this.$message({ type: 'error', message: response.rspMsg }) } }).catch(() => {}) } } } </script>
在指定頁面引入導出組件:
<el-dialog :visible.sync="exportDialog" width="500px" title="XLSX導出" @close="exportDialog=false" > <excel-page :export-feild="exportFeild" /> </el-dialog> import excelPage from '@/views/common/print/excel-export/index.vue' components: { excelPage }, data() { return { exportFeild: {} // 傳入到組件的對象 } }, method: { // 導出到Excel,列表頁導出按鈕事件: printPDF() { if (this.tableData.length > 0) { this.exportDialog = true this.exportFeild = { currentPage: this.currentPage, pageSize: this.pageSize, total: this.total, tableCol: [ { checked: true, colName: '業務編號', property: 'contNo' }, // 這里設置checked為true是默認勾選狀態 { checked: true, colName: '票據號碼', property: 'drftNo' }, { checked: true, colName: '票據來源', property: 'srcTyp', dictionaryFlag: true, dictionaryStr: 'srcTyp' }, { checked: true, colName: '票據屬性', property: 'drftAttr', dictionaryFlag: true, dictionaryStr: 'drftAttr' }, { checked: true, colName: '票據種類', property: 'drftTyp', dictionaryFlag: true, dictionaryStr: 'drftTyp' }, { checked: true, colName: '票據狀態', property: 'drftStat', dictionaryFlag: true, dictionaryStr: 'drftStat' }, { checked: true, colName: '票面金額(元)', property: 'isseAmt' }, { checked: true, colName: '出票日', property: 'isseDt' }, { checked: true, colName: '到期日', property: 'dueDt' }, { checked: true, colName: '承兌人名稱', property: 'accptrNm' }, { checked: true, colName: '出票人名稱', property: 'drwrNm' }, { checked: true, colName: '出票人開戶行名稱', property: 'drwrBkNm' }, { checked: true, colName: '收款人開戶行名稱', property: 'pyeeBkNm' }, { checked: true, colName: '所屬機構', property: 'orgId' }, { checked: true, colName: '交易對手', property: 'custName' }, { checked: true, colName: '經辦人', property: 'jbStf' }, { checked: true, colName: '交易日期', property: 'txnDt' } ], qryParams: this.qryParams, ck: 'CXGZCX001', exportFileName: '票據交易查詢.xlsx' } } else { this.$alert('暫無數據', '提示', { confirmButtonText: '確定', confirmButtonClass: 'ticket-comfirm-btn', callback: () => {} }) } } }
最后組件引入這里的代碼我就丟在一個框里展示了,偷懶一下
總結:其實思路的才是重點,之前小伙伴問怎么做導出指定列內容的時候一時間沒想到,還特意去搜了下有沒有特定的插件可以處理,沒找到,后面工作遇到了,仔細想想原理,然后一邊修改一邊測就出來了,所以寫出來當個筆記,也許會幫助到遇到導出指定內容問題的其他小伙伴,當是一個思路上的提示吧。