CTS-KB
情シス・社内IT📚 シリーズ 8/10

ActiveReports → Playwright + Scriban 移行 — 帳票エンジンを HTML/CSS とヘッドレス Chromium に置き換える

⏱ 約 18 分で読めます
#脱Microsoft#ActiveReports#Playwright#Scriban#帳票#PDF#バーコード#QRコード#ZXing#.NET#印刷#情シス

🎯 はじめに:この記事のスコープ

シリーズ「脱Microsoft・OSS移行」は、ここまで ハードウェア → OS → 開発環境 → データ層 → Microsoft 365 → Google Workspace → リモート開発 と積み上げてきました。第 8 回は、第 1 回で 「移行の最大ブロッカー」 と書いた ActiveReports の置換です。

読み進めやすい順番では後半に置いていますが、移行プロジェクトとしては Phase 1 です。帳票が Windows + Visual Studio のままでは、Linux 開発機に移っても出荷業務が止まります。

本記事の扱う範囲隣接領域
本記事(第 8 回)A4 納品書・ピッキングリストを Scriban HTML + Playwright Chromium の PDF に置換 / Code128・日本語 QR をサーバー側 SVG で埋め込み / 用紙超過の描画前拒否 / Windows 印刷エージェントの claim・submitted・要確認 / ラベルプリンターは PDF にせず SBPL運送会社の送り状 API・配送ラベル規格、実紙のミシン目合わせ、適格請求書の税計算

💡 Playwright は Microsoft 製 OSS です。 本シリーズの「脱Microsoft」は、Windows / Visual Studio / 商用帳票の ライセンス連鎖を切る話であって、Apache 2.0 の Playwright や .NET ランタイムまで捨てる話ではありません。帳票の描画エンジンとして Chromium を使う判断と、IDE のサブスクを払い続ける判断は別物です。


🚫 なぜ ActiveReports が移行の最大ブロッカーなのか

第 1 回で書いた 4 つの値上げのうち、帳票だけが 「OS を変えると業務が止まる」 種類のロックインです。今回 CTS が切った直接の理由は、次の 3 点です。

1. .NET を上げるたびに、高額なバージョンアップ費用が乗る

ActiveReports は 特定の .NET バージョン専用に組まれています。.NET 8 → 9 → 10 とランタイムを追うたびに、帳票エンジンも対応版へ買い直す必要があります。Microsoft が .NET を年次リリースに変えた結果、帳票側の更新サイクルも引きずられて短くなり、事実上の毎年課金になります。

アプリ本体は SDK を入れれば上がる。帳票だけが、そのたびに見積と発注を要求する。この非対称が、少数精鋭では特に効きます。

2. 1 ライセンス = 1 PC が、人数より先に重荷になる

ライセンスは PC 単位です。開発機、印刷用の Windows、予備ノート、検証用のもう 1 台、と増えるたびに 1 本ずつ必要になります。社員数ではなく 触る機械の台数で課金されるため、デュアルブートやリモート開発(第 7 回)を始めると、すぐ台数が膨らみます。Linux 側の VS Code には載せられず、Windows に戻って設計器を開く、その Windows にもライセンスが要る、という循環です。

3. ソースを共有すると、ActiveReports のファイルだけ宙に浮く

RDLX は Git に入ります。ただし開けるのは ライセンスの入ったその PC の Visual Studio 設計器だけです。ライセンスのないマシン、Linux、Dev Container、AI エージェントの作業用クローンでは、ファイルはあるのにプレビューも編集もできません。共有リポジトリの中で、帳票定義だけが 誰も触れない遺物になります。

HTML/CSS のテンプレートなら、ブラウザかエディタで開いて差分が読めます。RDLX は「リポジトリにはあるが、設計器のある席に座らないと存在しない」状態です。ソース共有・レビュー・引き継ぎが前提の今の開発では、ここが決定的に合いません。

制約現場で起きること
.NET 更新 × 高額バージョンアップ8 → 9 → 10 のたびに帳票エンジンも再購入。アプリは追えるが帳票だけ見積が要る
1 ライセンス = 1 PC開発機・印刷機・予備機がそれぞれ 1 本。人数より台数で膨らむ
共有ソースで RDLX が宙に浮くGit にはあるが、ライセンス PC の設計器以外では開けない
Windows + Visual Studio 前提設計器もランタイム印刷も Windows。Linux 側だけで納品書を出せない
RDLX + VB 式紙面定義が専用 XML。CSS の mm 指定のように「ブラウザで開いて直す」ができない
プレビューと無人印刷が同一ランタイムWPF の自動印刷も ActiveReports 依存。エンジンを残したまま UI だけ差し替えると二重投資になる

⚠️ 「帳票だけ Windows に残す」は安全網に見えて、毎日の出荷を Windows に釘付けにします。 デュアルブートは e-Tax や周辺機器の退避先としては有効ですが、10 分間隔の無人印刷まで Windows に残すと、Linux 移行の効果が出ません。ブロッカーから潰す理由はここにあります。

代替候補は一通り見たうえで、次の結論にしています。

候補見送り理由
QuestPDF / PdfSharp紙面が C# になる。RDLX の mm 座標を再現する作業がコードレビューに乗りにくい
wkhtmltopdfメンテが止まっている。古い WebKit では日本語フォントと CSS ページサイズが安定しない
Puppeteer実体は Node。CTS-EC の帳票処理は .NET 10 なので、ランタイムを増やしたくない
FastReport 等の別商用エンジンロックインの形が似る。Linux 対応があってもライセンス再購入サイクルは残る
採用: Scriban + Playwright ChromiumHTML/CSS で mm 指定できる。Linux / Windows 同じ Chromium。C# から直接呼べる

ラベルプリンター(SATO Petit lapin 等)は PDF に寄せません。 203 dpi の感熱紙は CSS ページでは再現しにくく、既存資産は SBPL です。A4 とラベルを一つの描画エンジンに統一しない、が本記事のもう一つの結論です。


✅ 結論:HTML を組んで Chromium で刷る、ラベルは印字言語のまま

✅ 結論:HTML を組んで Chromium で刷る、ラベルは印字言語のまま

Windows 印刷エージェント

ラベル

A4 帳票

入力

windowsQueue

satoSbpl

帳票ジョブ DTOテナント / 拠点 / 発行 ID

Scribanレビュー済みテンプレート

HTML + CSS mm + SVG

Playwright ChromiumJS 無効 / 外部通信遮断

印刷品質 PDF

.NET で SBPL 生成

SATO PW208 / PT208

claim リース

ローカル印刷履歴

方式ルーターフォールバック禁止

Windows スプーラー

到達点は次の 5 つです。

  1. 帳票データはテナント・拠点付きの DTO。 テンプレート側が文書から拠点を推測しない
  2. HTML はレビュー済みテンプレートだけ。 利用者が Scriban を投稿して実行する API は持たない
  3. PDF はヘッドレス Chromium。 JavaScript 無効、外部リソース遮断、フォント読み込み完了後に寸法検査
  4. バーコードはサーバー側 SVG。 ページ内 JS で描かない
  5. 印刷送信と紙の排出は別状態。 スプーラー受理を「印刷完了」にしない

共通納品書(新規テンプレート)は 12 明細で改ページする A4 横です。架空データ、2 ページ。

Scriban + Playwright で生成した共通納品書。A4横、出荷番号の Code128、12明細で改ページする新規テンプレート

先行テナント向けに移植した受注票兼納品書は、旧 RDLX の座標・条件表示を HTML に移したものです。7 商品で改ページ、加工指示 QR、包装・入金待ちなどの条件欄を維持しています。架空データ、A4 横 3 ページ。

旧 ActiveReports 帳票を Scriban に移植した発払用受注票兼納品書。棚番・包装・入金待ち・加工作業 QR を含む


🧱 プロジェクト分割:ブラウザを知らない契約から始める

帳票処理は「PDF を出すライブラリ」ではなく、端末・API・プレビューが同じ DTO を共有する層として切り出しています。

層役割依存しないもの
Contractsテナント・拠点・発行 ID・明細の DTOブラウザ、テンプレート、プリンター
Reportingテンプレート選択、HTML エンコード、Code128、改ページ、PDF、印刷履歴運送会社 API、Windows キュー名
Legacy 移植旧 JSON の比較用変換と、固定 3 レイアウトの組み込み Scriban実行時の VB / 任意テンプレート
Sato感熱ラベル・サーマル帳票の SBPLChromium
Agentclaim 済みジョブの照合、ローカル履歴、方式別ディスパッチサーバーから届く生 SBPL / IP / キュー名
Agent.HttpHTTPS で claim / submitted / review-requiredWindows キュー名、プリンター資格情報
Cli架空サンプル、ブラウザ導入、PDF、比較用 JSON本番認証

📌 公開 API の確定契約ではありません。 ローカル検証とエージェント実装のための入力形式です。CLR の型名や任意 JSON を復元せず、許可したスキーマ(共通帳票 / 固定レイアウト)だけを読みます。System.Text.Json は未マップメンバーを拒否します。

拠点設定(TenantReportSettings)は 呼出側が渡します。 文書の店名や住所からテンプレートを推測すると、別テナントの紙面が混ざる事故が起きます。ログイン拠点と DTO のテナント・拠点が一致しない場合は描画せず拒否します。


📝 Scriban:mm で紙面を書き、データは必ずエンコードする

テンプレートはアセンブリの埋め込みリソースです。一般利用者が任意の Scriban を実行する口はありません。レンダラー側では次を固定しています。

  • StrictVariables = true(未定義変数で失敗)
  • EnableRelaxedMemberAccess = false
  • ループ上限・再帰上限
  • データ文字列は WebUtility.HtmlEncode
  • 文字数・数量・単価の上限

紙面は CSS の mm 指定です。A4 横なら @page { size: 297mm 210mm; margin: 0; } と .page { width: 297mm; height: 210mm; } を一致させ、Playwright 側も同じ mm を渡します。

<!doctype html>
<html lang="ja"><head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
  content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:; base-uri 'none'; form-action 'none'">
<style>
@page { size: 297mm 210mm; margin: 0; }
.page { width: 297mm; height: 210mm; overflow: hidden; break-after: page; }
body { color: #000; font: 10pt/1.4 'Noto Sans CJK JP','Yu Gothic','Meiryo',sans-serif; }
</style>
</head><body>
{{ for page in pages }}
<section class="page">
  <!-- 宛名・明細・バーコード。値はホスト側で HTML エンコード済み -->
</section>
{{ end }}
</body></html>

CSP は default-src 'none' です。スタイルと data: 画像(SVG バーコード)以外は読みません。帳票 HTML に外部 CDN や Google Fonts を足すと、オフライン印刷とテナント隔離の両方を壊します。

💡 行間 1.4 は Windows の日本語フォント対策です。 Linux の Noto Sans CJK JP では収まっていた 12 明細が、Windows の游ゴシック系では備考付きで用紙を食みました。行間を上げて「Windows でも 12 明細が A4 に収まる」側に寄せています。見た目の密度より、環境差で溢れる事故を先に潰す判断です。


🖨 Playwright:描画エンジンであって、ブラウザアプリではない

PDF 化は Microsoft.Playwright(本実装は 1.62)の Chromium です。インストール済み Google Chrome を使う場合はチャネル chrome を指定できます。ポイントは「ブラウザを開く」ではなく 印刷メディアとして Chromium のレイアウトエンジンだけ借りることです。

await using var context = await browser.NewContextAsync(new()
{
    JavaScriptEnabled = false,
    ServiceWorkers = ServiceWorkerPolicy.Block,
    AcceptDownloads = false,
    Locale = "ja-JP",
    TimezoneId = "Asia/Tokyo"
});
await context.RouteAsync("**/*", route => route.AbortAsync());
await page.EmulateMediaAsync(new() { Media = Media.Print });
await page.SetContentAsync(html, new() { WaitUntil = WaitUntilState.Load });
設定意図
JavaScriptEnabled = false帳票内 JS でバーコードやトラッキングを動かさない
全ルート Abort外部画像・フォント・ビーコンを取らせない
EmulateMedia(Print)画面用 CSS ではなく印刷用でレイアウトする
PreferCSSPageSize@page の mm を優先する
余白 0テンプレート側の mm が正。Chromium 既定余白で紙面がずれるのを防ぐ

HTML を SetContent したあと、フォント読み込み完了を待ってから寸法検査します。検査に落ちた PDF は書きません。

await document.fonts.ready;
// [data-check-fit] の枠に対し、内容の scrollWidth / 高さが枠を超えていないか
// shrink 指定なら 6px 下限までフォントを詰める
// それでも収まらなければ field ID だけを返す(顧客文字列はエラーに出さない)

長い住所・商品名は「小さくなるまで描く」ではなく PDF 作成前に拒否します。旧 RDLX の ShrinkToFit 相当は 4.5pt(実装上の下限は px 換算で 6px 付近)まで縮小し、それでも溢れる値はジョブを失敗させます。黙って折り返して宛先が欠けるより、現場で直せる失敗のほうが安全です。

Linux 検証では Noto Sans CJK JP、Windows 検証では游ゴシック / メイリオ系です。Windows の MS PGothic 太字では「納品書」3 文字が幅 13mm に収まらず 2 行に折り返したため、見出し幅を 14mm に広げて 12pt 太字と位置は維持しました。座標を全部動かすのではなく、溢れた枠だけを 1mm 広げるのが移植の基本です。


📊 バーコードはページ内 JS ではなく、サーバー側 SVG

用語集の構想段階では JsBarcode を例に出していましたが、実装は ZXing.Net でビット行列を作り、SVG の <rect> にする方式です。JavaScript を無効にしている以上、クライアント側バーコードは選べません。

種類用途実装上の約束
Code128社内出荷番号数字のみ。桁数が偶数ならコードセット C、奇数なら値を変えず混合
QR加工指示などの日本語自由文Shift_JIS(旧帳票の Encoding=932)、誤り訂正 M、余白 4 モジュール

共通納品書の出荷番号は英数字・ピリオド・ハイフン 1〜24 文字、固定レイアウト側の出荷番号は数字、という差があります。どちらも運送会社の送り状バーコードではありません。 配送ラベル規格は未実装で、ここにヤマトの送り状イメージを足すと誤出荷の原因になります。

旧 RDLX の DistributeAllLines(文字列を枠幅へ均等配置)は、Chromium では効きません。バーコード下の出荷番号は、各桁をバーコードと同じ 38mm 幅へ CSS で均等配置して再現しています。

バーコード下の出荷番号を、枠幅 38mm へ各桁均等配置した例

復号テストでは、生成 SVG を読み戻して元の数字・日本語・改行と一致することを見ています。これは 画像一致や実機スキャナの保証ではありません。 QR の実機読取は残作業です。


📐 印刷品質:座標は維持し、線の持ち方をブラウザ向けに直す

RDLX を HTML に移すと、最初に崩れるのは文字より 罫線です。隣り合う枠がそれぞれ内側に線を描くと、共有境界だけが二重幅になります。

対応は次の 3 点です。

  1. 線幅を縦横とも 1 CSS px(0.75pt) に統一する
  2. 枠の境界を中心に描き、同じ位置に重ねる
  3. 共有線は 片方の欄だけが描く(支払情報の「店名」と「支払方法」など)

Windows Chromium で生成した PDF を 300 dpi で画像化すると、変更前に 6〜7 px あった二重線は 3〜4 px になりました。端数画素の 1px 差は含みます。ネコポス/発払/コレクトの右側欄は、同じ範囲を 300 dpi で比較して画素差 0 まで揃えました。

その他、ブラウザ移植で踏んだ差分です。

現象対応
COD の印刷日欄が幅 2mm他 2 帳票と同じ位置・28mm に修正(元の欠陥)
単価見出しの右端が明細列からずれる後から描く白背景に隠れないよう、見出しを先に描く
本文・挨拶文が薄い純黒に統一。Canon 実紙でも「黒くなった」ことを確認
Fields!!ShipmentId の誤記移植時に修正。旧式を再現しない
実運用では未使用だったネコポス原紙に包装欄がないSaaS では後期の発払・コレクトと同じ右側欄を正とする

⚠️ 移したのは受注票兼納品書の紙面です。 送り状の運送会社バーコード・仕分コード・発送データ発行は別工程です。左側の大きな余白を「新しい配送ラベルの実装済み領域」とは扱いません。

RDLX からの取り込みは、座標・表示条件を読み、許可した式だけを C# の固定処理へ対応付けるスクリプトにしています。未知の式・項目は変換を止めます。実行時に VB も、利用者が入力したテンプレートも評価しません。


🖥 印刷エージェント:取得しただけで印刷完了にしない

旧 WPF は 10 分間隔で発払・コレクトを取りに行き、その Windows 端末のキュー名へ ActiveReports を送っていました。キュー名は端末ローカルの値で、スマホの SATO IP とは混ぜられません。

新しいエージェントが引き継ぐのは「Windows 常駐・自動取得・ドライバー送信」という 役割だけです。ActiveReports は使わず、PDF をスプーラーへ渡します。ラベル用 SBPL は同じジョブ契約の別ディスパッチャーへ渡し、PDF をラベル用紙へ送るフォールバックは禁止です。

🖥 印刷エージェント:取得しただけで印刷完了にしないスプーラー / SATOローカル履歴Windows エージェントCTS-ECスプーラー / SATOローカル履歴Windows エージェントCTS-ECalt[設定版・印刷先が不一致][一致]GET 端末設定版POST /api/report-jobs/claimジョブ + リース + 印刷先 IDPOST review-requiredPending を保存PDF または SBPLPOST submitted
状態意味意味しないこと
claim短いリースで 1 件を確保印刷成功
submittedスプーラーまたは SATO 送信口が受理用紙排出・配送完了
review-required送信前失敗、結果不明、設定版不一致自動再送してよい
再発行権限付き管理画面が新しいジョブ ID を作るローカル履歴を消して同じ ID を再送

HTTP 本文に Windows キュー名、プリンター IP、TCP ポート、資格情報、任意 SBPL を入れません。 サーバーが返すのは不透明な印刷先 ID です。実キュー名への解決は、その Windows PC のローカル設定だけが行います。接続は HTTPS 必須です。

旧自動印刷には、取得引数 code ではなくプロセス全体の可変値でテンプレートを選ぶ経路があり、手動操作のあとで発払データにコレクト紙面が載る余地がありました。新方式はサーバーが各ジョブのスキーマとレイアウトを指定し、共有の可変コードを使いません。

ローカルの印刷履歴は、再起動後の重複送信を防ぎます。複数 PC の排他にはなりません。 排他の正本は claim リースとサーバー状態です。期限切れの claim は再送待ちへ戻さず、要確認へ移します。


🏷 サーマル印刷は「PDF の縮小」ではない

SATO Petit lapin(検証機種は PW208 W-LAN、203 dpi)向けは、共通 DTO から SBPL を組み立てます。Chromium は使いません。

帳票扱い
感熱ラベル各業務の旧座標を維持。チェックデジットを確認。未対応文字の黙った ? 置換はしない
追跡番号付きラベル差出人を明示データで渡す。追跡番号は発行済み値を受け取るだけで、採番しない
サーマル納品書新レイアウト候補。旧実装が単一商品前提で明細を上書きしていた制限は継承しない

方式ルーターは、登録したディスパッチャーにだけジョブを渡します。PDF 用キューへ SBPL を流す、ラベル機へ PDF を流す、未登録方式へ落とす、はいずれもオペレーターが見るべき失敗です。

📌 実機への送信と用紙原点の受入は未完了です。 SBPL 生成・非同期 Status3・ACK / ページ完了のテストダブルは通していますが、PW208 への実送信は別工程です。旧コードとのバイト比較成功を、配送に使える判定とはしません。


🧪 検証:何を見て、何を見ていないか

2026-09-10 時点の Linux 検証では、帳票テスト 78 件が成功しています(ブラウザーを使う PDF 生成・紙面超過を含む)。Windows では Chromium / Chrome の両方で、共通納品書 2 ページ、固定 3 帳票は各 3 ページの A4 横を確認しました。Canon LBP621C へ Linux CUPS から PDF を送り、挨拶文の濃度を実紙で確認しています。

見ていること見ていないこと
テナント/拠点不一致の拒否現行 ActiveReports 紙との重ね合わせ
HTML 混入のエンコード実紙のミシン目・プリンター倍率
改ページ(12 明細 / 7 商品)運送会社バーコードの規格適合
Code128 / QR の復号実機スキャナでの読取
用紙超過の描画前拒否Windows ドライバーからの本番自動印刷
再起動後の重複送信抑止複数端末をまたぐ排他の実運用
方式誤配線の拒否税・送料・値引き・適格請求書

単価のない行がある場合、全明細金額は出しません。送料・値引き・税率別計算は未移植です。「PDF が綺麗に出た」と「請求書として正しい」は分けて扱います。


⚠️ 残作業と、切替前に必要な受入

エンジン置換はここまで来ています。現行紙への切替条件にはまだ足りません。

  1. 現行 ActiveReports 出力との重ね合わせ(長い住所、複数口、セット品、代引、日本語 QR)
  2. 使用プリンターの余白・倍率、ミシン目への位置合わせ
  3. 運送会社の送り状発行 API・配送ラベル
  4. サーバー側の印刷履歴正本、許可付き再印刷、複数端末排他の通し受入
  5. QR / Code128 の実機読取
  6. Windows ドライバー実送信と PW208 の原点

手元の新規サンプル PDF の成功だけで切り替えない、が受入の一文です。デュアルブートで Windows を残しているのは、この受入が終わるまでの安全網でもあります。


✅ 第 8 回まとめ

  • ActiveReports を切った直接の理由は .NET 8 → 9 → 10 のたびに発生する高額バージョンアップ、1 ライセンス = 1 PC、共有ソースで RDLX だけが宙に浮くことの 3 点。Windows + Visual Studio 前提と重なり、Linux 移行の最大ブロッカーになる
  • 代替は「別の帳票ベンダー」ではなく Scriban で HTML を組み、Playwright Chromium で PDF にすること。ラベルは PDF にせず SBPL のまま出す
  • テンプレートはレビュー済みの組み込みに限定し、データは HTML エンコード、Chromium は JS 無効・外部通信遮断
  • 用紙に収まらない文字は縮小の末に 描画前拒否。黙って欠けるより失敗させる
  • バーコードは ZXing のサーバー側 SVG。ページ内 JS に依存しない
  • 印刷エージェントは claim / submitted / 要確認を分け、スプーラー受理を紙の排出にしない。方式のフォールバックは禁止
  • 旧 RDLX の受注票兼納品書は座標・条件表示を移植済み。送り状・実紙合わせ・税計算は残作業

これでシリーズの Phase 1(帳票エンジン)は、Linux 上で PDF を再現できるところまで来ました。Windows を残している理由は「まだ ActiveReports が必要だから」から、「実紙と配送ラベルの受入が残っているから」に変わっています。

次回「Mac / Windows をリモートビルド機にする — Ubuntu から SSH で出て MAUI・WPF を確認する」では、Ubuntu を正本にしたまま Mac と Windows 11 へ SSH で出て、iOS シミュレーターと WPF のビルドを回す接続手順を書きます。第 10 回(公開予定)「コスト削減効果と 1 年運用レビュー」では、ライセンス削減の実績と、本シリーズ全体の運用上のハマりどころをまとめます。帳票の実紙切替コストも、そこで初めて数字になります。


📚 シリーズ記事

回タイトル主題
1総論:脱Microsoft・OSS移行動機・コスト・全体地図
2Windows 11 + Ubuntu デュアルブート構築M.2 物理分離・KDE Plasma・GRUB
3Ubuntu PC セットアップNVIDIA・サスペンド・Howdy・プリンター
4Ubuntu 開発環境セットアップDocker Engine ネイティブ・DevContainer・Claude Code
5Ubuntu データ共有セットアップrclone Drive + systemd・QNAP NFS/SMB・Obsidian・AppArmor
6Microsoft 365 → Google Workspace 全面移行メール・SSO・MFA・MX 切替・OneDrive → Drive
7Ubuntu リモート開発セットアップTailscale + SSH + VS Code Remote / DevContainer・Wayland ホスト
8ActiveReports → Playwright + Scriban 移行(本記事)帳票エンジン置換・バーコード・印刷品質 PDF
9Mac / Windows をリモートビルド機にするUbuntu から SSH で出る・Windows OpenSSH Server・ローカル標準ユーザー・送信元限定の許可ルール
10コスト削減効果と 1 年運用レビュー(公開予定)実績ベースのコスト・運用上のハマりどころ

🔗 関連リソース

CTS-KB 内の関連記事

関連用語

  • ActiveReports — 置換対象の商用帳票ライブラリ
  • Scriban — 帳票 HTML を生成する .NET テンプレートエンジン
  • SBPL — ラベルプリンターの印字言語。A4 の PDF とは別経路
  • Playwright — ヘッドレス Chromium で印刷品質 PDF を出す
  • .NET MAUI — 検品端末。ラベル印刷は PDF とは別経路
  • Ubuntu / Linux — 帳票 CLI とテストを回している実行環境

外部リソース