27
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【前編】WebアプリでのPDF帳票印刷問題をPleasanter&pdfmeで解決!

Last updated at Posted at 2025-12-06

はじめに

本記事のテーマである帳票印刷含め様々なシーンでプリザンターを使わせていただき、業務改善を行っているといchです。
請求書や領収書といった帳票の印刷やPDF化を支援するツールを作ったので、既存アプローチの整理と今回のやり方になった理由や良さをご紹介します!

手順を共有するほど整える時間はありませんでしたので、ここでは簡単な構成図とスクショだけとして、実装手順の共有や構成の解説などは後半(次回記事)に回します。

既存アプローチ

紹介の前にすでにあった取り組みや難しさを認識していただく必要があります。(後述の公式パートナー様方からしたら簡単なのかも🙇‍♂️)

このあたりがポイントになってきます。

  • 文字列レイアウト:
    • 置換できる?
    • 改行や文字サイズ縮小で、長い文字の置換後に枠のはみだしをコントロール可能?
  • デザイン性:
    • 欲しいままの体裁が作れる?
    • 列とページの増減は?
    • メンテは楽?
  • Pleasanterとの連携:
    • ↑ 最重要です、あとセキュリティ

俺たちのデータは!Pleasanterにある!

Figma&SVG&PHPパターン

一般的な方法としては@ttskchさんの記事とスライドが勉強になりました。
Figma&SVG&PHPと書きましたが結論がそれなだけで、HTML&CSSパターン、Excel&LibreOfficeパターンといろいろ試されています。
勉強になるだけでなくスライドも面白かったです。

仕組みとしては、
Figmaでデザインを作成
→ SVGでテンプレをエクスポート
→ PHPでSVG内の%顧客名%のような置換タグを修正、実数値と置換したSVGを作成
→ JSでHTML上に描画し、枠をはみ出す文字や左右中央揃えを調整
→ ブラウザの印刷機能でPDFとして保存
という形です。

SVGでの描画というのは、このようなコードをブラウザで開くとこんな感じに描画されます。

サンプルコード(sample-svg.xml)
sample-svg.xml
<svg width="500" height="180" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <style>
      .cell-text {
        font-family: sans-serif;
        font-size: 14px;
      }
      .header {
        font-weight: bold;
      }
    </style>
  </defs>

  <rect x="0" y="0" width="500" height="180" fill="white" />


  <!-- rect と text を交互に配置 -->
  <!-- row0 -->
  <rect x="0"   y="0"  width="120" height="40" fill="#eeeeee" stroke="#333" />
  <text x="60"  y="20" class="cell-text header" text-anchor="middle" dominant-baseline="middle">ID</text>

  <rect x="120" y="0"  width="120" height="40" fill="#eeeeee" stroke="#333" />
  <text x="180" y="20" class="cell-text header" text-anchor="middle" dominant-baseline="middle">商品名</text>

  <rect x="240" y="0"  width="120" height="40" fill="#eeeeee" stroke="#333" />
  <text x="300" y="20" class="cell-text header" text-anchor="middle" dominant-baseline="middle">数量</text>

  <rect x="360" y="0"  width="140" height="40" fill="#eeeeee" stroke="#333" />
  <text x="430" y="20" class="cell-text header" text-anchor="middle" dominant-baseline="middle">商品名</text>

  <!-- row1 -->
  <rect x="0"   y="40" width="120" height="40" fill="white" stroke="#333" />
  <text x="60"  y="60" class="cell-text" text-anchor="middle" dominant-baseline="middle">001</text>

  <rect x="120" y="40" width="120" height="40" fill="white" stroke="#333" />
  <text x="180" y="60" class="cell-text" text-anchor="middle" dominant-baseline="middle">リンゴ</text>

  <rect x="240" y="40" width="120" height="40" fill="white" stroke="#333" />
  <text x="300" y="60" class="cell-text" text-anchor="middle" dominant-baseline="middle">10</text>

  <rect x="360" y="40" width="140" height="40" fill="white" stroke="#333" />
  <text x="430" y="60" class="cell-text" text-anchor="middle" dominant-baseline="middle">1,000</text>

  <!-- row2 -->
  <rect x="0"   y="80" width="120" height="40" fill="white" stroke="#333" />
  <text x="60"  y="100" class="cell-text" text-anchor="middle" dominant-baseline="middle">002</text>

  <rect x="120" y="80" width="120" height="40" fill="white" stroke="#333" />
  <text x="180" y="100" class="cell-text" text-anchor="middle" dominant-baseline="middle">みかん</text>

  <rect x="240" y="80" width="120" height="40" fill="white" stroke="#333" />
  <text x="300" y="100" class="cell-text" text-anchor="middle" dominant-baseline="middle">5</text>

  <rect x="360" y="80" width="140" height="40" fill="white" stroke="#333" />
  <text x="430" y="100" class="cell-text" text-anchor="middle" dominant-baseline="middle">500</text>
</svg>

これをWebアプリのHTMLに埋め込んで、ブラウザ機能を使って印刷なりPDF化なりをしようということです。
image.png

ただ文字が長いと、

  <rect x="120" y="40" width="120" height="40" fill="white" stroke="#333" />
  <text x="180" y="60" class="cell-text" text-anchor="middle" dominant-baseline="middle">
  リンゴ。リンゴ。リンゴ。リンゴ。
  </text>

このように対応するrecttext(リンゴ。リンゴ。、、、)がはみ出してしまうので、JavaScriptでtext要素の文字列に対して改行やフォント縮小によるケアが要るのです。
image.png

Figma&SVG&PHPパターンの記事にある膨大な手順を経ても、連票(複数ページのPDF)生成には対応していませんでした。(記事の時点では。)

また、大多数の方にとってはFigma&SVG&PHPパターンで問題ないでしょうが、過去の私にとっては以下がネックでした。

  • Figmaの業務利用が大変
    • 社内で検討した他SaaSの例を見ると許可自体が大変
    • アカウントの払い出しなどの運用負荷や、利用者のデータガバナンスのチェックが大変
      (↑ 情シスである自分の仕事)
  • Pleasanterで処理したいのでJavaScriptだけで作る必要があり、PHPやNode.jsは使えない
    (開発を始めたてで知識がないのもあり、そう思った)

PowerPoint&SVG&Pleasanterパターン

Pleasanterとしては@implem-shinodaさんが、PowerPointで作成したテンプレートを組み合わせた帳票印刷を紹介されています。

引用先にあるパートナー企業様のソリューションももちろん選択肢のひとつですが、私はまだその段階ではありませんので、有料ソリューションは検討対象外です。

こちらの方法では
PowerPointでデザインを作成
→ SVGでテンプレをエクスポート
→ JSで、実数値と置換し、HTML上に描画※
→ ブラウザの印刷機能でPDFとして保存
という流れです。

Figmaパターンを再掲(★の行がなくなる)

Figmaでデザインを作成
→ SVGでテンプレをエクスポート
→ ★PHPでSVG内の%顧客名%のような置換タグを修正、
 実数値と置換したSVGを作成(し、枠をはみ出す文字や左右中央揃えを調整)
→ JSでHTML上に描画
→ ブラウザの印刷機能でPDFとして保存

PowerPointの仕様で%果物%などのプレースホルダーが、

<text>%</text><text>果物</text><text>%</text> 

のように別のtext要素として出力されるため、PHPパターンとは別の理由で置換タグの修正が必要です。

そのため「ClassA」などのPleasanter項目名そのままの文字列をプレースホルダーとして使っています。
逆にこの仕様のおかげでPHPを使っていた置換タグを修正する部分が不要になりました。

※検証や紹介目的だと思いますので、JSでの文字列の調整まではしていませんでした。
※また、Figma同様、連票も対応していません。

ですが過去の私にとっては、標準ツールのPowerPointとPleasanter標準のJSだけで対応できる点がGoodでした。
早速自分も実装&改造!とやってみたのが半年ほど前のことです。

PowerPoint&SVG&Pleasanterパターン(改)

私が作ったものは泥臭いですが簡単で、PowerPointから出力したSVG要素の中から<text>とそれを囲む四角形<rect>のペアを探し、文字数 * fontサイズがはみ出すなら処理する(DescriptionXXなら改行、それ以外はfont縮小)というものです。
image.png

PowerPointでSVGを作る観点ではもう一つ悲しい仕様として、表オブジェクト作成した四角形は<rect>ではなく文字とセットで<table>になる、というものがあります。

つまり前述の果物の表を描いたら以下のようになると、後から気づいたんです。
これでは「<text>とそれを囲む四角形<rect>のペアを探すプログラム」が使えません。。
image.png

結局改修をする時間と技術がなく、今では以下のような気合と根性のテンプレート作成/修正を利用者の方にお願いしています(極悪)
表オブジェクト禁止ということは四角オブジェクトで表を作る必要があるので、エクセル方眼紙の何倍も凶悪です。

ズレの調整は神経を使いますし、明細となる子テーブルとの連携には通し番号が必要です。。(末尾の-0xで横列をそろえている。)
( ↓ PowerPointをDraw.ioで再現した図 ↓ )
image.png

Pleasanter&pdfmeパターン

上記のようなひどい状況を改善するために、pdfme1というOSSのPDFデザイン&生成ツールを組み合わせました!

これによってPleasanter利用者は、帳票のデザイン → 実数値の入力 → 帳票の生成(印刷/PDF化)、の流れを特定のサイトパッケージ内で完結させることが可能です。
四角形での表を作成する必要も、プレースホルダー関連で置換タグを修正する必要もありません!
動的に明細行が増えるうえに、自動的な改ページもしてくれます!

pdfme、最高です。。😭

Pleasanter&pdfmeパターンで出来ること

ようやくですが、どんなものに仕上がったのかご紹介します。

①帳票のデザイン

  • PowerPointやFigmaのような、UIでの帳票デザインを作成
  • 実数値の置換先となるプレースホルダー、明細が入るテーブルなどの設定
  • テンプレートの出力

②実数値の入力

  • Pleasanter画面で帳票に書き込む実数値を入力
    (手動、CSVインポート、スクリプトなど使い慣れた方式で。)
  • 明細は子テーブルをリンクすることで個数制限を緩和(というか制限が無い)

③帳票の生成(印刷/PDF化)

  • 事前設定済みのテンプレートとPleasanter入力済み情報から帳票PDFを作成
    (しかも印刷ボタンを押すだけ!)

(補足)簡易構成図

  • テンプレート(JSON)やデザインUIに触れるのは管理担当のみ
  • 実務担当はPleasanterにデータを書いて出力ボタン

地味にうれしい点としてPleasanter、pdfme用サーバーどちらもセルフホストしていますので、完全な内部構成にすることができました。
ただしAPI及びデザインUI用に別の実行環境が必要になる点がもったいないところですね!

おわりに

Pleasanterの子テーブルが勝手に明細に入るこのシステム、結構使いどころがありそうじゃないですか?
事前に記事を公開してくださっていたお二方の苦労を知り、自分も手を動かしたから美化されているだけかもしれません🤣

今回は時間が足りずに説明だけになってしまいましたが、再現できるような構築手順の記事を作成しますので是非お待ちください!
pdfmeにはクラウドですぐに触れるサンプルUI2もありますので、この記事を読んだ方は一度試してみるのはいかがでしょうか。

✍️ この記事が参考になったらいいねや保存をお願いします。

追記:後半追加

前編Qiitaの簡単な修正と、後編の公開を実施しました!

image.png

  1. https://pdfme.com

  2. https://pdfme.com/ja/template-design

27
8
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
27
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?