通过
Electron、Docxtemplater 和系统打印命令实现这一需求。
功能描述
我们将实现以下功能:
- 通过指定的模板文件生成 Word 文档,支持插入动态变量和图片。
- 将生成的文档保存为临时文件。
- 使用系统命令静默打印文档,无需用户手动操作。
所需工具和库
在开发中,我们将使用以下工具和库:
- Electron: 构建跨平台桌面应用。
- Docxtemplater: 用于模板填充和生成 Word 文档。
- JSZip: 处理 ZIP 格式的 Word 文件。
- Node.js 原生模块如
fs、path。 - 系统命令 (
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使用params和imgConfig动态填充变量和图片。 - 生成文件:
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 实例加载并打印文件。
- 使用
- 临时文件:
-
- 文件保存在系统的临时目录中,打印后自动删除。
运行流程
- 准备模板文件和变量数据:
-
- 创建一个
.docx模板文件,包含占位符变量。 - 定义
params对象,填充模板中的动态数据。
- 创建一个
- 调用
exportAndPrintWord函数:
-
- 传入模板路径、变量数据和图片配置。
- 系统执行打印命令:
-
- Windows 系统通过 VBS 实现静默打印。
注意事项
- 模板设计:
-
- 模板中的占位符应符合
Docxtemplater的语法,例如{name}表示变量。
- 模板中的占位符应符合
- 跨平台支持:
-
- 当前静默打印代码仅支持 Windows 系统。对于 macOS 和 Linux,可以使用对应的打印命令(如
lp或lpr)。
- 当前静默打印代码仅支持 Windows 系统。对于 macOS 和 Linux,可以使用对应的打印命令(如
- 权限管理:
-
- 确保程序运行时具有文件系统和打印机的访问权限。
- 异常处理:
-
- 在生成和打印过程中,捕获并处理可能的错误,如模板文件不存在、数据格式不符等。