0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

jsPDF + autoTable で PDF に表を描画

Posted at

やりたいこと

jsPDF で PDF に表を描画する。
表の描画には autoTable を使用する。

準備

jsPDF のフォントの設定などは、前回のjsPDF で PDF ファイルを作成を参照。

プロジェクト作成

React アプリケーションを作成。

npx create-react-app --template typescript test_pdf2
cd test_pdf2

ライブラリインストール

npm install jspdf
npm install jspdf-autotable

プログラム

メイン

App.tsx
import React from 'react';
import { DownloadPdfButton } from './download-pdf-button'

function App() {
  return (
    <div className="App">
      <DownloadPdfButton />
    </div>
  );
}

export default App;

PDF に表を描画

pdf-creator.ts
import { jsPDF as JsPDF } from 'jspdf'
import { autoTable } from 'jspdf-autotable'

import NotoSansRegularJP from './fonts/NotoSansJP-Regular-base64'
import NotoSansBoldJP from './fonts/NotoSansJP-Bold-base64'

const FONT = 'NotoSansJP'
const fontFileRegular = './fonts/NotoSansJP-Regular.ttf'
const fontFileBold = './fonts/NotoSansJP-Bold.ttf'

const FONT_TYPES = {
  NORMAL: 'normal',
  BOLD: 'bold',
}

const FONT_SIZES = {
  NORMAL: 16,
  SMALL: 12,
}

export class PdfCreator {
  font: string
  doc: any

  constructor() {
    this.font = FONT
    this.doc = null
  }

  create = () => {
    const fileName = `output.pdf`
    this.doc = new JsPDF('l', 'mm', 'a4') // l: landscape

    // normal font
    this.doc.addFileToVFS(fontFileRegular, NotoSansRegularJP)
    this.doc.addFont(fontFileRegular, this.font, FONT_TYPES.NORMAL)

    // bold font
    this.doc.addFileToVFS(fontFileBold, NotoSansBoldJP)
    this.doc.addFont(fontFileBold, this.font, FONT_TYPES.BOLD)

    // create PDF
    this.doc.setFont(this.font, FONT_TYPES.NORMAL)
    this.doc.setFontSize(FONT_SIZES.NORMAL)

    const pageWidth = this.doc.internal.pageSize.getWidth()
    const pageHeight = this.doc.internal.pageSize.getWidth()

    // table
    const header = [
      ['user', '', 'item', '', ''],
      ['id', 'name', 'id', 'name', 'etc'],
    ]

    const data = [
      ['1', 'user_01', '11', 'item_11', Array(200).fill('*').join('')],
      ['1', 'user_01', '12', 'item_12', Array(20).fill('*').join('\n')],
    ]

    autoTable(this.doc, {
      head: header,
      body: data,
      styles: { font: this.font, fontSize: FONT_SIZES.NORMAL },
      columnStyles: {
        0: { cellWidth: 40 },
        1: { cellWidth: 40 },
        2: { cellWidth: 40 },
        3: { cellWidth: 40 },
        4: { cellWidth: 80 },
      },
    })

    // page number
    this.addPageNumber()
    this.doc.save(fileName)
  }

  addPageNumber = () => {
    const totalPages = this.doc.internal.getNumberOfPages()
    const x = this.doc.internal.pageSize.width - 20
    const y = this.doc.internal.pageSize.height - 10

    for (let i = 1; i <= totalPages; i++) {
      const pageNumberText = `${i} / ${totalPages}`
      this.doc.setPage(i)
      this.doc.setFont(this.font, FONT_TYPES.NORMAL)
      this.doc.setFontSize(FONT_SIZES.SMALL)
      this.doc.text(pageNumberText, x, y, { align: 'right' })
    }
  }
}

ダウンロードボタン

download-pdf-button.tsx
import { PdfCreator } from './pdf-creator'

export const DownloadPdfButton = () => {
  const download = () => {
    const pdfCreator = new PdfCreator()
    pdfCreator.create()
  }

  return (
    <button onClick={download}>Download PDF</button>
  )
}

実行結果

以下のような PDF ファイルがダウンロードできる。

pdf_table.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?