こんにちは!現場でバリバリ動くAccessシステムを作っていると、避けて通れないのが「Excelデータとの連携」ですよね。
「毎日送られてくるExcelの売上データを、ボタン一つでAccessに取り込みたい!」
そんなときによく使われるのが、`DoCmd.TransferSpreadsheet` という魔法のような命令です。
でも、現場のデータって魔境です。
「日付を入れるべき場所に『未定』と書いてある」「数値のつもり全角で『123』が入っている」……。
こういうデータが混ざっていると、Accessはインポートの途中で機嫌を損ね、エラーを起こしてしまいます。
今回は、このエラーをただ放置するのではなく、「自動でエラーテーブルを監視し、どこがダメだったのかを優しく捕まえてログに残す」 という、ワンランク上の自動例外処理の極意を伝授します。
ここをクリアすれば、あなたの作るAccessアプリは一気に「プロのシステム」の仲間入りですよ!
—
1. なぜExcelインポートは失敗するのか?(Accessの裏側の仕組み)
`DoCmd.TransferSpreadsheet` を実行したとき、Accessは裏側で必死にデータを詰め込みます。
この時、型が合わない(文字列を数値に入れようとしたなど)データに出会うと、Accessはこう判断します。
> 「全体の取り込みは続けるけど、この行だけはルール違反だから除外して、代わりに『エラーテーブル』に記録しておこう!」
Accessは親切心で、自動的に `ImportErrors` といった名前のエラーテーブルをこっそり作ってくれるんです。
しかし、現場のユーザーが毎回このテーブルを探して「どれがエラーだったか確認して」とやるのは、あまりに不親切ですよね。
だからこそ、VBAでこのエラーテーブルの存在を自動で監視し、失敗したレコードをスマートに救出・記録する仕組み を作る必要があるのです。
—
2. 全体設計:エラー監視つきインポートのフロー
私たちが目指す自動化の流れはこうです。
1. お掃除: 以前残っていた古いエラーテーブルをあらかじめ削除しておく。
2. 実行: `DoCmd.TransferSpreadsheet` でExcelを取り込む。
3. 監視: エラーテーブル(Accessが自動生成するもの)が新しく生まれたかチェックする。
4. 記録(例外処理): もしエラーがあれば、中身を読み取って独自のログテーブルに避難させ、ユーザーに優しく通知する。
これらをすべてVBAのコード1つにまとめ上げます。
—
3. 実装コード:実戦で使える堅牢なプロシージャ
それでは、開発環境でそのままコピペして使えるコードを公開します。
標準モジュールに貼り付けて、コメントを読みながら構造を味わってみてください。
Option Compare Database
Option Explicit
‘ =========================================================================
‘ テーマ: Excelインポートのエラー自動監視と例外処理
‘ 概要: TransferSpreadsheet実行後のエラーテーブルを捕捉し、ログに残す
‘ =========================================================================
Public Sub ImportExcelWithExceptionHandling()
On Error GoTo ErrorHandler ‘ 予期せぬVBA自体のエラーを捕捉するため
Dim db As DAO.Database
Set db = CurrentDb
‘ — 設定値 —
Const TARGET_TABLE As String = “T_Mst_Product” ‘ 取り込み先のテーブル名
Const ERROR_TABLE_PREFIX As String = “T_Mst_Product_ImportErrors” ‘ Accessが自動生成するエラーテーブル名
Dim excelPath As String
excelPath = CurrentProject.Path & “\ProductData.xlsx” ‘ 読み込むExcelのパス
‘ —————————————————————–
‘ ステップ1: 事前準備(前回残った古いエラーテーブルの残骸を掃除する)
‘ —————————————————————–
If TableExists(ERROR_TABLE_PREFIX) Then
DoCmd.SetWarnings False
DoCmd.DeleteObject acTable, ERROR_TABLE_PREFIX
DoCmd.SetWarnings True
End If
‘ —————————————————————–
‘ ステップ2: インポートの実行
‘ —————————————————————–
‘ acImport: インポート, acSpreadsheetTypeExcel12Xml: Excel形式(xlsx)
‘ 第4引数(True): 先頭行をフィールド名として使用する
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, _
TARGET_TABLE, excelPath, True
‘ —————————————————————–
‘ ステップ3: エラーテーブルの監視と例外処理
‘ —————————————————————–
If TableExists(ERROR_TABLE_PREFIX) Then
‘ エラーテーブルが存在する場合 = インポート時にデータ型不一致などの弾かれた行がある!
MsgBox “⚠️ インポートは完了しましたが、一部のレコードでデータ型のエラーが発生しました。” & vbCrLf & _
“詳細はエラーログテーブルを確認してください。”, vbExclamation, “警告:一部スキップ”
‘ ここで独自のログテーブルに退避させたり、担当者にメールを送る処理を書くことができます。
‘ 例: エラーテーブルのレコード数をカウントしてログに残すなど
Call RecordErrorLog(ERROR_TABLE_PREFIX)
Else
‘ エラーが一切ない完璧な状態
MsgBox “✨ Excelデータのインポートがエラーなしで正常に完了しました!”, vbInformation, “成功”
End If
Exit Sub
ErrorHandler:
‘ VBA自体の実行時エラー(ファイルが見つからない、テーブルが排他制御されている等)
DoCmd.SetWarnings True
MsgBox “❌ 致命的なエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub
‘ =========================================================================
‘ 補助関数: 指定した名前のテーブルがデータベース内に存在するか判定する
‘ =========================================================================
Private Function TableExists(ByVal tableName As String) As Boolean
Dim tdf As DAO.TableDef
TableExists = False
For Each tdf In CurrentDb.TableDefs
If tdf.Name = tableName Then
TableExists = True
Exit For
End If
Next tdf
End Function
‘ =========================================================================
‘ 補助プロシージャ: エラーログの記録処理(実務向けの拡張ポイント)
‘ =========================================================================
Private Sub RecordErrorLog(ByVal errTableName As String)
Dim db As DAO.Database
Set db = CurrentDb
‘ ここでは例として、デバッグウィンドウにエラー件数を出力しています
Dim errCount As Long
errCount = db.OpenRecordset(“SELECT Count() FROM [” & errTableName & “]”)(0)
Debug.Print “【インポートエラー発生】日時: ” & Now & ” / 失敗件数: ” & errCount & “件”
‘ ※実務では、ここで「T_Error_History」のような独自のログテーブルに
‘ INSERT文を使ってエラー内容を蓄積していくと、後から監査できて非常に喜ばれます。
End Sub
—
4. チーフアーキテクトからのワンポイントアドバイス
このコードを書く上で、プログラマーとして絶対に知っておいてほしい「Accessの癖」が2つあります。
1. エラーテーブルの命名規則に注意
Accessが自動生成するエラーテーブルの名前は、原則として `[インポート先テーブル名] + “ImportErrors”` になります。ただし、すでにその名前のテーブルが存在する場合は末尾に数字が振られることもあるため、上記コードのように事前に存在チェック(`TableExists`関数)を挟むのが極限まで安定させるコツです。
2. `DoCmd.SetWarnings` の罠
エラーテーブルを削除する際に `DoCmd.SetWarnings False` を使っていますが、これを使いっぱなしにしてエラーでプロシージャが中断すると、Access全体の警告メッセージが出なくなってしまうバグ(状態の汚染)を引き起こします。必ずエラー時でも元に戻るような構文(または今回のコードのように `On Error GoTo` で確実にケアする)を心がけましょう。
—
まとめ
いかがでしたでしょうか?
「ただExcelを取り込むだけのコード」から、「失敗したデータを監視し、アプリケーション側でハンドリングするコード」へステップアップすることで、システムの信頼性は劇的に向上します。
「ここをクリアすれば、Access VBAの基本はバッチリですよ!」
ぜひ、あなたの現場のシステムにもこの「例外監視の眼」を組み込んでみてください。圧倒的にトラブルに強い、美しいデータベースが構築できるはずです。
