如果通过 vxe-table 实现 Excel,可以和 Excel、WPS 复制粘贴

如果通过 vxe-table 实现 Excel,可以和 Excel、WPS 复制粘贴

官网:https://vxetable.cn

<template>
  <div>
    <vxe-grid
      ref="gridRef"
      v-bind="gridOptions"
      @cell-area-selection-end="cellAreaSelectionEndEvent"
      @cell-area-extension-end="cellAreaExtensionEndEvent"
      @clear-cell-area-selection="clearCellAreaSelectionEvent">
      <template #toolbarButtons>
        <span>数据:</span>
        <vxe-select v-model="rowSize" :options="dataOptions" @change="changeRowSizeEvent"></vxe-select>
      </template>

      <template #bottom>
        <div>统计信息:{{ countText }}</div>
      </template>
    </vxe-grid>
  </div>
</template>

<script>
import XEUtils from 'xe-utils'
export default {
  data () {
    const rowSize = 50
    const countText = ''
    const dataOptions = [
      { label: '加载 3 行', value: 3 },
      { label: '加载 20 行', value: 20 },
      { label: '加载 50 行', value: 50 },
      { label: '加载 100 行', value: 100 },
      { label: '加载 500 行', value: 500 },
      { label: '加载 1000 行', value: 1000 },
      { label: '加载 5000 行', value: 5000 },
      { label: '加载 10000 行', value: 10000 },
      { label: '加载 50000 行', value: 50000 }
    ]
    const gridOptions = {
      border: true,
      height: 800,
      showOverflow: true,
      columnConfig: {
        resizable: true,
        width: 160
      },
      rowConfig: {
        keyField: 'id',
        resizable: true
      },
      resizableConfig: {
        isSyncAutoWidth: true,
        isDblclickAutoWidth: true,
        isSyncAutoHeight: true,
        isDblclickAutoHeight: true // 启用双击自适应行高
      },
      exportConfig: {
        types: [
          'xlsx'
        ]
      },
      toolbarConfig: {
        custom: true,
        zoom: true,
        export: true,
        slots: {
          buttons: 'toolbarButtons'
        }
      },
      mouseConfig: {
        area: true // 是否开启区域选取
      },
      areaConfig: {
        multiple: true,
        showColumnStatus: true,
        showRowStatus: true,
        selectCellToRow: true,
        extendByCalc: true,
        extendByCopy: true // 是否启用扩展区域自动填充,当选取一个单元格时,自动将当前内容填充到扩展区域的所有单元格中(同时按住 ctrl 键可取消值自动识别数字功能)
      },
      editConfig: {
        mode: 'cell',
        trigger: 'dblclick' // 双击单元格激活编辑状态
      },
      menuConfig: {
        header: {
          options: [
            // 引入 plugin-menu 扩展插件之后可以直接使用以下内置 code,使用最简单
            [
              { code: 'COPY_TITLE', name: '复制列标题' },
              { code: 'EXPORT_ALL', name: '导出 CSV', prefixIcon: 'vxe-icon-download', params: { filename: '导出数据', type: 'csv' } }
            ]
          ]
        },
        body: {
          options: [
            // 自行自定义 code 的功能,自己实现更灵活
            [
              { code: 'myCode', name: '自定义的菜单' }
            ],
            // 引入 plugin-menu 扩展插件之后可以直接使用以下内置 code,使用最简单
            [
              { code: 'CLEAR_CELL', name: '清除单元格值 (Del)' },
              { code: 'COPY_CELL', name: '页面内复制 (Ctrl+C)', prefixIcon: 'vxe-icon-copy' },
              { code: 'CUT_CELL', name: '页面内剪贴 (Ctrl+X)', prefixIcon: 'vxe-icon-cut' },
              { code: 'PASTE_CELL', name: '页面内粘贴 (Ctrl+V)', prefixIcon: 'vxe-icon-paste' }
            ],
            [
              { code: 'OPEN_FIND', name: '查找 (Ctrl+F)' },
              { code: 'OPEN_REPLACE', name: '替换 (Ctrl+H)' },
              { code: 'MERGE_OR_CLEAR', name: '合并/取消 (Ctrl+M)', prefixIcon: 'vxe-icon-merge-cells' }
            ],
            [
              {
                name: '插入数据',
                children: [
                  { code: 'INSERT_AT_ROW', name: '插入' },
                  { code: 'INSERT_NEXT_AT_ROW', name: '插入 next' },
                  { code: 'INSERT_AT_EDIT_ROW', name: '插入并编辑' },
                  { code: 'INSERT_NEXT_AT_EDIT_ROW', name: '插入并编辑 next' }
                ]
              }
            ],
            [
              {
                name: '删除数据',
                children: [
                  { code: 'DELETE_ROW', name: '删除行' },
                  { code: 'DELETE_AREA_ROW', name: '删除选取范围内的行' },
                  { code: 'DELETE_CHECKBOX_ROW', name: '删除复选框勾选行' }
                ]
              }
            ],
            [
              { code: 'EDIT_CELL', name: '编辑' },
              { code: 'REVERT_CELL', name: '还原值', prefixIcon: 'vxe-icon-repeat' }
            ],
            [
              { code: 'CLEAR_FILTER', name: '清除筛选' },
              { code: 'CLEAR_ALL_FILTER', name: '清除所有筛选' },
              {
                name: '排序',
                children: [
                  { code: 'CLEAR_SORT', name: '清除排序' },
                  { code: 'SORT_ASC', name: '升序', prefixIcon: 'vxe-icon-sort-alpha-asc' },
                  { code: 'SORT_DESC', name: '倒序', prefixIcon: 'vxe-icon-sort-alpha-desc' }
                ]
              }
            ],
            // 引入 plugin-menu 扩展插件之后可以直接使用以下内置 code,使用最简单
            [
              { code: 'PRINT_ALL', name: '打印', prefixIcon: 'vxe-icon-print', params: { columns: ['name', 'role', 'sex', 'num', 'age'] } },
              { code: 'EXPORT_ALL', name: '导出 CSV', prefixIcon: 'vxe-icon-download', params: { filename: '导出数据', type: 'csv' } }
            ]
          ]
        },
        footer: {
          options: [
            [
              { code: 'PRINT_ALL', name: '打印', prefixIcon: 'vxe-icon-print', params: { columns: ['name', 'role', 'sex', 'num', 'age'] } }
            ]
          ]
        }
      },
      keyboardConfig: {
        arrowCursorLock: true,
        isClip: true,
        isArrow: true,
        isShift: true,
        isTab: true,
        isEnter: true,
        isEdit: true,
        isBack: true,
        isDel: true,
        isEsc: true,
        isFNR: true,
        isMerge: true // 是否开启单元格合并功能
      },
      virtualXConfig: {
        enabled: true,
        gt: 0
      },
      virtualYConfig: {
        enabled: true,
        gt: 0
      },
      columns: [
        { field: 'seq', type: 'seq', fixed: 'left', width: 80, rowResize: true },
        { field: 'a', title: 'A', editRender: { name: 'input' } },
        { field: 'b', title: 'B', editRender: { name: 'input' } },
        { field: 'c', title: 'C', editRender: { name: 'input' } },
        { field: 'd', title: 'D', editRender: { name: 'input' } },
        { field: 'e', title: 'E', editRender: { name: 'input' } },
        { field: 'f', title: 'F', editRender: { name: 'input' } },
        { field: 'g', title: 'G', editRender: { name: 'input' } },
        { field: 'h', title: 'H', editRender: { name: 'input' } },
        { field: 'i', title: 'I', editRender: { name: 'input' } },
        { field: 'j', title: 'J', editRender: { name: 'input' } },
        { field: 'k', title: 'K', editRender: { name: 'input' } },
        { field: 'l', title: 'I', editRender: { name: 'input' } },
        { field: 'm', title: 'M', editRender: { name: 'input' } },
        { field: 'n', title: 'N', editRender: { name: 'input' } },
        { field: 'o', title: 'O', editRender: { name: 'input' } },
        { field: 'p', title: 'p', editRender: { name: 'input' } },
        { field: 'q', title: 'Q', editRender: { name: 'input' } }
      ]
    }
    return {
      rowSize,
      countText,
      dataOptions,
      gridOptions
    }
  },
  methods: {
    loadData (size) {
      // 模拟后台接口
      this.gridOptions.loading = true
      setTimeout(async () => {
        const list = []
        for (let i = 0; i < size; i++) {
          const item = {
            id: i + 1,
            a: '9',
            b: '2',
            c: '7',
            d: '6',
            e: '6',
            f: '3',
            g: '5',
            h: '5',
            i: '4',
            j: '0',
            k: '7',
            l: '8',
            m: '8',
            n: '5',
            o: '8',
            p: '1',
            q: '9',
            r: '3',
            s: '4',
            t: '1'
          }
          list.push(item)
        }
        this.gridOptions.loading = false
        const $grid = this.$refs.gridRef
        if ($grid) {
          await $grid.loadData(list)
          this.updateFooterInfo()
        }
      }, 200)
    },
    updateFooterInfo () {
      const $grid = this.$refs.gridRef
      if ($grid) {
        const cellAreas = $grid.getCellAreas() // 获取选取的区域
        const firstItem = cellAreas[0]
        let countNum = 0
        if (firstItem) {
          firstItem.rows.forEach(row => {
            firstItem.cols.forEach(column => {
              const cellValue = row[column.field]
              countNum += XEUtils.toNumber(cellValue)
            })
          })
        }
        this.countText = firstItem ? `当前已选择 ${firstItem.rows.length}${firstItem.cols.length} 列;合计:${countNum}` : ''
      }
    },
    // 单元格选取结束事件
    cellAreaSelectionEndEvent () {
      this.updateFooterInfo()
    },
    // 单元格扩展结束事件
    cellAreaExtensionEndEvent () {
      this.updateFooterInfo()
    },
    // 点击表格之外选取区域被清除时
    clearCellAreaSelectionEvent () {
      this.updateFooterInfo()
    },
    changeRowSizeEvent () {
      this.loadData(this.rowSize)
    }
  },
  mounted () {
    this.loadData(this.rowSize)
  }
}
</script>

https://gitee.com/x-extends/vxe-table

posted @   可不简单  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek-R1本地部署如何选择适合你的版本?看这里
· 开源的 DeepSeek-R1「GitHub 热点速览」
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 揭秘 Sdcb Chats 如何解析 DeepSeek-R1 思维链
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
点击右上角即可分享
微信分享提示