Access VBAの「サイレント・インポート」は業務の敵だ:インポートエラーを制する堅牢な設計
多くのAccess開発者が陥る罠がある。`DoCmd.TransferSpreadsheet`を実行し、無事に処理が終わったと安堵する瞬間だ。だが、その裏でAccessはひっそりと「インポートエラー」という名の呪いをデータベースに植え付けている。
データ型不一致、空文字の混入、桁数オーバー。これらが起きたとき、Accessは標準機能として「インポートエラー」テーブルを自動生成する。しかし、多くの現場ではこのテーブルの存在が放置され、翌日には数百ものゴミテーブルがデータベースを肥大化させている。
本稿では、この「インポートエラー」を検知し、即座に制御するプロフェッショナルな実装手法を伝授する。
—
なぜ「そのまま」ではいけないのか
`DoCmd.TransferSpreadsheet`は、失敗してもVBAの実行を止めないことが多い。ユーザーは「インポート完了」というメッセージボックスを見て安心するが、肝心なデータは一行も取り込まれていない——これが最も恐ろしいケースだ。
真のエンジニアは、「操作の成功」ではなく「操作後の状態」を常に監視する。
エラーテーブルの発生を検知し、ユーザーに「どの行の何が原因か」を明確にフィードバックする。これこそが、業務自動化ツールに求められる「信頼性」の正体だ。
—
実践:エラー監視付きインポート・モジュール
以下のコードは、単なるインポート実行に留まらない。「実行前準備」「実行」「エラー検知」「後処理」という、堅牢なライフサイクルを構築している。
‘ —————————————————————————
‘ 関数名:ImportExcelRobust
‘ 概要:エラーテーブルを監視し、失敗時に即座に検知する堅牢なインポート処理
‘ —————————————————————————
Public Sub ImportExcelRobust(strFilePath As String, strTableName As String)
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strErrorTable As String
Dim isErrorDetected As Boolean
Set db = CurrentDb
‘ 1. 事前にインポート先テーブルが存在する場合はクリア(またはバックアップ)
‘ ※本番環境ではトランザクション制御を推奨
‘ 2. インポート実行
On Error Resume Next
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, strTableName, strFilePath, True
On Error GoTo 0
‘ 3. インポートエラーテーブルを探索
‘ Accessはエラー発生時、インポート先テーブル名 + “$_ImportErrors” という名前で作成する
strErrorTable = strTableName & “$_ImportErrors”
isErrorDetected = False
For Each tdf In db.TableDefs
If tdf.Name = strErrorTable Then
isErrorDetected = True
Exit For
End If
Next tdf
‘ 4. エラー検知時の処理
If isErrorDetected Then
MsgBox “インポート処理でデータ不整合が発生しました。” & vbCrLf & _
“詳細を[” & strErrorTable & “]テーブルに出力しましたので確認してください。”, _
vbCritical, “自動インポート失敗”
‘ 必要に応じてここでログ出力や管理者にメール通知を行うロジックを挿入
Else
MsgBox “データインポートが正常に完了しました。”, vbInformation
End If
Set db = Nothing
End Sub
—
プロフェッショナルが教える設計の急所
1. エラーテーブルの「命名則」を逆手に取る
Accessの仕様では、エラーテーブル名は`[インポート先テーブル名] & “$_ImportErrors”`と決まっている。この「仕様上の制約」を監視対象にすることで、エラーハンドリングのロジックが極めてシンプルかつ高速になる。いちいち全てのテーブルの行数を比較する必要はない。
2. `CurrentDb`のキャッシュに注意せよ
大規模なシステムでは、`CurrentDb`を何度も呼び出すとメモリリークや同期ズレのリスクがある。必ずオブジェクト変数としてセットし、処理が終われば明示的に破棄(`Set db = Nothing`)する。この基本的な作法が、数ヶ月稼働した後の「謎のフリーズ」を防ぐ唯一の手段だ。
3. ユーザーへの「責任あるフィードバック」
エラーが起きた際、「インポートに失敗しました」とだけ出すのは怠慢だ。どのテーブルにエラーが格納されたのかを具体的に提示し、さらに可能であればそのテーブルの中身を自動的に開き(`DoCmd.OpenTable`)、ユーザーが「何が悪かったか」を即座に修正できるUI/UXを設計する。
—
最後に:自動化とは「エラーを消す」ことではない
自動化エンジニアの役割は、エラーを隠蔽することではない。エラーを顕在化させ、誰が対応すべきかを明確にすることだ。
この実装をベースに、さらに「エラーテーブルの内容を自動でCSV出力して管理者にメールする」といった機能を追加すれば、あなたのツールは「動く」レベルから「組織のインフラ」へと昇華するはずだ。
コードは嘘をつかない。だが、仕様の隙間を埋めるのは常にエンジニアの知見だ。さあ、あなたのAccessを、誰よりも信頼性の高いシステムへと磨き上げてほしい。
