DocRaptor とは、API 経由で受け取ったソース HTML データを PDF 形式に変換し、PDF ファイルとして返す Web サービスです。Questetra では DocRaptor と連携しPDF ファイルを生成する自動工程が提供されています。
本記事ではビルトイン自動工程「DocRaptor: PDF 生成」の基本的な使い方を説明します。
PDF ファイルを生成する類似の自動工程として、Adobe Acrobat Service API を対象とする[Adobe: PDF 生成(HTML to PDF)]も利用できます。
DocRaptor での準備
DocRaptor の Web サイト(英語のみ)にてアカウントを取得してください。メールアドレスと氏名、使用するパスワードを入力して「Sing up」すると API Key が発行され、Document History のページに表示されますのでメモします。
DocRaptor の無料アカウントでは月に 5 ドキュメントまでという制限がありますが、TEST モードでは DocRaptor のすかしが入る条件で無制限に作成できます。Questetra のワークフローアプリで[DocRaptor: PDF 生成]自動工程がデバッグ実行されると、DocRaptor では TEST モードとして動作します。
[DocRaptor: PDF 生成]工程の設定
[DocRaptor: PDF 生成]は、1.Docraptor の API にアクセスし、2.指定された HTML データを送信し、3.そのデータを元にDocRaptor によって生成された PDF ファイルをダウンロードし、格納する自動工程です。
[DocRaptor: PDF 生成]工程の設定は、以下の項目で行います。
- Docraptor の API にアクセスするための HTTP 認証設定の指定
- 送信される変換元の HTML データを保存するデータ項目の指定
- ダウンロードされた PDF ファイルを保存するデータ項目の指定
HTTP 認証設定
[設定はこちらから]ボタンで[HTTP 認証設定]画面を開きます。上部のタブで[Basic 認証]を開き、[アプリ固有の設定]の[+ 追加]で設定画面を開きます。
[名前]は個別の設定を識別するための文字列(DocRaptor-ユーザ名など)、[ユーザ名]には DocRaptor で取得した API key を入力し[保存]します。(パスワードは空白)
[DocRaptor: PDF 生成]の設定画面の[C1: API キーをユーザ名に設定した BASIC 認証設定]で指定した[名前]の HTTP 認証設定を選択します。(表示されない場合は画面を再読み込みしてください。)
API key のみの指定となりますが[トークン直接指定]ではなく[Basic 認証]タイプで追加作成します
変換元のソース HTML を保存するデータ項目
[C2: 変換元の HTML が保存されているデータ項目]にて、データ項目を選択指定します。文字型(複数行)かファイル型のデータ項目を指定できます。対象のデータ項目には入力工程にてソース HTMLが格納されます。
ソース HTML とは
HTML(Hyper Text Markup Language)は、Web ページを Chrome や Edge といった Web ブラウザで表示するためのマークアップ言語です。本記事では、PDF の変換元となる HTML データを「ソース HTML」と呼びます。ソース HTML には PDF に表示される文字列の情報に加えて、文字列の配置や体裁など紙面の書式に関わる情報が含まれています。
Questetra では HTML で記述されたメールがワークフローから自動送信される機能もあり、以下のページで HTML について少し解説されていますので参考にしてください。
Tutorial: ワークフローの途中でメールを自動送信しよう(HTML メール編)
PDF ファイルを保存するデータ項目
[C3: 生成された PDF ファイルを保存するデータ項目]に、ファイル型データ項目を指定します。保存される際のファイル名を指定するための[C5: 保存する際のファイル名]に、ファイル拡張子となる「.pdf」で終わる文字列を設定します。文字列の代わりに EL式も設定できます。
業務データが挿入されるソース HTML の準備
HTML のコードにデータ項目を参照する EL式が記述されたソース HTML を準備すると、業務データが挿入された動的な PDF ファイルを生成することができます。ここでは、EL式を利用して、HTML にデータ項目の値を挿入する方法について説明します。
まず、固定の文字列やそれらの配置などといった書式が定義された HTML を用意します。次に、その HTML の中でデータ項目の値やシステム変数を挿入したい箇所に、それぞれを参照する EL式を記述します。EL式の表記と挿入された値の表示については、以下のリファレンスページを参考にしてください。
Reference: R2272: EL式による文字列としての出力(データ設定式)
ソース HTML の準備の具体例は、本記事の後半で詳しく説明します
サンプルアプリ

アプリを作成して[DocRaptor: PDF 生成]の動作を実際に確認してみましょう。このアプリでは自動工程[テキストファイル生成]でHTML ファイルを生成し、それを PDF の変換元となるソース HTML としてセットします。
書式の定義を HTML でゼロから記述するのは大変なので、今回は DocRaptor が提供しているテンプレートを利用してソース HTML を準備します。以下のサイトから Invoice(請求書)の A4サイズのテンプレートファイル(invoice.A4.html)をダウンロードしてください。英語用の書面となってますが、書き換えて利用できるようにします。
DocRaptor のテンプレートページ:Free HTML to PDF Templates
ダウンロード:Download A4 Size(リンク先を保存)
アプリ設定
データ項目
[DocRaptor: PDF 生成]の動作に必要となるデータ項目は、ソース HTML を保存するものと生成された PDF ファイルを保存するものです。データ項目の値が挿入されたソース HTML を PDF ファイルの変換元にする場合は、挿入される分のデータ項目を用意します。
データ項目名 | データ型 | フィールド名 | 必須 | 「データ入力」工程 | 説明 |
件名 | – | – | – | 編集可 | プロセスの件名です。 |
HTML File | ファイル型 | q_html | – | 非表示 | ソース HTML を格納します。 |
PDF File | ファイル型 | q_pdf | – | 非表示 | 生成された PDF ファイルを格納します。 |
以下はテンプレートに挿入するデータ項目 | |||||
請求先名 | 文字型(単一行) | q_billing_name | – | 編集可 | |
請求先住所 | 文字型(複数行) | q_billing_address | – | 編集可 | |
請求先アドレス | 文字型(単一行) | q_billing_email | – | 編集可 | |
支払期限 | 日付型(YMD) | q_due_date | – | 編集可 | 初期値: #today.addDays(30) |
商品名1 | 文字型(単一行) | q_item_name1 | – | 編集可 | |
備考1 | 文字型(単一行) | q_remark1 | – | 編集可 | |
単価1 | 数値型 | q_unit1 | – | 編集可 | |
数量1 | 数値型 | q_quantity1 | – | 編集可 | |
価格1 | 数値型 | q_price1 | – | 編集可 | 式: #q_unit1 * #q_quantity1 |
商品名2 | 文字型(単一行) | q_item_name2 | – | 編集可 | |
備考2 | 文字型(単一行) | q_remark2 | – | 編集可 | |
単価2 | 数値型 | q_unit2 | – | 編集可 | |
数量2 | 数値型 | q_quantity2 | – | 編集可 | |
価格2 | 数値型 | q_price2 | – | 編集可 | 式: #q_unit2 * #q_quantity2 |
商品名3 | 文字型(単一行) | q_item_name3 | – | 編集可 | |
備考3 | 文字型(単一行) | q_remark3 | – | 編集可 | |
単価3 | 数値型 | q_unit3 | – | 編集可 | |
数量3 | 数値型 | q_quantity3 | – | 編集可 | |
価格3 | 数値型 | q_price3 | – | 編集可 | 式: #q_unit3 * #q_quantity3 |
小計 | 数値型 | q_subtotal | – | 編集可 | 式: #q_price1 + #q_price2 + #q_price3 |
消費税 | 数値型 | q_tax | – | 編集可 | 式: #q_subtotal * 0.1 |
合計金額 | 数値型 | q_total | – | 編集可 | 式: #q_subtotal + #q_tax |
請求書発行日 | 日付型(YMD) | q_issue_date | – | 編集可 | 初期値: #today |
請求書番号 | 文字型(単一行) | q_invoice_id | – | 編集可 | 初期値: #{processInstanceSequenceNumber} |
「HTML ファイル生成」工程(テキストファイル生成)
この工程で、ソース HTML となる HTML ファイルが自動生成されます。EL式によってデータ項目の値が挿入された HTML が、 HTML ファイルとして出力されます。出力先(保存先)として、「PDF 生成」工程の[C2: 変換元の HTML が保存されているデータ項目]に指定されているデータ項目を指定します。
項目名 | 必須 | 説明 |
C1: テキストファイルを保存するファイル型データ項目 | ✓ | ここでは「HTML File」を選択します。 |
C2: 保存時に他のファイルを削除する | – | |
C3: 保存ファイル名 | ✓ | source-#{processInstanceId}.html など、自動採番される変数を利用します(ファイル拡張子「.html」は必須です) |
C4: テキストファイルの内容 | ✓ | ソース HTML となるコードを登録します。 (書式を定義する HTML にデータ参照式(EL式)が挿入されたものー後述) |
C5: 保存する際の文字コード (未設定の場合、UTF-8) | – | UTF-8 を指定します(空白でも可) |
C6: 保存する際のファイルタイプ (未設定の場合、text/plain) | – | text/html を選択指定します。 |
「PDF 生成」工程(DocRaptor: PDF 生成)
DocRaptor にアクセスするための HTTP 認証設定や、PDF の元となるソース HTML と生成されダウンロードされたファイルが保存されるデータ項目について指定します。
項目名 | 必須 | 説明 |
C1: API キーをユーザ名に設定した BASIC 認証設定 | ✓ | Docraptor への接続に使用する HTTP 認証設定を指定します。指定する認証設定をあらかじめ作成しておく必要があります。(前述の「HTTP 認証設定」参照) |
C2: 変換元の HTML が保存されているデータ項目 | ✓ | PDF の元となるソース HTML を格能するデータ項目を指定します。(ここでは「HTML File」) |
C3: 生成された PDF ファイルを保存するデータ項目 | ✓ | ファイル型データ項目を指定します。(ここでは「PDF File」) |
C4: 保存時に他のファイルを削除する | – | |
C5: 保存する際のファイル名 | ✓ | #{processInstanceId}.pdf など、自動採番される変数を利用します(ファイル拡張子「.pdf」は必須です) |
テンプレートの編集と[DocRaptor: PDF 生成]の実行
今回はソース HTMLとして利用するダウンロードしたテンプレート(invoice.A4.html)を
- 業務データが挿し込まれるように編集し
- その結果を[DocRaptor: PDF 生成]の動作によって生成された PDF で確認します。
実際には、テンプレートのコードを部分的に編集しては確認する、ということを繰り返しながら進めていきます。この際、DocRaptor の契約プランによる PDF 生成数制限を消費しないよう、デバッグモードで実行します。以下の作業は、アプリエディタの編集モードにて進めます。
ダウンロードしたテンプレートを確認する
まず、ダウンロードしたテンプレートがどのようなものかを確認しましょう。
「PDF 生成」工程(DocRaptor: PDF 生成)の設定画面から[この工程のみデバッグ]を実行します。開始されたデバッグプロセスの入力工程で、「HTML File」にダウンロードしておいた invoice.A4.html を[追加]して[「テストデータを入力」処理完了]します。
デバッグプロセスの終了後、「PDF File」に保存されている PDF ファイルを確認します。


[テキストファイル生成]でセットする HTML のコードを編集する
生成された PDF ファイルを見てみましょう。ダウンロードしたままのテンプレート(invoice.A4.html)から生成されたこの PDF はすべて英語で表記されています。また、社名やメールアドレス等は仮の文字列が表示されています。HTML のコードを書き換えて、変更が必要な箇所を修正していきます。

上の図で緑色で囲われた部分は、請求書共通の固定の文字列です。日本語や社名など、適切な文字で書き換えます。また赤色で囲われた部分には、個々の請求によって異なる部分です。これらにはデータ項目の値が挿入されるようにします。
固定文字列を書き換える
では、ダウンロードした invoice.A4.html を編集して書き換えていきます。ファイルをテキストエディタ(メモ帳アプリなど)で開くとソース HTML となるコードが表示されます。テキストエディタ上でコードに変更を加えたら、コード全体をコピー&ペーストで「HTML ファイル生成」工程(テキストファイル生成)の[C4: テキストファイルの内容]に登録します。「HTML ファイル生成」工程が実行されると、変更が反映された HTML ファイルが生成されます。
表示されているコードの始めから3分の2くらいまでは、文字の配置などの体裁を指定するためのスタイルシートが記述されています(<style>~</style>)。実際に表示される文字等は<header>以下に記述されています。PDF 上で「Logo & Name」や「Invoice」と表示されている所を書き換えてみましょう。
<div class="logoAndName">
<svg>
<circle cx="50%" cy="50%" r="40%" stroke="black" stroke-width="3" fill="black" />
</svg>
<h1>Logo & Name</h1>
</div>
<!-- Details about the invoice are on the right top side of each page. -->
<div class="invoiceDetails">
<h2>Invoice #100</h2>
<p>
07 March 2021
</p>
</div>
<h1>Logo & Name</h1>を社名(Questetra)に、<h2>Invoice #100</h2>を「請求書番号:」に書き換え、さらに<p>07 March 2021</p>に「発行日:」を追加します。また<svg>~</svg>(ロゴマークの表示)は削除します。
<div class="logoAndName">
<h1>Questetra</h1>
</div>
<!-- Details about the invoice are on the right top side of each page. -->
<div class="invoiceDetails">
<h2>請求書番号:#100</h2>
<p>
発行日:07 March 2021
</p>
</div>
データ挿入 EL式で書き換える
つぎに、データ項目を参照して値を挿入する EL式で書き換えます。上記のコードでは「#100」の部分にデータ項目「請求書番号」、「07 March 2021」の部分には「請求書発行日」を参照する式を記述します。
<div class="logoAndName">
<h1>Questetra</h1>
</div>
<!-- Details about the invoice are on the right top side of each page. -->
<div class="invoiceDetails">
<h2>請求書番号:#{#q_invoice_id}</h2>
<p>
発行日:#{#q_issue_date}
</p>
</div>
データを参照する EL式は、基本 #{#フィールド名}
といった書式で記述しますが、関数を使って出力形式を変える事も可能です。例えば「Invoice to」に挿入する「請求先住所(文字型複数行)」や「Due Date」に挿入する「支払期限(日付型YMD)」をみてみましょう。
<div>
<h3>ご請求先</h3>
<p>
<b>#{#q_billing_name}</b>
<br />
#{#joiner.splitJoin(#q_billing_address, '<br>')}
<br />
<a href="mailto:#{#q_billing_email}">
#{#q_billing_email}
</a>
</p>
</div>
<!-- Additional details can be placed below the invoice details. -->
<div>
<h3>お支払期限</h3>
<p>
<b>#{#dateFormatter.format('yyyy年MM月dd日', #q_due_date)}</b>
</p>
文字型複数行に入力された値をそのまま #{#q_billing_address}
とすると、HTML では改行されず1行で表示されてしまいます。行ごとに<br> を挿入する関数を記述して複数行を保ちます。
#{#joiner.splitJoin(#q_billing_address, '<br>')}
R2272: EL式による文字列としての出力(データ設定式)
コードの一部分を書き換えると、コード全体をコピー&ペーストで「HTML ファイル生成」工程(テキストファイル生成)の[C4: テキストファイルの内容]に登録します。
アプリ先頭の開始イベントから[デバッグ実行]して、「データ入力」工程を処理しましょう。終了したデバッグプロセスの詳細画面で生成された PDF ファイルを確認してください。
正しく変更できていれば次の箇所を編集し結果を確認する、ということを繰り返して全体の編集を完了しましょう。本記事のために編集された HTML コードの全体も参考にしてください。
全体を編集したコード:HTML コードサンプル
動作確認
invoice.A4.html の編集が必要な個所のすべてを変更できれば、開始イベントから[デバッグ実行]して動作確認します。「データ入力」工程で入力した値が、「PDF 生成」工程で生成された PDF ファイルに挿し込まれていることを確認します。期待通りの PDF が生成されていない場合は、「HTML ファイル生成」工程の[C4: テキストファイルの内容]にセットする HTML の内容を見直しみてください。
以上のように、EL式を利用して業務データが挿入されるように「ソース HTML」を準備しておくことで、業務データが挿し込まれた PDF ファイルを生成することができます。


Appendix
PDF 生成サブプロセスとして準備する
社内各部門において共通の書式で発行される請求書など、特定の書式での PDF が複数の業務(アプリ)で生成される場合があります。このような時は、それぞれの業務アプリに PDF 生成工程を配置するかわりに、一連の PDF 生成処理をサブプロセス化することを検討します。
「PDF 生成」をサブプロセスとして独立したアプリで定義しておけば、このアプリにデータを受け渡すことで「PDF 生成」処理の組み込みが容易になります。また、生成される PDF の書式を変更したい場合も、個々の業務アプリで変更を行う必要はなく、サブプロセス側の1箇所を変更すれば良いのでメンテナンス性も高まります。
サブプロセスの詳細については以下の記事を参照してください。
複数のワークフローアプリを連携させて運用する(自動処理サブプロセス編)
HTML コードサンプル
DocRaptor からダウンロードしたテンプレート(invoice.A4.html)を元に、本記事で書き換えた HTML の全コードを以下に掲載します。(クリックして開く)
HTML コード(全文)
<!--
The following is the license for the original template file.
------------------------------------
MIT License
Copyright (c) 2021 Expected Behavior, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------
-->
<style>
/*
Import the desired font from Google fonts.
*/
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap');
/*
Define all colors used in this template
*/
:root{
--font-color: black;
--highlight-color: #60D0E4;
--header-bg-color: #B8E6F1;
--footer-bg-color: #BFC0C3;
--table-row-separator-color: #BFC0C3;
}
@page{
/*
This CSS highlights how page sizes, margins, and margin boxes are set.
https://docraptor.com/documentation/article/1067959-size-dimensions-orientation
Within the page margin boxes content from running elements is used instead of a
standard content string. The name which is passed in the element() function can
be found in the CSS code below in a position property and is defined there by
the running() function.
*/
size:A4;
margin:8cm 0 3cm 0;
@top-left{
content:element(header);
}
@bottom-left{
content:element(footer);
}
}
/*
The body itself has no margin but a padding top & bottom 1cm and left & right 2cm.
Additionally the default font family, size and color for the document is defined
here.
*/
body{
margin:0;
padding:1cm 2cm;
color:var(--font-color);
font-family: 'Montserrat', sans-serif;
font-size:10pt;
}
/*
The links in the document should not be highlighted by an different color and underline
instead we use the color value inherit to get the current texts color.
*/
a{
color:inherit;
text-decoration:none;
}
/*
For the dividers in the document we use an HR element with a margin top and bottom
of 1cm, no height and only a border top of one millimeter.
*/
hr{
margin:1cm 0;
height:0;
border:0;
border-top:1mm solid var(--highlight-color);
}
/*
The page header in our document uses the HTML HEADER element, we define a height
of 8cm matching the margin top of the page (see @page rule) and a padding left
and right of 2cm. We did not give the page itself a margin of 2cm to ensure that
the background color goes to the edges of the document.
As mentioned above in the comment for the @page the position property with the
value running(header) makes this HTML element float into the top left page margin
box. This page margin box repeats on every page in case we would have a multi-page
invoice.
*/
header{
height:8cm;
padding:0 2cm;
position:running(header);
background-color:var(--header-bg-color);
}
/*
For the different sections in the header we use some flexbox and keep space between
with the justify-content property.
*/
header .headerSection{
display:flex;
justify-content:space-between;
}
/*
To move the first sections a little down and have more space between the top of
the document and the logo/company name we give the section a padding top of 5mm.
*/
header .headerSection:first-child{
padding-top:.5cm;
}
/*
Similar we keep some space at the bottom of the header with the padding-bottom
property.
*/
header .headerSection:last-child{
padding-bottom:.5cm;
}
/*
Within the header sections we have defined two DIV elements, and the last one in
each headerSection element should only take 35% of the headers width.
*/
header .headerSection div:last-child{
width:35%;
}
/*
For the logo, where we use an SVG image and the company text we also use flexbox
to align them correctly.
*/
header .logoAndName{
display:flex;
align-items:center;
justify-content:space-between;
}
/*
The SVG gets set to a fixed size and get 5mm margin right to keep some distance
to the company name.
*/
header .logoAndName svg{
width:1.5cm;
height:1.5cm;
margin-right:.5cm;
}
/*
To ensure the top right section "Invoice #100" starts on the same level as the Logo &
Name we set a padding top of 1cm for this element.
*/
header .headerSection .invoiceDetails{
padding-top:.5cm;
}
/*
The H3 element "ISSUED TO" gets another 25mm margin to the right to keep some
space between this header and the client's address.
Additionally this header text gets the hightlight color as font color.
*/
header .headerSection h3{
margin:0 .75cm 0 0;
color:var(--highlight-color);
}
/*
Put some margin between the "DUE DATE" and "AMOUNT" headings.
*/
header .headerSection div:last-of-type h3:last-of-type{
margin-top:.5cm;
}
/*
The paragraphs within the header sections DIV elements get a small 2px margin top
to ensure its in line with the "ISSUED TO" header text.
*/
header .headerSection div p{
margin-top:2px;
}
/*
All header elements and paragraphs within the HTML HEADER tag get a margin of 0.
*/
header h1,
header h2,
header h3,
header p{
margin:0;
}
/*
The invoice details should not be uppercase and also be aligned to the right.
*/
header .invoiceDetails,
header .invoiceDetails h2{
text-align:right;
font-size:1em;
text-transform:none;
}
/*
Heading of level 2 and 3 ("DUE DATE", "AMOUNT" and "INVOICE TO") need to be written in
uppercase, so we use the text-transform property for that.
*/
header h2,
header h3{
text-transform:uppercase;
}
/*
The divider in the HEADER element gets a slightly different margin than the
standard dividers.
*/
header hr{
margin:1cm 0 .5cm 0;
}
/*
Our main content is all within the HTML MAIN element. In this template this are
two tables. The one which lists all items and the table which shows us the
subtotal, tax and total amount.
Both tables get the full width and collapse the border.
*/
main table{
width:100%;
border-collapse:collapse;
}
/*
We put the first tables headers in a THEAD element, this way they repeat on the
next page if our table overflows to multiple pages.
The text color gets set to the highlight color.
*/
main table thead th{
height:1cm;
color:var(--highlight-color);
}
/*
For the last three columns we set a fixed width of 2.5cm, so if we would change
the documents size only the first column with the item name and description grows.
*/
main table thead th:nth-of-type(2),
main table thead th:nth-of-type(3),
main table thead th:last-of-type{
width:2.5cm;
}
/*
The items itself are all with the TBODY element, each cell gets a padding top
and bottom of 2mm.
*/
main table tbody td{
padding:2mm 0;
}
/*
The cells in the last column (in this template the column containing the total)
get a text align right so the text is at the end of the table.
*/
main table thead th:last-of-type,
main table tbody td:last-of-type{
text-align:right;
}
/*
By default text within TH elements is aligned in the center, we do not want that
so we overwrite it with an left alignment.
*/
main table th{
text-align:left;
}
/*
The summary table, so the table containing the subtotal, tax and total amount
gets a width of 40% + 2cm. The plus 2cm is added because our body has a 2cm padding
but we want our highlight color for the total row to go to the edge of the document.
To move the table to the right side we simply set a margin-left of 60%.
*/
main table.summary{
width:calc(40% + 2cm);
margin-left:60%;
margin-top:.5cm;
}
/*
The row containing the total amount gets its background color set to the highlight
color and the font weight to bold.
*/
main table.summary tr.total{
font-weight:bold;
background-color:var(--highlight-color);
}
/*
The TH elements of the summary table are not on top but the cells on the left side
these get a padding left of 1cm to give the highlight color some space.
*/
main table.summary th{
padding:4mm 0 4mm 1cm;
}
/*
As only the highlight background color should go to the edge of the document
but the text should still have the 2cm distance, we set the padding right to
2cm.
*/
main table.summary td{
padding:4mm 2cm 4mm 0;
border-bottom:0;
}
/*
The content below the tables is placed in a ASIDE element next to the MAIN element.
To ensure this element is always at the bottom of the page, just above the page
footer, we use the Prince custom property "-prince-float" with the value bottom.
See Page Floats on https://www.princexml.com/howcome/2021/guides/float/.
*/
aside{
-prince-float: bottom;
padding:0 2cm .5cm 2cm;
}
/*
The content itself is shown in 2 columns we use flexbox for this.
*/
aside > div{
display:flex;
justify-content:space-between;
}
/*
Each "column" has a width of 45% of the document.
*/
aside > div > div{
width:45%;
}
/*
The list with the payment options has no bullet points and no margin.
*/
aside > div > div ul{
list-style-type:none;
margin:0;
}
/*
The page footer in our document uses the HTML FOOTER element, we define a height
of 3cm matching the margin bottom of the page (see @page rule) and a padding left
and right of 2cm. We did not give the page itself a margin of 2cm to ensure that
the background color goes to the edges of the document.
As mentioned above in the comment for the @page the position property with the
value running(footer) makes this HTML element float into the bottom left page margin
box. This page margin box repeats on every page in case we would have a multi-page
invoice.
The content inside the footer is aligned with the help of line-height 3cm and a
flexbox for the child elements.
*/
footer{
height:3cm;
line-height:3cm;
padding:0 2cm;
position:running(footer);
background-color:var(--footer-bg-color);
font-size:8pt;
display:flex;
align-items:baseline;
justify-content:space-between;
}
/*
The first link in the footer, which points to the company website is highlighted
in bold.
*/
footer a:first-child{
font-weight:bold;
}
</style>
<!-- The header element will appear on the top of each page of this invoice document. -->
<header>
<div class="headerSection">
<!-- As a logo we take an SVG element and add the name in an standard H1 element behind it. -->
<div class="logoAndName">
<h1>Questetra</h1>
</div>
<!-- Details about the invoice are on the right top side of each page. -->
<div class="invoiceDetails">
<h2>請求書番号:#{#q_invoice_id}</h2>
<p>
発行日:#{#q_issue_date}
</p>
</div>
</div>
<!-- The two header rows are divided by an blue line, we use the HR element for this. -->
<hr />
<div class="headerSection">
<!-- The clients details come on the left side below the logo and company name. -->
<div>
<h3>ご請求先</h3>
<p>
<b>#{#q_billing_name}</b>
<br />
#{#joiner.splitJoin(#q_billing_address, '<br>')}
<br />
<a href="mailto:#{#q_billing_email}">
#{#q_billing_email}
</a>
</p>
</div>
<!-- Additional details can be placed below the invoice details. -->
<div>
<h3>お支払期限</h3>
<p>
<b>#{#dateFormatter.format('yyyy年MM月dd日', #q_due_date)}</b>
</p>
<h3>ご請求金額</h3>
<p>
<b>#{#q_total}円</b>
</p>
</div>
</div>
</header>
<!-- The footer contains the company's website and address. To align the address details we will use flexbox in the CSS style. -->
<footer>
<a href="https://questetra.com">
questetra.com
</a>
<a href="mailto:customer-sevice@questetra.com">
customer-sevice@questetra.com
</a>
<span>
京都市中京区 御池通間之町東入高宮町206<br>御池ビル4階 604-0835
</span>
</footer>
<!-- In the main section the table for the separate items is added. Also we add another table for the summary, so subtotal, tax and total amount. -->
<main>
<table>
<!-- A THEAD element is used to ensure the header of the table is repeated if it consumes more than one page. -->
<thead>
<tr>
<th>商品名</th>
<th>単価</th>
<th>数量</th>
<th>価格</th>
</tr>
</thead>
<!-- The single invoice items are all within the TBODY of the table. -->
<tbody>
<tr>
<td>
<b>#{#q_item_name1}</b>
<br />
#{#q_remark1}
</td>
<td>
#{#q_unit1}
</td>
<td>
#{#q_quantity1}
</td>
<td>
#{#q_price1}
</td>
</tr>
<tr>
<td>
<b>#{#q_item_name2}</b>
<br />
#{#q_remark2}
</td>
<td>
#{#q_unit2}
</td>
<td>
#{#q_quantity2}
</td>
<td>
#{#q_price2}
</td>
</tr>
<tr>
<td>
<b>#{#q_item_name3}</b>
<br />
#{#q_remark3}
</td>
<td>
#{#q_unit3}
</td>
<td>
#{#q_quantity3}
</td>
<td>
#{#q_price3}
</td>
</tr>
</tbody>
</table>
<!-- The summary table contains the subtotal, tax and total amount. -->
<table class="summary">
<tr>
<th>
小計
</th>
<td>
#{#q_subtotal}
</td>
</tr>
<tr>
<th>
消費税
</th>
<td>
#{#q_tax}
</td>
</tr>
<tr class="total">
<th>
合計
</th>
<td>
#{#q_total}
</td>
</tr>
</table>
</main>
<!-- Within the aside tag we will put the terms and conditions which shall be shown below the invoice table. -->
<aside>
<!-- Before the terms and conditions we will add another blue divider line with the help of the HR tag. -->
<hr />
<div>
<div>
<b>手数料について</b>
<p>
お振込手数料は御社ご負担にてお願い致します。
</p>
</div>
<div>
<b>お振込先</b>
<ul>
<li>○○銀行 ○○支店 普通 000000000</li>
<li>名義:カ)クエステトラ</li>
</ul>
</div>
</div>
</aside>