【入門編】DoCmd.TransferSpreadsheetの「インポートエラーテーブル」を監視する自動例外処理 – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。チーフアーキテクトの私です。

現場でバリバリとシステムを組んでいると、避けて通れないのが「外部からのデータの取り込み(インポート)」です。ExcelのデータをポチポチとAccessに取り込む……よくある業務ですよね。

ここであなたに質問です。
`DoCmd.TransferSpreadsheet` メソッドを使ってExcelを取り込んでいるとき、「日付を入れるべきセルに文字列が入っていた」「データが長すぎてフィールドに入りきらなかった」といった理由で、インポートがしれっと失敗(または一部スキップ)したことはありませんか?

Accessは優しい(?)ので、エラーが起きた行をスルーして、勝手に「インポートエラー」という名のテーブルを裏で作ってくれます。でも、これ、現場のユーザーからすると「あれ?データが足りないんだけど!」という大クレームに直結する恐怖の仕様なんです。

今回は、この「見えないエラー」をVBAで完璧に監視し、自動で検知してユーザーを優しく守るための「極限のエラーハンドリング術」を伝授します。ここをクリアすれば、あなたの作るAccessアプリは一気に「プロのシステム」の仲間入りですよ!

1. なぜ「インポートエラーテーブル」を監視しなければならないのか?

`DoCmd.TransferSpreadsheet` は、VBAのコードとしては非常にシンプルで書きやすい命令です。

‘ Excelファイルを取り込む基本のコード
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, “T_売上データ”, “C:\Data\Uriage.xlsx”, True

このコード自体はエラー(VBAの実行時エラー)になりません。なぜなら、Accessは「データの不整合があっても、読める部分だけ読んで、ダメだった行はエラーテーブルに退避させておいたよ!」という親切心を発動するからです。

その結果何が起きるか?

  • VBE(VBAの画面)では「エラーなし」でプログラムが完了する。
  • テーブル `T_売上データ` を開くと、おかしなデータが抜けている。
  • アクセスの裏側には `T_売上データムーブエラー``インポートエラー` といった、見慣れないテーブルがこっそり生成されている。

現場のユーザーがこれに気づくわけがありません。「システムが勝手にデータを消した!」と誤解されるのがオチです。だからこそ、「インポートの直後に、エラーテーブルが生まれていないかをVBAで監視し、あれば即座にキャッチして警告する」という防衛策が必要なのです。

2. エラー監視メカニズムの全体像

今回構築する仕組みの流れはこうです。

1. 事前掃除: インポート前に、もし過去のエラーテーブルが残っていれば削除しておく。
2. インポート実行: `DoCmd.TransferSpreadsheet` でExcelを取り込む。
3. 事後監視: `CurrentDb.TableDefs` を走査し、「〇〇_ImportErrors」や「〇〇ムーブエラー」といったエラーテーブルが生成されたかをチェックする。
4. フィードバック: 発見した場合、エラーの内容をわかりやすくユーザーにポップアップで伝え、処理を安全に中断(またはロールバック)する。

図解するなら、まさに「工場の検品ライン」です。流れてきた製品をそのまま出荷せず、不良品を検知するセンサーを置くイメージですね。

3. 実装コード:実務でそのまま使える堅牢なファンクション

それでは、開発現場でコピペしてすぐに使えるプロ仕様のコードをお見せします。
今回は、エラー監視を組み込んだスマートなインポート用のプロシージャを書きました。

Option Compare Database
Option Explicit

‘ ==============================================================================
‘ 担当:チーフアーキテクト
‘ 概要:エラーテーブルの自動検知機能付き Excelインポートプロシージャ
‘ ==============================================================================
Public Sub ImportExcelWithSafetyCheck()

Dim strExcelPath As String
Dim strTargetTable As String
Dim tdf As TableDef
Dim bolErrorFound As Boolean
Dim strErrorTableName As String
Dim ws As Workspace

‘ 0. 事前設定
strExcelPath = “C:\Data\Uriage_2023.xlsx” ‘ 取り込むExcelのパス
strTargetTable = “T_売上データ” ‘ 格納先のテーブル名
bolErrorFound = False

‘ トランザクション制御の準備(高度な安全性のためにWorkspacesを使用)
Set ws = DBEngine.Workspaces(0)
ws.BeginTrans

On Error GoTo ErrorHandler

‘ 1. 【事前掃除】もし以前のエラーテーブルが残っていれば削除しておく
Call CleanupExistingErrorTables(strTargetTable)

‘ 2. 【実行】Excelのインポート
‘ ヘッダーあり(True)の前提
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, _
strTargetTable, strExcelPath, True

‘ 3. 【監視】CurrentDbを走査して、エラーテーブルが生成されたかチェック
‘ Accessはエラー時、”[テーブル名] + エラー” または “[テーブル名] + ムーブエラー” を自動生成する
For Each tdf In CurrentDb.TableDefs
If tdf.Name Like strTargetTable & “エラー” Or _
tdf.Name Like strTargetTable & “Error” Then
bolErrorFound = True
strErrorTableName = tdf.Name
Exit For
End If
Next tdf

‘ 4. 【判定とフィードバック】
If bolErrorFound Then
‘ エラーテーブルを発見した場合:処理をキャンセルしてロールバック
ws.Rollback

MsgBox “【インポート中断】” & vbCrLf & _
“Excelデータの中に、Accessのデータ型と一致しない不正なセルが含まれています。” & vbCrLf & _
“データの型(数値や日付など)を確認し、Excelを修正してから再度実行してください。” & vbCrLf & _
vbCrLf & “生成されたエラーテーブル: ” & strErrorTableName, _
vbCritical, “データインポートエラー”

Exit Sub
End If

‘ エラーがない場合は変更を確定
ws.CommitTrans

MsgBox “データのインポートが正常に完了しました!”, vbInformation, “完了”
Exit Sub

ErrorHandler:
‘ 予期せぬVBAエラー(ファイルが開いている、パスが違うなど)
ws.Rollback
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”

End Sub

‘ ——————————————————————————
‘ 補助プロシージャ:既存のエラーテーブルを安全に削除する
‘ ——————————————————————————
Private Sub CleanupExistingErrorTables(ByVal baseTableName As String)
Dim tdf As TableDef

‘ 念のため最新の定義を反映
CurrentDb.TableDefs.Refresh

For Each tdf In CurrentDb.TableDefs
If tdf.Name Like baseTableName & “エラー” Or _
tdf.Name Like baseTableName & “Error” Then
DoCmd.DeleteObject acTable, tdf.Name
End If
Next tdf
End Sub

4. コードの深掘りポイント(知るべき本質)

このコードには、実務で生き抜くための「エンジニアの知見」がいくつも詰め込まれています。初学者から一歩抜け出すために、重要なポイントを解説しておきますね。

① `TableDefs` と `Like` 演算子による動的監視

Accessが生成するエラーテーブルの名前は、厳密には元のテーブル名に「ムーブエラー」や「インポート エラー」といった接尾辞がついたものになります。環境(Accessのバージョンなど)によって微妙に名前が変わることもあるため、固定の名前で決め打ちするのは危険です。
ここでは `Like strTargetTable & “エラー”` というワイルドカードを使ったパターンマッチングを使い、「どの名前でエラーテーブルが生成されても確実に検知する」仕組みにしています。

② トランザクション(`BeginTrans` / `Rollback`)の重要性

もしインポートの途中でエラー行が大量発生した場合、そのまま放置すると「半分だけデータが入った中途半端な状態」になります。
これを防ぐために `ws.BeginTrans` で処理を囲み、エラーテーブルを検知した瞬間に `ws.Rollback` で「インポートそのものを無かったこと(巻き戻し)」にしています。これにより、データベースの整合性が完璧に保たれます。

5. まとめ:ここをクリアすればAccess VBAの基本はバッチリ!

お疲れ様でした!今回は `DoCmd.TransferSpreadsheet` の裏側で起きているドラマと、それを制御する自動例外処理のコードを解説しました。

  • Accessはエラーが起きても止まらず、裏で「エラーテーブル」を作る。
  • プロはそれを `TableDefs` で監視し、ユーザーに放置させない。
  • トランザクションを使って、中途半端なデータの侵入を防ぐ。

このレベルのエラーハンドリングが書けるようになれば、あなたが作るAccessシステムは、現場のユーザーから「エラーで止まらない、信頼できるシステムだね!」と絶賛されるはずです。

ぜひご自身の開発環境にこのコードを取り入れて、ワンランク上のAccess VBAエンジニアを目指してくださいね。応援しています!

タイトルとURLをコピーしました