前言

  • 本文所提及的导出方法是基于本人自己使用的项目,若要满足自己的项目需求,需要对方法做适量的调整
  • 本文知识学习于网上,经过整理所得,时间跨度较长,已遗忘参考于哪个博主,如有侵权,联系即删!

一、导出 Excel

1、按装依赖

npm install -S xlsx

2、方法

  • 使用方式参考下文使用示例
import * as XLSX from 'xlsx';

/**
   * 导出 Excel 表格
   * @param {*} title 表头信息
   * @param {*} data 表格体内容
   * @param {*} outFileName 保存的文件名
   * @param {*} orderProp 序号列的字段名
   */
  exportExcel(title, data, outFileName, orderProp) {
    let prop = 'prop'
    let titleList = this.toolTitleList(title)
    let tableData = [
      [...titleList]//导出表头
    ] // 表格表头

    data.forEach((tableItem, tableIndex) => {
      let rowData = []
      title.forEach((titleItem) => {
        if (titleItem[prop] === orderProp) {
          rowData.push(tableIndex + 1)
        } else {
          rowData.push(tableItem[titleItem[prop]])
        }
      })
      tableData.push(rowData)
    })

    // 以下部分才是生成 Excel 的重点
    let aoaToSheet = XLSX.utils.aoa_to_sheet(tableData)
    let bookNew = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(bookNew, aoaToSheet, outFileName) // 工作簿名称
    XLSX.writeFile(bookNew, outFileName + '.xlsx') // 保存的文件名
  },
  /**
   * 获取表头信息
   * @param {*} data 传入的表头信息数组
   * @returns 
   */
  toolTitleList(data) {
    let result = []
    data.forEach(item => {
      result.push(item['label'])
    })
    return result
  },

3、在本文中的使用示例

  • 在 Vue 中 methods 中使用
  • 由于后端返回的数据没有“序号”对应的字段,前端又需要展示,于是最后一个参数用于判断是否有“序号”字段,不需要可以将该参数置为空字符串

methods: {
  handleDownloadClick() {
  	let titleList = [
        {
          label: "序号",
          prop: "order_id",
          width: "4%",
        },
        {
          label: "区域名称",
          prop: "area_name",
          width: "9%",
        },
        {
          label: "厂站名称",
          prop: "st_name",
          width: "20%",
        },
       ]
    let tableList = [
    	{
          area_name: "AREANAME",
          st_name: "STNAME"
        },
       ]
    let outfilename = "数据表";  // 导出的文件名称
    let orderProp = "order_id"; // 序号列对应的字段名称
    exportWordExcelPdf.exportExcel(
      titleList,
      tableList,
      outfilename,
      orderProp
    );
  },
}

二、导出 Word

1、按装依赖

npm install -S docxtemplater file-saver jszip-utils pizzip

2、方法

import docxtemplater from 'docxtemplater';
import { saveAs } from 'file-saver';
import JSZipUtils from 'jszip-utils';
import PizZip from 'pizzip';

/**
   * 导出 Word 文档
   * @param {Object} tempDocxPath 模板文件路径
   * @param {Object} wordData 导出数据
   * @param {Object} fileName 导出文件名
   **/
  exportWord(tempDocxPath, wordData, fileName) {

    // 读取并获得模板文件的二进制内容
    JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {

      if (error) {
        throw error;
      }

      // 创建一个PizZip实例,内容为模板的内容
      let zip = new PizZip(content);
      // 创建并加载docxtemplater实例对象
      let doc = new docxtemplater();
      // doc.attachModule(new ImageModule(opts));
      doc.loadZip(zip);

      doc.setData(wordData);

      try {
        // 用模板变量的值替换所有模板变量
        doc.render();
      } catch (error) {
        // 抛出异常
        let e = {
          message: error.message,
          name: error.name,
          stack: error.stack,
          properties: error.properties
        };
        console.log(JSON.stringify({
          error: e
        }));
        throw error;
      }

      // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
      let out = doc.getZip().generate({
        type: "blob",
        mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      });
      // 将目标文件对象保存为目标类型的文件,并命名
      saveAs(out, fileName + ".docx");
    });
  },

3、在本文中的使用示例

  • 第一个参数是模版文件的路径,在 Vue3 项目中放在 public 目录下
  • 第二个参数是在模版中展示的数据内容,默认是一个对象的形式,模版中使用示例如下图
  • 第三个参数是导出的文件名
methods: {
    exportWordFile() {
      let param = {
      	message: "这是一段文本信息"
      }
      exportWord("/word.docx", param, "exportTestWord");
    },
},

在这里插入图片描述

三、导出 PDF

1、安装依赖

npm install -S html2canvas jspdf

2、方法

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

/**
   * 导出 PDF 文件
   * @param {*} dom 要导出的 PDF 元素
   * @param {*} outFileName 导出的文件名
   */
  exportPdf(dom, outFileName) {
    var element = document.querySelector(dom); // 这个dom元素是要导出pdf的div容器
    // element.style.height = param.height
    setTimeout(() => {
      html2Canvas(element).then(function (canvas) {
        var contentWidth = canvas.width;
        var contentHeight = canvas.height;

        // 一页pdf显示html页面生成的canvas高度;
        var pageHeight = contentWidth / 592.28 * 841.89;
        // 未生成pdf的html页面高度
        var leftHeight = contentHeight;
        // 页面偏移
        var position = 0;
        // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        var imgWidth = 595.28;
        var imgHeight = 592.28 / contentWidth * contentHeight;

        var pageData = canvas.toDataURL('image/jpeg', 1.0);

        var pdf = new JsPDF('', 'pt', 'a4');

        // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        // 当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
          pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
        } else {
          while (leftHeight > 0) {
            pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight;
            position -= 841.89;
            // 避免添加空白页
            if (leftHeight > 0) {
              pdf.addPage();
            }
          }
        }
        pdf.save(outFileName + '.pdf');
      });
      // element.style.height = param.minHeight
    }, 0);
  }

3、在本文中的使用示例

 methods: {
    /**
     * 下载为PDF
     */
    handleDownloadPdfClick() {
      // console.log("下载为PDF=>");
      let dom = "#pdfDom"
      let outFileName = "Pdf导出"
      this.getPdf(dom, outFileName);
    },
  },

四、综合文件

1、安装依赖

npm install -S xlsx

npm install -S docxtemplater file-saver jszip-utils pizzip

npm install -S html2canvas jspdf

2、工具文件

  • exportWordExcelPdf.js
import docxtemplater from 'docxtemplater';
import { saveAs } from 'file-saver';
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
import JSZipUtils from 'jszip-utils';
import PizZip from 'pizzip';

export default {
  /**
   * 导出 Excel 表格
   * @param {*} title 表头信息
   * @param {*} data 表格体内容
   * @param {*} outFileName 保存的文件名
   * @param {*} orderProp 序号列的字段名
   */
  exportExcel(title, data, outFileName, orderProp) {
    let prop = 'prop'
    let titleList = this.toolTitleList(title)
    let tableData = [
      [...titleList]//导出表头
    ] // 表格表头

    data.forEach((tableItem, tableIndex) => {
      let rowData = []
      title.forEach((titleItem) => {
        if (titleItem[prop] === orderProp) {
          rowData.push(tableIndex + 1)
        } else {
          rowData.push(tableItem[titleItem[prop]])
        }
      })
      tableData.push(rowData)
    })

    // 以下部分才是生成 Excel 的重点
    let aoaToSheet = XLSX.utils.aoa_to_sheet(tableData)
    let bookNew = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(bookNew, aoaToSheet, outFileName) // 工作簿名称
    XLSX.writeFile(bookNew, outFileName + '.xlsx') // 保存的文件名
  },
  /**
   * 获取表头信息
   * @param {*} data 传入的表头信息数组
   * @returns 
   */
  toolTitleList(data) {
    let result = []
    data.forEach(item => {
      result.push(item['label'])
    })
    return result
  },


  /**
   * 导出 Word 文档
   * @param {Object} tempDocxPath 模板文件路径
   * @param {Object} wordData 导出数据
   * @param {Object} fileName 导出文件名
   **/
  exportWord(tempDocxPath, wordData, fileName) {

    // 读取并获得模板文件的二进制内容
    JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {

      if (error) {
        throw error;
      }

      // 创建一个PizZip实例,内容为模板的内容
      let zip = new PizZip(content);
      // 创建并加载docxtemplater实例对象
      let doc = new docxtemplater();
      // doc.attachModule(new ImageModule(opts));
      doc.loadZip(zip);

      doc.setData(wordData);

      try {
        // 用模板变量的值替换所有模板变量
        doc.render();
      } catch (error) {
        // 抛出异常
        let e = {
          message: error.message,
          name: error.name,
          stack: error.stack,
          properties: error.properties
        };
        console.log(JSON.stringify({
          error: e
        }));
        throw error;
      }

      // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
      let out = doc.getZip().generate({
        type: "blob",
        mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      });
      // 将目标文件对象保存为目标类型的文件,并命名
      saveAs(out, fileName);
    });
  },

  /**
   * 导出 PDF 文件
   * @param {*} dom 要导出的 PDF 元素
   * @param {*} outFileName 导出的文件名
   */
  exportPdf(dom, outFileName) {
    var element = document.querySelector(dom); // 这个dom元素是要导出pdf的div容器
    // element.style.height = param.height
    setTimeout(() => {
      html2Canvas(element).then(function (canvas) {
        var contentWidth = canvas.width;
        var contentHeight = canvas.height;

        // 一页pdf显示html页面生成的canvas高度;
        var pageHeight = contentWidth / 592.28 * 841.89;
        // 未生成pdf的html页面高度
        var leftHeight = contentHeight;
        // 页面偏移
        var position = 0;
        // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        var imgWidth = 595.28;
        var imgHeight = 592.28 / contentWidth * contentHeight;

        var pageData = canvas.toDataURL('image/jpeg', 1.0);

        var pdf = new JsPDF('', 'pt', 'a4');

        // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        // 当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
          pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
        } else {
          while (leftHeight > 0) {
            pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight;
            position -= 841.89;
            // 避免添加空白页
            if (leftHeight > 0) {
              pdf.addPage();
            }
          }
        }
        pdf.save(outFileName + '.pdf');
      });
      // element.style.height = param.minHeight
    }, 0);
  }
}

3、在本文中的使用示例

  • 引入
import exportWordExcelPdf from "./../../utils/exportWordExcelPdf";
  • 使用
methods: {
	handleDownloadClick() {
        let outfilename = "厂站数据表";
        let orderProp = "order_id"; // 序号列对应的字段名称
        
        exportWordExcelPdf.exportExcel(
            this.factoryTableTitle,
            this.factoryTableList,
            outfilename,
            orderProp
        );
    },
}

总结

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐