实现vue导出excel和echart图形分别在不同工作表

背景

实现一键导出excel
并且区分图表和表格为不同的sheet工作表
最终效果为
在这里插入图片描述

代码实现

功能实现


  
  <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, // 表格数据
    dialog: false, // 模态框显示、隐藏
    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: { // 坐标轴指示器,坐标轴触发有效
            type: 'shadow' // 默认为直线,可选为:'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 = ['序号', '年份', '月份', '充电量', '放电量', '温度']; // 表头数据
    tableData.unshift(header);
        const columnIndexToRemove = 0;

// 遍历 elTable 数组,将每一行的第一列数据删除
        tableData.forEach(row => {
    row.splice(columnIndexToRemove, 1);
    });


        const worksheet = workbook.addWorksheet('数据图形');
        const worksheet2 = workbook.addWorksheet('数据表格');
        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">导出图表</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>

## 模态框点击以及自定义文件名
添加模态框组件

 <el-dialog v-model="dialog" title="表格导出" width="30%" @close="closeDialog">
      <el-input v-model="name" placeholder="请输入导出文件的文件名"></el-input>
      <el-alert title="默认文件名为(站点名+数据文件)" 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-button @click="openExportDialog">导出图表</el-button> <!-- 导出按钮 -->
    

对应的方法是

      openExportDialog() {
      this.dialog = true; // 打开模态框
    },

    closeDialog() {
      this.dialog = false; // 关闭模态框
    },

然后修改相应的状态

全部代码


  
  <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, // 表格数据
    dialog: false, // 模态框显示、隐藏
    name: '' // 自定义文件名
})
let filename = ''; 
const { tableData, dialog, name } = toRefs(state)

  export default {
    data() {
        const state = reactive({
    tableData: [] as any, // 表格数据
    dialog: false, // 模态框显示、隐藏
    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: { // 坐标轴指示器,坐标轴触发有效
            type: 'shadow' // 默认为直线,可选为:'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; // 打开模态框
    },

    closeDialog() {
      this.dialog = false; // 关闭模态框
    },

       close() {
	// 模态框取消,重新获取数据
    this.fetchData();
},
      exportExcel() {
        if (state.name === '') {
      // 默认导出文件名
      filename = '站点' + store.siteid + '数据文件';
    } 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 = ['序号', '年份', '月份', '充电量', '放电量', '温度']; // 表头数据
    tableData.unshift(header);
        const columnIndexToRemove = 0;

// 遍历 elTable 数组,将每一行的第一列数据删除
        tableData.forEach(row => {
    row.splice(columnIndexToRemove, 1);
    });


        const worksheet = workbook.addWorksheet('数据图形');
        const worksheet2 = workbook.addWorksheet('数据表格');
        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 === '') {
      // 默认导出文件名
      filename = '站点' + store.siteid + '数据文件.xlsx';
    } else {
      filename = state.name += '.xlsx';
    }
    const header = ['序号', '年份', '月份', '充电量', '放电量', '温度']; // 表头数据

// 将表头插入到 elTable 数组的开头

    // 创建工作簿
    const workbook = XLSX.utils.book_new();
    const xlsxParam = { raw: true }; // 转化成Excel使用原始格式

    // 获取表格数据
    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 数组,将每一行的第一列数据删除
        tableData.forEach(row => {
    row.splice(columnIndexToRemove, 1);
    });
    // 创建工作表1
    const sheet1 = XLSX.utils.aoa_to_sheet(tableData);

    // 将工作表1添加到工作簿
    XLSX.utils.book_append_sheet(workbook, sheet1, '表格');




// 将echarts图表转换为图片

// 创建工作表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) // 获取图表实例
//       const base64Image = chart.getDataURL({
//         pixelRatio: 2, // 导出图片的分辨率比例,默认为1,即图片的分辨率为屏幕分辨率的一倍
//         backgroundColor: '#fff' // 导出图片的背景色
//       })
//       let image= workbook.addImage({ // 添加图片
//           base64: base64Image, // 图片的base64编码
//           extension: 'png'  // 图片的扩展名
//         });
//         worksheet.addImage(image, 'A1:J20'); // 将图片添加到工作表中
//         workbook.xlsx.writeBuffer().then(function (buffer) { // 生成excel文件的二进制数据
//         saveAs.saveAs(new Blob([buffer], {  // 生成Blob对象
//           type: 'application/octet-stream'  // 指定文件的MIME类型
//         }), 'xchart.xlsx');  // 指定文件名
//       });


 XLSX.utils.book_append_sheet(workbook, sheet2, '图表');

    // 导出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">导出图表</el-button>
      <el-button type="primary" @click="exportExcel">导出</el-button>导出按钮 -->
      <el-button @click="openExportDialog">导出图表</el-button> <!-- 导出按钮 -->
    
 <!-- 模态框 -->
 <el-dialog v-model="dialog" title="表格导出" width="30%" @close="closeDialog">
      <el-input v-model="name" placeholder="请输入导出文件的文件名"></el-input>
      <el-alert title="默认文件名为(站点名+数据文件)" 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.js,excel,javascript)