如何在Web应用中实现Excel文件的前端展示与编辑:基于SheetJS与Handsontable的实战

在现代Web应用中,处理Excel文件是一个常见的需求。用户希望能够在浏览器中展示Excel文件的内容,并能够对部分内容进行编辑,最后将修改后的文件保存回服务器。为了实现这一需求,我们可以使用 SheetJSHandsontable 这两个强大的库。本文将详细介绍如何实现这一功能,并探讨在处理公式时的难点与解决方案。

1. 依赖库的选择与安装

首先,我们需要安装 SheetJSHandsontable 这两个库。SheetJS 用于读取和写入Excel文件,而 Handsontable 则提供了一个类似于Excel的表格编辑器。

bash 复制代码
npm install xlsx handsontable @handsontable/vue3

对于一些特定的需求,比如公式的实时计算,可能需要使用 SheetJS 的付费版本。不过,本文我们将重点介绍如何在不依赖付费功能的情况下,实现基本的Excel文件展示与编辑。

2. 从服务器读取Excel文件

我们从服务器获取Excel文件流,并将其解析为可用于前端展示的数据格式。以下是获取文件流并解析的代码示例:

javascript 复制代码
const fileArrayBuffer = ref()
const fileLoading = ref(false)

const getExcelFileData = async () => {
  fileLoading.value = true
  const res = await getExcelReq(参数)
  fileLoading.value = false
  fileArrayBuffer.value = res
}

const parseExcel = (arrayBuffer) => {
  const workbook = XLSX.read(arrayBuffer, { type: 'array', cellFormula: true })
  const firstSheetName = workbook.SheetNames[0]
  const worksheet = workbook.Sheets[firstSheetName]
  const data = XLSX.utils.sheet_to_json(worksheet, {
    header: 1,
    defval: '',
    raw: false,
    formula: true,
  })
  dataSource.value = data

  // 提取公式
  const formulas = {}
  const range = XLSX.utils.decode_range(worksheet['!ref'])
  for (let R = range.s.r; R <= range.e.r; ++R) {
    for (let C = range.s.c; C <= range.e.c; ++C) {
      const cellAddress = XLSX.utils.encode_cell({ r: R, c: C })
      const cell = worksheet[cellAddress]
      if (cell && cell.f) {
        formulas[cellAddress] = cell.f
      }
    }
  }

  // 提取合并单元格信息
  const merges = worksheet['!merges'] || []

  // 提取冻结区域信息
  const freeze = {
    rows: worksheet['!freeze']?.rows || 0,
    cols: worksheet['!freeze']?.cols || 0,
  }

  return { data, formulas, merges, freeze }
}

在这段代码中,我们首先通过 XLSX.read 读取文件流,然后提取工作表、数据、公式、合并单元格和冻结区域等信息。这些信息将用于后续的表格展示与编辑。

3. 使用Handsontable展示与编辑表格

接下来,我们使用 Handsontable 来展示从Excel文件中提取的数据,并允许用户进行编辑。以下是初始化 Handsontable 的代码:

javascript 复制代码
const initHandsontable = (container, parsedData) => {
  if (hotInstance.value) {
    hotInstance.value.destroy()
    hotInstance.value = null
  }
  const { data, formulas, merges, freeze } = parsedData
  hotSettings.value = {
    data: data,
    rowHeaders: true,
    colHeaders: true,
    contextMenu: true,
    manualRowResize: true,
    manualColumnResize: true,
    mergeCells: merges.map((merge) => ({
      row: merge.s.r,
      col: merge.s.c,
      rowspan: merge.e.r - merge.s.r + 1,
      colspan: merge.e.c - merge.s.c + 1,
    })),
    fixedRowsTop: freeze.rows,
    fixedColumnsLeft: freeze.cols,
    formulas: formulas,
    licenseKey: 'non-commercial-and-evaluation',
    cells: (row, col, prop) => {
      const cellAddress = XLSX.utils.encode_cell({ r: row, c: col })
      if (formulas[cellAddress]) {
        return { readOnly: true }
      }
      return {}
    },
  }
  hotInstance.value = new Handsontable(container, hotSettings.value)
}

在这段代码中,我们配置了 Handsontable 的各种选项,包括数据、合并单元格、冻结区域、以及公式的处理。对于包含公式的单元格,我们将其设置为只读,以防止用户修改公式。

4. 保存编辑后的Excel文件

用户完成编辑后,我们可以将修改后的数据保存回服务器。以下是保存文件的代码:

javascript 复制代码
const handleSettleSave = async () => {
  if (!hotInstance.value) return
  const updatedData = hotInstance.value.getData()

  const worksheet = XLSX.utils.aoa_to_sheet(updatedData)
  const workbook = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
  const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' })
  const blob = new Blob([excelBuffer], {
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  })
  const formData = new FormData()
  formData.append('file', blob, 'updated_file.xlsx')
  try {
    loading.value = true
    const response = await saveSettleFileReq(formData)
    if (response.code == 200 || response.data) {
      Message.success('文件保存成功')
    }
    loading.value = false
  } catch (error) {
    console.error('文件上传失败:', error)
  }
}

在这段代码中,我们将修改后的数据转换成Excel文件,并将文件流上传到服务器。

5. 公式处理的挑战

在使用 SheetJS 时,公式的实时计算是一个较为复杂的问题。SheetJS 的免费版本虽然可以读取公式,但不支持实时计算和更新。如果您的应用需要实时计算功能,可能需要使用 SheetJS 的付费版本,或者考虑其他支持公式计算的库。

6. 总结

通过 SheetJSHandsontable,我们可以轻松地在Web应用中实现Excel文件的前端展示与编辑。尽管在处理公式时存在一些挑战,但对于大多数基础需求来说,这套方案已经足够强大且易于实现。

希望这篇文章能帮助你在项目中更好地处理Excel文件。如果你有任何问题或建议,欢迎在评论区留言讨论!

相关推荐
毕设源码-朱学姐1 天前
【开题答辩全过程】以 基于web教师继续教育系统的设计与实现为例,包含答辩的问题和答案
前端
web打印社区1 天前
web-print-pdf:突破浏览器限制,实现专业级Web静默打印
前端·javascript·vue.js·electron·html
RFCEO1 天前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
Amumu121381 天前
Vuex介绍
前端·javascript·vue.js
We་ct1 天前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
2601_949480061 天前
【无标题】
开发语言·前端·javascript
css趣多多1 天前
Vue过滤器
前端·javascript·vue.js
理人综艺好会1 天前
Web学习之用户认证
前端·学习
We་ct1 天前
LeetCode 36. 有效的数独:Set实现哈希表最优解
前端·算法·leetcode·typescript·散列表
weixin_395448911 天前
main.c_cursor_0129
前端·网络·算法