Access VBAのバージョン管理|モジュールエクスポートとGit活用
.accdbバイナリのままではGitで差分を追えません。VBEのエクスポート(.bas/.cls)でVBAをテキスト化してGit管理する手順と、フォーム定義も対象にするSaveAsText/LoadFromTextの使い方・非サポートの注意点を解説します。
結論:.accdbバイナリのままではGitで差分を追えない。モジュールをテキストに出してから管理する
Access VBAのコードは.accdbファイルの中に埋め込まれています。バイナリ形式なので、Gitにコミットしても「Binary files differ」と表示されるだけで、行単位の差分は追えません。「誰がどの処理を変えたか」を追いかけるには、コードをテキストファイルとして外に出す工程が必要です。
現実的な方法は2系統あります。一つはVBE(Visual Basic Editor)のファイルメニューからモジュールを.basや.clsファイルにエクスポートしてGit管理する方法。もう一つはApplication.SaveAsText/LoadFromTextでフォームやレポートも含めてテキスト化する方法です。ただし後者はMicrosoftが「隠し・非公式機能」として扱っていた経緯があり、現行ドキュメントには掲載されているものの、将来の挙動は保証されません。本記事ではそれぞれの現実的な使い方と注意点を整理します。エラー処理の書き方はAccess VBAのエラー処理入門、デバッグ方法はAccess VBAのデバッグとテストを参照してください。
なぜ.accdbはGitに向かないのか
.accdbはACE(Access Connectivity Engine)データベースエンジンのバイナリフォーマットです。テーブルのデータだけでなく、フォームの定義、VBAのコード、マクロ定義がすべて1つのファイルに格納されています。
テキストファイルと違ってバイナリは、1行変えただけでも関係ない範囲のバイト列が変化するため、Gitの行単位diffは機能しません。コメントを1行追加しても、どのSubが変わったかをGitのログから読み取るのはほぼ不可能です。
加えて、複数人が同じ.accdbのVBAを別々に編集した場合、マージの手段がありません。上書き保存したほうが勝つ状態になります。この状態が続くと、「誰が何を変えたかわからない」「直す前に戻せない」という属人化の温床になります。
手法1:VBEでモジュールをエクスポートしてGit管理する
標準モジュールとクラスモジュールは、VBEのファイルメニューからテキストとして書き出せます。VBEの公式ドキュメント(Export File dialog box)によると、標準モジュールは.bas、クラスモジュールは.cls、フォームは.frm の拡張子でエクスポートされます。Accessのフォームモジュールは.clsとして出力されます。
手順は次のとおりです。
- AccessでVBEを開く(Alt+F11)
- プロジェクトエクスプローラーで対象モジュールを選択
- 「ファイル」メニュー→「ファイルのエクスポート」を選択
- 保存先とファイル名を指定して保存
書き出した.basや.clsファイルはただのテキストです。Gitリポジトリに置いてコミットすれば、どの関数を追加・変更・削除したかをdiffで確認できます。
インポートはその逆です。VBEのファイルメニューから「ファイルのインポート」を選び、.basや.clsを指定します。既存のモジュールと同名のものをインポートする場合、VBEは自動的に末尾に連番を付けた別モジュールとして追加するため、古いモジュールを先に削除してからインポートするのが安全です。
VBAで標準モジュール・独立クラスモジュールを一括エクスポートする
モジュール数が多い場合、手作業でのエクスポートは手間です。VBAコードからVBEを操作して一括出力できます。Application.VBEプロパティ(公式ドキュメント)はVBEオブジェクトへの参照を返し、ActiveVBProject.VBComponentsコレクションでモジュールを列挙できます。
Sub ExportAllModules()
Dim vbComp As Object ' VBComponent(遅延バインディング:Extensibility参照設定不要)
Dim exportPath As String
Dim filePath As String
exportPath = "C:\repo\access-modules\" ' 保存先フォルダ(末尾必須)
' Export は既存ファイルを上書きしない(既存ファイルがあるとエラー)
' 毎回実行する場合は日付フォルダを切るか、先に既存ファイルを削除すること
For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
Select Case vbComp.Type
Case 1 ' 標準モジュール(= vbext_ct_StdModule)
filePath = exportPath & vbComp.Name & ".bas"
If Dir(filePath) <> "" Then Kill filePath ' 既存ファイルを先に削除
vbComp.Export filePath
Case 2 ' クラスモジュール(= vbext_ct_ClassModule)
filePath = exportPath & vbComp.Name & ".cls"
If Dir(filePath) <> "" Then Kill filePath
vbComp.Export filePath
' Case 100(vbext_ct_Document: フォーム/レポートに埋め込まれたモジュール)は
' コードとモジュール属性のみ出力可。フォームのデザインや制御関連は復元できないため
' 省略。フォーム定義ごと保存したい場合は SaveAsText を使用する。
End Select
Next vbComp
MsgBox "エクスポート完了: " & exportPath
End Sub注意点として、VBComponent.Export は同名ファイルが既に存在するとエラーになります(上書きしません)。定期実行する場合はDir関数で存在確認してからKillで削除するか、実行日ごとのサブフォルダに書き出す運用にしてください。上のコードは前者の方法を採用しています。
また、VBComponent.Export はコードとモジュール属性行を出力しますが、フォームのデザインやAccessオブジェクトとの関連は含まれません。フォームやレポートに書かれたイベントコード(Type=100)はこのコードの対象外です。「標準・クラスモジュールのVBAロジック変更を追う」用途には十分ですが、フォームのイベントコードや定義ごとバックアップしたい場合はSaveAsText(後述)を使います。
このコードは遅延バインディング(As Object)を使っているためVBE Extensibility 5.3の参照設定は不要です。なお、Microsoftのサポートドキュメントによると、AccessにはExcelなどで表示される「VBAプロジェクトオブジェクトモデルへのアクセスを信頼する」設定はありません。実行にはVBAプロジェクトが表示可能な状態(パスワードでロックされていない)で、かつ保存先フォルダへの作成・削除権限があることが必要です。早期バインディングやvbext_ct_StdModule等の定数名を使う場合はExtensibility 5.3の参照設定が追加で必要になります。
手法2:SaveAsText/LoadFromTextでフォームやレポートも含めてテキスト化する
Application.SaveAsTextは、フォーム・レポート・クエリ・マクロ・標準モジュールをテキストファイルとして書き出すメソッドです。Microsoft Learnのリファレンス(Access 2019/2024対象)に構文と使用例が掲載されています。
ただし、このメソッドの位置づけには注意が必要です。Microsoftが2006年に公開した旧ブログ記事では「隠し・ドキュメント化されていない機能」と明記されており、「バージョン管理のためのエクスポートポイントとして設計されたものではなく、ウィザードがAccess定義をプリセットから作成するための仕組みとして実装された」と書かれています。現在はSaveAsTextはMicrosoft Learnにページがありますが、LoadFromTextは同じ公式ドキュメント内で「サポートされていないが広く使われている(unsupported but widely used)」と明記されています。本番運用で使う場合は、動作をよく確認したうえで、将来のAccessバージョンアップで挙動が変わる可能性を想定した運用にしてください。
' フォーム "F_受注一覧" をテキストファイルとして書き出す
Application.SaveAsText acForm, "F_受注一覧", "C:\repo\forms\F_受注一覧.txt"
' テキストから復元する
' ※当社検証では同名オブジェクトは警告なしに置換された(非サポート機能のため動作は保証されない)
Application.LoadFromText acForm, "F_受注一覧", "C:\repo\forms\F_受注一覧.txt"SaveAsTextが対応する主なオブジェクト種別は、acForm・acReport・acQuery・acMacro・acModule です。テーブル定義(acTable)には対応していません(公式解説によると「テーブルの保存はこのメカニズムの対象外」と明記)。
出力されるテキストはAccess独自のプロパティ記述形式で、人間が読むには少し癖があります。差分を取るだけなら十分で、「フォームにボタンを追加した」「クエリの条件を変えた」程度の変更はdiffで把握できます。
ただし復元(LoadFromText)には注意が必要です。LoadFromTextの公式ドキュメントには「複雑なサブクエリを含むクエリでは、ロード時にクエリが破損することがある」と明記されています。本番データベースに直接LoadFromTextで復元する前に、テスト環境でのVerificationを行うことを推奨します。
手法の比較と使い分け
| 手法 | 対象 | 公式度 | テキスト可読性 | 主な用途 |
|---|---|---|---|---|
| VBE Export(.bas/.cls) | 標準モジュール・クラスモジュール | 公式(VBEドキュメントに記載) | 高い(VBAソースを中心としたテキスト形式。属性行が一部含まれる) | VBAロジックのGit管理・コードレビュー |
| SaveAsText / LoadFromText | フォーム・レポート・クエリ・マクロ・モジュール | SaveAsTextはLearnに掲載。LoadFromTextは「non-supported」と公式に明記 | 中程度(Access独自形式) | フォーム定義を含む広範囲のバックアップ |
| .accdbのファイルコピー(世代管理) | データベース全体(テーブルデータ含む) | 標準的な手段(全ユーザーがファイルを閉じた状態でコピーすること) | なし(バイナリ) | 世代ロールバック・災害対策 |
当社の実務では、VBAロジックの変更追跡には VBE Export + Git を使い、定期的な世代バックアップには.accdbのファイルコピーを併用するパターンが現実的だと考えています。SaveAsTextはフォームの変更履歴を残したい場合に追加で使う、という位置づけです。
命名・コメント規約で変更を追いやすくする
バージョン管理の仕組みを整えても、モジュール名や変数名がバラバラだと、コミット履歴から「何を変えたか」を読み取りにくくなります。最低限の規約を決めておくと差分が読みやすくなります。
| 対象 | 規約の例 | 理由 |
|---|---|---|
| 標準モジュール名 | 機能単位で分割(mod_受注処理、mod_在庫など) | 1モジュールの変更が他に波及しにくい |
| プロシージャの先頭コメント | 処理概要・引数・更新日・変更理由を1〜4行で記述 | Git logがない環境でも経緯を追える |
| 変更箇所のインラインコメント | '[2025-11-08 変更者名] 理由: ○○に対応 | 差分と理由を1か所で確認できる |
| 廃止したコードの扱い | 削除する(コメントアウトして残さない) | 「なぜコメントアウトされているか」が不明になるため |
コメントアウトして残すのは、削除した理由がわからなくなるのでむしろ混乱の原因になります。Gitがあればいつでも復元できるため、不要なコードは思い切って削除するほうがコードベースが読みやすくなります。
.accdbファイル自体の世代バックアップとの組み合わせ
テキストエクスポートでVBAの変更履歴は追えますが、テーブルのデータをロールバックしたい場合や、SaveAsTextでバックアップしていないオブジェクトを含めてデータベース全体を一括復元したい場合は.accdbのファイルコピーが必要です。「VBAのコミット履歴」と「.accdbの世代バックアップ」は目的が違うため、両方を並行して運用します。
.accdbの世代バックアップの設計については延命中のAccessを守るバックアップ設計に詳しくまとめています。バックアップ先にOneDriveや共有フォルダを使う場合の注意点(同期の競合・ファイルロック)も確認してください。
VBAが複雑化・属人化している場合は、エクスポートしたコードを整理する前に現状の把握が先決です。コードの改修や移行を検討しているなら、無料の解析可否チェックで現状のVBAの複雑度を確認してから進める方法もあります。
なお、VBAのPコードが肥大化して動作が不安定になった場合の対処はAccessの/decompileとはで解説しています。
よくある質問
Q. SaveAsTextは公式にサポートされていますか。
SaveAsTextはMicrosoft Learn(Access 2019/2024対象)にリファレンスページがあります。一方、LoadFromTextは同じくLearnに掲載されていますが、ドキュメント内に「unsupported but widely used by developers」と明記されており、Microsoftはサポート対象外と位置づけています。当社としては、使う前に動作確認をしたうえで、Accessのバージョンアップ時に挙動が変わる可能性を想定した運用にすることを推奨します。
Q. SaveAsTextはテーブル定義にも使えますか。
対応していません。Microsoftの解説によると、SaveAsText/LoadFromTextはフォーム・レポート・クエリ・マクロ・モジュールが対象で、「テーブルの保存はこの仕組みの対象外(for historical reasons)」と明記されています。テーブル定義のバックアップには.accdbのファイルコピーか、SQLでのスキーマ書き出しを使います。
Q. VBEのエクスポートとSaveAsTextのどちらを使えばよいですか。
「VBAロジックだけ追えればよい」ならVBE Export(.bas/.cls)が素直です。出力がVBAコードそのものなので差分が読みやすく、VBEの標準機能です。フォームのレイアウト変更やクエリの変更履歴も残したい場合はSaveAsTextを追加で使います。ただしSaveAsTextの出力はAccess独自形式で可読性が下がるため、差分チェックは限定的になります。
Q. Gitを使っていない環境でもコード管理できますか。
できます。VBE Exportでモジュールを.basファイルに書き出し、ファイル名に日付を付けてフォルダに保存するだけでも、変更前のコードに戻せる手がかりになります。Gitほどの追跡精度はありませんが、「昨日の状態に戻したい」という局面では十分機能します。定期エクスポートをバックアップ運用のルーティンに組み込むのが現実的です。
触れないAccessが「診断できるか」だけ、確かめませんか。
顧客データは送信不要。発注の義務もありません。
約2分・ファイル送信不要・発注義務なし/説明はオンライン・売り込みはしません