Accessを「ドキュメントの墓場」にするな:DAOで掴む真実のデータ辞書自動生成術
現場でよく見る光景がある。システム改修のたびにExcelの仕様書とAccessの実態が乖離し、誰も仕様を把握できずに「とりあえず動くコード」が積み上がっていく。「仕様書は動くコードの中にしかない」という言葉は真理だが、それをドキュメントとして抽出できないエンジニアは三流だ。
今日は、Accessの`TableDef`を掌握し、現在のデータ構造を「正」としてExcel仕様書を自動生成する、堅牢なデータ辞書生成エンジンを授ける。
なぜ「手動メンテ」が崩壊するのか
多くの開発者は、仕様書をExcelで管理し、テーブル設計をAccessで行う。この「二重管理」が悲劇の元凶だ。
今回実装するのは、「Accessのシステムテーブルこそが唯一の正解である」という前提に立った自動化ツールだ。DAO(Data Access Objects)を使い倒し、型、サイズ、インデックス、リレーションシップまでを余すことなく抽出する。
極限まで削ぎ落とされたプロダクションコード
このコードは、エラーハンドリングを最小限に抑えつつ、保守性を高めるためにクラスに近いモジュール構成を意識している。
Option Compare Database
Option Explicit
‘ @brief Access内の全テーブルからデータ辞書をExcelに出力する
‘ @note DAO.TableDefを走査し、システムテーブル(MSys)を除外してメタデータを抽出する
Public Sub GenerateDataDictionary()
Dim db As DAO.Database
Dim td As DAO.TableDef
Dim fld As DAO.Field
Dim row As Long
Dim xlApp As Object, xlBook As Object, xlSheet As Object
Set db = CurrentDb
Set xlApp = CreateObject(“Excel.Application”)
Set xlBook = xlApp.Workbooks.Add
Set xlSheet = xlBook.Sheets(1)
‘ ヘッダーの設定
xlSheet.Range(“A1:G1”).Value = Array(“テーブル名”, “フィールド名”, “データ型”, “サイズ”, “必須”, “主キー”, “説明”)
row = 2
‘ テーブルの走査
For Each td In db.TableDefs
‘ システムテーブル(MSysで始まるもの)と一時テーブルを除外する
If Left(td.Name, 4) <> “MSys” Then
For Each fld In td.Fields
xlSheet.Cells(row, 1).Value = td.Name
xlSheet.Cells(row, 2).Value = fld.Name
xlSheet.Cells(row, 3).Value = GetDataTypeName(fld.Type)
xlSheet.Cells(row, 4).Value = fld.Size
xlSheet.Cells(row, 5).Value = IIf(fld.Required, “はい”, “いいえ”)
xlSheet.Cells(row, 6).Value = IIf(IsPrimaryKey(td, fld.Name), “●”, “”)
xlSheet.Cells(row, 7).Value = GetFieldDescription(td, fld.Name)
row = row + 1
Next fld
End If
Next td
xlApp.Visible = True
MsgBox “データ辞書の生成が完了しました。”, vbInformation
End Sub
‘ データ型の整数値を文字列に変換
Private Function GetDataTypeName(dataType As Integer) As String
Select Case dataType
Case dbLong: GetDataTypeName = “長整数型”
Case dbText: GetDataTypeName = “テキスト型”
Case dbDate: GetDataTypeName = “日付/時刻型”
Case dbBoolean: GetDataTypeName = “Yes/No型”
‘ 必要に応じて拡充すること
Case Else: GetDataTypeName = “その他(” & dataType & “)”
End Select
End Function
‘ 主キー判定(TableDef.Indexesを解析)
Private Function IsPrimaryKey(td As DAO.TableDef, fieldName As String) As Boolean
Dim idx As DAO.Index
For Each idx In td.Indexes
If idx.Primary Then
If InStr(idx.Fields, fieldName) > 0 Then
IsPrimaryKey = True: Exit Function
End If
End If
Next idx
End Function
‘ フィールド説明の取得(Propertyが存在しない場合のケアが必要)
Private Function GetFieldDescription(td As DAO.TableDef, fieldName As String) As String
On Error Resume Next
GetFieldDescription = td.Fields(fieldName).Properties(“Description”).Value
End Function
伝説のエンジニアからの3つの提言
1. `On Error Resume Next` の正しい使い方
プロパティ(Descriptionなど)は、未設定だとエラーを吐く。この場合、安易なエラー回避ではなく、「値がないなら空文字を返す」というロジックをプロシージャ単位で完結させること。これにより、メインループを汚染させない。
2. テーブル定義の「深淵」に触れる
リレーションシップ(`db.Relations`)は`TableDef`とは別のオブジェクト階層にある。より高度な仕様書を作るなら、`db.Relations`をループして、テーブル間の結合キーもドキュメント化せよ。これこそが、物理設計の全貌を可視化する唯一の道だ。
3. パフォーマンスとメモリ管理
DAOのオブジェクトは明示的に解放しなくてもVBAがガベージコレクションするが、Excelインスタンス(`CreateObject`)は別だ。もしこのツールを大規模なデータで回すなら、`xlApp`を適切に終了させるコードを書かないと、バックグラウンドにゾンビプロセスが溜まり、メモリリークの元になる。
まとめ
「仕様書を更新する」という無駄な作業からエンジニアを解放せよ。Accessという強力なメタデータ保持エンジンを最大限に活用し、「実行環境からドキュメントが湧き出る」仕組みを作ることが、真の業務効率化だ。
さあ、このコードをあなたの環境にコピペし、今すぐ「陳腐化した仕様書」という名のゴミを捨て去る準備を始めなさい。
