在日常开发中,我们经常遇到需要在 Web 端处理 Office 文档的需求,其中“将 Excel 文件转换为 PDF”是极为常见的场景。无论是生成报表、归档数据,还是实现文档预览,PDF 的跨平台与稳定性都让它成为首选输出格式。而在 JavaScript 生态中,借助 Spire.XLS for JavaScript ,我们可以在浏览器或 Node.js 环境中轻松实现高质量、无依赖的 Excel 转 PDF 功能。本文将带你从零开始,搭建一个 React 示例,并深入讲解多种转换控制技巧。

一、为什么选择 Spire.XLS for JavaScript?

Spire.XLS for JavaScript 是一个基于 WebAssembly 的纯前端 Excel 操作库,无需安装 Office 或任何本地软件,即可在浏览器中创建、读取、修改和转换 Excel 文档。它的核心优势包括:

  • 跨平台 :支持所有现代浏览器(Chrome、Firefox、Edge 等),也兼容 Node.js。
  • 高性能 :基于 WASM,处理大文件依然流畅。
  • 功能丰富 :不仅支持转换,还能操作单元格、样式、图表、数据透视表等。
  • 无需网络 :所有处理均在本地完成,不依赖云服务,保障数据隐私。

本文我们将重点介绍如何利用它实现 Excel → PDF 的转换,并扩展多种自定义设置。

二、安装与初始化

首先,在你的项目中安装 spire.office 包:

npm i spire.office

安装完成后,你需要将 spire.xls.js 及其对应的 .wasm 文件放置在项目的公共目录(如 public/)下,以便在浏览器中动态加载。如果你的构建工具是 Webpack,注意使用 webpackIgnore: true 来避免资源被错误打包。

在 React 中,我们通过 useEffect 异步加载 WASM 模块,并将其实例挂载到 window 上供全局使用。核心加载逻辑如下:

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;

这里我们指定了 .wasm 文件的查找路径,确保所有资源能被正确加载。加载成功后,我们就可以通过 window.wasmModule.spirexls 访问 Excel 处理的核心 API。

三、基础转换流程

转换一个 Excel 文件到 PDF 只需要几个核心步骤:加载字体与文件到虚拟文件系统(VFS)、创建 Workbook 对象、执行转换并导出下载。下面是一段完整的 React 组件代码,它实现了从加载模块到触发下载的全流程:

import React, { useState, useEffect } from 'react';

function App() {
  const [wasmModule, setWasmModule] = useState(null);
  
  // 加载 Spire.XLS
  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);
      }
    })();
  }, []);

  // Excel 转 PDF 的函数
  const ExcelToPDF = async () => {
    const wasmModule = window.wasmModule.spirexls;

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

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

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

      // 4. 创建 Workbook 对象并加载文档
      const workbook = new wasmModule.Workbook();
      workbook.LoadFromFile({ fileName: inputFileName });
      
      // 5. 设置转换选项(让工作表适应一页)
      workbook.ConverterSetting.SheetFitToPage = true;

      // 6. 保存为 PDF 格式
      workbook.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.PDF });

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

      // 8. 创建下载链接并触发下载
      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);

      // 9. 释放资源
      workbook.Dispose();
    }
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1> Convert Excel file to PDF using JavaScript in React </h1>
      <button onClick={ExcelToPDF} disabled={!wasmModule}>
        Convert
      </button>
    </div>
  );
}

export default App;

步骤解析:

  1. 将字体和待转换文件载入虚拟文件系统(VFS)
    Spire.XLS 依赖系统字体来渲染文本,因此我们需要提前加载所需的 TrueType 字体(如 Arial.ttf)到 VFS 的 /Library/Fonts/ 目录。同样,输入 Excel 文件也需要通过 FetchFileToVFS 存入 VFS。
  2. 创建 Workbook 对象并加载 Excel
    Workbook 类代表整个 Excel 文档,通过 LoadFromFile 加载我们刚刚存入的源文件。
  3. 设置转换选项(可选)
    例如将 SheetFitToPage 设为 true,让每个工作表自适应一页。
  4. 保存为 PDF
    调用 SaveToFile 并指定格式为 wasmModule.FileFormat.PDF
  5. 读取生成的 PDF 并触发下载
    通过 FS.readFile 从 VFS 中获取 PDF 二进制数据,创建 Blob 对象,再利用 URL.createObjectURL 生成下载链接。
  6. 释放资源
    调用 workbook.Dispose() 回收内存。

上述步骤在示例代码的 ExcelToPDF 函数中得到了完整实现。点击按钮后,用户即可下载转换好的 PDF 文件。

四、更多控制:定制你的 PDF 输出

实际业务中,我们往往不满足于“一键转换”,而是需要精细控制转换结果。Spire.XLS 提供了丰富的设置接口,下面介绍四种常用的定制方式。

1. 转换特定的工作表(Sheet)

默认情况下,workbook.SaveToFile 会转换所有工作表。如果你只需要输出某一页,可以改为使用 Worksheet.SaveToPdf 方法:

// 获取第一个工作表(索引从 0 开始)
let sheet = workbook.Worksheets.get(0);
// 仅将该工作表保存为 PDF
sheet.SaveToPdf({ fileName: outputFileName });

这在只需要报表摘要或特定数据页时非常实用。

2. 让每个工作表适应一页

当工作表内容较多时,直接导出可能导致多页或内容被截断。通过 ConverterSetting 可以一键启用“适应页面”功能:

workbook.ConverterSetting.SheetFitToPage = true;

该设置会整体缩放工作表内容,确保所有列和行恰好容纳在一页内,非常适合生成概览型 PDF。

3. 调整页边距

PDF 的页边距影响最终排版美观度。Spire.XLS 允许你分别设置上、下、左、右边距(单位:英寸):

let sheet = workbook.Worksheets.get(0);
sheet.PageSetup.TopMargin = 0.5;
sheet.PageSetup.BottomMargin = 0.5;
sheet.PageSetup.LeftMargin = 0.3;
sheet.PageSetup.RightMargin = 0.3;

合理调整边距可以避免内容紧贴边缘,提升阅读体验。

4. 指定页面大小

不同的使用场景对页面尺寸有不同要求,例如合同常用 A4,海报可能用 A3。你可以通过 PaperSize 属性轻松切换:

sheet.PageSetup.PaperSize = wasmModule.PaperSizeType.PaperA3;

除了 A3,库还支持 A4、A5、Letter、Legal 等常见纸张类型,可根据需求灵活选择。

五、完整示例与注意事项

本文提供的 React 组件 App 已经集成了以上所有功能。你只需将准备好的字体文件(.ttf)和示例 Excel(.xlsx)放置在 public/static/font/ 和 public/static/data/ 目录下,即可运行体验。

关键注意事项:

  • 字体加载 :如果 PDF 中出现乱码或空白,多半是因为缺少对应字体。请确保加载的字体支持 Excel 中的文本字符集。
  • WASM 加载 :由于 WASM 文件较大,首次加载可能需要几秒钟,建议在 UI 中展示加载状态。
  • 文件路径 :FetchFileToVFS 的第三个参数是源文件在服务器上的 URL 路径,需保证可访问。
  • 内存管理 :处理完文档后务必调用 Dispose(),避免内存泄漏,尤其是在频繁转换的场景下。

六、结语

通过 Spire.XLS for JavaScript,我们将原本复杂、依赖后端服务的 Excel 转 PDF 任务完全迁移到了前端,既减轻了服务器压力,也提升了用户体验。本文从加载模块、基础转换到高级控制,为你提供了一套完整的实战方案。你可以在此基础上进一步扩展,例如添加文件上传界面、支持批量转换、整合水印等。

未来,随着 WebAssembly 技术的不断成熟,前端文档处理能力将更加强大。Spire.XLS 已经为我们铺平了道路,现在,就动手试试吧!

更多推荐