docxtemplater研究word模版---最基础填入数据

一、最简单的填充数据值

1、配置word文件

注意:配置一个docx文件保存在public文件下。比如:信息模版.docx

1、安装插件

"docxtemplater": "^3.67.5",
"file-saver": "^2.0.5",
"docx-preview": "^0.3.7",
"pizzip": "^3.2.0",

2、引入插件

import { saveAs } from "file-saver";
import { renderAsync } from "docx-preview";

3、加载Word模板文件

const fileName = "info.docx";
const response = await fetch(`/${fileName}`);

if (!response.ok) {
    throw new Error(`模板文件不存在,状态码:${response.status}`);
}

const arrayBuffer = await response.arrayBuffer();

4、初始化docxtemplater

const PizZip = require("pizzip");
const Docxtemplater = require("docxtemplater");
const zip = new PizZip(arrayBuffer);

const doc = new Docxtemplater(zip, {
  nullGetter: () => "",
});

5、准备模板数据(填入的值)

const data = {
          name: "张三",
          gender: "男",
          birthday: "1995-06-15",
          phone: "13800138000",
          email: "zhangsan@example.com",
          address: "北京市朝阳区某某街道123号",
          education: "本科",
          experience: 3,
        };

6、设置数据并渲染

doc.setData(data);
doc.render();

7、生成文档

const zipData = doc.getZip();
  const docContent = zipData.generate({
    type: "uint8array",
    mimeType:
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  // 6. 生成 blob
  const blob = new Blob([docContent], {
    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  this.wordBlob = blob;
  this.downloadFileName = `信息-${new Date().getTime()}.docx`;

8、转换为 ArrayBuffer 用于预览

  const outputArrayBuffer = await blob.arrayBuffer();
  this.loading = false;

9、等待 DOM 更新后再渲染

  await this.$nextTick();

10、使用 docx-preview 在页面上渲染

  if (this.$refs.wordContent) {
    try {
      this.$refs.wordContent.innerHTML = "";
      await renderAsync(
        outputArrayBuffer,
        this.$refs.wordContent,
        null,
        {
          className: "docx-wrapper",
          inWrapper: true,
          ignoreWidth: false,
          ignoreHeight: false,
          ignoreFonts: false,
          breakPages: true,
          ignoreLastRenderedPageBreak: true,
          experimental: false,
          trimXmlDeclaration: true,
          useBase64URL: false,
          useMathMLPolyfill: true,
          showChanges: false,
          showComments: false,
          showInserted: true,
          showDeleted: false,
        }
      );
    } catch (renderError) {
      this.$message.warning("文档预览失败,但可以下载查看");
    }
  }

11、下载按钮的函数

downloadWord() {
  if (this.wordBlob && this.downloadFileName) {
    saveAs(this.wordBlob, this.downloadFileName);//下载成功
  } else {
    this.$message.warning("文档尚未生成,请先生成文档");
  }
},

12、实现的结果显示

全部代码:

<template>
  <div class="word-container">
    <div class="word-card">
      <div class="header-actions">
        <el-button type="primary" @click="downloadWord" :disabled="!wordBlob">
          <i class="el-icon-download"></i> 下载文档
        </el-button>
        <el-button @click="generateWord" :loading="loading">
          <i class="el-icon-refresh"></i> 重新生成
        </el-button>
      </div>

      <div v-if="loading" class="loading">
        <i class="el-icon-loading"></i>
        <p>正在生成 Word 文档...</p>
      </div>
      <div v-else-if="!wordBlob" class="error-message">
        <p>文档生成失败,请重试</p>
      </div>
      <div v-else ref="wordContent" class="word-content"></div>
    </div>
  </div>
</template>

<script>
import { saveAs } from "file-saver";
import { renderAsync } from "docx-preview";

export default {
  name: "InfoPage",
  data() {
    return {
      loading: false,
      wordBlob: null,
      downloadFileName: "",
    };
  },
  mounted() {
    this.generateWord();
  },
  methods: {
    async generateWord() {
try {
  this.loading = true;

  // 1. 加载Word模板文件
  const fileName = "info.docx";
  const response = await fetch(`/${fileName}`);

  if (!response.ok) {
    throw new Error(`模板文件不存在,状态码:${response.status}`);
  }

  const arrayBuffer = await response.arrayBuffer();

  // 2. 初始化docxtemplater
  const PizZip = require("pizzip");
  const Docxtemplater = require("docxtemplater");
  const zip = new PizZip(arrayBuffer);

  const doc = new Docxtemplater(zip, {
    nullGetter: () => "",
  });

  console.log("✅ Docxtemplater 实例已创建");

  // 3. 准备模板数据(填入的值)
  const data = {
    name: "张三",
    gender: "男",
    birthday: "1995-06-15",
    phone: "13800138000",
    email: "zhangsan@example.com",
    address: "北京市朝阳区某某街道123号",
    education: "本科",
    experience: 3,
  };

  // 4. 设置数据并渲染
  doc.setData(data);
  doc.render();

  console.log("✅ 模板渲染完成");

  // 5. 生成文档
  const zipData = doc.getZip();
  const docContent = zipData.generate({
    type: "uint8array",
    mimeType:
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  // 6. 生成 blob
  const blob = new Blob([docContent], {
    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  this.wordBlob = blob;
  this.downloadFileName = `信息-${new Date().getTime()}.docx`;

  // 7. 转换为 ArrayBuffer 用于预览
  const outputArrayBuffer = await blob.arrayBuffer();
  this.loading = false;

  // 8. 等待 DOM 更新后再渲染
  await this.$nextTick();

  // 9. 使用 docx-preview 在页面上渲染
  if (this.$refs.wordContent) {
    try {
      this.$refs.wordContent.innerHTML = "";
      await renderAsync(
        outputArrayBuffer,
        this.$refs.wordContent,
        null,
        {
          className: "docx-wrapper",
          inWrapper: true,
          ignoreWidth: false,
          ignoreHeight: false,
          ignoreFonts: false,
          breakPages: true,
          ignoreLastRenderedPageBreak: true,
          experimental: false,
          trimXmlDeclaration: true,
          useBase64URL: false,
          useMathMLPolyfill: true,
          showChanges: false,
          showComments: false,
          showInserted: true,
          showDeleted: false,
        }
      );
    } catch (renderError) {
      this.$message.warning("文档预览失败,但可以下载查看");
    }
  }
} catch (error) {
  this.$message.error("生成 Word 文档失败: " + (error.message || "未知错误"));
}
    },
downloadWord() {
  if (this.wordBlob && this.downloadFileName) {
    saveAs(this.wordBlob, this.downloadFileName);//下载成功
  } else {
    this.$message.warning("文档尚未生成,请先生成文档");
  }
},
  },
};
</script>

<style lang="scss" scoped>
.word-container {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: linear-gradient(135deg, #74b9ff 0%, #0984e3 50%, #005f99 100%);
  padding: 20px;
}

.word-card {
  width: 100%;
  max-width: 1200px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
  padding: 20px;
  animation: fadeInUp 0.5s ease-out;
  min-height: 600px;
  display: flex;
  flex-direction: column;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  color: #0984e3;

  i {
    font-size: 32px;
    margin-bottom: 20px;
    animation: rotating 2s linear infinite;
  }

  p {
    font-size: 16px;
    color: #666;
  }
}

@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.header-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-bottom: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid #eee;
}

.word-content {
  width: 100%;
  min-height: 400px;
  max-height: 80vh;
  overflow-y: auto;
  position: relative;

  :deep(.docx-wrapper) {
    background: #fff;
    padding: 40px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    border-radius: 4px;
    margin: 0 auto;
    max-width: 800px;
    min-height: 400px;
  }
}

.error-message {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  color: #f56c6c;
  font-size: 16px;
}

@media (max-width: 768px) {
  .word-card {
    padding: 30px 20px;
    max-width: 100%;
  }
}
</style>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值