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

相关推荐
wanhengidc几秒前
服务器租用:高防CDN和加速CDN的区别
运维·服务器·前端
哆啦刘小洋27 分钟前
HTML Day04
前端·html
再学一点就睡1 小时前
JSON Schema:禁锢的枷锁还是突破的阶梯?
前端·json
保持学习ing2 小时前
帝可得 - 设备管理
javascript·vue.js·elementui
从零开始学习人工智能2 小时前
FastMCP:构建 MCP 服务器和客户端的高效 Python 框架
服务器·前端·网络
烛阴2 小时前
自动化测试、前后端mock数据量产利器:Chance.js深度教程
前端·javascript·后端
好好学习O(∩_∩)O3 小时前
QT6引入QMediaPlaylist类
前端·c++·ffmpeg·前端框架
敲代码的小吉米3 小时前
前端HTML contenteditable 属性使用指南
前端·html
testleaf3 小时前
React知识点梳理
前端·react.js·typescript
站在风口的猪11083 小时前
《前端面试题:HTML5、CSS3、ES6新特性》
前端·css3·html5