メインコンテンツへスキップ

beaで銀行のCSVをBeancountにインポートする

beaを使って銀行のCSVをBeancount元帳にインポート:列をマッピングし、ルールで分類し、仕訳をプレビューし、重複を確認してから適用します。

一般的な銀行CSVにはPythonインポーターは不要です。--csvで列をマッピングし、--accountで送金元口座を指定し、--rulesで行を分類し、bea importでエントリをプレビューして適用します。

既存の台帳が必要です。新しい帳簿を始める場合は、CLIクイックスタートに従ってください。元の銀行エクスポートを保存しておき、プレビューと比較できるようにしてください。

1. CSV列をマッピングする​

このサンプルをstatement.csvとして保存し、同じディレクトリから以下のコマンドを実行します:

Date,Payee,Narration,Amount
2026-08-02,Whole Foods,groceries,-20.00
2026-08-03,Shell,gas,-40.00
2026-08-04,Unknown Shop,mystery,-9.99

金額は銀行の符号規則に従います:支出はマイナス、入金はプラスです。通貨はデフォルトで台帳の運用通貨になるため、このファイルには通貨列は不要です。銀行の説明列をnarrationに配置し、payeeには加盟店を残します。

台帳を作成し、後で使用する燃料サブアカウントを開きます:

bea --no-input init books --currency USD --date 2026-08-01 \
  --opening-balance "Assets:Checking 1000"
bea --file books/main.bean add open --date 2026-08-01 --account Expenses:Transport:Fuel -c USD

テンプレートはすでにExpenses:Groceriesと他の一般的なアカウントを開いています。Expenses:Transport:Fuelは開いていないため、2番目のコマンドでインポート前に開きます。--fileなどのグローバルオプションはサブコマンドの前に置きます。

2. エントリをプレビューする​

以下の分類ルールをrules.tomlとして保存し、プレビューします:

cat > rules.toml <<'EOF'
[[rule]]
match = "whole foods|trader joe|corner market"
account = "Expenses:Groceries"
 
[[rule]]
match = "shell|chevron|exxon"
account = "Expenses:Transport:Fuel"
EOF
bea --file books/main.bean import statement.csv --csv date=Date,amount=Amount,payee=Payee,narration=Narration --account Assets:Checking --rules rules.toml

ルールは最初にpayee、次にnarrationを大文字小文字を無視してマッチします。最初にマッチしたルールが優先されます。どのルールにもマッチしない行は、フラグ!付きでExpenses:Uncategorizedに転記され、後で確認できます。IMPORTINGガイドには、debitとcreditのペア、category列、--csv autoヘッダー読み取りを含む完全なマッピングリファレンスが記載されています。

まだ台帳には何も書き込まれません。プレビューは3 ready, 0 exact duplicates, 0 possible duplicatesと報告し、終了コード0で終了します。RULE列には、各行の該当パターン名、またはUnknown Shop行の場合はunmatchedと表示されます。日付、payee、符号付きの送金元金額、送金先アカウント、重複マッチ、提案されたファイル差分を確認してください。誤ったルールやカテゴリを修正し、再度プレビューしてください。インポートを適用する前に、不足しているアカウントを開いてください:台帳が開いていないアカウントを指定するルールは検証に失敗します。

3. 確認済みエントリを適用する​

bea --file books/main.bean import statement.csv --apply
bea --file books/main.bean check
bea --file books/main.bean list transaction --flag '!'
bea --file books/main.bean query "SELECT account, sum(position) WHERE account = 'Assets:Checking' GROUP BY account"

列マッピングは台帳、ヘッダー行、送金元口座ごとに記憶されるため、--applyはフラグなしで再実行され、記憶された列マッピングを使用して報告します。現在のファイルに対してプレビューを再計算し、書き込み前に完全な候補台帳を検証して、3つのエントリを書き込みます。bea checkはエラーを報告しません。!キューには、マッチしない1行、Unknown Shopがmysteryで-9.99 USDとしてリストされます。チェックが成功したからといって、その行がExpenses:Uncategorizedに属することが証明されるわけではありません。台帳で意図的に再分類してください。チェックは930.01 USDで終了します:1,000 USDの開始残高から69.99 USDの支出を差し引いたものです。

4. 繰り返しインポートは何も追加しない​

bea --file books/main.bean import statement.csv --apply

プレビューは0 ready, 3 exact duplicatesと報告し、実行は0エントリを書き込み、終了コード0で終了します。書き込まれた各行には、コンテンツハッシュを持つimport-idメタデータが付与されるため、同一ファイルを再インポートするとすべての行がスキップされます。この規則より前に書き込まれたエントリにはbea_import_idメタデータが残っている場合があり、再インポート時にもマッチします。インポートされたエントリを編集する場合は、そのメタデータを保持してください。インポートはエントリを追加するだけで、既存の取引を更新または削除しません。台帳で意図的に修正し、その後bea checkを実行してください。bea add transactionsでのバルクJSONエントリには重複検出はありません。

5. 可能性のある重複を解決する​

後日のダウンロードでは、説明や銀行IDが異なる行が繰り返されることがあります。日付、正規化されたpayee、符号付きの送金元金額が、可能性のあるマッチとしてマークします:

プレビューステータス意味対処法
new重複の証拠が見つからない金額とカテゴリを確認する
duplicate安定したIDと取引詳細が一致するか、同一の非取引ディレクティブが存在するすでにスキップされる
possible_duplicate日付、正規化されたpayee、符号付きの送金元金額/通貨が一致するプレビューを既存エントリと比較する
conflict安定したIDが異なる取引詳細と一致するIDまたはデータの不一致を解決し、再度プレビューする

銀行IDが異なっていても重複を除外できません。銀行は後日のダウンロードでIDを変更することがあります。また、2つの実際の購入が日付、payee、金額を共有することもあるため、可能性のあるマッチは証拠であり証明ではありません。beaはAIモデルで推測せず、ルール以外の分類を自動で行うことはありません。

デフォルトの--duplicates reviewは、未解決のマッチを適用することを拒否します。検証実行では、2026-08-02 Whole Foods -20.00 USD行を別の説明で繰り返す2番目のファイルが1つの可能性のある重複としてプレビューされ、--applyは何も書き込まず終了コード4で終了しました。すべての可能性のあるマッチを確認した後、以下のいずれかの選択肢を選びます:

bea --file books/main.bean import statement.csv --apply --duplicates skip
bea --file books/main.bean import statement.csv --apply --duplicates include

正当な繰り返し購入を保持するにはincludeを選択します。この決定は、その呼び出し内のすべての可能性のあるマッチに適用されます。完全一致の重複はスキップされたままです。ID競合は書き込みをブロックします。--no-inputと--yesはその確認をバイパスしません。すべての行をスキップする意図的な決定は、台帳への追加なしで終了コード0で終了します。

6. 他の形式にはPythonインポーターを使用する​

OFXやQIF、または変則的なレイアウトのCSVなど、列マッピングで表現できない形式の場合、bea importは現在のBeangulpインターフェースを使用して設定されたインポーターを呼び出します:identify(filepath)、account(filepath)、extract(filepath, existing)。インポーターは銀行固有の解析と分類を担当します。重複マッチングが実際の銀行金額を使用するよう、送金元口座の転記に明示的な金額を提供する必要があります。Pythonインポーターはこれらの形式の上級者向けパスです。銀行のネイティブCSVには、まず--csvを試してください。

最初の練習実行として、カテゴリ化されたCSV設定の例をimporters.pyとしてルート台帳の隣に保存します。BeancountとPythonの標準ライブラリのみを使用するため、Homebrewインストールで動作します。サンプルのbank.csvは符号付きの当座預金口座金額を使用します:-5.25 USDの食事費用と1,000 USDの給与入金です。サンプル設定は、記載された列を正確に想定しています。信頼するPython設定のみを実行してください。

bea --file books/main.bean import bank.csv --config importers.py
bea --file books/main.bean import bank.csv --config importers.py --importer categorized-checking
bea --file books/main.bean import bank.csv --config importers.py --apply

importers.py設定はCONFIG = [importer, ...]をエクスポートします。複数のインポーターがファイルを認識する場合は、名前で1つを選択します。不明な名前は設定された名前をリストします。ファイルを認識しない既知のインポーターは、それを個別に報告します。

CLIはこのルート台帳の設定パスを記憶します。今後の実行は、明示的な--config、次に記憶されたパス、次にルートの隣のimporters.pyの順で選択します。出力はパスとその由来を表示します。

--applyは現在のファイルに対してプレビューを再計算します。書き込み前に完全な候補台帳を検証します。検証失敗は元の台帳を変更せず、終了コード1で終了します。同時の台帳変更は終了コード4で終了します;変更を確認し、再試行する前に新しいプレビューを実行してください。

インポートを再現可能に保つ​

デフォルトでは、重複マッチングはインポーターの送金元口座内のbank_id、fitid、transaction_id、imported_idメタデータをチェックします。繰り返しの--id-key KEYオプションを使用して、そのセットを置き換えます。

安定した銀行IDを持つ行は、bank:やofx:プレフィックスなどの種類を示すimport-idメタデータ付きで書き込まれます。それがない行は、日付、金額、説明、口座に基づくcsv:sha256:コンテンツハッシュ付きで書き込まれるため、同じファイルを再インポートするとすべての行がスキップされます。この規則より前に書き込まれたエントリにはbea_import_idメタデータが残っている場合があり、再インポート時にもマッチします。可能性のあるマッチは、既存の取引と同一バッチ内の受け入れられた行に対してチェックされます。

payee、narration、文字列メタデータは、プレビューと書き込みの前に改行をスペースに置き換えます。引用符とバックスラッシュは内容を保持します。インポートされた加盟店テキストは、したがって単一の台帳行で読みやすくなります。

インクルードされたファイルに書き込む​

--fileをルートに向けたまま、--intoで宛先を選択します:

bea --file books/main.bean import statement.csv --into 2026.bean
bea --file books/main.bean import statement.csv --into 2026.bean --apply

2026.beanは既に存在し、ルートにインクルードされている必要があります。そのパスはルートディレクトリからの相対パスです。エクスポートパスは作業ディレクトリからの相対パスのままです。プレビューは変更されるファイルを特定します。

スクリプトでインポートを使用する​

bea --file books/main.bean --json --no-input import statement.csv --apply --duplicates skip

可能性のあるマッチに対する意図したポリシーがskipの場合のみ選択してください。JSONはプレビューと書き込み数をdata内に返します。拒否された適用は、プレビューをstderrのerror.resultに置き、written: 0とします。常に終了ステータスを確認してください。無人インポートをスケジュールする前に、JSONと終了コードのリファレンスを参照してください。

インポーターのトラブルシューティング​

インポーター設定は管理エンジンで実行されます。設定がBeangulpをインポートする場合、システムのlibmagicライブラリをインストールし、そこでBeangulpを一度有効にします:

bea engine enable beangulp
bea --file books/main.bean import bank.ofx --config importers.py
bea --debug --file books/main.bean import bank.csv --config importers.py

bea engine statusは有効な機能を報告します。beaフロントエンドと一緒に銀行インポーターをインストールしても、エンジン内で利用可能にはなりません。追加のパッケージをインポートする設定は、それらの依存関係をエンジンにインストールする必要があります;Beangulpを有効にするだけではインストールされません。インポーターの依存関係が利用できない場合は、以下のCSVマッパーまたはコンバーターを使用してください。

インポーターの例外の場合は、コマンドの前に--debugを置いてトレースバックを表示します。インポーター出力はimporter_outputにキャプチャされるため、JSONを破損しません。JSONデバッグモードでは、トレースバックはerror.tracebackです。

Pythonインポーターなしの一回限りの変換には、CSVコンバーターまたはOFXおよびQIFコンバーターを試してください。簿記に追加する前に生成されたエントリを確認してください。

出典: https://beancount.io/ja/docs/Solutions/import-bank-exports-cli