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