中級向けn8n 公式テンプレート承認済み

請求書の下書きを自動作成

Google Chat、Slack、フォームで「Aoba の9月分」と頼むと、スプレッドシートの明細から請求書を作り、PDF を添付した Gmail の下書きまで用意します。送るのは人です。

AI(Claude)が読むのは「誰の何月分か」だけです。金額、税、支払期日、請求書番号は、コードがシートから計算します。

客や月が読み取れない、作成済み、明細がおかしいときは、何も作らずに理由を返します。架空の客3社で、フォーム、本物の Google Chat、本物の Slack から試しました。

人の手間は、どう変わるか

Before(人が手でやっていたこと)

  • 月末に、客ごとに、その月の明細をシートから拾い出す
  • 数量 × 単価、小計、税、合計、支払期日を計算して、請求書のひな形に打ち込む
  • PDF にして、メールを書いて添付する。同じ請求書を二重に作っていないかも確かめる

After(このワークフローを入れると)

  • Chat・Slack・フォームで「Aoba の9月分」と頼むと、PDF を添付した Gmail の下書きまで出来る
  • 金額・日付・請求書番号はコードが計算し、記録のタブに1行残る
  • 客や月が読み取れない、作成済み、明細がおかしいときは、作らずに理由を返す

それでも人に残ること

  • 下書きを開いて、中身を確かめてから送る
  • 明細のシートを、正しく保つ
  • 止まった理由を読んで、シートや依頼を直す

動作確認: — n8n 2.36.8 / Claude Haiku 4.5 / Google スプレッドシート・ドキュメント・ドライブ・Gmail / Google Chat(Google Workspace) / Slack

n8n 公式テンプレート: 英語版が n8n の審査を通過しました()。注記を読む

この記事で配っている JSON は、承認された英語版に、Slack からの依頼、Google Chat の返事のボタン、Google の呼び出しの試し直しと失敗したときの返事を足したものです。足した部分は、審査を受けていません。n8n が内容を保証するものではありません。 n8n 公式のページ(英語版)を見る

請求書は、金額を1円でも間違えたら困る書類です。AI に作らせて大丈夫なのか、と思う人は多いはずです。

このワークフローの答えは、AI に数字を書かせないことです。AI(Claude)に任せるのは、「Aoba の9月分」のような依頼文から、誰の何月分かを読むところだけ。Claude には明細の金額を見せず、金額、税、支払期日、請求書番号は、すべてコードが Google スプレッドシートから計算します。

さらに、Claude には「どの言葉からそう読んだか」もあわせて返させ、コードがその言葉を依頼文の中で探します。 見つからない、客の名前と合わない、月の読み方が言葉と違う、というときは、請求書を作らずに理由を返します。最後にメールを送るのも、人です。

約45秒で、仕組みの全体(音声あり。音声:VOICEVOX:雨晴はう)

invoice-drafts.json をダウンロード(英語版。n8n 公式テンプレートとして承認された版に、Slack からの依頼などを足したものです)

頼むフォームGoogle ChatSlackClaude が読む誰の・何月分か+ そう読んだ言葉金額は見せないコードが確かめ、計算する言葉は依頼文にあるか・客の名前と合うか月は言葉から自分で計算して照らす明細 → 小計・税・合計・支払期日請求書番号・作成済みなら止まる(スプレッドシートから)下書きを作る(送らない)ドキュメントのテンプレートを埋める→ PDF → Gmail の下書きに添付→ Invoices タブに1行記録頼んだところに返す作った:番号・合計・文書のリンク止まった:何も作らず、理由を返すGoogle の失敗:どの段階かを返す合わない
Claude には、明細の金額を見せません。Claude が間違えて読んでも、コードの確かめで止まり、請求書は作られません。

AI に任せるのは「誰の何月分か」だけ

Claude に渡すのは、今日の日付、客の一覧(ID・名前・別名)、依頼文の3つです。返させるのは、次の4つだけです。

項目 例(「青葉商事さんの9月分」)
customer_id C001
customer_words(客を指した言葉) 青葉商事
month(請求する月) 2026-09
month_words(月を指した言葉) 9月

コードは、これを次のように確かめます。

  • 客: customer_words が依頼文の中にあり、その客の名前か別名(other_names の列)と合うか。一覧にない ID なら止まる
  • 月: month_words が依頼文の中にあるか。そのうえで、月はコードが言葉から自分で計算し、Claude の答えと比べる。「9月」「September」「先月」「last month」「2026-09」が読める。年のない「9月」は、今日より前で一番近い9月にする
  • 未来の月: 今月より先の月なら止まる

試した結果

架空の客3社(Aoba Trading、Blue Harbor Cafe、Northwind Studio)と、9月・10月の明細で試しました(2026年10月19日〜20日。Claude Haiku 4.5、各1回)。

依頼 どこから 結果
Aoba の9月分の請求書を作って フォーム 作成。小計 ¥90,200、税 ¥9,020、合計 ¥99,220(手計算と一致)
Blue Harbor last month please フォーム 作成。「last month」を 2026-09 と計算。合計 ¥58,960
青葉商事さんの9月分をもう一度 フォーム 止まった: 作成済み(別名でも同じ客と判定した)
Sakura Bakery の9月分 フォーム 止まった: 客の一覧にない
Aoba の請求書をお願い フォーム 止まった: 月が書かれていない
Aoba の10月分 本物の Google Chat 作成。合計 ¥116,600。返事まで 12.2秒
Northwind の9月分 本物の Google Chat 作成。合計 ¥191,400
Blue Harbor の10月分 本物の Google Chat 作成。合計 ¥73,700。文書はボタンで開く形
@アプリ Aoba の9月分 本物の Slack 作成。合計 ¥99,220。スレッドに返事。11.8秒
@アプリ Northwind の9月分(5の直しのあと) 本物の Slack 作成。合計 ¥191,400。スレッドに返事
@アプリ Northwind の10月分(5の直しのあと) 本物の Slack 止まった: 作成済み
Northwind の10月分(明細11行) Chat と同じ形のデータ 作成。11行が1行ずつ並び、合計 ¥151,250
登録していない人から Chat と同じ形のデータ 断った: 使える人の一覧にない

作った文書のうち3つと、Gmail の下書きに添付された PDF 1つを開いて、中身を目で確かめました。

止まる場面

止まるときは、何も作らずに、頼んだところ(フォームの画面、Chat、Slack)に理由を返します。

止まる場面 返す理由の例
客の一覧にない The request does not name a customer from the Customers tab.
客を指した言葉が、依頼文にない・名前と合わない “…” does not match Aoba Trading Co., Ltd. or its other names.
月がない・言葉と違う・未来の月 The request does not say which month.
その月の明細がない・多すぎる・数量や単価が数字でない No lines for … in 2026-09 in the Items tab.
作成済みの請求書番号 INV-202609-C001 was already created. To create it again, set its status to “void”.
Google の呼び出しが、3回試しても失敗した Google returned an error while copying the template …

作り直したいときは、Invoices タブのその行の status を void にします。

作って見つけた5つの落とし穴

1. 使わなかった明細の行が、空白として残った

最初は、テンプレートに {{line_1}} 〜 {{line_10}} の10行を用意し、使わない行を空にしていました。PDF を見ると、明細と小計の間に、空の行が7行分の空白として残りました。

{{lines}} の1か所にまとめ、明細を改行でつないで入れる形に変えました。Google ドキュメントの置き換え(replaceAllText)で改行を入れると、行数ぶんの段落になり、空白は残りません。10行までという制限もなくなりました(念のため、上限は Config の max_lines に残しています)。

2. Google Chat のリンクのプレビューが、置き換える前の文書だった

Chat の返事の本文に文書の URL を書くと、Chat がプレビューを付けます。ところが、そのプレビューには {{invoice_no}} のような、置き換える前の文字が写っていました。文書そのものは正しく出来ていたので、コピーした直後の古い画像が使われたのだと考えています。

見た人が「置き換わっていない」と勘違いしそうなので、URL を本文に書くのをやめ、「Open the document」のボタンで開く形にしました。ボタンにしてからは、プレビューは出ていません。

3. Google が一時的に失敗し、返事がないまま止まった

本物の Slack で試したとき、1回目は、Google ドライブがテンプレートのコピーに 500(Internal Error)を返して止まりました。下の試し直しを入れてから、もう一度頼むと通りました(その回のコピーは、1回目で成功していました)。

困ったのは、止まると Slack に何も返らず、頼んだ人が待たされたままになることです。Google を呼ぶ6つのノードに Retry On Fail(最大3回、2秒おき) を入れ、それでも失敗したら、エラー出力から「どの段階で止まったか」を返すようにしました。

4. 「試し直し」と「続行」は、一緒に使えた(既存の記事を訂正した)

このサイトのエラー時の記事には、「On Error を続行にすると、Retry On Fail は発動しない」と書いていました。それなら、3の作りは試し直しをしていないことになります。

測り直すと、入ってくるアイテムが1件なら、エラー出力でも試し直していました(試し直しなしで 1,137ms、ありで 5,137ms。Google ドライブのコピー)。試し直さないのは、複数のアイテムのうち一部だけが失敗したときでした。既存の記事は、その形だけで測って、全体の結論にしていました。訂正した経緯は、その記事に残しています。

このワークフローは、請求書を1通ずつ作るので、どのノードにも1件しか入りません。試し直しと、失敗の返事の両方が効きます。

5. エラー出力を付けたら、後の Code ノードから結果が読めなくなった

エラー出力を付けたあと、正常に作れたときの返事が壊れました。返事を書く Code ノードで、コピーしたノードの結果を $('Copy the template').first() で読んでいたのが、何も返さなくなったのが原因です(失敗した段階の名前を取り違えたのも、同じ原因でした)。

成功した側の出力を $('Copy the template').all(0)[0] と、はっきり指定して読むように直しました。失敗した段階は、Code ノードの $prevNode.name(そのアイテムがどのノードから来たか)で取っています。なぜ .first() が何も返さなくなるのかは、n8n の実装を読んでいないので分かりません。

Google Chat と Slack から頼む仕組み

どちらも任意です。フォームだけでも使えます。使わない方のノードは、消してかまいません。

Google Chat Slack
頼み方 Chat アプリに、1対1で送る チャンネルで、アプリを @メンションする
受け取り Webhook ノード(Chat アプリの「HTTP エンドポイント URL」) Slack Trigger ノード(app_mention)
返事 30秒以内に、その場で返す(手元では10〜15秒) 依頼のスレッドに投稿する
使える人 Chat settings にメールアドレスを書く Slack settings にメンバー ID を書く
前提 Google Workspace(個人の Gmail では使えない) Slack アプリに app_mentions:read と chat:write

Google Chat のアプリは、Google Cloud コンソールの「Google Chat API」の「構成」で作ります。「Google Workspace アドオンとして作成」のオン・オフで、届くデータの形と、返す形が変わります。このワークフローは、どちらの形にも対応しています(本物で試したのは、アドオンの方だけです)。

使うための設定

  1. 認証情報: Google スプレッドシート、Google ドライブ、Google ドキュメント、Gmail(いずれも OAuth2)、Anthropic。Slack を使うなら Slack も
  2. スプレッドシート: 3つのタブを作る(1行目は見出し)
    • Customers:customer_id, name, email, address, payment_terms_days, other_names
    • Items:customer_id, month(YYYY-MM), description, quantity, unit_price
    • Invoices:invoice_no, customer_id, month, subtotal, tax, total, due_date, doc_url, gmail_draft_id, created_at, status
  3. 請求書のテンプレート(Google ドキュメント): 次の文字を入れておく。{{lines}} は1行に単独で置く(明細が1行ずつ入る) {{invoice_no}} {{issue_date}} {{due_date}} {{customer_name}} {{customer_address}} {{period}} {{lines}} {{subtotal}} {{tax_rate}} {{tax}} {{total}} {{seller_name}} {{seller_address}} {{payment_details}} {{notes}}
  4. Config: スプレッドシートの ID、テンプレートの ID、自社の名前・住所・振込先、通貨、税率、端数の処理(初期値は切り捨て)、タイムゾーン、メールの文面
  5. フォームで試す: Request form のフォームの URL を開いて頼み、Gmail の下書きを確かめる
  6. Chat や Slack を使うなら、上の「頼む仕組み」の設定をして、公開する

確認していないこと

  • 実際の請求書の業務。 試したのは、架空の客3社と、自分で作った明細です
  • ほぼ同時に、同じ依頼が2回届いたとき。 作成済みの確かめを、両方がすり抜けて、2通作られる可能性があります
  • コピーより後の段階(ドキュメントの置き換え、PDF、Gmail、記録)での失敗。 わざと失敗させる方法がなく、試したのはコピーの段階の失敗だけです。後の段階で失敗すると、途中まで出来た文書(と、場合によっては Gmail の下書き)が残ります。返事でそう伝えます
  • 税率が明細ごとに違う請求書(軽減税率など)。小計に1つの税率を掛ける作りです
  • インボイス制度(適格請求書)の記載事項を満たすかどうか。登録番号などの欄は、テンプレートに自分で足してください

次に読む

次に読む