帳票を作る
請求書や納品書のような帳票を、テンプレートとデータから BDF として作れます。テンプレートは、文字のところにタグ({{名前}})を書いた Excel のブック、Word の文書、PowerPoint のプレゼンテーション、入力欄のある PDF、pdfme のテンプレート、帳票の行をタグつきで書いたテキストファイルです。データは JSON・YAML・CSV・Excel のファイルで、bdf fill がタグをデータに置き換え(または入力欄を埋め)、組版して .bdf を書き出します。Office のファイルは書き出しません。できた帳票は bdf pdf で PDF にできます。タグ付き PDF と PDF/A も選べます。
bdf fill -data order.yaml -data items=lines.csv invoice.xlsx invoice.bdf
bdf pdf invoice.bdf invoice.pdf
| テンプレート | 帳票の形 | 向いているもの |
|---|---|---|
Excel(.xlsx) |
ブックが印刷するページ。行が増えればページが増える | 表が中心の帳票、数式で計算する帳票、決まった行数の伝票 |
Word(.docx) |
文書のページ。長くなった分は次のページへ流れる | 文章と表の帳票、通知書、差し込みの手紙 |
PowerPoint(.pptx) |
スライド。図形は置いた場所から動かない | 位置が決まった帳票、証書、ラベル、1 件 1 枚の資料 |
PDF フォーム(.pdf) |
PDF のページ。入力欄の場所に値が入る | すでに PDF として配られている帳票。申請書、公的な様式 |
pdfme(.json) |
デザイナーで見えているページ。表はページをまたいで伸びる | pdfme のデザイナーを使い、ブラウザでレイアウトした帳票 |
テキスト(.txt) |
行と桁の格子に並べた文字。プリンタのテキストモードが印字するとおり | ドットインパクトの連帳・複写伝票、レシート、ほかのシステムに渡す固定長のテキスト |
タグの書き方とデータは、Office の 3 つの形式とテキストのテンプレートに共通です。同じデータを、形式の違うテンプレートに流し込めます。PDF フォームと pdfme のテンプレートにはタグの代わりにフィールドがあり、その名前で同じ形のデータを受け取ります。
インストールせずに試すなら、フォームのページにテンプレートをドロップしてください。タグを読んで入力フォームを作り、入力した値で穴埋めした帳票を表示して、PDF で保存できます。処理はすべてブラウザの中で行われ、ファイルはアップロードされません。
テンプレートを書く
普段どおりに帳票を作り、値を入れたいところにタグを書きます。まず Excel のブックで説明します。Word と PowerPoint は、同じタグが何を繰り返すかだけが違います(Word のテンプレート、PowerPoint のテンプレート)。
Excel では、用紙・余白・印刷範囲・印刷タイトル・改ページ・ヘッダーとフッターは、ブックのページ設定がそのまま使われます(Excel の印刷ビュー)。
| タグ | 意味 |
|---|---|
{{name}} |
値。{{customer.name}} は値の中の値、{{.}} は項目そのもの |
{{total | fmt:"#,##0"}} |
表示形式を付けた値。書式は Excel の表示形式コード(yyyy年m月d日、ggge年、0.0% …) |
{{#items}} … {{/items}} |
区間。リストなら項目ごとに繰り返し、それ以外なら値が真のときだけ出す |
{{^items}} … {{/items}} |
逆の区間。リストが空、または値が偽のときだけ出す |
{{%photo}} |
画像。Excel ではセル(結合セルならその範囲)に、Word と PowerPoint では置いてある画像の枠に収める。{{%photo | fit:cover}} で枠を覆う、fit:stretch で引き伸ばす |
{{%url | qr}}、{{%jan | barcode:jan}} |
値の QR コード、バーコード(QR コードとバーコード) |
{{%sign | signature}}、{{%seal | seal}} |
{{%photo}} と同じ画像。手書きのサインや印影のように、人が渡す方法が決まっているもの(サインと印影) |
- 波括弧・記号・引用符は、日本語入力や Word が置き換えた全角や曲がった引用符(
{{、#、“ ”)でもかまいません。 \{{と書くと、タグではなく文字の{{になります。- セルがタグ 1 つだけなら、値はそのままセルの値になります。数値は数値(セルの表示形式で表示され、数式から読める)、日付は日付です。文字列の
"2026-10-13"は、セルかタグの表示形式が日付のときだけ日付として読みます。 - ほかの文字と一緒に書いたタグは、文字に置き換わります(
{{customer}} 御中)。 - タグは名前を引くだけで、計算はしません。合計・税・繰越とその端数処理はデータの側で済ませてください(ブックの数式は別で、後述のとおり計算し直します)。
行を繰り返す
区間の開始と終了のタグを別々のセルに書くと、行の繰り返しになります。繰り返す行のセルからは、その項目の値が見えます。
行を増やす(開始と終了が同じ行): 項目ごとに行が 1 つ増え、下の行は押し下げられ、用紙に入らなければページが増えます。印刷タイトルの行は各ページで繰り返されます。
| A | B | C | D | E |
|---|---|---|---|---|
{{#items}}{{_index}} |
{{name}} |
{{qty}} |
{{price}}{{/items}} |
=C4*D4 |
| 合計 | =SUM(E4:E4) |
決まった行数に入れる(開始と終了が別の行): 開始のタグの行から終了のタグの行までが、項目を 1 つずつ入れる枠になります。行は増えず、項目のない行は罫線だけの空行として残ります。1 行目のタグと数式が、自分のタグを持たない残りの行にも使われます。項目が枠より多いとエラーになります。
| A | B | C |
|---|---|---|
{{#rows}}{{no}} |
{{name}} |
{{amount}} |
(10 行目){{/rows}} |
ページとして繰り返す(| pages): 開始から終了までの行のまとまりを項目ごとに複製し、それぞれを新しいページにします。10 行の伝票を 25 行分のデータで 3 枚にする、という帳票はこの形です。データは、ページごとの行と繰越をあらかじめ分けて渡します。
{ "pages": [
{ "rows": [ … 10 行 … ], "carry_in": 0, "carry_out": 55000 },
{ "rows": [ … 10 行 … ], "carry_in": 55000, "carry_out": 210000 },
{ "rows": [ … 4 行 … ], "carry_in": 210000, "carry_out": 300000 } ],
"total": 300000 }
{{#pages | pages}} … {{/pages}} の中に {{#rows}} … {{/rows}} の枠を置きます。ページ番号は {{_page}} / {{_pages}}、最後のページだけに出す合計は {{#_last}}合計 {{total}}{{/_last}} と書けます。
{{#groups | rows}} と書けば、別の行にまたがるまとまりを、行を増やしながら繰り返します(グループの見出し・明細・小計)。区間は入れ子にできます。
開始と終了のタグを同じセルに書いた区間は、セルの中の文字を繰り返します({{#tags}}{{.}} {{/tags}})。同じセルでも | rows を付ければ行の繰り返しになるので、1 列だけの表でも行を増やせます({{#items | rows}}{{name}}{{/items}})。繰り返し方を書いた区間は、文字ではなく行(Word では段落、PowerPoint ではスライドなど)を繰り返す、という規則は 3 つの形式に共通です。逆の区間にも書けます({{^items | rows}}明細なし{{/items}} は、項目がないときだけその行を出します)。
区間の中で使える変数
| 変数 | 意味 |
|---|---|
_index、_count |
何番目の項目か(1 から)、項目の数 |
_first、_last |
最初・最後の項目か |
_page、_pages |
` |
_blank、_blank_first |
枠の行で、項目のない行か、その最初の行か({{#_blank_first}}以下余白{{/_blank_first}}) |
_slide、_slides |
PowerPoint で、そのスライドの番号と、できあがったスライドの数 |
行に追随するもの
行が増えたり複製されたりすると、Excel で行を挿入したときと同じように、行を指しているものが付いてきます。結合セル、条件付き書式、リンク、印刷範囲と印刷タイトル、改ページ、図形、そして数式の参照です。複製された行の中の数式は自分の行(自分のページ)を指し、繰り返す行を含む範囲はすべての複製を含みます(=SUM(E4:E4) は全明細の合計になります)。
数式は穴埋めのあとで計算し直します。条件付き書式の評価器が知っている関数(四則、SUM、AVERAGE、COUNT、COUNTIF、IF、ROUND、文字列、日付 など)が対象で、それ以外の数式のセルは空にして警告を出します。
Excel の表見出しとセクションの改ページ
請求書では、Excel の「印刷タイトル」の「タイトル行」を表の見出しだけ
(例: $15:$15)にします。帳票タイトルや宛名はこの範囲に含めません。
通常の印刷タイトルは後続の全ページに繰り返されますが、「数式 → 名前の管理」で
次の名前をシートのスコープに定義すると、BDF の改ページを調整できます。
| 名前 | 参照範囲の例 | 動作 |
|---|---|---|
_bdf.Print_TitleScope |
'Invoice'!$A$15:$H$16 |
この表の明細が続くページだけに印刷タイトルを繰り返す。見出しと明細タグの行を含めると、項目数に合わせて範囲が伸びる。合計や備考だけのページには表見出しを付けない。 |
_bdf.Print_KeepTogether |
'Invoice'!$F$18:$H$20,'Invoice'!$A$22:$H$25,'Invoice'!$A$27:$H$31 |
各範囲の行を同じページにまとめ、残りの高さに入らなければ次のページへ送る。合計・振込先・備考などを別々の範囲で指定する。 |
範囲はテンプレートの行の増減に追従します。繰り返す項目の中に置いた範囲は 各項目に適用されます。重なった範囲は一つのまとまりになり、隣接するだけの 範囲は別々に扱います。1 ページより高いまとまりは分割でき、手動の改ページは 優先されます。この名前は BDF の出力を制御するもので、Excel 自体の印刷プレビューは Excel の規則に従います。公開している Excel の請求書サンプルには両方を設定済みです。
Word のテンプレート
Word の文書では、本文・表のセル・テキストボックス・ヘッダーとフッターの文字にタグを書きます。穴埋めのあと文書を組み直すので、値が長くなれば行が増え、表の行が増えれば次のページへ流れます。表の見出し行(「タイトル行の繰り返し」)は、流れた先のページでも繰り返されます。帳票はページのビューだけになります。
区間が繰り返すものは、開始と終了のタグを両方含むいちばん小さいまとまりで決まります。
| タグの位置 | 繰り返すもの |
|---|---|
| 同じ段落 | 段落の中の文字 |
| 本文(または同じセル、同じテキストボックス)の別々の段落 | 開始の段落から終了の段落までの、段落と表 |
| 表の同じ行の別々のセル | その行(項目ごとに行が増える) |
| 表の別々の行 | 開始の行から終了の行までが、項目を 1 つずつ入れる枠(| rows を付ければ、行を増やしながら繰り返す) |
- タグだけの段落(
{{#items}}や{{/items}}だけを書いた段落)は、帳票には出ません。 | rowsを付けた区間は、タグが同じ段落にあっても、表の中ならその行を、表の外ならその段落を繰り返します。箇条書きの 1 段落に{{#items | rows}}{{name}}{{/items}}と書けば、項目ごとの箇条書きになります。| pagesを付けた区間は、開始から終了までの段落と表を項目ごとに繰り返し、2 つ目からは新しいページで始めます。1 ページの帳票を人数分作る、10 行の伝票をページごとのデータで複数枚にする、という形です。- 画像は、文書に置いた画像の代替テキストに
{{%photo}}と書きます。その画像が、データの画像に置き換わります。代替テキストの残りの文字は、新しい画像の代替テキストになります。 - Word は、スペルチェックや編集の履歴でタグを途中で分けて保存します(
{{custo+mer}})。段落の中の文字はひと続きとして読むので、そのままで動きます。値の書式は、タグが始まる位置の文字の書式です。 - ヘッダーとフッター、区間の外のテキストボックスからは、データのいちばん外側の値が見えます。区間の中に置いたテキストボックスからは、その項目の値が見えます。脚注と文末脚注は穴埋めしません。
- ページ番号は Word のフィールド(
PAGE、NUMPAGES)をそのまま使えます。
PowerPoint のテンプレート
PowerPoint では、図形・テキストボックス・表のセルの文字にタグを書きます。スライドは固定のページで、図形は置いた場所から動きません。
| タグの位置 | 繰り返すもの |
|---|---|
| 同じ段落 | 段落の中の文字 |
| 同じ図形(または同じセル)の別々の段落 | 開始の段落から終了の段落まで |
| 表の同じ行の別々のセル | その行(項目ごとに行が増える) |
| 表の別々の行 | 開始の行から終了の行までが、項目を 1 つずつ入れる枠(| rows で行を増やす繰り返し) |
| 同じスライドの別々の図形 | そのスライド(項目ごとに 1 枚) |
| 別々のスライド | 開始のスライドから終了のスライドまで |
| rowsを付けた区間は、タグが同じ段落にあっても、表の中ならその行を、それ以外ならその段落を繰り返します。| pagesを付けた区間はスライドを繰り返します({{^items | pages}}は、項目がないときだけそのスライドを出します)。- 文字の収まりは、値を入れたあとで PowerPoint と同じ規則で決め直します。「はみ出す場合だけ自動調整」の図形は文字を縮め、「テキストに合わせて図形のサイズを調整」の図形は高さを変えます。図形どうしが押し合うことはありません。
- 行が増えた表がスライドに収まらなくなると、同じスライドを複製して続きを載せます。繰り返す行より上の行(見出し)は各スライドに、下の行(合計など)は最後のスライドに出ます。表は、下にある図形の上端か、スライドの下の余白までを使います。
- スライド番号は
{{_slide}} / {{_slides}}と書けます。繰り返しや表の続きで増えたスライドを含めた番号と枚数になります。 - 画像は、スライドに置いた画像の代替テキストに
{{%photo}}と書きます。 - PowerPoint も言語の切り替わりでタグを途中で分けて保存しますが、段落の中の文字はひと続きとして読みます。
PDF フォーム
入力欄のある PDF(AcroForm。Acrobat や LibreOffice、多くのフォーム作成ツールが作るもの)は、そのままテンプレートになります。入力欄の名前がデータの名前です。bdf fill は入力欄の場所に値を描き、PDF のページを BDF の文書として書き出します。できた帳票に入力欄は残りません。
bdf template schema -json-schema application.pdf # 入力欄を、データの JSON Schema として
bdf fill -data applicant.json application.pdf application.bdf
bdf pdf application.bdf filled.pdf
| 入力欄 | データ |
|---|---|
| テキスト | 文字列か数値。複数行の欄は欄の幅で折り返し、マス目の欄(comb)は 1 文字ずつマスに入れ、大きさが自動の欄は収まる大きさにする |
| チェックボックス | true か false |
| ラジオボタン | 選ぶボタンの値 |
| リスト、ドロップダウン | 選択肢の値。欄には、その選択肢の表示名が出る |
| 署名 | 画像(手書きのサインなど)。欄の箱の中央に、全体が収まるように描く(サインと印影) |
- 入力欄の名前が、データで値を引く名前です。
applicant.nameという欄は、オブジェクトapplicantのnameです(ドットを含む名前そのままでも渡せます)。 - スキーマには、PDF が欄について持っている情報が入ります。選択肢(
enum。表示名はx-bdf.labels)、最大の文字数(maxLength)、PDF に入っている値(default)、欄のツールチップ(タイトル)です。 - 文字は、欄が指定する大きさ・色・揃えで、その文字を持つマシンのフォントを使って描きます。フォームのフォントは欧文だけのことが多いので、日本語の値はそれに左右されません。
- データに値がない欄は、PDF にある状態のまま残り、警告が出ます(
-strictではエラー)。押しボタンは埋めません。 - 欄の枠線と背景は残ります。チェックボックスとラジオボタンは、PDF が持っているその状態の外観を使います。
pdfme のテンプレート
pdfme は、ブラウザで動くデザイナーを持つオープンソースの PDF 生成ライブラリです。そのデザイナーが保存するテンプレート(JSON のファイル。土台の PDF か白紙のページと、ミリ単位で場所を決めたフィールド)も、そのままテンプレートになります。pdfme の生成器と同じ規則で埋めます。
bdf fill -data invoice.json template.json invoice.bdf
bdf template compile template.json invoice.bdft # デザイナーで入れてあった内容のページになる
| pdfme のフィールド | データ |
|---|---|
text、select |
文字列か数値(select は選択肢の 1 つ) |
multiVariableText |
変数のオブジェクト。"customer": {"company": "…", "person": "…"} |
date、time、dateTime |
日付(2026-10-14、2026/10/14)、時刻(09:30)、またはその両方。フィールドの書式で描く(月や曜日の名前は英語と日本語) |
checkbox、radioGroup、circleMark |
true か false |
image、signature、svg |
ファイルのパスか data: URL(svg は SVG そのものでもよい) |
qrcode、ean13、ean8、code39、code128、nw7、itf14、upca |
コードの内容 |
table |
行の配列。行は、列の名前をキーにしたオブジェクトか、セルの配列 |
list |
文字列の配列(先頭にタブを置くと 1 段深くなる) |
- データは JSON の値で渡します。pdfme は表の行を JSON の文字列として受け取りますが、ここでは配列です。
- 白紙のページが土台のときは、表・リスト・伸びるテキスト(
overflow: expand)がデータに合わせて伸び、下にあるものを押し下げ、次のページへ続きます。表はテンプレートの指定(repeatHead)があれば列の見出しをページごとに繰り返し、土台のページの固定のフィールド(staticSchema)は全ページに出ます。PDF が土台のときは、フィールドは置いた場所のまま、番号の対応する PDF のページに載ります。 - 読み取り専用のテキストには式を書けます(
{price * 1.1}、{currentPage} / {totalPages})。四則演算、比較、? :、文字列・数値・配列のメソッド、Math、JSONが使えます。それ以外のコードは動きません。式が読むデータの名前はスキーマのフィールドになります。pdfme が時計から読むdateとdateTimeも同じ扱いなので、同じデータからは同じ帳票ができます。 - テンプレートが指定するフォントは、マシンのフォントから探します(
-font-dir)。指定がなければ pdfme の既定の Roboto です。マシンにないフォントは代わりのフォントで組みます。 - デザイナーでフィールドに入れてあった内容が、テンプレートのサンプルになります。
-sampleなしのbdf template compileはそれを見せ、フォームのページもそこから始まります。 - pdfme と違うところ: テキストの中の Markdown 風の書式は使えません。
japanpost、upce、gs1datamatrix、pdf417のコードは描かず、警告を出します。バーコードの下の文字は、バーの下に 1 行で置きます。QR コードは内容は同じですが、マスクの選び方が違うことがあります。SVG の画像は枠の中に全体を収めます(pdfme の生成器は一部を切り落とすことがあります)。 - 土台の PDF を URL で指定したテンプレートは読みに行きません。デザイナーが保存するとおり、テンプレートの中に入れてください。
テキストのテンプレート
テキストファイル(UTF-8)は、ドットインパクトプリンタが連続用紙や複写伝票に、レシートプリンタがロール紙に印字する帳票のテンプレートになります。行と桁の格子に文字を並べた帳票です。エディタで見えているものがそのまま帳票で、ファイルの 1 行がページの 1 行、1 文字が 1 桁、全角の文字(漢字、かな)は 2 桁です。ほかのテンプレートと同じタグとデータで穴埋めします。
---
cpi: 10 # 1 インチあたりの桁数
lpi: 6 # 1 インチあたりの行数
columns: 80 # 用紙の幅(桁)
lines: 33 # ページの長さ(行。0 はロール紙で、帳票の長さだけ伸びる)
margin: {left: 2, top: 1}
skip: 2 # ミシン目をまたいで空ける行数
---
{{#_big}}納品書{{/_big}} {{date | fmt:"yyyy年m月d日"}}
{{#preprinted}}得意先{{/preprinted}} {{customer | width:30}}{{#preprinted}}御中{{/preprinted}} No. {{no | right:8}}
{{#preprinted}}
┌──────────────────────┬──────┬────────────┐
│ 品名 │ 数量 │ 金額 │
{{/preprinted}}
{{#rows}}
│ {{name | width:20 | cut}} │ {{qty | right:4}} │ {{amount | fmt:"#,##0" | right:10}} │
│ │ │ │
│ │ │ │
{{/rows}}
bdf fill -data order.json slip.txt slip.bdf # 文書として: 表示、印刷、PDF に
bdf fill -data order.json slip.txt slip.txt # プレーンテキストとして: 行を並べ、ページは改ページ(FF)で区切る
bdf template compile -sample order.json slip.txt slip.bdft
前書き(--- の行で囲んだ YAML。なくてもよい)が格子を決めます。前書きがなければ、10 CPI・6 LPI の 80 桁 × 66 行(8 × 11 インチの連続用紙)です。
| キー | 意味 |
|---|---|
cpi、lpi |
1 インチあたりの桁数と行数。10・12・15・17.1・20 CPI、6・8 LPI(ESC/P のピッチ。ほかの値は警告) |
columns、lines |
用紙の大きさを桁と行で。余白を含む。lines: 0 はロール紙で、ページはその行の数だけの長さになる(レシート) |
margin: {left, top} |
各行の前に空ける桁数と、先頭の行の上に空ける行数 |
skip |
各ページの下に空ける行数(ミシン目スキップ) |
title |
帳票の先頭の行を、各ページの上に繰り返す(一覧の見出し) |
font |
ページを描く等幅フォント。ファミリー名(BIZ UDGothic)か、テンプレートの隣のフォントファイル(fonts/slip.ttf。ディレクトリは -files で変えられる) |
ambiguous |
東アジアの文字幅が「あいまい」な文字(罫線素片、○、※、ギリシャ文字)の桁数。narrow(1。既定。多くのエディタの表示と同じ)か wide(2) |
値は、その文字の桁数だけ場所を取り、後ろの文字を押します。桁数を書いた値はちょうどその桁数を取り、全角は 2 桁と数えます。{{name | width:20}} は 20 桁に左揃え、{{no | right:8}} は右揃え、{{title | center:30}} は中央揃えです。値が桁数を超えると、切らずに書いて警告を出します。| cut は切り、| wrap は残りを下の行の同じ桁に続けます({{address | width:30 | wrap}})。値の中の改行も、同じように次の行へ続けます。
タグだけの行。 行をまたぐ区間のタグだけの行は、帳票の行を占めません。ファイルの中の改ページ(FF)はページを改めます。
区間は、ファイルの行をブックの行とみなして、Excel と同じに繰り返します(行を繰り返す)。1 行の中の区間は文字を繰り返し({{#tags}}{{.}} {{/tags}})、行をまたぐ区間はタグの間の行に 1 行 1 項目ずつ入れます(枠。項目のない行は値なしでそのまま残り、タグのない枠の行は最初の行と同じになります)。{{#items | rows}} は項目ごとに行を繰り返し、ページが埋まると改ページして、title の行を各ページの上に置きます。{{#pages | pages}} は項目ごとに別のページで繰り返します。| rows の区間のない帳票はページに収まらなければなりません(折り返した値は下の行を押し下げ、ページの終わりを越えるとエラーです)。区間の変数はほかのテンプレートと同じです。
データを引かない区間が 3 つあります。
| 区間 | 意味 |
|---|---|
{{#preprinted}} … {{/preprinted}} |
用紙に印刷済みの罫線と項目名。役割 background のレイヤーに描くので、その用紙に刷るときは抜けます(プリンタの設定の SkipRoles)。行をまたいでも、1 行の中でも書ける |
{{#_wide}} … {{/_wide}} |
倍幅の文字。半角は 2 桁、全角は 4 桁 |
{{#_tall}} … {{/_tall}}、{{#_big}} … {{/_big}} |
倍高の文字と、倍角(幅と高さが倍)の文字。その行はページの 2 行を占め、文字は下の行のベースラインに立つ |
帳票は、用紙の大きさ(columns / cpi × lines / lpi インチ)のページの fixed View です。文字は等幅フォントでそれぞれの桁に描きます。BIZ UDゴシック(Google Fonts、SIL Open Font License)、次に IPAゴシック、Noto Sans Mono CJK JP、システムの等幅フォントの順に探し、どのフォントでも文字は格子からずれません。検索・コピー・タグ付き PDF のために、各行は段落、rows と枠の区間の行は表になります。
印字像。 文書は、格子と各行の文字を専用の Part(t: "text"、仕様 §4。JSON の形は Go の form/textpart パッケージが説明しています)にも持ちます。どの範囲がプレ印刷の用紙で、どの範囲が倍角かも入ります。ビューアはこの Part を読みません。プリンタのテキストモード(ドットインパクトの ESC/P、レシートプリンタの ESC/POS)はこれから印字し、bdf fill … out.txt もこれを書きます。
-param |
意味 |
|---|---|
encoding=shift_jis |
テキストの文字コード。utf-8(既定)、shift_jis(Windows-31J)、euc-jp、iso-2022-jp、ほか WHATWG Encoding Standard の名前。その文字コードにない文字は 〓 にして警告を出す |
newline=crlf |
行の終わりを LF の代わりに CR LF にする |
paper=preprinted |
プレ印刷の用紙の範囲を空白で書く |
印刷。 bdf print は、ESC/P のドットインパクトプリンタにはテキストモードで送ります。ピッチ・行送り・用紙長・ミシン目スキップはテンプレートのもので、文字はプリンタのフォントで(漢字は漢字モード)、-skip background でプレ印刷の用紙の範囲を刷りません。ESC/POS のレシートプリンタは -print-mode text で同じように刷ります。
bdf print -printer 'socket://192.168.0.20:9100?profile=vp-f2000' -skip background slip.bdf
bdf print -printer 'serial:///dev/ttyUSB0?profile=tm-t88' -print-mode text receipt.bdf
ambiguous: narrow のテンプレートの 1 桁の文字(罫線素片、○、※)を、ESC/P は半角の漢字で刷ります。レシートプリンタにはそれが無いので、罫線素片と × は 1 バイトの文字の表から刷り、ほかは警告を出して ? にします。○ や ※ を使うレシートは ambiguous: wide と書いてください。ESC/P には漢字を縦だけ 2 倍にする命令が無いので、_tall の漢字は普通の大きさで刷り、警告を出します。ESC/P は 10・12・15・17.1・20 CPI(漢字は 10〜15)、ESC/POS は 1 桁が 12 ドット以上になるピッチ(180 dpi と 203 dpi で 15 CPI まで)を刷れます。そう刷れない帳票は、警告を出してドットで刷ります(-print-mode text のときは誤り)。
テキストのテンプレートに画像、QR コード、バーコードは書けません(プリンタのテキストモードは文字を印字するため)。私用領域の文字(外字)と絵文字は、プリンタが持っていないので警告します。
QR コードとバーコード
画像のタグに qr か barcode:種類 を付けると、値を符号化したコードを画像の代わりに描きます。置く場所は画像と同じです。Excel ではタグを書いたセル(結合セルならその範囲)、Word と PowerPoint では代替テキストにタグを書いた画像の枠です。
| タグ | 描くもの |
|---|---|
{{%url | qr}} |
QR コード(モデル 2、バージョン 1〜40)。誤り訂正レベルは M。qr:L、qr:Q、qr:H で変える |
{{%jan | barcode:jan}} |
JAN / EAN-13。12 桁の値にはチェックデジットを付け、13 桁の値は確かめる。barcode:ean13 も同じ |
barcode:ean8、barcode:upca |
JAN / EAN-8(7 桁か 8 桁)、UPC-A(11 桁か 12 桁) |
barcode:code39 |
Code 39。数字、英大文字、空白、- . $ / + %。前後の * は自動で付く |
barcode:code128 |
Code 128。ASCII の文字。コードセット A・B・C は自動で選ぶ |
barcode:gs1-128 |
GS1-128。値は (01)04901234567894(10)ABC のように、AI を括弧で書く |
barcode:itf、barcode:itf14 |
ITF(数字。奇数桁なら先頭に 0 を足す)、ITF-14(13 桁ならチェックデジットを付ける) |
barcode:nw7 |
NW-7(Codabar)。数字と - $ : / . +。スタートとストップ(A〜D)を値に書かなければ A で挟む |
- コードは黒いベクターの輪郭で描きます。拡大しても、PDF にして印刷しても、にじみません。
- QR コードは枠の中央に、正方形のまま収まります。バーコードは数字も含めて枠に収まります。読み取り機が必要とする太さになるように、枠の大きさを決めてください(JAN の標準は幅 37.29 mm、0.8 倍から 2 倍まで)。
- コードの周りには、読み取りに必要な余白(クワイエットゾーン。QR コードは 4 モジュール、バーコードは左右に 10 モジュール)が付きます。枠の外に余白があるなら
quiet:0で外せます。quiet:2のようにモジュール数も書けます。 - 値は文字列か数値です。先頭が 0 のコード(
0490…)は、データで文字列として渡してください。 - 値がない(空か
null)ときは何も描きません。コードに入らない値(桁数の違う JAN、チェックデジットの誤り、使えない文字、大きすぎる QR コード)は、コードを描かずに警告を出します。-strictではエラーです。 - 支援技術と検索のために、コードには図としての代替テキストが付きます。Excel と、代替テキストがタグだけの画像では、コードの内容そのものです。
- JAN / EAN-13、EAN-8、UPC-A は、チェックデジットも含めた数字をバーの下に描きます。数字の輪郭は
image/barcodeに内蔵しているため、フォントや別の値タグは不要です。
フォームを使わず、同じ描画を直接生成することもできます。
symbol, err := barcode.Encode("jan", "490123456789", nil) // チェックデジットを補い 4901234567894 に
// err を確認してから、バーと数字を一緒に描きます。
drawing := symbol.Object(113, 36)
バーだけ描く場合は &barcode.Options{NoText: true} を渡します。Symbol.At と Symbol.Rects は、数字の描画とは独立して符号化されたモジュールだけを返します。
PDF にする
bdf pdf は、BDF の文書を PDF に書き出します。帳票に限らず、どの文書でも使えます。
bdf pdf invoice.bdf invoice.pdf
bdf pdf -skip background -skip master slip.bdf slip.pdf # 印刷済みの用紙に重ねて刷る
bdf pdf -tagged report.bdf report.pdf # タグ付き PDF
bdf pdf -pdfa 2a invoice.bdf invoice.pdf # 保存用の PDF/A
- 文字は文字のまま書き出します。文書のフォントを、使っているグリフだけにして埋め込むので、PDF の中で検索とコピーができます。名前で参照しているフォントは、書き出すマシンのフォントから埋め込みます(
-font-dir)。埋め込みが許可されていないフォントの文字は、文字のアウトラインとして描き、検索のための文字列を付けます。 - 図形・線・グラデーション・透明・ブレンド・ソフトマスクはベクタのまま、JPEG はそのまま、ほかの画像は画素として入ります。SVG の画像は 300 dpi の画像にします。リンクと文書情報(タイトル・作成者・日付)も入ります。
- ページのあるビュー(Excel の印刷ビュー、Word のページ、スライド)を書き出します。ページのない文書(表計算のシート、スクロールだけの文書)は、全体を 1 ページにします。
-viewでビューを選べます。 - 影(
SHADOW)は PDF に相当するものがないので、影だけを 300 dpi の半透明の画像にして、図形の下に敷きます。図形そのものはベクタのままです。 FILTERと Canvas 特有の合成(destination-outなど)は PDF に相当するものがないので、省くか通常の重ね描きにして警告を出します。暗号化は、まだ書き出しません。- 同じ文書からは、同じバイト列の PDF ができます。
タグ付き PDF と PDF/A
タグ付き PDF(-tagged)は、ページの見た目とは別に、文書の構造を持つ PDF です。どの文字が見出しで、どれが段落、箇条書きの項目、表のセルなのか、どの順に読むのか、図は何を表しているのかが入ります。スクリーンリーダーはこの構造をたどって読み上げ、PDF から文字を取り出すツールは段落や表を崩さずに取り出せます。
- 構造は BDF が持っているもの(変換器が書く
MARK命令)をそのまま写します。見出しとそのレベル、段落、リスト、表(見出しセルと結合セルを含む)、代替テキストつきの図、リンク、文字の言語です。 - ページのヘッダーとフッター、スライドのマスター、背景、シートの枠線、影は、装飾(アーティファクト)として印を付けます。読み上げでは飛ばされます。
PDF/A(-pdfa)は、長期保存のための PDF です。10 年後に開いても同じに見えるように、開くマシンに頼るものを一切持ちません。
| レベル | 約束すること |
|---|---|
2b |
どこで開いても同じに見える。すべてのフォントを埋め込み、色は PDF に入れた出力インテント(sRGB)で決まり、メタデータが規格を名乗る |
2u |
加えて、文字が Unicode に対応する。検索とコピーで正しい文字が得られる |
2a |
加えて、タグ付きである(-tagged を兼ねる) |
3b、3u、3a |
規格の第 3 部で、同じ内容 |
- PDF/A が許さないものは、別の形で書きます。画像はビューアに補間させず、どのフォントにもない文字は、空の箱を描く代わりに省いて警告を出します。
- レベル
aでは、私用領域の文字(アイコンフォントなど)に警告を出します。規格が、その文字が何であるかを示す文字列を求めるためです。 - 書き出したファイルは、開発の中で veraPDF で検査しています。PDF/UA は名乗りません。文書そのもののタイトル、言語、順序の正しい見出しも必要になるためです。透明を持てない PDF/A-1 は書き出しません。
データ
データは JSON の値でできた 1 つのオブジェクトです。-data を繰り返して組み立てます。
| 書き方 | 読み方 |
|---|---|
-data order.json、-data order.yaml |
オブジェクト。後のファイルが同じ名前の値を置き換える |
-data items=lines.csv |
CSV・TSV を、1 行目を名前にしたオブジェクトのリストとして、その名前に置く。文字コードと区切りは自動で判定(Shift_JIS も読む) |
-data book.xlsx、-data items=book.xlsx |
ブックのシートごとのリスト(シート名が名前)。名前を付けた 1 シートのブックはそのリスト |
-data customer.address=addr.json |
JSON・YAML の値を、その名前に置く |
CSV の値は、JSON の数値と同じ書き方のものだけが数値になります(007 や 1,234 は文字列のまま)。true と false は真偽値、空は値なしです。画像はファイルのパス(-files のディレクトリ、既定ではテンプレートのディレクトリから)か data: URL で渡します。パスはそのディレクトリの中にとどまります。.. や外へ出るリンクはたどりません。
データにない名前のタグは空にして警告を出します。-strict を付けるとエラーにします。
レコードごとに 1 つずつ帳票を作るには -each を使い、出力のパスにタグを書きます。
bdf fill -each orders.csv -data items=lines.csv invoice.xlsx 'out/{{customer}}-{{no}}.bdf'
1 つの文書に全員分をまとめるなら、テンプレートの側で {{#orders | pages}} を使います。
コンパイル済みテンプレート(.bdft)
bdf template compile はテンプレートを検査し(タグの閉じ忘れや、行をまたぐ区間の書き間違いを、セルの番地や段落・図形の場所つきで報告します)、コンパイル済みテンプレートを書き出します。中身は BDF の文書で、サンプルデータで穴埋めしたページ(サンプルがなければタグのままのページ)を見せ、テンプレートそのものと、タグが引く名前の一覧を持ちます。ビューアやサムネイルでそのまま開け、bdf fill にテンプレートの代わりに渡せます。
bdf template compile -sample sample.yaml invoice.xlsx invoice.bdft
bdf template schema invoice.bdft # タグが引く名前を JSON で
bdf fill -data order.yaml invoice.bdft out.bdf
一部だけ埋めた帳票(.bdff)
帳票を何人かで埋めることがあります。契約書なら、送る側が自分の欄を埋めて署名し、相手が残りを埋めます。-open で後に残す名前を指定すると、bdf fill は残りを空けた帳票(.bdff)を書き出します。
bdf fill -data mine.yaml -open party_b contract.bdft contract.bdff # 甲の分
bdf template schema -json-schema contract.bdff # 残りの欄: party_b
bdf fill -data theirs.json contract.bdff contract.bdf # 乙が残りを埋めて完成
- .bdff は、それまでに渡した値を持つコンパイル済みテンプレートです。ページはその値で埋めたもので、残した欄は空です。ふつうの文書としてビューアで開けます。スキーマは残した名前の分だけなので、入力のページは相手にその人の欄だけを見せます。
- 完成させるときは、.bdff が持つ値と渡したデータを合わせて、テンプレートを 1 回で埋めます。できる文書は、全部のデータで一度に埋めたものとバイト列まで同じです。
- 完成させるデータが渡せるのは、残した名前だけです。埋まっている名前や、残されていない名前を渡すとエラーになります。残した名前はすべて渡すか(
nullで空)、-openでもう一度残します。もう一度残すと、3 人目に回す .bdff になります。-open '*'は、データにない名前をすべて残します。 - .bdff を作るときは、テンプレートのどの名前も、データで渡すか
-openで指定します。名前を書き忘れるとエラーになります。他の人が署名する書類に、気づかない空欄を残さないためです。 - ドットを含む名前で、オブジェクトの中の値だけを残せます(
-open party_b.sign)。リスト(表の行)は、全部埋めるか全部残すかのどちらかです。 - ファイルのパスで渡した画像は、
data:URL にして .bdff の中に入れます。相手はそのファイルを持っていないからです。 - 値は JSON の形で持ちます。YAML の日付は文字列になります。どちらの経路でも同じ帳票にするには、日付を文字列(
2026-10-22)で渡します。 - .bdff は書き換えから守られていません。ファイルを持つ人は、中の値を変えられます。相手がウェブサイトで残りを埋める使い方なら、.bdff はサーバーに置いたまま、相手からは残りの値だけを受け取ります。ファイルを手から手へ渡すなら、値に署名します(次の節)。
値に署名する
-sign-key と -sign-cert は、その穴埋めで渡したものに署名します。署名するのは、そのときの帳票の値・空けた名前・テンプレート(の SHA-256)で、ページではありません。ページは他の人が埋めると変わるからです。.bdff は署名を持ち、そこから完成させた帳票は、値の記録とすべての署名を持ちます(型 fill の Part、spec §4.5)。
bdf fill -data mine.yaml -open party_b -sign-key alice.key -sign-cert alice.pem -sign-role author contract.bdft contract.bdff
bdf fill -data theirs.json -sign-key bob.key -sign-cert bob.pem contract.bdff contract.bdf
bdf sign -key witness.key -cert witness.pem -role witness contract.bdf # ページと記録に
bdf verify -roots ca.pem contract.bdf
bdf verify は値の署名ごとに、署名した値がすべて帳票の値と同じか、署名した人が埋めた名前を帳票が空けていないかを確かめます。完成させる前に .bdff の値を書き換えると、その値を渡した人の署名が成り立たなくなります。ページへの署名は bdf sign です(sign, verify)。その署名は記録も覆います。-open なしで署名すると、帳票の値をすべて署名します。
フォームのページでは、「Leave for another person」で名前にチェックを付けると、文書を .bdff として保存できます。そのページで .bdff を開くと、残した名前の欄だけが出ます。
サインと印影
{{%sign | signature}} と {{%seal | seal}} は画像で、{{%photo}} と同じように埋めて描きます(| fit: も使えます)。違うのは人がどうやって渡すかで、スキーマの x-bdf.input に入ります。
| input | フォームのページ |
|---|---|
signature |
ペン・指・マウスで書くパッド。書いた線は SVG の画像(data: URL)になり、PDF でどれだけ拡大してもぼけません |
seal |
印影の画像を選ぶと、白い部分を抜きます。文字の上に重ねて押せます |
PDF フォームの署名欄(/FT /Sig)と pdfme の signature も、同じく signature の画像の欄になります。
手書きのサインは、サインの絵であって電子署名ではありません。誰が書いたかも、その後に文書が書き換えられていないことも証明しません。
データの JSON Schema と入力フォーム
テンプレートが求めるデータの形は、JSON Schema として取り出せます。入力フォームを自動で作るライブラリや、データの検証にそのまま渡せます。フォームのページの入力欄も、このスキーマから作っています。
bdf template schema -json-schema invoice.xlsx invoice.schema.json
bdf template schema -json-schema -sample sample.yaml invoice.xlsx # サンプルで型と場所を確かめる
タグは値の型を書かないので、スキーマはタグから推し量ったものです。
| テンプレートの書き方 | スキーマ |
|---|---|
{{name}} |
文字列か数値("type": ["string", "number"]) |
{{total | fmt:"#,##0"}} |
数値。日付の表示形式(yyyy/mm/dd)なら "format": "date" の文字列 |
{{customer.name}} |
オブジェクト customer のプロパティ name |
中に名前か {{.}} がある区間、| rows・| pages の区間 |
配列。項目はオブジェクトか値。枠の区間(slots)は maxItems が枠の数 |
それ以外の区間({{#paid}}■{{/paid}}) |
真偽値 |
{{%photo}} |
文字列(ファイルのパスか data: URL)。| signature・| seal は x-bdf に "input" が付く |
{{%url | qr}}、{{%jan | barcode:jan}} |
文字列(コードの内容) |
- プロパティはテンプレートに出てくる順に並びます。それぞれの
x-bdfに、タグの種類(kind)、表示形式(format)、繰り返し方(mode、slots)、コードの種類(code)、タグのある場所(at)が入ります。 - 区間の中の名前は、項目とその外側の両方から探されるので、タグだけではどちらのものか決まりません。外側でも同じ名前を使っていれば外側のもの、そうでなければ項目のものとして扱います。
- サンプルデータがあれば、それで確定します。名前はサンプルにある場所に置かれ、値の型はサンプルの値の型になり、区間は値が配列かオブジェクトか真偽値かで決まります。
- コンパイル済みテンプレート(.bdft)は、サンプルで確定したスキーマを中に持っています。
bdf template schema -json-schema invoice.bdftはそれを返すので、テンプレートを読み直さずにフォームを作れます。 - 必須の項目(
required)は付きません。データにない名前のタグは空になるだけです。 - PDF フォームと pdfme のテンプレートは、タグより多くのことをフィールドについて知っています。チェックボックスは真偽値、日付のフィールドは
"format": "date"、選択肢はenum、入っている値はdefault、文字数の上限はmaxLengthになります。
Go から使う
data, err := form.LoadData(
form.Source{FileName: "order.yaml", Data: order},
form.Source{Name: "items", FileName: "lines.csv", Data: lines})
res, err := form.Fill(template, size, &form.Options{Data: data})
err = res.Doc.WriteSingle(out)
form.Fill は、テンプレートの形式を中身から判定します(Office のファイル、PDF フォーム、pdfme のテンプレート、テキストのテンプレート、コンパイル済みテンプレート、一部だけ埋めた帳票)。Options.Open を渡すと一部だけ埋めた帳票を作り、res.Partial がそれを記述します。form.Fields はタグが引く名前を、form.SchemaOf はデータの JSON Schema を、form.Compile はコンパイル済みテンプレートを返します。形式が決まっていれば xlsx.Fill、docx.Fill、pptx.Fill、textform.Fill を直接呼べます。textpart.Read は文書からテキストの帳票の印字像を読み、textform.Plain はそれをプレーンテキストにします。PDF は pdfbdf.Write で書き出します。
res, err := pdfbdf.Write(out, doc, &pdfbdf.Options{}) // PDF
res, err = pdfbdf.Write(out, doc, &pdfbdf.Options{Tagged: true, PDFA: "2a"}) // タグ付きの PDF/A-2a
知っておくこと
- Excel のページの切れ目は Excel と同じ規則で決めますが、Excel は印刷のときに行の高さと列幅をプリンタの画素に丸めるので、自動の改ページが 1 行ずれることがあります。位置が大事な改ページは、手動の改ページにしてください。
- 文字は変換するマシンのフォントで組みます。テンプレートが指定するフォントがなければ代わりのフォントで組むので、
-font-dirで使うフォントを決めておくと、どこで作っても同じ帳票になります。 - 同じテンプレートと同じデータからは、同じバイト列の文書ができます。Excel のヘッダーとフッターの
&D・&T(日付と時刻)は、そのために空にします。 - Word と PowerPoint のテンプレートは計算をしません(Excel の数式にあたるものがありません)。合計や繰越はデータで渡します。
- テンプレートは信頼できない入力として扱います。タグはコードを実行せず、できあがる帳票の大きさ(セル、スライド、要素の数)には上限があります。pdfme テンプレートの式にも、評価のステップ数、書き出す文字列(1 MiB)、作るリストの要素数の上限があります。PDF フォームのフィールドの文字列は 65,536 文字で切ります。