Electron 按模板导出 Word 并静默打印

465 阅读3分钟

长发可爱动漫美女回眸4k壁纸.jpg 通过 ElectronDocxtemplater 和系统打印命令实现这一需求。

功能描述

我们将实现以下功能:

  1. 通过指定的模板文件生成 Word 文档,支持插入动态变量和图片。
  2. 将生成的文档保存为临时文件。
  3. 使用系统命令静默打印文档,无需用户手动操作。

所需工具和库

在开发中,我们将使用以下工具和库:

  • Electron: 构建跨平台桌面应用。
  • Docxtemplater: 用于模板填充和生成 Word 文档。
  • JSZip: 处理 ZIP 格式的 Word 文件。
  • Node.js 原生模块如 fspath
  • 系统命令 (cscript.exe 用于 Windows)。

核心实现

以下是核心功能的实现,包括模板渲染、导出文件以及静默打印。

1. 按模板渲染并导出 Word 文件

首先,我们使用 Docxtemplater 渲染模板文件,将变量和图片插入到 Word 文档中。以下是代码:

/**
 * 导出并打印 Word 文档
 * @param {Object} params - 模板变量数据
 * @param {string} inputPath - 模板文件路径
 * @param {Object} imgConfig - 图片配置对象,包含图片的键和 Buffer 数据
 * @returns {Promise<void>} - 当文档导出并打印完成时解决的 Promise
 */
export function exportAndPrintWord(params, inputPath, imgConfig = {}) {
  if (!inputPath) throw '请设置模板地址';

  // 使用 JSZipUtils 加载模板内容
  JSZipUtils.getBinaryContent(inputPath, (error, content) => {
    if (error) {
      throw error;
    }

    const imgDataDict = {};
    if (imgConfig) {
      imgDataDict[imgConfig.key] = imgConfig.imgBuffer;
      params[imgConfig.key] = imgConfig.key;
    }

    // 创建 Docxtemplater 实例
    const zip = new JSZip(content);
    const doc = new Docxtemplater(zip, {
      paragraphLoop: true,
      linebreaks: true,
      modules: [new ImageModule({
        getImage: (key) => imgDataDict[key] || '',
        getSize: () => [imgConfig.w || 150, imgConfig.h || 150],
      })],
    });

    doc.setData(params);

    try {
      doc.render();
    } catch (err) {
      console.error('文档渲染失败:', err);
      throw err;
    }

    const buffer = doc.getZip().generate({ type: 'nodebuffer' });

    // 调用打印功能
    printFileStreamSilently(buffer, 'docx');
  });
}

在这段代码中:

  • 模板加载:通过 JSZipUtils 加载 Word 模板。
  • 模板填充Docxtemplater 使用 paramsimgConfig 动态填充变量和图片。
  • 生成文件doc.getZip().generate 将文档生成二进制 Buffer,以便后续处理。

2. 静默打印文件

静默打印文件需要结合操作系统命令。以下是实现静默打印的代码:

/**
 * 将文件流保存为临时文件并静默打印
 * @param {Buffer} fileBuffer - 文件的二进制流
 * @param {string} extension - 文件扩展名(如 'pdf', 'docx')
 */
function printFileStreamSilently(fileBuffer, extension) {
  if (!fileBuffer || !(fileBuffer instanceof Buffer)) {
    throw new Error('文件流必须是 Buffer 格式');
  }

  const randomFileName = `export_${Math.random().toString(36).substring(2, 10)}`;
  const tempFilePath = path.join(os.tmpdir(), `${randomFileName}.${extension}`);

  try {
    fs.writeFileSync(tempFilePath, fileBuffer);

    const platform = process.platform;

    if (platform === 'win32') {
      const vbsScript = path.join(os.tmpdir(), 'silent-print.vbs');
      fs.writeFileSync(vbsScript, `
        Set objWord = CreateObject("Word.Application")
        objWord.Visible = False
        Set objDoc = objWord.Documents.Open("${tempFilePath}")
        objDoc.PrintOut
        objDoc.Close
        objWord.Quit
      `);

      exec(`cscript.exe //NoLogo "${vbsScript}"`, (error, stdout, stderr) => {
        if (error) {
          console.error('打印失败:', error);
          return;
        }
        console.log(`打印成功: ${stdout || stderr}`);
        fs.unlinkSync(tempFilePath);
        fs.unlinkSync(vbsScript);
      });
    } else {
      throw new Error('静默打印目前仅支持 Windows 平台');
    }
  } catch (error) {
    console.error('文件处理失败:', error);
    throw error;
  }
}

关键点

  • Windows 静默打印
    • 使用 cscript.exe 运行 VBS 脚本实现打印。
    • VBS 脚本创建一个隐藏的 Word 实例加载并打印文件。
  • 临时文件
    • 文件保存在系统的临时目录中,打印后自动删除。

运行流程

  1. 准备模板文件和变量数据:
    • 创建一个 .docx 模板文件,包含占位符变量。
    • 定义 params 对象,填充模板中的动态数据。
  1. 调用 exportAndPrintWord 函数:
    • 传入模板路径、变量数据和图片配置。
  1. 系统执行打印命令:
    • Windows 系统通过 VBS 实现静默打印。

注意事项

  1. 模板设计
    • 模板中的占位符应符合 Docxtemplater 的语法,例如 {name} 表示变量。
  1. 跨平台支持
    • 当前静默打印代码仅支持 Windows 系统。对于 macOS 和 Linux,可以使用对应的打印命令(如 lplpr)。
  1. 权限管理
    • 确保程序运行时具有文件系统和打印机的访问权限。
  1. 异常处理
    • 在生成和打印过程中,捕获并处理可能的错误,如模板文件不存在、数据格式不符等。