最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue導出PDF實現(xiàn)方式(vue2,插件:pdfmake,表格)

 更新時間:2026年03月09日 09:30:28   作者:積硅步 以至千里  
文章主要介紹了如何使用pdfmake插件生成PDF文件,并提供了一個示例代碼,用于將嵌套的數(shù)組轉換為一維數(shù)組,以便在PDF中生成表格,同時,文章還討論了如何設置表格的樣式,包括顏色、背景色和文字位置等

:文章為記錄為主,想直接看pdfmake 打印的請劃到最下面部分

需求

頁面有一個表格,之前導出excel 表(用XLSX和XLSXS制作了樣式之類的表格),現(xiàn)在需要制作帶樣式的pdf,而且格式如下,并且最上面的三行需要在每一頁的頂部出現(xiàn)作為表頭

效果圖,(換頁前面三行也會有)

script 要打印的盒子:ref="printSection" ,這個表格是用 el-table 來寫的,而且表格中存在嵌套children,一共嵌套了3層

如上圖:大寫數(shù)字(一、二)是第一層,附和大寫字母(A、B)是第二層,其他(沒有序號的的行)是第三層

<div id="pdfDom" ref="printSection">
      <el-table
        empty-text="暫無報告"
        v-loading="loading"
        :data="staffJieyuList"
        @selection-change="handleSelectionChange"
        default-expand-all
        row-key="row"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      >
        <el-table-column align="center" :label="subTitle">
          <el-table-column :label="searchInformation.lysuoName">
            <el-table-column prop="id" align="center" label="序號">
            </el-table-column>
            <el-table-column prop="name" align="center" label="項目">
            </el-table-column>
            <el-table-column prop="amount" align="center" label="金額">
            </el-table-column>
            <el-table-column prop="contractNum" align="center" label="備注">
            </el-table-column>
          </el-table-column>
        </el-table-column>
      </el-table>
    </div>

上面表格data對應的staffJieyuList數(shù)據(jù)的格式如下:

          staffJieyuList = [ //這里是第一層數(shù)組,里面數(shù)據(jù)是對象格式
           {
            id: "一",
            row: 1,
            name: "業(yè)務收入",
            amount: "",
            contractNum: "",
             //這里是第二層數(shù)組,里面數(shù)據(jù)是對象格式
            children: [
              {
                id: "",
                row: 101,
                name: "本月合計",
                amount: data.income,
              },
              {
                id: "",
                row: 102,
                name: "本年累計",
                amount: data.incomeYear,
              },
              {
                id: "附",
                row: 103,
                name: "累計本年未收款明細",
                amount: "",
                //這里是第三層數(shù)組,里面數(shù)據(jù)是對象格式
                children: data.incomeUnpaidList.map((ele, index) => {
                  let i = {
                    id: "",
                    row: "104" + index,
                    name: ele.fapiaoName + "(占比:" + ele.portion + ")",
                    amount: ele.amount,
                  };
                  return i;
                }),
              },
            ],
          },
            第二個數(shù)組...
           ]

我要打印的主要是四列:

序號id 、項目name、金額amount、備注contractNum(打印出來的看最上面的圖)

一.window.print();

打印可以直接調(diào)用:window.print(); 但是這里只調(diào)用了一次,取消打印之后不再彈出,而且打印的內(nèi)容也不符合我的要求

    printDiv3() {
      console.log("觸發(fā)---");
      const printContents = this.$refs.printSection.innerHTML;
      const originalContents = document.body.innerHTML;
      document.body.innerHTML = printContents;
      window.print();
      this.$nextTick(() => {
        document.body.innerHTML = originalContents;
      });
    }

效果圖:

二.用 iframe 來打印

printDiv2() {
      const printContent = document.querySelector("#pdfDom").innerHTML;
      const iframe = document.createElement("iframe");
      iframe.setAttribute("style", "position: absolute; width: 0; height: 0;");
      document.body.appendChild(iframe);
      const iframeDoc = iframe.contentWindow.document;
      // 設置打印展示方式 - 橫向展示
      iframeDoc.write('<style media="print">@page {size: landscape;}</style>');
      // 向 iframe 中注入 printContent 樣式
      iframeDoc.write(
        `<link href="./print.css" rel="external nofollow"  media="print" rel="stylesheet" />`
      );
      // 寫入內(nèi)容
      iframeDoc.write("<div>" + printContent + "</div>");
      setTimeout(function () {
        iframe.contentWindow.print();
        document.body.removeChild(iframe);
      }, 50);
    },

樣式?jīng)]研究,打印出來的效果圖如下,連邊框線也沒加,更別說需要算哪里的背景色,字體居中和靠左了

三.JsPDF 插件

用 JsPDF 插件來導出pdf (配合插件html2canvas) 導出的第二頁也會被截斷,樣式我也沒有研究,感興趣的朋友可以研究下,文件:htmlToPdf.js

// 導出頁面為PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
    install(Vue, options) {
        Vue.prototype.getPdf = function (flieName) {
            // 當下載pdf時,若不在頁面頂部會造成PDF樣式不對,所以先回到頁面頂部再下載
            let top = document.getElementById('pdfDom');
            if (top != null) {
                top.scrollIntoView();
                top = null;
            }
            let title = flieName;
            html2Canvas(document.querySelector('#pdfDom'), {
                allowTaint: true
            }).then(function (canvas) {
                // 獲取canvas畫布的寬高
                let contentWidth = canvas.width;
                let contentHeight = canvas.height;
                // 一頁pdf顯示html頁面生成的canvas高度;
                let pageHeight = contentWidth / 841.89 * 592.28;
                // 未生成pdf的html頁面高度
                let leftHeight = contentHeight;
                // 頁面偏移
                let position = 0;
                // html頁面生成的canvas在pdf中圖片的寬高(本例為:橫向a4紙[841.89,592.28],縱向需調(diào)換尺寸)
                let imgWidth = 841.89;
                let imgHeight = 841.89 / contentWidth * contentHeight;
                // console.log('pdf寬-高-pageHeight--imgHeight',contentWidth,contentHeight,pageHeight,imgHeight);
                let pageData = canvas.toDataURL('image/jpeg', 1.0);
                let PDF = new JsPDF('l', 'pt', 'a4');
                // 兩個高度需要區(qū)分: 一個是html頁面的實際高度,和生成pdf的頁面高度
                // 當內(nèi)容未超過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 -= 592.28;
                        // 避免添加空白頁
                        if (leftHeight > 0) {
                            PDF.addPage();
                        }
                    }
                }
                PDF.save(title + '.pdf')
            })
        }
    }
}

引入和使用(這里是全局注冊了的)

main.js

import htmlToPdf from '@/utils/htmlToPdf';

Vue.use(htmlToPdf);

 頁面使用該組件:

<el-col :span="1.5">
  <el-button type="primary" plain icon="" size="mini" @click="printDiv" >打印</el-button>
</el-col>

printDiv() {
      this.$nextTick(() => {
        this.getPdf(this.exportPDFtitle);
      });
    },

四. pdfmake 導出表格

pdfMake 文檔:

先解決下載安裝問題:(版本:"pdfmake": "^0.2.10",我是直接下載默認最新的版本)

npm install pdfmake  --save   

下載字體和導入字體:

找到 node_modules 的pdfmake (下載的插件) 文件,新建 examples/fonts文件夾,導入需要的字體,這里的字體需要去找對應的字體文件,我的字體是本機電腦找的,我在我的C盤找到一些,這里用的是 仿宋

把這個文件復制,下載,放到下面examples/fonts文件夾下,復制出來的名字是大寫,我改為:simfang.ttf 小寫

控制臺定位到pdfmake文件夾下,運行命令:node build-vfs.js "./examples/fonts"

這樣就算完成了(可以導入多種字體,我這里沒有字體要求,只用了仿宋)

前置問題和解決方案:pdfmake 要求的表格的內(nèi)容傳入需要時一個個的對象數(shù)組,如下圖:(紅色框是我完成需求用到的一些屬性)

要解決的問題:

1). 之前嵌套的數(shù)組(樹結構)要導出為一維數(shù)組(我發(fā)現(xiàn)導出的表格只需要4列,而且是固定的,只需要給每一條的數(shù)據(jù)固定4個屬性就可以,表頭也可以單獨寫,非常方便)

下面是嵌套的數(shù)組轉為一維數(shù)組的代碼(使用遞歸)

//嵌套的多維數(shù)組 生成 一維數(shù)組
    flattenData(staffJieyuList) {
      // 初始化一維數(shù)組
      const flattenedData = [];

      // 遞歸函數(shù),處理對象及其子數(shù)組
      function processObject(obj) {
        const flattenedObj = {
          id: obj.id || "", // 如果 id 不存在,則用空字符串填充
          name: obj.name || "", // 如果 name 不存在,則用空字符串填充
          amount: obj.amount || "", // 如果 amount 不存在,則用空字符串填充
          contractNum: obj.contractNum || "", // 如果 contractNum 不存在,則用空字符串填充
        };

        // 將當前對象添加到一維數(shù)組中
        flattenedData.push(flattenedObj);

        // 處理子數(shù)組
        if (obj.children && obj.children.length > 0) {
          obj.children.forEach((child) => {
            processObject(child);
          });
        }
      }

      // 遍歷主列表中的每個對象
      staffJieyuList.forEach((item) => {
        processObject(item);
      });

      // 返回轉換后的一維數(shù)組
      return flattenedData;
    },

當然上面的代碼可以拆分為兩個函數(shù):(函數(shù)都在methods: {} 中)

// 輔助函數(shù),處理對象及其子數(shù)組
processObject(obj, flattenedData) {
  const flattenedObj = {
    id: obj.id || "",
    name: obj.name || "",
    amount: obj.amount || "",
    contractNum: obj.contractNum || "",
  };

  // 將當前對象添加到一維數(shù)組中
  flattenedData.push(flattenedObj);

  // 處理子數(shù)組
  if (obj.children && obj.children.length > 0) {
    obj.children.forEach((child) => {
      this.processObject(child, flattenedData);
    });
  }
}

// 調(diào)用輔助函數(shù)來生成一維數(shù)組
flattenDataWithHelper(staffJieyuList) {
  // 初始化一維數(shù)組
  const flattenedData = [];

  // 遍歷主列表中的每個對象
  staffJieyuList.forEach((item) => {
    this.processObject(item, flattenedData);
  });

  // 返回轉換后的一維數(shù)組
  return flattenedData;
}

2).表頭是3行,直接用下圖的屬性 headerRows: 3, 表頭占一行,可以直接:colSpan: 4,其余的列用{} 來占位

[{ text: 我是表頭內(nèi)容, colSpan: 4, }, {}, {}, {}],

3).顏色,背景色,文字顯示位置,需要 alignment: 'center', fillColor: '#91aadf' 等屬性

頁面使用:(全局跟上面一樣引入,這里是單獨頁面使用)

import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.fonts = {
  simfang: {
    normal: "simfang.ttf",
    bold: "simfang.ttf",
    italics: "simfang.ttf",
    bolditalics: "simfang.ttf",
  },
};
pdfMake.vfs = pdfFonts.pdfMake.vfs;

打印按鈕:

<el-col :span="1.5">
  <el-button type="primary" plain icon="" size="mini" @click="printDiv" >打印PDF</el-button>
</el-col>

下面附上完整的pdfmake 導出表格的代碼:

printDiv() {
      // 調(diào)用函數(shù),獲得所需的一維數(shù)組
      const flattenedArray = this.flattenData(this.staffJieyuList);
      console.log("flattenedArray----", flattenedArray);

      var fileName = this.exportPDFtitle + ".pdf";

      // 匹配大寫字母、大寫阿拉伯數(shù)字或者特定的中文字符的正則表達式
      const pattern = /^(附|[A-Z]|[一二三四五六七八九十])+$/;
      //除了1-3行,還有下面匹配的這些 文字居中,項目這里列的其他內(nèi)容要往左
      const pattern2 = /^([一二三四五六七八九十])+$/
      const docDefinition = {
        content: [
          {
            table: {
              headerRows: 3,
              widths: [50, "auto", 60, "auto"],
              body: [
                [{ text: this.subTitle, colSpan: 4, alignment: 'center', fillColor: '#91aadf'}, {}, {}, {}],
                [{ text: this.searchInformation.lysuoName, colSpan: 4, alignment: 'left', fillColor: '#91aadf'}, {}, {}, {}],
                [
                { text: "序號",  alignment: 'center', fillColor: '#91aadf' },
                { text: "項目",  alignment: 'center', fillColor: '#91aadf' },
                { text: "金額",  alignment: 'center', fillColor: '#91aadf' },
                { text: "備注",  alignment: 'center', fillColor: '#91aadf' },
                ],
                ...flattenedArray.map((item) => {
                  const backgroundColor =
                  pattern.test(item.id) ? "#d9e1f4" : "#ffffff";
                  const fontPosition = 
                  pattern2.test(item.id) ? "center" : "left"
                  return [
                    { text: item.id, fillColor: backgroundColor, alignment: 'center', },
                    { text: item.name, fillColor: backgroundColor, alignment: fontPosition, },
                    { text: item.amount, fillColor: backgroundColor, alignment: 'center', },
                    { text: item.contractNum, fillColor: backgroundColor, alignment: 'center', },
                  ];
                }),
              ],
            },
          },
        ],
        defaultStyle: {
          font: "simfang",
        },
      };
      pdfMake.createPdf(docDefinition).download(fileName);
    },

效果:

 

總結

用pdfmake插件制作pdf確實方便,而且樣式等配置也比較齊全,(上面寫的不好的地方歡歡迎指正,相互討論學習)純前端用XLSX和XLSXS制作導出excel 之前沒有記錄,有空再做記錄

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 詳解Vue的數(shù)據(jù)及事件綁定和filter過濾器

    詳解Vue的數(shù)據(jù)及事件綁定和filter過濾器

    這篇文章主要為大家介紹了Vue的數(shù)據(jù)及事件綁定和filter過濾器,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Vue中使用Teleport的方法示例

    Vue中使用Teleport的方法示例

    這篇文章主要為大家介紹了Vue中使用Teleport的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Vue3中customRef自定義ref過程

    Vue3中customRef自定義ref過程

    Vue3的customRef允許自定義響應式邏輯,通過get/set控制依賴追蹤與更新觸發(fā),適用于防抖、驗證、異步等場景,最佳實踐包括封裝函數(shù)、正確調(diào)用track/trigger、清理資源及優(yōu)化性能
    2025-09-09
  • Vue項目markdown內(nèi)容預覽顯示優(yōu)化方式

    Vue項目markdown內(nèi)容預覽顯示優(yōu)化方式

    在Vue項目中使用markdown-it組件預覽Markdown內(nèi)容時,通過安裝pnpm和markdown-it-github-markdown-css依賴,并重寫markdown部分樣式,實現(xiàn)了Markdown內(nèi)容的美化,在MarkdownPreview.vue組件中,通過變量renderedMarkdown接收并渲染Markdown內(nèi)容
    2025-10-10
  • Vue 封裝公告滾動的方法

    Vue 封裝公告滾動的方法

    文章介紹了如何在需求系統(tǒng)中創(chuàng)建一個位于頁面上方的公告展示組件,展示了如何在App.vue或其他頁面組件中使用這個公告組件,感興趣的朋友一起看看吧
    2025-01-01
  • 基于Vue實現(xiàn)封裝一個虛擬列表組件

    基于Vue實現(xiàn)封裝一個虛擬列表組件

    正常情況下,我們對于數(shù)據(jù)都會分頁加載,最近項目中確實遇到了不能分頁的場景,如果不分頁,頁面渲染幾千條數(shù)據(jù)就會感知到卡頓,使用虛擬列表就勢在必行了。本文主要介紹了如何基于Vue實現(xiàn)封裝一個虛擬列表組件,感興趣的可以了解一下
    2023-03-03
  • vue2.0 better-scroll 實現(xiàn)移動端滑動的示例代碼

    vue2.0 better-scroll 實現(xiàn)移動端滑動的示例代碼

    本篇文章主要介紹了vue2.0 better-scroll 實現(xiàn)移動端滑動的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2018-01-01
  • vue如何使用模擬的json數(shù)據(jù)查看效果

    vue如何使用模擬的json數(shù)據(jù)查看效果

    這篇文章主要介紹了vue如何使用模擬的json數(shù)據(jù)查看效果,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • vue封裝一個彈幕組件詳解

    vue封裝一個彈幕組件詳解

    這篇文章主要介紹了vue封裝一個彈幕組件詳解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙可以參考一下
    2022-08-08
  • 第一個Vue插件從封裝到發(fā)布

    第一個Vue插件從封裝到發(fā)布

    這篇文章主要為大家詳細介紹了第一個Vue插件從封裝到發(fā)布的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11

最新評論

裕民县| 湘西| 淄博市| 兴仁县| 治多县| 微山县| 上饶市| 兴安盟| 独山县| 哈尔滨市| 闻喜县| 珲春市| 巴青县| 卢氏县| 麻栗坡县| 九龙县| 永胜县| 通州市| 乐山市| 青川县| 呼图壁县| 桦川县| 温州市| 安仁县| 会昌县| 汝州市| 桐城市| 读书| 彰武县| 秦安县| 陇西县| 甘谷县| 都昌县| 社会| 怀集县| 达尔| 武平县| 丘北县| 广州市| 和静县| 曲沃县|