• 作者:老汪软件技巧
  • 发表时间:2024-09-24 07:02
  • 浏览量:

需求

在开发过程中遇到一个需求,动态生成一个word报表,当时考虑了是前端做还是后端做的问题,最后发现两个解决需求的方法都大差不差,但考虑到前端少发一个请求,就此使用的前端来解决。

首先,我们需要安装以下几个库:

npm i docxtemplater     是一个用于基于模板生成动态 `.docx` 文档的 JavaScript 库。它允许你将动态数据填充到 `.docx` 模板文件中

npm i jszip-utils       用于在浏览器中处理 ZIP 文件的工具库

npm file-saver          是一个用于在浏览器中保存文件的 JavaScript 库

创建一个工具函数,用于加载 .docx 模板,填充数据并生成文档。

//引入工具
import PizZip from 'pizzip';
import Docxtemplater from 'docxtemplater';
import JSZipUtils from 'jszip-utils';
import { saveAs } from 'file-saver';
// 加载 .docx 模板文件
function loadFile(url, callback) {
    JSZipUtils.getBinaryContent(url, callback);
}
// 下载生成的文档
export function download(file, name) {
    saveAs(file, name);
}
// 生成并下载 Word 文档(templatePath是word文档模版地址,data是对应的数据)
export function generateWordDocument(templatePath, data) {
    return new Promise((resolve, reject) => {
        loadFile(templatePath, function (error, content) {
            if (error) {
                reject(new Error(`Error loading template file: ${error.message}`));
                return;
            }
            try {
                // 加载模板文件内容到 PizZip
                const zip = new PizZip(content);
                const doc = new Docxtemplater(zip, {
                    paragraphLoop: true,
                    linebreaks: true,
                });
                // 设置模板中的占位符数据
                doc.setData(data);
                // 渲染文档
                doc.render();
                // 生成最终的文档 Blob
                const fileWord = doc.getZip().generate({
                    type: 'blob',
                    mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                });
                // 返回生成的文档 Blob
                resolve(fileWord);
            } catch (error) {
                console.error('Error rendering document:', error);
                reject(new Error(`Error rendering document: ${error.message}`));
            }
        });
    });
}

在需要的组件内调用


 
<script setup>
import { ref } from 'vue';
import { generateWordDocument, download } from '../utils/wordGenerate.js';
const generatedFile = ref(null);
// 模板文件的路径,一般放在 public 目录中
const templatePath = '/template.docx'; 
const data = { name: '测试', date: '2024-09-23' };
const startGeneration = async () => { 
try {
    generatedFile.value = await generateWordDocument(templatePath, data); 
    console.log('文档生成成功');
} catch (error){
    console.error('Error generating document:', error);
  }
};
//文档下载
const downloadWord = () => {
if (generatedFile.value) {
download(generatedFile.value, 'generated-document.docx');
} else {
console.error('No file generated');
}};
script>

就此功能完成了,当然如果需求是生成成功的同时就下载文档,可以将下载功能直接写在生成功能内,就可以省去异步处理的代码量。