同じ形式のCSVを毎月や毎週Accessに取り込むとき、ウィザードで列の型や文字コードを毎回選び直していると、結果が回ごとに変わってしまいます。先頭の0が消える、日付が空欄になる、前回と列の型が違う、といったずれが起きます。取り込み条件を「インポート定義」として保存し、VBAの DoCmd.TransferText から定義名を指定すれば、毎回同じ条件で取り込めます。
この記事では、インポート定義の作り方、TransferTextの書き方、取り込み後に件数とエラーテーブルを確認する方法を順に説明します。
全体の流れ
- 取り込み先のテーブルを用意する
- テキストインポートウィザードでインポート定義を作り、名前を付けて保存する
- VBAの
DoCmd.TransferTextに、定義名・テーブル名・ファイルパス・見出しの有無を指定する - 取り込み後に件数を数える
- インポートエラーのテーブルが作られていないか確認する
先に区別しておく:「インポート定義」と「保存済みのインポート操作」
Accessには、名前の似た保存機能が2つあります。TransferTextで使えるのは片方だけです。
| 項目 | インポート定義 | 保存済みのインポート操作 |
|---|---|---|
| 作る場所 | テキストインポートウィザードの[設定]ボタン(英語版はAdvanced)で開く画面 | ウィザードの最後にある「インポート操作の保存」 |
| 保存される内容 | 区切り記号、文字列の引用符、コードページ、日付の形式、各列のフィールド名・データ型・スキップの有無 | ファイルパスや取り込み先を含めた操作一式 |
| VBAからの呼び出し | DoCmd.TransferText の SpecificationName に定義名を指定する |
DoCmd.RunSavedImportExport に操作名を指定する |
ウィザードの最後で操作を保存しても、TransferTextに渡す定義名は作られません。次の手順で、[設定]の画面から定義を保存してください。
手順1:取り込み先のテーブルを先に作る
TransferTextは、指定したテーブルが存在すればそこへレコードを追加し、存在しなければ新しいテーブルを作ります。毎回同じ型で受け取りたいなら、取り込み先のテーブルをデザインビューで先に作っておくほうが管理しやすくなります。
- フィールド名はCSVの見出しと同じにする(見出しありで取り込むと、名前で列が対応付けられるため)
- 顧客コードなどのコード類は短いテキスト型にする
- 本番のテーブルに直接取り込まない。「T_売上_取込」のような取り込み専用のテーブルに入れて確認し、そのあと追加クエリで本番へ移す
取り込み専用のテーブルを分けておけば、取り込みに失敗しても本番のデータが中途半端な状態になりません。
手順2:インポート定義を作って保存する
メニューの名前はAccessのバージョンによって多少異なります。お使いの画面の表示に読み替えてください。
- [外部データ]タブ →[新しいデータ ソース]→[ファイルから]→[テキスト ファイル]を選ぶ
- 取り込みたいCSVの見本ファイルを指定し、取り込み先として手順1のテーブルへの追加を選ぶ
- ウィザードで「区切り記号付き」を選び、画面左下の[設定]ボタンを押す
- 開いた画面で、下の表の項目を設定する
- [名前を付けて保存]で定義名を付けて保存する(例:
売上CSV_取込定義) - 同じ画面の[定義]ボタンで一覧を開き、保存した名前が表示されることを確認する
[設定]の画面で決める主な項目は次のとおりです。
| 項目 | 設定の考え方 |
|---|---|
| フィールドの区切り記号 | CSVならカンマ |
| 文字列の引用符 | 値を " で囲んでいるCSVなら " を指定する。指定しないと、値の中のカンマで列がずれる |
| コードページ | CSVの文字コードに合わせる。UTF-8なら「Unicode (UTF-8)」、Shift_JISなら「日本語 (シフト JIS)」など、一覧に表示される名前から選ぶ |
| 日付の順序・区切り記号・4桁の年 | CSV内の日付の書き方に合わせる(例:2026/10/06 なら年月日の順、区切りは /) |
| 先頭行をフィールド名として使う | 見出し行があるCSVならオン |
| フィールド情報 | 列ごとにフィールド名・データ型・スキップするかどうかを指定する |
フィールド情報では、特に次のような列の型を決めておきます。
| 列の例 | 型 | 理由 |
|---|---|---|
| 顧客コード、商品コード、郵便番号、電話番号 | 短いテキスト | 数値として読まれると先頭の0が消える |
| 金額、数量 | 通貨、または数値 | 計算に使う列なので数値系の型にする。小数があるかどうかで選ぶ |
| 取引日 | 日付/時刻 | 定義の日付の順序がCSVの書き方と合っていないと、変換エラーになる |
| 取り込まない列 | スキップ | テーブルにない列をそのまま渡さない |
既存のテーブルに追加する場合、最終的な型はテーブル側の設定で決まります。定義の型とテーブルの型をそろえておけば、どちらを見ても迷いません。
手順3:TransferTextで定義名を指定して取り込む
引数の対応
| 引数 | 指定する値 | 説明 |
|---|---|---|
| TransferType | acImportDelim |
区切り記号付きテキストを取り込む |
| SpecificationName | "売上CSV_取込定義" |
手順2で保存した定義名。一字一句合わせる |
| TableName | "T_売上_取込" |
取り込み先のテーブル |
| FileName | CSVのフルパス | 拡張子まで含める |
| HasFieldNames | True / False |
CSVの1行目が見出しならTrue |
| CodePage | 省略 | 文字コードは定義側で決める。引数でも指定できるが、まずは定義だけで指定して結果を確認する |
HasFieldNamesをFalseにすると、1行目もデータとして扱われます。見出しの文字列が1件目のレコードとして入ったり、型の合わない列でエラーになったりします。次の3つを必ずそろえてください。
- CSVの1行目が見出しかどうか
- 定義の「先頭行をフィールド名として使う」の設定
- HasFieldNamesの値
コード例
標準モジュールに貼り付けて使います。定義名・テーブル名・パスは、ご自分の環境に合わせて書き換えてください。
Option Explicit
Public Sub ImportSalesCsv()
Const SPEC_NAME As String = "売上CSV_取込定義"
Const TABLE_NAME As String = "T_売上_取込"
Dim filePath As String
Dim beforeCount As Long
Dim afterCount As Long
filePath = "C:\取込\sales_202610.csv"
If Dir(filePath) = "" Then
MsgBox "ファイルが見つかりません。" & vbCrLf & filePath, vbExclamation
Exit Sub
End If
beforeCount = DCount("*", TABLE_NAME)
DoCmd.TransferText TransferType:=acImportDelim, _
SpecificationName:=SPEC_NAME, _
TableName:=TABLE_NAME, _
FileName:=filePath, _
HasFieldNames:=True
afterCount = DCount("*", TABLE_NAME)
MsgBox "取り込み前: " & beforeCount & " 件" & vbCrLf & _
"取り込み後: " & afterCount & " 件" & vbCrLf & _
"増えた件数: " & (afterCount - beforeCount) & " 件", vbInformation
End Sub
DCount は、テーブルが存在しないとエラーになります。このコードは、手順1でテーブルを作ってあることが前提です。
取り込み専用テーブルを毎回空にしてから取り込む場合
取り込み専用のテーブルを毎回入れ替える運用なら、TransferTextの前に中身を削除します。削除は元に戻せません。対象が取り込み専用のテーブルであることを必ず確認してから使ってください。
CurrentDb.Execute "DELETE FROM [" & TABLE_NAME & "]", dbFailOnError
この行は、beforeCount を数える前に置きます。本番のテーブル名を入れて実行しないように、テーブル名に「取込」などの目印を付けておくと安全です。
手順4:件数を確認する
取り込みが終わったら、増えた件数がCSVのデータ行数と一致するかを確かめます。
- CSVをテキストエディタで開き、最終行の行番号から見出しの1行を引いた数と比べる
- 値の中に改行を含むCSVでは、エディタの行数とレコード数が一致しない。その場合は、CSVを出力した元のシステム側で出力件数を確認する
- 件数に加えて金額の列の合計も比べると、取り込み漏れや型変換の失敗に気づきやすい
金額の合計は、イミディエイトウィンドウで次のように確認できます(フィールド名は例です)。
? DSum("金額", "T_売上_取込")
手順5:インポートエラーのテーブルを確認する
取り込み中に変換できない値があると、Accessは「(ファイル名)_インポート エラー」のような名前のテーブルを自動で作ります(英語版では _ImportErrors を含む名前になります)。このテーブルには、エラーの内容、対象のフィールド、エラーが出た行の番号が記録されます。
注意したいのは、件数が合っていてもエラーが起きている場合があることです。型変換に失敗したレコードは、そのフィールドだけが空の状態で取り込まれることがあります。件数を確認しただけで終わらせず、ナビゲーションウィンドウにエラーテーブルが増えていないかを毎回確認してください。
VBAで確認する場合は、取り込み処理の後に次の処理を実行します。
Public Sub ListImportErrorTables()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim found As Boolean
Set db = CurrentDb
For Each tdf In db.TableDefs
If tdf.Name Like "*インポート*エラー*" Or tdf.Name Like "*ImportErrors*" Then
Debug.Print tdf.Name, DCount("*", "[" & tdf.Name & "]") & " 件"
found = True
End If
Next tdf
If Not found Then Debug.Print "インポートエラーのテーブルはありません"
End Sub
テーブル名の付き方は、環境によって異なる可能性があります。初回は実際に作られたテーブル名を確認し、それに合わせて Like の条件を直してください。
エラーテーブルは、次回以降も残り続けます。内容を確認して原因を直したら、手動で削除するか名前を変えておきましょう。そうすれば、次の取り込みで新しく出たエラーと区別できます。
エラーが出たときに確認することは、次のとおりです。
| エラーの内容 | 確認すること |
|---|---|
| 型変換エラー(日付・数値の列) | 定義の日付の順序や区切り記号がCSVと合っているか。数値の列に「-」や空白、単位付きの文字が入っていないか |
| 値の切り捨て | 短いテキスト型のフィールドサイズが足りているか |
| 特定の行だけ列がずれる | 定義の「文字列の引用符」が " になっているか |
うまく取り込めないときに最初に確認すること
- 定義名が間違っている:定義が存在しないという内容のエラーになります。[定義]の一覧に表示される名前とコード内の文字列を見比べ、スペースの有無や全角・半角の違いがないかを確認してください。
- 見出しの名前がフィールド名と合わない:見出しありで既存のテーブルに追加するとき、CSVの見出しとフィールド名が違う列は対応付けられません。どちらかの名前を合わせます。
- 文字化けする:まず、定義のコードページがCSVの文字コードと合っているかを確認します。
取り込み処理を作ったら確認するチェックリスト
- 定義を[設定]の画面から保存し、[定義]の一覧に名前が表示されている
- コード類の列が短いテキスト型になっている
- 定義の日付の形式がCSVの書き方と合っている
- 定義・CSV・HasFieldNamesで、見出しの扱いがそろっている
- 取り込み専用のテーブルに入れ、確認してから本番へ移している
- 増えた件数と金額の合計をCSV側と比べた
- インポートエラーのテーブルが増えていないか確認した
