在 React 中使用 JavaScript 将 Excel 转换为 PDF

在日常数据处理和报表生成场景中,将 Excel 文件转换为 PDF 格式是一项常见需求。PDF 的跨平台兼容性和稳定的排版表现,使其成为文档共享和归档的理想选择。本文介绍如何利用 Spire.XLS for JavaScript 这个基于 WebAssembly 的库,在 React 应用中实现这一转换功能。

关于 Spire.XLS for JavaScript

Spire.XLS for JavaScript 是一个基于 WebAssembly 的 Excel 操作库,支持在浏览器端直接创建、读取、编辑和转换 Excel 文件,无需依赖 Microsoft Office 环境。它兼容主流的 React、Vue、Angular 等前端框架,并提供对 .xls.xlsx.xlsm 等格式的支持。

在 PDF 转换方面,该库提供了 Workbook.SaveToFile()Worksheet.SaveToPdf() 等方法,支持将整个工作簿或单个工作表导出为 PDF,并可控制页面适配等输出设置。

环境配置

安装依赖

通过 npm 安装 Spire.XLS for JavaScript:

bash 复制代码
npm i spire.office

安装完成后,需要将依赖文件复制到 React 项目的 public 文件夹中。具体需要复制的文件包括 spire.xls.jsSpire.Xls.Wasm.zipspire.common.jsSpire.Common.Wasm.zip 以及 _framework 目录。同时,为保证 PDF 中文本的正确渲染,还需准备所需的字体文件(如 Arial.ttf)并放置到可访问的路径。

初始化 WASM 模块

在 React 组件中,需在组件挂载时加载并初始化 WebAssembly 模块:

javascript 复制代码
import React, { useState, useEffect } from 'react';

function App() {
  const [wasmModule, setWasmModule] = useState(null);

  useEffect(() => {
    (async () => {
      try {
        const publicUrl = process.env.PUBLIC_URL || '';
        const spireModule = await import(/* webpackIgnore: true */ `${publicUrl}/spire.xls.js`);
        const rawModule = spireModule.default || spireModule;
        window.wasmModule = typeof rawModule === 'function'
          ? await rawModule({ locateFile: p => p.endsWith('.wasm') ? `${publicUrl}/${p}` : p })
          : rawModule;
        setWasmModule(window.wasmModule);
      } catch (error) {
        console.error('Failed to load spire.xls.js WASM module:', error);
      }
    })();
  }, []);

  // 后续转换逻辑...
}

将整个工作簿转换为 PDF

将 Excel 文件的所有工作表一次性导出为单个 PDF 文件,适用于报表归档、数据分发等场景。

核心步骤如下:

  1. 将字体文件和目标 Excel 文件加载到虚拟文件系统(VFS)中。
  2. 创建 Workbook 对象并加载 Excel 文件。
  3. 调用 Workbook.SaveToFile() 方法,指定输出格式为 PDF。
  4. 从 VFS 读取生成的 PDF 文件,转换为 Blob 并触发下载。

示例代码:

javascript 复制代码
const ExcelToPDF = async () => {
  const wasmModule = window.wasmModule.spirexls;
  if (!wasmModule) return;

  // 将字体加载到虚拟文件系统(VFS)中
  await window.spire.FetchFileToVFS('Arial.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);

  // 指定输出PDF文件路径
  const outputFileName = 'out.pdf';

  // 将输入文件加载到虚拟文件系统(VFS)中
  const inputFileName = 'ToPDF.xlsx';
  await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);

  // 创建一个新的工作簿
  const workbook = new wasmModule.Workbook();

  // 加载现有的Excel文档
  workbook.LoadFromFile({ fileName: inputFileName });
  workbook.ConverterSetting.SheetFitToPage = true;

  // 将工作簿保存为PDF
  workbook.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.PDF });

  // 读取保存的文件并转换为Blob对象
  const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
  const modifiedFile = new Blob([modifiedFileArray], { type: 'application/pdf' });

  // 为Blob创建一个URL并启动下载
  const url = URL.createObjectURL(modifiedFile);
  const a = document.createElement('a');
  a.href = url;
  a.download = outputFileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);

  // 清理工作簿使用的资源
  workbook.Dispose();
};

将特定工作表转换为 PDF

如果仅需导出工作簿中的某一页(如汇总报表页),可先通过 Workbook.Worksheets.get() 方法获取目标工作表,再调用 SaveToFile() 方法。在保存时指定输出文件名,可以基于工作表名称动态命名。

javascript 复制代码
const ExcelToPDF = async () => {
  const wasmModule = window.wasmModule.spirexls;
  if (!wasmModule) return;

  // 将字体加载到虚拟文件系统(VFS)中
  await window.spire.FetchFileToVFS('Arial.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);

  // 将输入文件加载到虚拟文件系统(VFS)中
  const inputFileName = 'ToPDF.xlsx';
  await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);

  // 创建一个新的工作簿
  const workbook = new wasmModule.Workbook();

  // 加载现有的Excel文档
  workbook.LoadFromFile({ fileName: inputFileName });

  // 获取第二个工作表(索引从0开始)
  let sheet = workbook.Worksheets.get(1);

  // 指定输出PDF文件路径(以工作表名称命名)
  const outputFileName = sheet.Name + '.pdf';

  // 将工作表保存为PDF
  workbook.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.PDF });

  // 读取并下载(代码同上)
  // ...
  workbook.Dispose();
};

需要注意的是,此方法保存的是整个工作簿,但 PDF 内容仅为选中工作表的数据。如果希望仅导出单个工作表且不包含其他工作表的空白页,建议将目标工作表复制到一个新的 Workbook 实例中再进行保存。

输出控制:工作表适配单页

对于宽表或行数较多的工作表,转换后可能会出现内容被拆分到多页的情况。通过设置 Workbook.ConverterSetting.SheetFitToPage = true,可让工作表内容自动缩放到一页内,提升 PDF 的可读性。

javascript 复制代码
workbook.ConverterSetting.SheetFitToPage = true;

此设置对所有工作表生效,适合内容较多但希望单页展示的场景。

总结

综上所述,在 React 应用中实现 Excel 到 PDF 的转换,可以借助 Spire.XLS for JavaScript 这个基于 WebAssembly 的库在浏览器端完成。该方案不依赖后端服务,适合需要纯前端 Excel 处理能力的应用场景。根据实际需求,开发者既可以选择将整个工作簿输出为单一 PDF,也可以只导出指定的工作表,并通过调整页面适配属性来控制 PDF 的打印分页与内容缩放效果。整体来看,这套技术方案提供了一套较为完整的前端文件处理逻辑,可应用于数据展示、报表导出等常见业务场景中。

相关推荐
用户938515635073 小时前
从 Prompt 到 Harness:AI 工程化的三年跃迁与实战解码
javascript·人工智能
木木剑光3 小时前
我开源了一个 React 组件库,沉淀了多个高频组件和实用 Hooks
前端·javascript·react.js
Csvn4 小时前
React 19 `use()` 来了:以后数据加载可以不用 useEffect?
前端·react.js
竹林8185 小时前
Solana DApp 开发踩坑实录:从零用 @solana/web3.js 实现链上数据查询与交易签名
前端·javascript
梯度不陡5 小时前
Signal #17:Agent 开始进入组织系统
前端·javascript
许我半盏清茶5 小时前
前端路由:理解 hash 路由和 history 路由原理
前端·react.js
胡萝卜术5 小时前
从暴力到Z字形消元:力扣240「搜索二维矩阵II」的降维打击之路
前端·javascript·面试
云浪6 小时前
前端二进制数组完全指南:ArrayBuffer、TypedArray、DataView 一次讲透
前端·javascript
铁皮饭盒7 小时前
26年bunjs, elysia+pg一把梭, redis都省了
前端·javascript·后端