首页 > 其他分享 >vue +echarts+ docxtemplater导出word和图表图片

vue +echarts+ docxtemplater导出word和图表图片

时间:2022-09-29 15:11:25浏览次数:51  
标签:vue const name -- word image import docxtemplater

1.下载插件

//-- 安装 docxtemplater
npm install docxtemplater pizzip  --save
//-- 安装 jszip-utils
npm install jszip-utils --save 
//-- 安装 jszip
npm install jszip --save
//-- 安装 FileSaver
npm install file-saver --save
//--安装 docxtemplater-image-module-free
npm install --save docxtemplater-image-module-free 

2.引入依赖

import fileSaver from "file-saver";
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils';
import ImageModule from 'docxtemplater-image-module-free ';

如果引入docxtemplater-image-module-free 报错,可尝试使用require方法引入。

const ImageModule = require("docxtemplater-image-module-free");

3.组件内容

父组件

<template>
    <div id="app">
        <div style="width: 100%; height: 100%;">
            <echart ref="chart"></echart>
        </div>
        <button @click="exportWord()">下载word</button>
    </div>
</template>

<script>
import fileSaver from "file-saver";
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils';
import echart from "./components/infCharts"

export default {
    name: 'App',
    data() {
        return {
            //文档数据
            wordData: {
                projectName: "二氧化碳排放量统计",
                type: "xx",
                time: "2022-9-29",
                company: "非自然局",
                list: [
                    { value: 548721, name: "南非" },
                    { value: 984207, name: "加拿大" },
                    { value: 671493, name: "墨西哥" },
                ],
            },
            // 导出文件名字
            exportFileName: "二氧化碳排放量报表",
            // 模版文件名字(文件需放在public目录下,文件格式为docx)
            templateFileName: "templateFile",
            // 图表option 数组,可多个图表
            // chartOptions: {
            //     type: Array,
            //     default: [],
            // },
        }
    },
    components: {
        echart
    },
    methods: {
        // 导出echarts图片,格式转换
        base64DataURLToArrayBuffer(dataURL) {
            const base64Regex = /^data:image\/(png|jpg|svg|svg\+xml);base64,/;
            if (!base64Regex.test(dataURL)) {
                return false;
            }
            const stringBase64 = dataURL.replace(base64Regex, "");
            let binaryString;
            if (typeof window !== "undefined") {
                binaryString = window.atob(stringBase64);
            } else {
                binaryString = new Buffer(stringBase64, "base64").toString("binary");
            }
            const len = binaryString.length;
            const bytes = new Uint8Array(len);
            for (let i = 0; i < len; i++) {
                const ascii = binaryString.charCodeAt(i);
                bytes[i] = ascii;
            }
            return bytes.buffer;
        },
        // 导出文档
        exportWord() {
            const ImageModule = require("docxtemplater-image-module-free");
            const that = this;
            // 存放echarts 图表 base64图片数组
            const str = [];
            // 读取并获得模板文件的二进制内容
            // `${that.templateFileName}.docx`,
            JSZipUtils.getBinaryContent(
                "template.docx",
                (error, content) => {
                    if (error) {
                        // 抛出异常
                        throw error;
                    }
                    const zip = new PizZip(content); // 创建一个JSZip实例,内容为模板的内容
                    const doc = new docxtemplater();
                    doc.loadZip(zip); // 创建并加载docxtemplater实例对象
                    //   如果有echarts图表
                    if (true) {
                        // for (const iterator of that.$refs["chart"]) {
                        //   // 这个getChartImg方法是我的echart组件中获取echarts图表图片的base64的dataurl
                        //   iterator.getChartImg((chartImg) => {
                        //     str.push({ image: chartImg });
                        //   });
                        // }
                        str.push({ image: that.$refs["chart"].getChartImg() });
                        // 图片处理
                        const opts = {};
                        opts.centered = true; // 图片居中,在word模板中定义方式为{%%image}
                        opts.fileType = "docx";
                        opts.getImage = (chartId) => {
                            return that.base64DataURLToArrayBuffer(chartId);
                        };
                        opts.getSize = () => {
                            return [600, 300];
                        };
                        const imageModule = new ImageModule(opts);
                        doc.attachModule(imageModule);
                    }
                    doc.setData({ ...that.wordData, chartList: str }); // 设置模板变量的值
                    try {
                        doc.render(); // 用模板变量的值替换所有模板变量
                    } catch (error) {
                        const e = {
                            message: error.message,
                            name: error.name,
                            stack: error.stack,
                            properties: error.properties,
                        };
                        console.log(JSON.stringify({ error: e }));
                        throw error; // 抛出异常
                    }
                    // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
                    const out = doc.getZip().generate({
                        type: "blob",
                        mimeType:
                            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    });
                    // 将目标文件对象保存为目标类型的文件,并命名
                    fileSaver.saveAs(out, `${that.exportFileName}.docx`);
                }
            );
        },
    }
}
</script>

<style>
#app {
    height: 1000px;
    background-color: #fff;
    text-align: center;
}

button {
    background-color: aqua;
}
</style>

图表组件

<template>
  <div class="orderEcharts">
    <div id="myChart6" :style="{ width: '100%' }"></div>
  </div>
</template>

<script>
import echarts from "echarts";
export default {
  name: "InfCharts",
  data() {
    return {
      myChart6: "",
      infData: [
        { value: 548721, name: "南非" },
        { value: 984207, name: "加拿大" },
        { value: 671493, name: "墨西哥" },
      ],
    };
  },
  mounted() {
    this.drawLine();
  },
  methods: {
    // 获取图表base64图
    getChartImg() {
      return this.myChart6.getDataURL({
        pixelRatio: 2, // 解决模糊
        backgroundColor: '#fff'
      });
    },
    drawLine() {
      // 基于准备好的dom,初始化echarts实例
      this.myChart6 = echarts.init(document.getElementById("myChart6"));
      // 绘制图表
      let option = {
        title: {
          text: "二氧化碳排放图表",
          //subtext: "纯属虚构",
          left: "center",
          textStyle: {
            color: 'black',
            fontSize: 32,
          }
        },
        tooltip: {
          trigger: "item",
        },
        color: ['Orange', '#4682B4', '#696969',],
        series: [
          {
            name: "访问来源",
            type: "pie",
            radius: "80%",
            center: ['50%', '50%'],//设置饼图位置
            data: this.infData,
            label: {
              normal: {
                show: true,
                position: 'inside',
                formatter: (data) => {
                  return (data.name + "\n" + data.value + " CO₂");
                },
                textStyle: {
                  color: 'black',
                  fontSize: 38,
                }
              }
            },
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)",
              },
            },
          },
        ],
      };
      this.myChart6.setOption(option);
      //自适应
      window.addEventListener("resize", () => {
        this.myChart6.resize();
      });
    },
  },
  beforeDestroy() {
    this.$bus.$off("inf");
  },
};
</script>

<style scoped>
.orderEcharts {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  color: black !important;
}
</style>

4.word模板

5.导出的word展示

标签:vue,const,name,--,word,image,import,docxtemplater
From: https://www.cnblogs.com/sevenccode/p/16738904.html

相关文章

  • wangEditor增加自定义工具栏暨百度编辑器上传WORD文档并保留源格式自动填充到编辑框
    ​ 在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper。通过知乎提供的思路找到粘......
  • Vue2,Vue3,React,vue-cli和Vite创建和启动
    vue2-project创建项目vuecreatexxx名字下依赖包npminstall启动项目npmrunserve项目打包npmrunbuildvue3-project创建项目vuecreatexxx名字下依......
  • FCKEditor富文本实现导入word功能.
    ​ 当前功能基于PHP,其它语言流程大抵相同。大概流程:1.将docx文件上传到服务器中2.使用PHPoffice/PHPword实现将word转换为HTML3.将HTML代码返回并赋值到编辑器中......
  • Vue 手动配置路由
    不用一键创建项目的方式 手动引用 1.安装路由组件(vue2)npmivue-router@3 2.创建路由映射js创建src/router/index.js//引用Vue和路由组件importVuef......
  • FCKEditor粘贴word里图文内容到编辑器中
    ​ 1.编辑器修改(可选)1.1在 ueditor/config.json 中添加代码块    /* 上传word配置 */    "wordActionName":"wordupload",/* 执行上传视频的action......
  • 如何监听Vue或js项目报错的4种方式
    背景onerrorelement.onerrorerrorHandlererrorCapturederror传播规则(划重点)如何监听异步错误总结背景在开发Vue项目时,使用浏览器调试可以比较清晰的看到报的什......
  • FCKEditor富文本实现导入word功能
    ​这种方法是servlet,编写好在web.xml里配置servlet-class和servlet-mapping即可使用后台(服务端)java服务代码:(上传至ROOT/lqxcPics文件夹下)<%@ page language="java" i......
  • vue项目环境搭建
    vue项目环境搭建安装Nodejs环境地址:https://nodejs.org/en/download/安装包管理工具#推荐安装yarnnpminstall--globalyarn#或者安装cnpmnpmconfigsetregis......
  • vue 类似苹果手机的悬浮球
    悬浮球效果3种位置展示悬浮球组件代码<template><divclass="ys-float-btn":style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','......
  • vue组件中如何首次加载就触发watch
    watch:{"val":{immediate:true,//首次加载的时候执行函数deep:true,//深入观察数组值的变化,inputVal:function(){}}} ......