DoCmd.TransferSpreadsheetの「甘い誘惑」を断ち切り、堅牢なデータパイプラインを構築する
Accessエンジニアであれば、一度は経験があるはずだ。`DoCmd.TransferSpreadsheet`を実行し、意気揚々と結果を確認した瞬間に「エラーログテーブル」が生成されている絶望的な光景を。
「なぜ、ただExcelを読み込むだけで型不一致が起きるのか?」
答えは単純だ。AccessがExcelの先頭数行を見て、勝手に列のデータ型を「推測」しているからだ。 この「推測機能」は、小規模なプロトタイプには適しているが、実務レベルの業務システムにおいては、システムの信頼性を根底から破壊する時限爆弾に他ならない。
本稿では、この「推測の罠」を回避し、プロフェッショナルとして恥ずかしくない、堅牢なインポート設計を伝授する。
—
1. なぜ「推測」に頼ってはいけないのか
Accessのインポートエンジンは、先頭の数行をスキャンしてデータ型を決定する。もし、1行目が空欄であればテキスト型と判断され、その後に数値が入っていればエラーとなり、逆に数値が並んでいれば数値型と判断され、後から混入したテキストデータは「切り捨て」か「エラー」となる。
この挙動を「仕様だから」と許容してはならない。データ型を制御できないシステムは、自動化とは呼ばない。ただのギャンブルだ。
—
2. 解決策:インポート定義(Specification)の強制
最も確実な回避策は、GUIで作成した「インポート定義」をコードから呼び出すことだ。これにより、列ごとのデータ型を明示的に固定できる。
手順
1. Accessの「外部データ」タブからExcelファイルを読み込むウィザードを起動する。
2. 途中で「詳細設定」ボタンを押し、各列のデータ型を厳密に定義する。
3. その設定を名前を付けて保存する(例: `Import_Spec_SalesData`)。
この定義さえあれば、VBA側で型推測を無効化できる。
—
3. プロダクションコード:堅牢なインポート実装
以下に、実務でそのまま使える、エラーハンドリングを備えたクラスライブラリ的な実装コードを提示する。
‘ =============================================================
‘ 堅牢なExcelインポート処理
‘ ————————————————————-
Public Sub ImportExcelRobustly(ByVal filePath As String, ByVal tableName As String)
Const SPEC_NAME As String = “Import_Spec_SalesData” ‘ 事前に保存したインポート定義名
‘ エラーハンドリングの徹底
On Error GoTo Err_Handler
‘ 1. ファイルの存在確認(基本中の基本だが、ここを怠る者が多すぎる)
If Dir(filePath) = “” Then
Err.Raise vbObjectError + 1, , “インポート対象のファイルが見つかりません: ” & filePath
End If
‘ 2. 一時テーブルのクリア(または既存データの削除)
‘ 実務では、直接テーブルを上書きするのではなく、ステージングテーブルを経由させるのが鉄則
CurrentDb.Execute “DELETE FROM ” & tableName, dbFailOnError
‘ 3. インポート定義を用いた実行
‘ HasFieldNames:=True を明示し、推測を排除する
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, _
tableName, filePath, True, , SPEC_NAME
MsgBox “インポートが正常に完了しました。”, vbInformation
Exit Sub
Err_Handler:
‘ エラーが発生した際、どのファイルで何が起きたかをログに出力する設計にする
MsgBox “致命的なエラーが発生しました:” & vbCrLf & Err.Description, vbCritical
End Sub
—
4. プロの視点:さらなる高みへ
このコードを「完成」としてはいけない。真のエンジニアは、さらに一歩先を見据える。
- ステージングテーブルの活用: 直接本番テーブルに読み込むのではなく、一度「取り込み用の一時テーブル」に読み込み、そこで値の検証(バリデーション)を行い、クエリ(`INSERT INTO … SELECT`)で本番テーブルへ転記する。これがデータ整合性を守るための唯一の「聖域」だ。
- 型変換エラーログの追跡: `DoCmd.TransferSpreadsheet`で生じたエラーは、`ImportErrors`テーブルに自動生成される。このテーブルの存在を定期的にチェックし、ユーザーに通知する仕組みを組み込むことが、運用の安定化に直結する。
結びに代えて
「とりあえず動くコード」を書くのは、初心者でもできる。しかし、「仕様外の入力に対しても壊れず、万が一の時に原因が即座に特定できるコード」を書くのが、我々プロフェッショナルの仕事だ。
Accessは古いツールと言われることもあるが、適切に設計されたAccessアプリケーションは、巨大なERPにも負けない信頼性を発揮する。次にExcelファイルをインポートする際は、ぜひこの「インポート定義」という武器を思い出してほしい。
あなたの書くコードが、誰かの業務の重荷を下ろすものであることを確信している。健闘を祈る。
