使用jsPDF 和jspdf-autotable 導出中文表格頁面


剛做完把頁面表格導出為PDF的功能,記錄一下。
把頁面導出pdf我們有2種方式:

  1. 把頁面變成圖片,然后把圖片弄成pdf
  2. 直接把html變成pdf

方式一:

簡單快捷,但不是很清晰,而且如果需要打印出來,會有一點黑色背景。適合要求不高,不需要打印的。
用到的庫:html2canvas 和 jsPDF,安裝一下:npm install html2canvas jsPDF

html部分

<button onclick="downloadPdf">導出PDF</button>
<div id="myPage">
	HTML的的內容
</div>

JS部分

import { jsPDF as JsPDF } from 'jspdf'; //這里是因為用了eslint,構造函數要大寫,才弄個別名
import html2canvas from 'html2canvas';

  const downloadPdf = () => {
    const printHtml = document.getElementById('myPage'); //myPage里面的內容會經過庫處理變成圖片
    html2canvas(printHtml).then((canvas) => {
      const contentWidth = canvas.width;
      const contentHeight = canvas.height;
      // 一頁pdf顯示html頁面生成的canvas高度;
      const pageHeight = contentWidth / 592.28 * 841.89;
      // 未生成pdf的html頁面高度
      let leftHeight = contentHeight;
      // 頁面偏移
      let position = 0;
      // a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
      const imgWidth = 595.28;
      const imgHeight = 592.28 / contentWidth * contentHeight;

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

      const pdf = new JsPDF('', 'pt', 'a4'); // 縱向方向p,單位pt|mm, 格式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('pdf的名字.pdf');
    });
  };

方式二:

清晰可見,打印出來效果很好。
用到的庫:jsPDF 和 jspdf-autotable 安裝一下:npm install jsPDF jspdf-autotable

坑:處理中文,因為默認不支持中文
解決導出中文不亂碼問題,我們需要提供一個編譯處理過的js字體文件,給jsPDF設置上字體,就可以了。

方法:
1.先去這里 轉換你需要的字體(只支持 .ttf格式的字體)
2. 在上面轉換后你會得到一個js文件,打開文件我們只需要保留那很長的字符串,並且把它導出,其他代碼可以注釋掉。
const myFont ="那一堆超長字符串";
export defalut myFont;
3. 使用時
doc.addFileToVFS("ok.ttf", myFont);// 前面.ttf隨便寫,后面就是那個超長字符串
doc.addFont("ok.ttf", "hahaFont", "normal"); //.ttf和上一行對應;定義的字體名字,后面要用到;默認normal

html部分
使用的是table標簽,然后如果單元格內容多需要換行的使用
標簽,這樣到時導出的pdf才會換行,同時不需要再套p或div標簽。不然頁面上會空出很多。

<button onclick="downloadPdf">導出PDF</button>
<div id="myPage">
	xxxx的內容
	<table id="indexTable" border="1" cellPadding="10" cellspacing="0">
          <thead>
            <tr>
              <th style={{ width: '10%', textAlign: 'center' }}>類</th>
              <th style={{ width: '10%', textAlign: 'center' }}>指標</th>
            </tr>
          </thead>
          <tbody>
		  	<tr>
				<td>課堂適應學生<br>清晰一二</td>
				<td>四五六</td>
			</tr>
			<tr>
				<td>蒸餾水<br>水電費<br/>朗讀一下</td>
				<td>臨時凍結</td>
			</tr>
		  </tbody>
	</table>	  
</div>

js部分

import { jsPDF as JsPDF } from 'jspdf';
import 'jspdf-autotable';
import myFont from './myzt-normal';//引入字體js文件,解決中文亂碼

const downloadPdf = () => {
    const doc = new JsPDF('p', 'pt'); // 獲取實例
    const res = doc.autoTableHtmlToJson(document.getElementById('indexTable'));
    // 設置中文字體
    doc.addFileToVFS('ok.ttf', myFont);
    doc.addFont('ok.ttf', 'myFont', 'normal');
    doc.setFont('myFont');

    doc.autoTable({
      styles: {//設置表格的字體,不然表格中文也亂碼
        fillColor: [255, 255, 255], font: 'myFont', textColor: [0, 0, 0], halign: 'left', fontSize: 12,
      },
      headStyles: { lineWidth: 1, halign: 'center' },
      columnStyles: {
        0: { valign: 'middle', cellWidth: 50 },
        1: { valign: 'middle', cellWidth: 50 },
        2: { valign: 'middle' },
        3: { valign: 'middle', cellWidth: 200 },
        4: { valign: 'middle', minCellWidth: 30 }, // 第4列居中,寬度最小30
      },
      theme: 'grid', // 主題
      startY: 80, // 距離上邊的距離
      margin: 20, // 距離左右邊的距離
      body: res.data, // 表格內容
      columns: [ // 表頭
        { header: '類', dataKey: 'lei' },
        { header: '指標', dataKey: 'zhibiao' },
        { header: '要點及要素', dataKey: 'yaosu' },
        { header: '大數據計分方案', dataKey: 'fangan' },
        { header: '得分', dataKey: 'defen' },
      ],
    });

    const pageWidth = doc.getPageWidth(); // A4紙:595.28
    const x1 = (pageWidth - doc.getTextWidth(indexTitle)) / 2;
    doc.text(x1, 40, indexTitle); // x坐標,y坐標,文字
    doc.setFontSize(12);// 設置文字大小,下一行起有效
    doc.text(20, 60, `總分:${score}`);

    doc.save(`${indexTitle}-大數據指數.pdf`);
  };


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM