在React应用中动态生成包含目录的Word文档,能够显著提升数据报告、技术文档或业务材料的专业性与可读性,尤其当处理多章节长文档时,自动化的目录生成机制不仅消除了手动维护章节页码的繁琐,更确保了内容更新时目录与正文的实时同步。通过JavaScript开发者可以直接在前端操作Word文档,特别适合需要离线操作或严格数据管控的企业级应用场景。本文将介绍如何使用JavaScript在React应用中实现插入目录到Word文档

  • 用JavaScript插入默认风格目录到Word文档
  • 用JavaScript插入自定义风格目录到Word文档

本文所使用的方法需要用到Spire.Doc for JavaScript,npm:npm i spire.doc

用JavaScript插入默认风格目录到Word文档

Spire.Doc for JavaScript通过WebAssembly模块来处理Word文档,我们可以直接在模块中创建文档,也可以将文档读取到虚拟文件系统中来对其进行修改。在插入目录到Word文档时,我们可以直接根据设置好的标题登记在Word文档中插入目录。如果文档没有设置标题级别,可以在插入目录前使用Paragraph.ApplyStyle(BuiltinStyle)方法设置标题级别。
使用Paragraph.AppendTOC(lowerLevel: int, upperLevel: int)方法可以在Word文档任意段落插入目录,并指定要显示的标题。需要注意插入目录后,使用Document.UpdateTableOfContents()方法更新目录,以便正确显示其内容。操作步骤示例如下:

  1. 加载Spire.Doc.Base.js文件以初始化WebAssembly模块。
  2. 使用wasmModule.FetchFileToVFS()方法将Word文件加载到虚拟文件系统。
  3. 通过调用wasmModule.Document.Create()方法创建一个Document实例。
  4. 利用Document.LoadFromFile()方法将Word文档加载到Document实例中。
  5. 使用Document.AddSection()方法创建一个新的节。
  6. 使用Section.AddParagraph()方法在节中添加一个段落。
  7. 使用Paragraph.AppendTOC()方法添加目录到段落,并设置目录中展示的最大和最小标题等级。
  8. 使用Document.Sections.Insert()方法将目录节插入到文档合适的位置。
  9. 使用Document.UpdateTableOfContents()方法更新目录。
  10. 使用Document.SaveToFile()将将Word文档保存到虚拟文件系统。
  11. 读取并下载Word文档,或进行其他处理。

代码示例

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

function App() {

  // State to store the loaded WASM module
  const [wasmModule, setWasmModule] = useState(null);

  // useEffect hook to load the WASM module when the component mounts
  useEffect(() => {
    const loadWasm = async () => {
      try {
        // Access the Module and spiredoc from the global window object
        const { Module, spiredoc } = window;

        // Set the wasmModule state when the runtime is initialized
        Module.onRuntimeInitialized = () => {
          setWasmModule(spiredoc);
        };
      } catch (err) {
        // Log any errors that occur during module loading
        console.error('Failed to load the WASM module:', err);
      }
    };

    // Create a script element to load the WASM JavaScript file
    const script = document.createElement('script');
    script.src = `${process.env.PUBLIC_URL}/Spire.Doc.Base.js`;
    script.onload = loadWasm;

    // Append the script to the document body
    document.body.appendChild(script);

    // Cleanup function to remove the script when the component unmounts
    return () => {
      document.body.removeChild(script);
    };
  }, []);

  // 插入默认目录到Word文档的方法
  const InsertTOCWord = async () => {
    if (wasmModule) {
      // 指定输入和输出文件名
      const inputFileName = 'Sample94.docx';
      const outputFileName = '默认目录.docx';

      // 获取字体文件并添加到 VFS
      await wasmModule.FetchFileToVFS('HarmonyOS_Sans_SC_Regular.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/`);

      // 获取输入文件并添加到 VFS
      await wasmModule.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/`);

      // 创建 Document 对象
      const doc = wasmModule.Document.Create();

      // 加载 Word 文档
      doc.LoadFromFile({ fileName: inputFileName });

      // 创建一个新的节
      const section = doc.AddSection();
      // 在节中创建一个段落
      const paragraph = section.AddParagraph();

      // 插入目录到段落
      paragraph.AppendTOC(1, 2);

      // 将节插入到封面节之后
      doc.Sections.Insert(1, section);

      // 更新目录
      doc.UpdateTableOfContents();

      // 将文档保存到 VFS
      doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2019})

      // 从 VFS 读取文档
      const wordArray = await wasmModule.FS.readFile(outputFileName);

      // 生成 Blob 对象,并触发下载 Word 文件
      const blob = new Blob([wordArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${outputFileName}`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    }
  };

  return (
      <div style={{ textAlign: 'center', height: '300px' }}>
        <h1>在 React 中使用 JavaScript 插入默认目录到 Word 文档</h1>
        <button onClick={InsertTOCWord} disabled={!wasmModule}>
          插入并下载
        </button>
      </div>
  );
}

export default App;

结果

代码示例
我们还可以通过初始化TableOfContent对象来创建目录,并通过switch对其进行自定义。例如,"{\o \”1-2\” \\1-1}"表示在目录中显示一级到三级的标题,并省略一级标题的页码。步骤示例如下:

  1. 加载Spire.Doc.Base.js文件以初始化WebAssembly模块。
  2. 使用wasmModule.FetchFileToVFS()方法将Word文件加载到虚拟文件系统。
  3. 通过调用wasmModule.Document.Create()方法创建一个Document实例。
  4. 利用Document.LoadFromFile()方法将Word文档加载到Document实例中。
  5. 使用Document.AddSection()方法创建一个新的节。
  6. 使用Section.AddParagraph()方法在节中添加一个段落。
  7. 使用Document.Sections.Insert()方法将节插入到文档合适的位置。
  8. 使用wasmModule.TableOfContent.Create()方法创建TableOfContent对象。
  9. 使用Paragraph.Items.Add()方法将目录添加到新建的段落中。
  10. 使用Paragraph.AppendFieldMark()方法分别添加字段分隔和结束标记。
  11. 通过Document.TOC属性将该目录设置为当前文档的目录。
  12. 使用Document.UpdateTableOfContents()方法更新目录。
  13. 使用Document.SaveToFile()将将Word文档保存到虚拟文件系统。
  14. 读取并下载Word文档,或进行其他处理。

代码示例

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

function App() {

  // State to store the loaded WASM module
  const [wasmModule, setWasmModule] = useState(null);

  // useEffect hook to load the WASM module when the component mounts
  useEffect(() => {
    const loadWasm = async () => {
      try {
        // Access the Module and spiredoc from the global window object
        const { Module, spiredoc } = window;

        // Set the wasmModule state when the runtime is initialized
        Module.onRuntimeInitialized = () => {
          setWasmModule(spiredoc);
        };
      } catch (err) {
        // Log any errors that occur during module loading
        console.error('Failed to load the WASM module:', err);
      }
    };

    // Create a script element to load the WASM JavaScript file
    const script = document.createElement('script');
    script.src = `${process.env.PUBLIC_URL}/Spire.Doc.Base.js`;
    script.onload = loadWasm;

    // Append the script to the document body
    document.body.appendChild(script);

    // Cleanup function to remove the script when the component unmounts
    return () => {
      document.body.removeChild(script);
    };
  }, []);

  // 插入自定义目录到Word文档的方法
  const InsertTOCWord = async () => {
    if (wasmModule) {
      // 指定输入和输出文件名
      const inputFileName = 'Sample94.docx';
      const outputFileName = '自定义目录.docx';

      // 获取字体文件并添加到 VFS
      await wasmModule.FetchFileToVFS('HarmonyOS_Sans_SC_Regular.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/`);

      // 获取输入文件并添加到 VFS
      await wasmModule.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/`);

      // 创建 Document 对象
      const doc = wasmModule.Document.Create();

      // 加载 Word 文档
      doc.LoadFromFile({ fileName: inputFileName });

      // 创建一个新的节
      const section = doc.AddSection();
      // 在节中创建一个段落
      const paragraph = section.AddParagraph();
      // 将节插入到封面节之后
      doc.Sections.Insert(1, section);

      // 创建一个自定义目录
      let toc = wasmModule.TableOfContent.Create(doc,`{\\o "1-2" \\n 1-1}`);

      // 将目录添加到新建的段落中
      paragraph.Items.Add(toc);

      // 插入字段分隔符和归档结束标记,以结束 TOC 字段
      paragraph.AppendFieldMark(wasmModule.FieldMarkType.FieldSeparator);
      paragraph.AppendFieldMark(wasmModule.FieldMarkType.FieldEnd);

      // 将该目录设置为文档的目录
      doc.TOC = toc;

      // 更新目录
      doc.UpdateTableOfContents();

      // 将文档保存到 VFS
      doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2019});

      // 从 VFS 读取文档
      const wordArray = await wasmModule.FS.readFile(outputFileName);

      // 生成 Blob 对象,并触发下载 Word 文件
      const blob = new Blob([wordArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${outputFileName}`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    }
  };

  return (
      <div style={{ textAlign: 'center', height: '300px' }}>
        <h1>在 React 中使用 JavaScript 插入自定义目录到 Word 文档</h1>
        <button onClick={InsertTOCWord} disabled={!wasmModule}>
          插入并下载
        </button>
      </div>
  );
}

export default App;

结果

本文演示了如何使用JavaScript在Word文档中插入目录。


大丸子
12 声望3 粉丝