Handsontable vue如何实现在线编辑excal

官网地址:https://handsontable.com/

1.实现效果

 

2.安装

import { HotTable } from '@handsontable/vue'
import Handsontable from 'handsontable'
 
3.页面引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
           <hot-table
                  ref="tableServer"
                  :data="hotSettings.dataList"                          // excal中的数据源
                  :context-menu="hotSettings.contextMenu"               // 右击鼠标可进行的操作
                  :col-headers="hotSettings.colHeaders"                 // 表格头部标题
                  :start-rows="hotSettings.startRows"                   // 默认固定行数
                  :start-cols="hotSettings.startCols"                   // 默认固定列数
                  :row-headers="hotSettings.rowHeaders"                 // 默认显示表格行头部
                  :row-heights="hotSettings.rowHeights"                 // 默认设置行高度
                  :manual-row-resize="hotSettings.manualRowResize"      //
                  :manual-column-resize="hotSettings.manualColumnResize"
                  :manual-row-move="hotSettings.manualRowMove"
                  :columns="hotSettings.columns"
                  :before-remove-row="hotSettings.beforeRemoveRow"          // 删除行之前触发的事件
                  :after-create-row="hotSettings.afterCreateRow"            // 添加行后触发的事件                   //一定要记住所有的事件、数值一定要绑定在标签上才可使用,只在js的data中绑定是不可以的
                  :after-change="hotSettings.afterChange"                   // 新增行,动态改变值触发的事件
                  :id="`hotTableAll${$route.params.id}`"
                  class="table_hot"
                  license-key="non-commercial-and-evaluation"
                />
              </el-form-item>
              <el-button class="primary-button uploadButton"
                         size="small"
                         type="primary"
                         icon="el-icon-upload"
                         @click="uploadFile">导出</el-button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<script>
import { HotTable } from '@handsontable/vue'
import Handsontable from 'handsontable'
import { Message } from 'element-ui'import priceList from '@/utils/priceList.js'// 如果excal中有值为空,可拦截const validatorList = (rule, value, callback) => {  for (let i = 0; i < value.length; i++) {
    if (!value[i].region || !value[i].destination) {
      callback(new Error('请输入价格表中所有信息, 多余的可通过鼠标右击进行删除行'))
      return
    }
  }
  callback()
}
const riseWeightVal = function (value, callback) {
  if (/^\d+(?=\.{0,1}\d+$|$)/.test(value) || value === '') {
    callback(true)
  } else {
    Message.error({
      message: '请输入数字'
    })
    callback(false)
  }
}
 
export default {
  components: {
    HotTable
  },
  data() {
    return {
      addressList: [{
        area: []
      }],
      hotSettings: {
        dataList: [],  //
        colHeaders: ['区域', '目的地', '首重 kg', '首重价格', '续重 kg', '续重价格'],
        startRows: 8,
        startCols: 6,
        rowHeaders: true,
        rowHeights: 40,
        manualRowResize: true,
        manualColumnResize: true,
        manualRowMove: true,
        customBorders: true,
        columns: [      //data: dataList数组中对应的 键,readOnly: 只读, type: 属于什么类型 例:text, numeric, validator: 数据验证
          { data: 'region', readOnly: false, type: 'text' },
          { data: 'destination', readOnly: false, type: 'text' },
          { data: 'firstWeight', readOnly: false, validator: riseWeightVal, allowInvalid: false },
          { data: 'firstWeightPrice', readOnly: false, validator: riseWeightVal, allowInvalid: false },
          { data: 'riseWeight', readOnly: false, validator: riseWeightVal, allowInvalid: false },
          { data: 'riseWeightPrice', readOnly: false, validator: riseWeightVal, allowInvalid: false }
        ],
        beforeRemoveRow: this.beforeRemoveRowMe,
        afterCreateRow: this.afterCreateRowMe,
        afterChange: this.afterChangeMe,
        contextMenu: {
          items: {
            'row_above': {
              name: '在此行上方插入行'
            },
            'row_below': {
              name: '在此行下方插入行'
            },
            'separator': Handsontable.plugins.ContextMenu.SEPARATOR,
            'copy': {
              name: '复制'
            },
            'undo': {
              name: '撤消'
            },
            'separator1': Handsontable.plugins.ContextMenu.SEPARATOR,
            'remove_row': {
              name: '删除行'
            },
            'clear_column': {
              name: '删除列'
            },
            'clear_custom': {
              name: '删除所有单元格',
              callback: function () {
                this.clear()
              }
            }
          }
        }
      },
      expressCompanyList: [],
      dateRange: [],
      typeBol: false,
      searchParam: {
        supplierServiceRegionPriceVos: []
      },
      searchParamRules: {
        supplierServiceRegionPriceVos: [
          { type: 'array', required: true, message: '请填写价格表', trigger: 'blur' },
          { validator: validatorList, required: true, message: '请输入价格表中所有信息, 多余的可通过鼠标右击进行删除行', trigger: 'blur' }
        ]
      },
      showContent: false,
      loadShow: false,
      saveLimit: false
    }
  },
 
  mounted() {   this.hotSettings.dataList = this._.cloneDeep(priceList)  },
  methods: {
    // 删除行之前调用
    beforeRemoveRowMe: function (changes, source) { // 数据改变时触发此方法
      this.hotSettings.dataList.splice(changes, source)
    },
    // 添加行
    afterCreateRowMe: function (changes) {
      this.hotSettings.dataList.splice(changes, 0, {
        region: '',
        destination: '',
        firstWeight: '',
        firstWeightPrice: '',
        riseWeight: '',
        riseWeightPrice: ''
      })
    },
    // 新增行时,动态改变值
    afterChangeMe: function (changes) {
      if (changes) {
        changes.forEach(([row, prop, oldValue, newValue]) => {
          console.log(oldValue)
          this.hotSettings.dataList[row][prop] = newValue
        })
      }
    },
    // 查看-excel不可编辑
    excalEdit() {
      this.hotSettings.columns.forEach(par => {
        par.readOnly = true
      })
    },
    definedShow() {
      this.showContent = true
    },
    saveSubmit() {      // 防止点击多次触发
      if (this.saveLimit) return
    conso.log()
      const that = this
      that.searchParam.supplierServiceRegionPriceVos = that.hotSettings.dataList
      const temp = that._.cloneDeep(this.searchParam)
      that.$refs.searchForm.validate((valid) => {
        if (valid) {      console.log(this.hotSettings.dataList)          that.saveLimit = true
        }
      })
    },
    // 导出文件
    uploadFile() {
      // 可查看网址https://handsontable.com/docs/7.1.0/ExportFile.html
      const container = this.$refs.tableServer.hotInstance
      const exportPlugin = container.getPlugin('exportFile')
      exportPlugin.downloadFile('csv', {
        bom: 'UTF-8', // 允许您使用BOM签名导出数据。
        columnDelimiter: ',', // 允许您定义列分隔符。
        columnHeaders: false, // 允许使用列标题导出数据。
        exportHiddenColumns: true, // 允许您从隐藏列导出数据。
        exportHiddenRows: true, // 允许您从隐藏行导出数据
        fileExtension: 'csv', // 允许您定义文件扩展名。
        filename: '供应商服务价格表[YYYY]-[MM]-[DD]', // 允许您定义文件名。
        mimeType: 'text/csv', // 允许您定义MIME类型。
        rowDelimiter: '\r\n', // 允许您定义行分隔符。
        rowHeaders: true // 允许您使用行标题导出数据。
      })
    }
  }
}
</script>

  

  

 

posted @   小短腿奔跑吧  阅读(4661)  评论(2编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示