【vue3+ts】动态生成word文件并下载

动态生成word文件并下载

  • 下载依赖
  • 新建docx的word模板
  • 新建ts文件
  • 在vue文件中引入
  • 如果你不想要ts,这里也有ts装成的js代码

看了很多帖子,最后还是自己搞定的……没一个靠谱的,都说不清楚,那就自己动手吧!

下载依赖

npm i docxtemplater
npm i file-saver
npm i pizzip

新建docx的word模板

  1. 建议在项目文件夹里面手动创建,不要在编译器里面创建。
  2. 要在public目录下创建,和favicon.ico这个图片在同一等级的目录下创建哦。 我这里是命名的demo.docx。
  3. 在这个docx文件里写上模板,具体应该是{}+内容:
    【vue3+ts】动态生成word文件并下载_第1张图片

【vue3+ts】动态生成word文件并下载_第2张图片

新建ts文件

在哪里创建都行,反正他只扫描public里面的文件,我这里命名的是exportWord.ts文件。
在里面复制粘贴以下代码:

import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import {
    saveAs
} from "file-saver";

export const exportWordDocx = () => {

// 读取并获得模板文件的二进制内容
    function loadFile(url: string, callback: (error: any, content: any) => void) {
        PizZipUtils.getBinaryContent(url, callback);
    }

// demo.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
    loadFile("demo.docx", function(
        error:Error | null,
        content
    ) {
        // 抛出异常
        if (error) {
            throw error;
        }
        console.log(content)

        // 创建一个JSZip实例,内容为模板的内容
        const zip: PizZip = new PizZip(content);
        const doc: Docxtemplater = new Docxtemplater().loadZip(zip) as Docxtemplater;
        // 设置模板变量的值
        doc.setData({
            title: "John",
        });
        try {
            // 用模板变量的值替换所有模板变量
            doc.render();
        } catch (error:any) {
            // The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
            // eslint-disable-next-line no-inner-declarations
            function replaceErrors(key:any, value:any) {
                if (value instanceof Error) {
                    return Object.getOwnPropertyNames(value).reduce(function(
                        error: any,
                        key: string
                    ) {
                        error[key] = value[key as keyof Error];
                        return error;
                    }, {});
                }
                return value;
            }
            console.log(JSON.stringify({
                error: error
            }, replaceErrors));

            if (error.properties && error.properties.errors instanceof Array) {
                const errorMessages = error.properties.errors
                    .map(function(error:any) {
                        return error.properties.explanation;
                    })
                    .join("\n");
                console.log("errorMessages", errorMessages);
                // errorMessages is a humanly readable message looking like this : 'The tag beginning with "foobar" is unopened'
            }
            throw error;
        }
        // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        const out = doc.getZip().generate({
            type: "blob",
            mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        });
        // 将目标文件对象保存为目标类型的文件,并命名
        saveAs(out, "output.docx");
    });

}

里面有这一行:

loadFile("demo.docx", function(

这个是你的模板文件。
还有这样一行:

title: "John",

这是你的数据,要和上面那个docx文件的内容对应的上。
还有最后的一行:

saveAs(out, "output.docx");

这个output.docx是你下载以后的文件名称。

在vue文件中引入

这个就很简单了,直接

import exportWordDocx from ‘你的这个ts文件目录’

exportWordDocx 是你上面ts文件的开头,导出的名称。
然后在button按钮上使用点击事件,直接调用就行了!

<template>
  <button @click="exportWord">123123</button>
</template>

<script setup lang="ts">
import {exportWordDocx} from "@/plugins/exportWord";
const exportWord=()=>{
  exportWordDocx()
}

</script>

如果你不想要ts,这里也有ts装成的js代码

import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import {
    saveAs
} from "file-saver";

export const exportWordDocx = () => {

// 读取并获得模板文件的二进制内容
    function loadFile(url, callback) {
        PizZipUtils.getBinaryContent(url, callback);
    }

// demo.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
    loadFile("demo.docx", function(
        error,
        content
    ) {
        // 抛出异常
        if (error) {
            throw error;
        }
        console.log(content)

        // 创建一个JSZip实例,内容为模板的内容
        var zip = new PizZip(content);
        // 创建并加载docxtemplater实例对象
        var doc = new Docxtemplater().loadZip(zip);
        // 设置模板变量的值
        doc.setData({
            title: "John",
        });
        try {
            // 用模板变量的值替换所有模板变量
            doc.render();
        } catch (error) {
            // The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
            // eslint-disable-next-line no-inner-declarations
            function replaceErrors(key, value) {
                if (value instanceof Error) {
                    return Object.getOwnPropertyNames(value).reduce(function(
                        error,
                        key
                    ) {
                        error[key] = value[key];
                        return error;
                    }, {});
                }
                return value;
            }
            console.log(JSON.stringify({
                error: error
            }, replaceErrors));

            if (error.properties && error.properties.errors instanceof Array) {
                const errorMessages = error.properties.errors
                    .map(function(error) {
                        return error.properties.explanation;
                    })
                    .join("\n");
                console.log("errorMessages", errorMessages);
                // errorMessages is a humanly readable message looking like this : 'The tag beginning with "foobar" is unopened'
            }
            throw error;
        }
        // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        var out = doc.getZip().generate({
            type: "blob",
            mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        });
        // 将目标文件对象保存为目标类型的文件,并命名
        saveAs(out, "output.docx");
    });

}

你可能感兴趣的:(Vue3,vue,word)