vue導(dǎo)出excel和echart圖形分別在不同工作表的實(shí)現(xiàn)方法
背景
實(shí)現(xiàn)一鍵導(dǎo)出excel并且區(qū)分圖表和表格為不同的sheet工作表
最終效果為
代碼實(shí)現(xiàn)
功能實(shí)現(xiàn)
<script lang="ts"> import * as echarts from 'echarts'; import ExcelJS from 'exceljs'; import { saveAs } from 'file-saver'; import {getAsyncTempCurrentData} from '../../../api/fenxi' import { toRefs } from 'vue' import FileSaver from "file-saver"; import * as XLSX from 'xlsx' import { ref, reactive, onMounted ,getCurrentInstance,nextTick } from 'vue' export default { data() { const state = reactive({ tableData: [] as any, // 表格數(shù)據(jù) dialog: false, // 模態(tài)框顯示、隱藏 name: '' // 自定義文件名 }) // const tableData = ref(); const { tableData, dialog, name } = toRefs(state) return { chart: null, tableData }; }, mounted() { this.chart = echarts.init(this.$refs.chart); this.fetchData(); }, methods: { fetchData() { getAsyncTempCurrentData().then((response) => { console.log(response); this.tableData = response.data; const years = response.data.map((item) => item.year + '年' + item.month + '月'); const charges = response.data.map((item) => item.charge); const discharges = response.data.map((item) => item.discharge); const temps = response.data.map((item) => item.temp); const option = { textStyle:{ color:"gray"}, tooltip: { trigger: 'axis', axisPointer: { // 坐標(biāo)軸指示器,坐標(biāo)軸觸發(fā)有效 type: 'shadow' // 默認(rèn)為直線,可選為:'line' | 'shadow' }, show: true, }, grid: { left: '2%', right: '4%', bottom: '14%', top:'16%', containLabel: false }, legend: { data: ['充電量', '放電量', '溫度'], right: 10, top:12, textStyle: { color: "#fff" }, // itemGap: 35 }, xAxis: { type: 'category', data: years, axisLine: { lineStyle: { color: 'white' } }, axisLabel: { // interval: 0, // rotate: 40, textStyle: { fontFamily: 'Microsoft YaHei' } }, }, yAxis: [ { type: 'value', scale: false, min: 0, axisLine: { show: false, lineStyle: { color: 'white' } }, splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.3)' } }, axisLabel: {} }, { type: 'value', scale: true, axisLine: { show: false, lineStyle: { color: 'gray' } }, splitLine: { show: true, lineStyle: { color: 'gray' } }, axisLabel: {} } ], series: [{ name: '充電量', type: 'bar', barWidth: '15%', yAxisIndex: 0, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#fccb05' }, { offset: 1, color: '#f5804d' }]), barBorderRadius: 12, }, }, data: charges, }, { name: '放電量', type: 'bar', barWidth: '15%', yAxisIndex: 0, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#8bd46e' }, { offset: 1, color: '#09bcb7' }]), barBorderRadius: 11, } }, data: discharges }, { name: '溫度', type: 'line', yAxisIndex: 1, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#248ff7' }, { offset: 1, color: '#6851f1' }]), barBorderRadius: 11, } }, data: temps }] }; this.chart.setOption(option); }); }, exportExcel() { const workbook = new ExcelJS.Workbook(); const tableData = Array.from(document.querySelectorAll('#el-table tbody tr')).map(row => { return Array.from(row.querySelectorAll('td')).map(cell => cell.innerText); }); const header = ['序號', '年份', '月份', '充電量', '放電量', '溫度']; // 表頭數(shù)據(jù) tableData.unshift(header); const columnIndexToRemove = 0; // 遍歷 elTable 數(shù)組,將每一行的第一列數(shù)據(jù)刪除 tableData.forEach(row => { row.splice(columnIndexToRemove, 1); }); const worksheet = workbook.addWorksheet('數(shù)據(jù)圖形'); const worksheet2 = workbook.addWorksheet('數(shù)據(jù)表格'); const chart = echarts.getInstanceByDom(this.$refs.chart); const base64Image = chart.getDataURL({ pixelRatio: 2, backgroundColor: '#fff', }); let image = workbook.addImage({ base64: base64Image, extension: 'png', }); worksheet.addImage(image, 'A1:Z30'); worksheet2.addRows(tableData); workbook.xlsx.writeBuffer().then(function (buffer) { saveAs.saveAs( new Blob([buffer], { type: 'application/octet-stream', }), 'xchart.xlsx' ); }); }, }, }; </script> <template> <div> <div ref="chart" id="lineChart" style="height: 400px; width: 1000px"></div> <el-button @click="exportExcel">導(dǎo)出圖表</el-button> <el-table :data="tableData" style="width: 100%" id="el-table" border ref="tableRef" v-show="true"> <el-table-column type="selection" width="50" align="center" /> <el-table-column prop="year" label="年份"></el-table-column> <el-table-column prop="month" label="月份"></el-table-column> <el-table-column prop="charge" label="充電量"></el-table-column> <el-table-column prop="discharge" label="放電量"></el-table-column> <el-table-column prop="temp" label="溫度"></el-table-column> </el-table> </div> </template>
## 模態(tài)框點(diǎn)擊以及自定義文件名
添加模態(tài)框組件
<el-dialog v-model="dialog" title="表格導(dǎo)出" width="30%" @close="closeDialog"> <el-input v-model="name" placeholder="請輸入導(dǎo)出文件的文件名"></el-input> <el-alert title="默認(rèn)文件名為(站點(diǎn)名+數(shù)據(jù)文件)" type="info" :closable="false" style="margin-top: 10px;" /> <template #footer> <span class="dialog-footer"> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" @click="exportExcel">確定</el-button> </span> </template> </el-dialog>
綁定開閉狀態(tài),在按鈕上修改觸發(fā)方法為開啟模態(tài)框
<el-button @click="openExportDialog">導(dǎo)出圖表</el-button> <!-- 導(dǎo)出按鈕 -->
對應(yīng)的方法是
openExportDialog() { this.dialog = true; // 打開模態(tài)框 }, closeDialog() { this.dialog = false; // 關(guān)閉模態(tài)框 },
然后修改相應(yīng)的狀態(tài)
全部代碼
<script lang="ts"> import * as echarts from 'echarts'; import ExcelJS from 'exceljs'; import { saveAs } from 'file-saver'; import {getAsyncTempCurrentData} from '../../../api/fenxi' import { toRefs } from 'vue' import FileSaver from "file-saver"; import * as XLSX from 'xlsx' import { ref, reactive, onMounted ,nextTick } from 'vue' import { selectedStoreHook,useselectedStore } from "../../../store/modules/selected"; const store = useselectedStore(); const state = reactive({ tableData: [] as any, // 表格數(shù)據(jù) dialog: false, // 模態(tài)框顯示、隱藏 name: '' // 自定義文件名 }) let filename = ''; const { tableData, dialog, name } = toRefs(state) export default { data() { const state = reactive({ tableData: [] as any, // 表格數(shù)據(jù) dialog: false, // 模態(tài)框顯示、隱藏 name: '' // 自定義文件名, }) return { chart: null, tableData, dialog, name, }; }, mounted() { this.chart = echarts.init(this.$refs.chart); this.fetchData(); }, methods: { fetchData() { getAsyncTempCurrentData().then((response) => { console.log(response); this.tableData = response.data; const years = response.data.map((item) => item.year + '年' + item.month + '月'); const charges = response.data.map((item) => item.charge); const discharges = response.data.map((item) => item.discharge); const temps = response.data.map((item) => item.temp); const option = { textStyle:{ color:"gray"}, tooltip: { trigger: 'axis', axisPointer: { // 坐標(biāo)軸指示器,坐標(biāo)軸觸發(fā)有效 type: 'shadow' // 默認(rèn)為直線,可選為:'line' | 'shadow' }, show: true, }, grid: { left: '2%', right: '4%', bottom: '14%', top:'16%', containLabel: false }, legend: { data: ['充電量', '放電量', '溫度'], right: 10, top:12, textStyle: { color: "#fff" }, // itemGap: 35 }, xAxis: { type: 'category', data: years, axisLine: { lineStyle: { color: 'white' } }, axisLabel: { // interval: 0, // rotate: 40, textStyle: { fontFamily: 'Microsoft YaHei' } }, }, yAxis: [ { type: 'value', scale: false, min: 0, axisLine: { show: false, lineStyle: { color: 'white' } }, splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.3)' } }, axisLabel: {} }, { type: 'value', scale: true, axisLine: { show: false, lineStyle: { color: 'gray' } }, splitLine: { show: true, lineStyle: { color: 'gray' } }, axisLabel: {} } ], series: [{ name: '充電量', type: 'bar', barWidth: '15%', yAxisIndex: 0, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#fccb05' }, { offset: 1, color: '#f5804d' }]), barBorderRadius: 12, }, }, data: charges, }, { name: '放電量', type: 'bar', barWidth: '15%', yAxisIndex: 0, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#8bd46e' }, { offset: 1, color: '#09bcb7' }]), barBorderRadius: 11, } }, data: discharges }, { name: '溫度', type: 'line', yAxisIndex: 1, itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#248ff7' }, { offset: 1, color: '#6851f1' }]), barBorderRadius: 11, } }, data: temps }] }; this.chart.setOption(option); }); }, openExportDialog() { this.dialog = true; // 打開模態(tài)框 }, closeDialog() { this.dialog = false; // 關(guān)閉模態(tài)框 }, close() { // 模態(tài)框取消,重新獲取數(shù)據(jù) this.fetchData(); }, exportExcel() { if (state.name === '') { // 默認(rèn)導(dǎo)出文件名 filename = '站點(diǎn)' + store.siteid + '數(shù)據(jù)文件'; } else { filename = state.name ; } const workbook = new ExcelJS.Workbook(); const tableData = Array.from(document.querySelectorAll('#el-table tbody tr')).map(row => { return Array.from(row.querySelectorAll('td')).map(cell => cell.innerText); }); const header = ['序號', '年份', '月份', '充電量', '放電量', '溫度']; // 表頭數(shù)據(jù) tableData.unshift(header); const columnIndexToRemove = 0; // 遍歷 elTable 數(shù)組,將每一行的第一列數(shù)據(jù)刪除 tableData.forEach(row => { row.splice(columnIndexToRemove, 1); }); const worksheet = workbook.addWorksheet('數(shù)據(jù)圖形'); const worksheet2 = workbook.addWorksheet('數(shù)據(jù)表格'); const chart = echarts.getInstanceByDom(this.$refs.chart); const base64Image = chart.getDataURL({ pixelRatio: 2, backgroundColor: '#fff', }); let image = workbook.addImage({ base64: base64Image, extension: 'png', }); worksheet.addImage(image, 'A1:Z30'); worksheet2.addRows(tableData); workbook.xlsx.writeBuffer().then(function (buffer) { saveAs.saveAs( new Blob([buffer], { type: 'application/octet-stream', }), filename+'.xlsx' ); }); },// save() { nextTick(function () { let filename = ''; if (state.name === '') { // 默認(rèn)導(dǎo)出文件名 filename = '站點(diǎn)' + store.siteid + '數(shù)據(jù)文件.xlsx'; } else { filename = state.name += '.xlsx'; } const header = ['序號', '年份', '月份', '充電量', '放電量', '溫度']; // 表頭數(shù)據(jù) // 將表頭插入到 elTable 數(shù)組的開頭 // 創(chuàng)建工作簿 const workbook = XLSX.utils.book_new(); const xlsxParam = { raw: true }; // 轉(zhuǎn)化成Excel使用原始格式 // 獲取表格數(shù)據(jù) const tableData = Array.from(document.querySelectorAll('#el-table tbody tr')).map(row => { return Array.from(row.querySelectorAll('td')).map(cell => cell.innerText); }); tableData.unshift(header); const columnIndexToRemove = 0; // 遍歷 elTable 數(shù)組,將每一行的第一列數(shù)據(jù)刪除 tableData.forEach(row => { row.splice(columnIndexToRemove, 1); }); // 創(chuàng)建工作表1 const sheet1 = XLSX.utils.aoa_to_sheet(tableData); // 將工作表1添加到工作簿 XLSX.utils.book_append_sheet(workbook, sheet1, '表格'); // 將echarts圖表轉(zhuǎn)換為圖片 // 創(chuàng)建工作表2 const sheet2 = XLSX.utils.aoa_to_sheet([]); const img = new Image(); img.src = 'http://localhost:4444/src/assets/admin.png'; // const chart = echarts.getInstanceByDom(this.$refs.chart) // 獲取圖表實(shí)例 // const base64Image = chart.getDataURL({ // pixelRatio: 2, // 導(dǎo)出圖片的分辨率比例,默認(rèn)為1,即圖片的分辨率為屏幕分辨率的一倍 // backgroundColor: '#fff' // 導(dǎo)出圖片的背景色 // }) // let image= workbook.addImage({ // 添加圖片 // base64: base64Image, // 圖片的base64編碼 // extension: 'png' // 圖片的擴(kuò)展名 // }); // worksheet.addImage(image, 'A1:J20'); // 將圖片添加到工作表中 // workbook.xlsx.writeBuffer().then(function (buffer) { // 生成excel文件的二進(jìn)制數(shù)據(jù) // saveAs.saveAs(new Blob([buffer], { // 生成Blob對象 // type: 'application/octet-stream' // 指定文件的MIME類型 // }), 'xchart.xlsx'); // 指定文件名 // }); XLSX.utils.book_append_sheet(workbook, sheet2, '圖表'); // 導(dǎo)出Excel文件 XLSX.writeFile(workbook, filename); }); } } }; </script> <template> <div ref="export" > <div ref="chart" id="lineChart" style="height: 400px; width: 1000px" v-show="false"></div> <!-- <el-button @click="exportExcel">導(dǎo)出圖表</el-button> <el-button type="primary" @click="exportExcel">導(dǎo)出</el-button>導(dǎo)出按鈕 --> <el-button @click="openExportDialog">導(dǎo)出圖表</el-button> <!-- 導(dǎo)出按鈕 --> <!-- 模態(tài)框 --> <el-dialog v-model="dialog" title="表格導(dǎo)出" width="30%" @close="closeDialog"> <el-input v-model="name" placeholder="請輸入導(dǎo)出文件的文件名"></el-input> <el-alert title="默認(rèn)文件名為(站點(diǎn)名+數(shù)據(jù)文件)" type="info" :closable="false" style="margin-top: 10px;" /> <template #footer> <span class="dialog-footer"> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" @click="exportExcel">確定</el-button> </span> </template> </el-dialog> <el-table :data="tableData" style="width: 100%" id="el-table" border ref="tableRef" v-show="false"> <el-table-column type="selection" width="50" align="center" /> <el-table-column prop="year" label="年份"></el-table-column> <el-table-column prop="month" label="月份"></el-table-column> <el-table-column prop="charge" label="充電量"></el-table-column> <el-table-column prop="discharge" label="放電量"></el-table-column> <el-table-column prop="temp" label="溫度"></el-table-column> </el-table> </div> </template>
以上就是vue導(dǎo)出excel和echart圖形分別在不同工作表的實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于vue導(dǎo)出excel和echart在不同工作表的資料請關(guān)注腳本之家其它相關(guān)文章!
- vue3+echarts實(shí)現(xiàn)好看的圓角環(huán)形圖
- echarts設(shè)置tootip輪播切換展示(vue3搭配vue-echarts粘貼即用)
- 手把手教你Vue3?按需引入?Echarts的過程(收藏)
- vue使用echarts實(shí)現(xiàn)柱狀圖動(dòng)態(tài)排序效果
- vue2.0如何實(shí)現(xiàn)echarts餅圖(pie)效果展示
- vue中如何使用echarts動(dòng)態(tài)渲染數(shù)據(jù)
- vue使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)的示例詳解
- Vuex進(jìn)行Echarts數(shù)據(jù)頁面初始化后如何更新dom
- vue+echarts圖表的基本使用步驟總結(jié)
- 在Vue中使用Echarts+封裝
- 使用vue3+ts打開echarts的正確方式
- vue3中使用Vchart的示例代碼
相關(guān)文章
vue實(shí)現(xiàn)卡片翻轉(zhuǎn)輪播展示
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)卡片翻轉(zhuǎn)輪播展示,同時(shí)在翻轉(zhuǎn)時(shí)切換數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01Vue監(jiān)聽Enter鍵的方法總結(jié)與區(qū)別
這篇文章主要給大家介紹了關(guān)于Vue監(jiān)聽Enter鍵的方法與區(qū)別的相關(guān)資料,在Vue中我們可以通過監(jiān)聽鍵盤事件來實(shí)現(xiàn)回車鍵切換焦點(diǎn)的功能,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10vue如何自定義InputNumber計(jì)數(shù)器組件
這篇文章主要介紹了vue如何自定義InputNumber計(jì)數(shù)器組件問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10vue頁面設(shè)置滾動(dòng)失敗的完美解決方案(scrollTop一直為0)
這篇文章主要介紹了vue頁面設(shè)置滾動(dòng)失敗的解決方案(scrollTop一直為0),本文通過場景分析實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05Vue的v-model的幾種修飾符.lazy,.number和.trim的用法說明
這篇文章主要介紹了Vue的v-model的幾種修飾符.lazy,.number和.trim的用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08關(guān)于vue路由緩存清除在main.js中的設(shè)置
今天小編就為大家分享一篇關(guān)于vue路由緩存清除在main.js中的設(shè)置,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11Vue組件內(nèi)部實(shí)現(xiàn)一個(gè)雙向數(shù)據(jù)綁定的實(shí)例代碼
這篇文章主要介紹了Vue組件內(nèi)部實(shí)現(xiàn)一個(gè)雙向數(shù)據(jù)綁定的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue3數(shù)據(jù)監(jiān)聽watch/watchEffect的示例代碼
我們都知道監(jiān)聽器的作用是在每次響應(yīng)式狀態(tài)發(fā)生變化時(shí)觸發(fā),在組合式?API?中,我們可以使用?watch()函數(shù)和watchEffect()函數(shù),下面我們來看下vue3如何進(jìn)行數(shù)據(jù)監(jiān)聽watch/watchEffect,感興趣的朋友一起看看吧2023-02-02