如何在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文件。如果你有任何问题或建议,欢迎在评论区留言讨论!

相关推荐
vvilkim21 分钟前
Vue.js 插槽(Slot)详解:让组件更灵活、更强大
前端·javascript·vue.js
学无止境鸭27 分钟前
uniapp报错 Right-hand side of ‘instanceof‘ is not an object
前端·javascript·uni-app
豆豆(设计前端)32 分钟前
一键秒连WiFi智能设备,uni-app全栈式物联开发指南。
前端
Aphasia31135 分钟前
🧑🏻‍💻前端面试高频考题(万字长文📖)
前端·面试
程序饲养员39 分钟前
Javascript中export后该不该加default?
前端·javascript·前端框架
腥臭腐朽的日子熠熠生辉1 小时前
nvm 安装某个node.js版本后不能使用或者报错,或不能使用npm的问题
前端·npm·node.js
软件开发随心记1 小时前
EasyExcel动态拆分非固定列Excel表格
java·excel
汐ya~1 小时前
python写入excel多个sheet表 以及追加sheet表
开发语言·python·excel
最新资讯动态1 小时前
点击即玩!《萌宠历险记》现身Pura X外屏,随时随地开启轻松解压之旅
前端
一只韩非子1 小时前
一句话告诉你什么叫编程语言自举!
前端·javascript·后端