QuickBooksからBeancountへの移行ガイド
ステージ1:QuickBooksからのデータエクスポート
5年分のデータを移行するには、まずQuickBooksの全レコードを利用可能な形式で取得することから始まります。QuickBooks DesktopとQuickBooks Onlineでは、エクスポートオプションが異なります。
1.1 QuickBooks Desktopのエクスポートオプション
IIF (Intuit Interchange Format): QuickBooks Desktopでは、リスト(勘定科目表、顧客、ベンダーなど)を.IIF
テキストファイルにエクスポートできます。QuickBooks Desktopで、[ファイル] → [ユーティリティ] → [エクスポート] → [IIFファイルへのリスト] に進み、必要なリスト(例:勘定科目表、顧客、ベンダー)を選択します。これにより、勘定科目名、タイ プ、リストデータを含むテキストファイルが生成されます。IIFはプロプライエタリな形式ですが、プレーンテキストであり、比較的簡単に解析できます。これを使用して、Beancountでの参照用に勘定科目表と連絡先リストを取得します。
CSV経由の総勘定元帳/一般仕訳帳: 取引データについては、QuickBooks Desktopにはワンクリックでの完全なエクスポート機能はありませんが、レポートを使用できます。推奨される方法は、希望する期間の一般仕訳帳(すべての取引)をエクスポートすることです。QuickBooks Desktopで、[レポート] → [会計士と税務] → [一般仕訳帳] を開き、日付を最も古い取引から今日までに設定し、[エクスポート] → [Excel] をクリックします。レポートのヘッダー/フッターや空の列を削除した後、結果をCSVとして保存します。数値データがクリーンであることを確認してください:セントを含める(例:3
ではなく3.00
)、余分な引用符がない、通貨記号や二重の負号がCSVにないようにします。CSVには、日付、取引番号、名前、勘定科目、メモ、借方、貸方、残高(またはレポート形式によっては単一の金額列)などの列が必要です。
ヒント: QuickBooks Desktop 2015以降では、検索ダイアログからも取引をエクスポートできます。[編集] → [検索] → [詳細] を使用し、日付範囲を5年間に設定してから、結果をCSVにエクスポートします。警告: 一部のバージョンではエクスポートが32,768行に制限されています。データ量が非常に多い場合は、切り捨てを避けるために年ごと(またはより小さなチャンクで)エクスポートし、後で結合してください。重複を避けるために、日付範囲が重ならないようにしてください。
その他のフォーマット (QBO/QFX/QIF): QuickBooks Desktopは.QBO
(Web Connect) または.QFX/.OFX
ファイルを介して銀行取引をインポートできますが、QuickBooksからエクスポートする場合には一般的ではありません。銀行取引のみを抽出することが目的であれば、銀行からQBO/OFX形式で既に入手している可能性があります。ただし、完全な元帳のエクスポートのためには、IIFとCSVを使用してください。QuickBooks Desktopは、サードパーティ製ツールなしでは直接QIF (Quicken Interchange Format) にエクスポートできません。もしQIFを取得する方法を見つけた場合、一部の会計ツール(古いLedger 2.xなど)はQIFを読み取れましたが、我々のプロセスではCSVを扱う方が良いでしょう。
1.2 QuickBooks Onlineのエクスポートオプション
Excel/CSVへの統合エクスポート: QuickBooks Online (QBO) にはデータのエクスポートツールが用意されています。[設定] ⚙ → [ツール] → [データのエクスポート] に進みます。エクスポートダイアログで、[レポート] タブを使用してデータ(例:総勘定元帳または取引リスト)を選択し、[リスト] タブでリスト(勘定科目表など)を選択し、[すべての日付] を選んでExcelにエクスポートします。QuickBooks Onlineは、選択されたレポートとリスト(例:損益計算書、貸借対照表、総勘定元帳、顧客、ベンダー、勘定科目表など)の複数のExcelファイルを含むZIPをダウンロードします。その後、これらのExcelファイルをCSVに変換して処理できます。
取引詳細レポート: QBOのデフォルトのエクスポートに単一の総勘定元帳ファイルが含まれていない場合、手動で詳細レポートを実行できます:
- [レポート] に移動し、[勘定科目別取引詳細](または一部のQBOバージョンでは**[総勘定元帳]**)を検索します。
- [レポート期間] を5年間の全範囲に設定します。
- レポートオプションで、[グループ化] = [なし] に設定します(小計なしで個々の取引をリストするため)。
- 少なくとも次の列を含むように列をカスタマイズします:日付、取引タイプ、番号、名前(受取人/顧客)、メモ/説明、勘定科目、借方、貸方(または単一の金額列)、および残高。クラスや場所を使用していた場合はそれらも含めます。
- レポートを実行し、[Excelにエクスポート] します。
これにより、すべての取引の詳細な元帳が生成されます。これをCSVとして保存します。各行は取引の1つの明細(仕訳)を表します。後で変換のために、取引ごとに行をグループ化する必要があります。
勘定科目表およびその他のリスト: QuickBooks Onlineでは、[会計] → [勘定科目表] → [一括処理] → [Excelにエクスポート] を介して勘定科目表をエクスポートできます。これを行って勘定科目名とタイプを取得します。同様に、メタデータ用に名前を転送したい場合は、顧客、ベンダーなどもエクスポートします。
QuickBooks Online API (オプション): プログラムによるアプローチとして、IntuitはQBOデータ用のREST APIを提供しています。上級ユーザーは、QuickBooks Onlineアプリケーションを作成し(開発者アカウントが必要)、APIを使用してデータをJSONで取得できます。たとえば、Account
エンドポイントで勘定科目表を、JournalEntry
またはGeneralLedger
レポートエンドポイントで取引を照会できます。python-quickbooks
のようなPython SDKがAPIをラップしています。ただし、APIの使用にはOAuth認証が必要であり、自動化を好む場合を除き、一度きりの移行には過剰です。ほとんどの場合、CSV/Excelへの手動エクスポートの方が簡単でエラーが発生しにくいです。
ステージ2:データの変換とクリーンアップ
QuickBooksのデータをCSV(および/またはIIF)で取得したら、次のステップはそれをBeancountのプレーンテキスト元帳形式に変換することです。これには、エクスポートの解析、QuickBooksの勘定科目をBeancountの勘定科目表にマッ ピングし、取引をBeancountの構文にフォーマットすることが含まれます。
2.1 PythonによるQuickBooksエクスポートの解析
Pythonを使用することで、変換の正確性と再現性が保証されます。ここでは、2つの主要なタスクのためのスクリプトを概説します:勘定科目表のインポートと取引の変換です。
勘定科目のインポートとマッピング: 取引を追加する前に、Beancountで勘定科目を設定することが重要です。QuickBooksの勘定科目にはタイプ(銀行、売掛金、費用など)があり、これらをBeancountの階層(資産、負債、収益、費用など)にマッピングします。たとえば、次のようなマッピングを使用できます:
# QuickBooksの勘定タイプからBeancountのルートカテゴリへのマッピング
AccountTypeMap = {
'BANK': 'Assets', # 資産
'CCARD': 'Liabilities', # 負債
'AR': 'Assets', # 売掛金を資産として
'AP': 'Liabilities', # 買掛金を負債として
'FIXASSET': 'Assets',
'OASSET': 'Assets', # その他資産
'OCASSET': 'Assets', # その他流動資産
'LTLIAB': 'Liabilities',# 長期負債
'OCLIAB': 'Liabilities',# その他流動負債
'EQUITY': 'Equity', # 純資産
'INC': 'Income', # 収益
'EXP': 'Expenses', # 費用
'EXINC': 'Income', # その他収益
'EXEXP': 'Expenses', # その他費用
}
QuickBooks DesktopのIIFエクスポートまたはQBOの勘定科目リストCSVを使用して、各勘定科目の名前とタイプを取得します。次に:
-
Beancount勘定科目名の作成: QuickBooksでは、サブ勘定を示すためにコロン(
:
)を使用することがあります(例:"流動資産:当座預金")。Beancountも階層に同じコロン表記を使用します。多くの場合、名前を直接再利用できます。QuickBooksの勘定科目名がカテゴリで始まらない場合は、マッピングされたカテゴリを先頭に追加します。たとえば、BANK
タイプのQuickBooks勘定科目 "当座預金" は、BeancountではAssets:当座預金
になります。EXP
(費用)勘定の "食事代" はExpenses:食事代
になります。 -
有効な名前の確保: Beancountを混乱させる可能性のある文字を削除または置換します。QuickBooksでは
&
や/
などの文字が名前に使用できます。特殊文字を削除または置換する(例:&
をand
に置き換える、スラッシュやスペースを削除する)のが賢明です。また、変換後、すべての勘定科目名が一意であることを確認してください。QuickBooksでは、異なる親の下で同じサブ勘定名が許可されている場合がありますが、Beancountでは完全な名前(親を含む)が一意でなければなりません。必要に応じて、名前を変更するか、区別するための修飾子を追加します。 -
勘定開設の生成: Beancountでは、使用される各勘定は
open
ディレクティブで開設する必要があります。最初の取引より前の日付を選択できます(例:2019-2023のデータを移行する場合、すべての開設に2018-12-31
またはそれ以前の日付を使用)。スクリプトは次のような行を書き出します:2018-12-31 open Assets:Checking USD
2018-12-31 open Expenses:Meals USD
各勘定について(USDが主要通貨であると仮定)。各勘定に適切な通貨を使用してください(下記の多通貨に関する注意参照)。
取引の変換: 主な課題は、QuickBooksの取引エクスポート(CSV)をBeancountの仕訳に変換することです。各QuickBooks取引(請求書、支払手形、小切手、仕訳など)には複数の明細(行)があり、これらを単一のBeancount取引にグループ化する必要があります。
PythonのCSVリーダーを使用して、エクスポートされた行を反復処理し、明細を蓄積します:
import csv
from collections import defaultdict
# QuickBooksの一般仕訳帳CSVからすべての行を読み込む
rows = []
with open('quickbooks_exported_journal.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for line in reader:
rows.append(line)
# 取引ごとに行をグループ化する('取引番号'が取引を識別すると仮定)
transactions = defaultdict(list)
for line in rows:
trans_id = line.get('Trans #') or line.get('Transaction ID') or line.get('Num')
transactions[trans_id].append(line)
これで transactions
は、各キーが取引ID/番号で、値がその取引の明細リストである辞書になります。次に、各グループをBeancountに変換します:
def format_date(qb_date):
# QuickBooksの日付は "12/31/2019" のような形式
m, d, y = qb_date.split('/')
return f"{y}-{int(m):02d}-{int(d):02d}"
output_lines = []
for trans_id, splits in transactions.items():
# 必要に応じて明細を行の順序でソート(通常は順序通りに出力される)
splits = sorted(splits, key=lambda x: x.get('Line') or 0)
first = splits[0]
date = format_date(first['Date'])
payee = first.get('Name', "").strip()
memo = first.get('Memo', "").strip()
# 取引ヘッダー
output_lines.append(f"{date} * \"{payee}\" \"{memo}\"")
if first.get('Num'): # 参照番号があれば含める
output_lines.append(f" number: \"{first['Num']}\"")
# 各明細/仕訳をループ処理
for split in splits:
acct_name = split['Account'].strip()
# QuickBooks勘定科目名をBeancount勘定にマッピング(上記のマッピングを使用)
beancount_acct = account_map.get(acct_name, acct_name)
# 符号付きの金額を決定
amount = split.get('Amount') or ""
debit = split.get('Debit') or ""
credit = split.get('Credit') or ""
if amount:
# 一部のエクスポートは単一の金額列を持つ(貸方は負)
amt_str = amount
else:
# 借方/貸方が別の列の場合
amt_str = debit if debit else f"-{credit}"
# 安全のために数値のカンマを削除
amt_str = amt_str.replace(",", "")
# 通貨を追加
currency = split.get('Currency') or "USD"
amt_str = f"{amt_str} {currency}"
# 明細のメモ/説明
line_memo = split.get('Memo', "").strip()
comment = f" ; {line_memo}" if line_memo else ""
output_lines.append(f" {beancount_acct:<40} {amt_str}{comment}")
# 取引の 終わり – 空行
output_lines.append("")
このスクリプトのロジックは次のことを行います:
- 日付をBeancount用のYYYY-MM-DD形式にフォーマットします。
- 受取人(名前)とメモを取引の説明に使用します。例:
2020-05-01 * "ACME Corp" "請求書の支払い"
(受取人がない場合、QuickBooksの取引タイプを使用するか、受取人を空の引用符で囲むことができます)。 - 参照番号(小切手番号、請求書番号など)がある場合は、
number
メタデータを追加します。 - 各明細行を反復処理します:
account_map
辞書を使用して、QuickBooksの勘定科目名をBeancountの勘定にマッピングします(勘定科目表のステップで作成)。- 金額を決定します。エクスポートによっては、単一の金額列(正/負の値)または別々の借方と貸方列がある場合があります。上記のコードは両方のケースを処理します。貸方がBeancountの負の金額として表されることを確認します(Beancountでは、仕訳ごとに1つの符号付き数値が使用されるため)。
- 通貨を付加します(別の通貨列がない限りUSDと仮定)。
- 勘定、金額、および行メモのコメントを含むBeancountの仕訳行を書き込みます。例:
Assets:Checking 500.00 USD ; 預 金
Income:Sales -500.00 USD ; 預金
これは$500の預金(収益から当座預金へ)を反映しています。
- すべての明細をリストした後、空行が取引を区切ります。
多通貨の処理: QuickBooksデータに複数の通貨が含まれる場合、各仕訳に通貨コードを含めます(上記参照)。外貨建ての勘定がその通貨で開設されていることを確認してください。たとえば、EURの銀行口座がある場合、open Assets:Bank:Checking EUR
を生成し、その勘定での取引はEURを使用します。Beancountは多通貨元帳をサポートし、暗黙的な換算を追跡しますが、レポートで基本通貨への換算が必要な場合は、為替レートの価格エントリを追加する必要があるかもしれません。また、Beancountファイルの先頭で主要な運用通貨を宣言することをお勧めします(例:option "operating_currency" "USD"
)。
変換の実行: Pythonスクリプトを(例えばqb_to_beancount.py
として)保存し、エクスポートされたファイルに対して実行します。すべての勘定と取引を含む.beancount
ファイルが生成されるはずです。
2.2 特殊ケースの処理とデータクリーンアップ
変換中、これらの一般的な問題とその対処法に注意してください:
-
互換性のない勘定科目名: QuickBooksには、Beancountの階層的な名前と競合する勘定科目名がある場合があります。たとえば、QuickBooksには2つの異なる親勘定があり、それぞれに "保険" という名前のサブ勘定があるかもしれません。Beancountでは、
Expenses:Insurance
は一意でなければなりません。これを解決するには、エクスポート前に一方の名前を変更する(例:「保険-車両」vs「保険-健康」)か、スクリプトで一意のBeancount勘定にマッピングします。一貫した命名規則(特殊文字なし、階層の使用)は頭痛の種を減らします。必要であれば、再マッピングファイルアプローチを使用します:古い名前→新しいBeancount名のCSVまたは辞書を保持し、変換中に適用します(我々のサンプルコードはaccount_map
を使用し、ファイルから上書きを読み込むことができます)。 -
日付とフォーマット: すべての日付が一貫してフォーマットされていることを確認してください。上記のスクリプトはM/D/YをISO形式に正規化します。また、5年間の期間が年度末をまたぐ場合、会計年度と暦年の問題に注意してください。Beancountは会計年度の境界を気にしませんが、後で便宜上、ファイルを年ごとに分割したい場合があります。
-
数値の精度: QuickBooksは通貨をセント単位で処理するため、セント単位での作業は通常問題ありません。理想的には、すべての金額がCSVで小数点以下2桁を持つべきです。もし金額が整数に変換された(小数点なし)場合や、カンマ/括弧(負の場合)がある場合は、スクリプトでクリーンアップします(カンマを削除し、
(100.00)
を-100.00
に変換するなど)。指示に従って正しく行われたCSVエクスポートは、これらのフォーマットの問題を既に回避しているはずです。 -
負の金額と符号: QuickBooksのレポートでは、負の値を
-100.00
、(100.00)
、または特定のExcelエクスポートでは--100.00
として表示することがあります。クリーンアップステップでこれを処理する必要があります。各取引の借方と貸方がゼロになるようにバランスが取れていることを確認してください。Beancountはこれを強制します(バランスが取れていない場合、インポート時にエラーをスローします)。 -
重複した取引: 取引をバッチで(例:年ごとや勘定ごと)エクスポートする必要があった場合、重複しないようにマージするように注意してください。ある年の最初の取引が前のバッチの最後の取引でもないことを確認するなど。境界で誤っていくつかの取引を重複させてしまうのは簡単です。重複が疑われる場合は、最終的なBeancountの仕訳を日付でソートし、同一のエントリを探すか、Beancountの一意の取引タグを使用して検出できます。戦略の1つは、QuickBooksの取引番号をメタデータとして含め(例:
取引番号
や請求書番号をtxn
タグやquickbooks_id
メタデータとして使用)、それらのIDの重複がないことを確認することです。 -
不均衡な明細 / 未決算勘定: QuickBooksには、QuickBooksが自動的に「期首残高純資産」または「利益剰余金」勘定に調整した不均衡を持つ取引のような奇妙なケースがあるかもしれません。たとえば、期首勘定残 高を設定する際、QuickBooksはしばしば差額を純資産勘定に記録します。これらはエクスポートされた取引に現れます。Beancountは明示的なバランスを要求します。QuickBooksを反映させるために、期首残高用の純資産勘定(一般的に
Equity:Opening-Balances
)を導入する必要があるかもしれません。元帳の初日にすべての勘定の期首残高を設定する期首残高仕訳を持つのが良い習慣です(ステージ5参照)。 -
多通貨の特殊ケース: 多通貨を使用する場合、QuickBooksのエクスポートはすべての金額を現地通貨またはネイティブ通貨でリストするかもしれません。理想的には、各勘定のネイティブ通貨でデータを取得します(QuickBooks Onlineのレポートは通常これを行います)。Beancountでは、各仕訳は通貨を持ちます。QuickBooksが為替レートまたは現地通貨への換算を提供した場合、それらを無視してBeancountの価格エントリに依存することができます。QuickBooksが為替レートをエクスポートしなかった場合、評価を一致させるために主要な日付に手動で価格レコードを追加したい場合があります(例:Beancountの
price
ディレクティブを使用)。ただし、元帳の基本的な整合性のためには、取引が元の通貨でバランスが取れていれば十分です。未実現損益は、同じレポートが必要でない限り、明示的に記録する必要はありません。 -
売掛金 / 買掛金: QuickBooksは、プレーンテキスト元帳には完全には引き継がれない請求書や支払手形の詳細(支払期日、支払状況など)を追跡します。ARおよびAP取引(ARを増加させる請求書、ARを減少させる支払いなど)は取得できますが、請求書ドキュメントや請求書ごとの顧客残高は取得できません。その結果、移行後、BeancountのARおよびAP勘定の残高が、QuickBooksの未処理の顧客/ベンダー残高と一致することを確認する必要があります。請求書を追跡する必要がある場合は、Beancountのメタデータを使用できます(例:
invoice
タグやリンクを含める)。QuickBooksの請求書番号はNum
またはMemo
フィールドに入っているはずです。我々のスクリプトはNum
を取引メタデータのnumber: "..."
として保持します。 -
非アクティブまたは閉鎖された勘定: IIFエクスポートには非アクティブな勘定が含まれる場合があります(含めるように選択した場合)。これらをインポートしても問題ありません(取引がなく、本当に非アクティブであれば残高はゼロになります)。最後の取引日の後に
close
ディレクティブを使用してBeancountで閉鎖済みとしてマークできます。これにより、元帳が整理されます。例:2023-12-31 close Expenses:OldAccount ; 移行後に閉鎖
これはオプションであり、主に整理のためです。
上記のようにデータを慎重にクリーンアップし、マッピングすることで、QuickBooksのデータを構造的に反映したBeancount元帳ファイルができます。次のステップは、それがQuickBooksを数値的にも反映していることを確認することです。