LoginSignup
3
1

More than 1 year has passed since last update.

jsPDFで日本語対応したPDFを作成する方法(テーブルもあり)

Posted at

やりたいこと

・ReactプロジェクトでDOM描画したものをそのままPDF化したい

・画像PDFではなく、テキストのPDFにしたい

参考にしたサイト

ほとんどこちら参考にしました。
ただ、これだけではテーブルの内容が日本語化がうまくいかず、文字化けしたままでした。

結論

上記サイトを元にipaexg-normal.jsを作成します。
ソース内容もほとんど同じです。

一部DOM操作してい箇所がありましたのでReactっぽい記述に変更しました。
Table内がどうしても文字化けして困りました。。。

table th,td に対して、 fontFamily: "ipaexg"

のスタイルを付与することで解決できました!


import { jsPDF } from "jspdf";
import "./ipaexg-normal";


export const PdfViewer = () => {
  // PDF
  const targetRef = useRef<HTMLDivElement>(null); 
// ↑ ここdocument.querySelectorではなくuseRefに変更しました。
  const pdfRef = useRef(new jsPDF());

  const getFileName = () => {
    const timestamp = new Date().getTime();
    return `download_${timestamp}.pdf`;
  };

  const savePdf = () => {
    if (!targetRef.current) return;
    pdfRef.current.html(targetRef.current, {
      callback(doc) {
        const fileName = getFileName();
        doc.setFont("ipaexg", "normal"); // ここもuseEffect使用しなくても大丈夫でした。
        doc.setFontSize(12);
        doc.save(fileName);
      },
      x: 15,
      y: 15,
      width: 170,
      windowWidth: 775,
    });
  };

  const JpFont = {
    fontFamily: "ipaexg",
  };

  return (
    <Layout>
      <div>
        <SectionTitle title={"PDF"} />

        <div
          ref={targetRef}  // idではなくrefで取得します
          style={{
            fontFamily: "ipaexg",  
          }}
        >
          <div>
            <div>
              <span>2023/05/01発行</span>
              <span>2023/06/01有効期限</span>
            </div>
          </div>
          <h2>
            見積書
          </h2>

              // 省略

            // テーブル

          <div>
            <div style={JpFont}>
              <table
                style={{
                  minWidth: 650,
                  fontSize: "12px",
                  fontFamily: "ipaexg",
                }}
              >
                <thead>
                  <tr>
                    <th style={JpFont}>
                      箇所
                    </th>
                    <th style={JpFont}>
                      施工内容
                    </th>
                    <th style={JpFont}>
                      数量
                    </th>
                    <th style={JpFont}>
                      単位
                    </th>
                    <th style={JpFont}>
                      単価
                    </th>
                    <th style={JpFont}>
                      金額
                    </th>
                    <th style={JpFont}>
                      備考
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {rows.map((row) => {
                    return (
                      <tr key={row.id}>
                        <td style={JpFont}>
                          {row.area}
                        </td>
                        <td style={JpFont}>
                          {row.item}
                        </td>
                        <td style={JpFont}>
                          {row.quantity}
                        </td>
                        <td style={JpFont}>
                          {row.unit}
                        </td>
                        <td style={JpFont}>
                          {row.price.toLocaleString()}
                        </td>
                        <td  style={JpFont}>
                          {(row.quantity * row.price).toLocaleString()}
                        </td>
                        <td style={JpFont}>
                          {row.memo}
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>

        <button
          type="submit"
          onClick={() => savePdf()}
        >
          PDFを保存する
        </button>
      </div>
    </Layout>

出力したPDF

本当に実装した方には表に枠などあったのですが、デモ用に簡単なものになっていますが、
本題は表内のテキストも日本語化(文字化けしない)きちんとされているところなので

sample.jpg

3
1
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
3
1