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

## やりたいこと

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

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



## 参考にしたサイト

https://blog.capilano-fw.com/?p=11213

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



## 結論

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

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

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

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

```jsx

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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483702/8a6726ff-ee0d-36a7-c673-d54017612a3d.jpeg)