毎月や毎週、同じ形式のCSVをAccessから出しているなら、そのたびにエクスポートのウィザードを開く必要はありません。区切り文字・引用符・文字コードなどを決めた「エクスポート定義」を一度保存しておけば、VBAの DoCmd.TransferText でその定義を呼び出せます。ボタン1つで、毎回同じ形式のCSVを出力できます。

この記事では、定義がすでに保存されている前提で、次の3点をコードで指定する方法を説明します。

  • どの定義を使うか(定義名)
  • 1行目に列名を出すか(見出し)
  • 出力先とファイル名(日付入り)

先に確認する:「定義」と「保存済みのエクスポート操作」は別のもの

Accessには、似た名前の保存機能が2つあります。取り違えると、コードに名前を書いても「定義が見つからない」という趣旨のエラーになります。

種類 保存する場所 中身 VBAから呼ぶ方法
インポート/エクスポート定義 テキストのエクスポートウィザードの「詳細設定」画面 区切り文字、引用符、文字コード、日付の形式、各フィールドの設定 DoCmd.TransferText の SpecificationName
保存済みのエクスポート操作 ウィザードの最後の「エクスポート操作の保存」 対象のテーブル・出力先まで含めた操作一式 DoCmd.RunSavedImportExport

DoCmd.TransferText に渡すのは、前者の定義名です。保存されている定義名は、テキストのエクスポートウィザードで「詳細設定」を開き、定義の一覧を表示するボタンから確認できます(ボタンの表示名はバージョンによって違うことがあります)。全角・半角やスペースまで含めて、コードの名前と完全に一致させてください。

もう1つ注意したいのは、定義がデータベースファイルの中に保存されることです。VBAのコードだけを別のaccdbにコピーしても、定義は付いてきません。移すときは、Accessのオブジェクトをインポートする画面の「オプション」で、インポート/エクスポートの定義も一緒に取り込む設定があるか確認してください。

DoCmd.TransferTextの引数

DoCmd.TransferText TransferType, SpecificationName, TableName, FileName, HasFieldNames, HTMLTableName, CodePage

CSVを出力するときは、次のように指定します。

引数 CSV出力での指定 補足
TransferType acExportDelim 区切り記号付きテキストの出力。固定長なら acExportFixed
SpecificationName 保存した定義名 ここで形式を固定する
TableName テーブル名またはクエリ名 列の順番・並び順・絞り込みはクエリ側で決めておく
FileName 出力ファイルのフルパス 拡張子は .csv か .txt にしておく
HasFieldNames True / False True で1行目にフィールド名を出す
HTMLTableName 指定しない HTML用の引数
CodePage 基本は指定しない 文字コードは定義側で決め、2か所で指定しない

見出しの有無は出力したファイルで確かめる

ウィザードにも「1行目に列名を入れるか」を選ぶ画面があるため、定義を作ったときの想定とコードの HasFieldNames が食い違うことがあります。コードでは HasFieldNames を必ず明示してください。そのうえで最初の1回は、出力したCSVをメモ帳などのテキストエディターで開き、1行目が想定どおりかを確認します。

Excelで開くと、先頭の0が消えたり日付の表示が変わったりして、ファイルの中身とは違って見えます。形式の確認はテキストエディターで行うのが確実です。

日付入りのファイル名で出力するコード

標準モジュールに次のプロシージャを置きます。例では、クエリ「q_売上CSV」を定義「売上CSV定義」の形式で、データベースと同じ場所にある「出力」フォルダへ出力します。

Public Sub ExportSalesCsv()
    Const SPEC_NAME As String = "売上CSV定義"     ' 保存済みのエクスポート定義名
    Const SOURCE_NAME As String = "q_売上CSV"     ' 出力するテーブルまたはクエリ
    Const FILE_PREFIX As String = "売上_"

    Dim folderPath As String
    Dim filePath As String
    Dim recCount As Long

    On Error GoTo ErrHandler

    folderPath = CurrentProject.Path & "\出力"
    If Dir(folderPath, vbDirectory) = "" Then
        MsgBox "出力先フォルダがありません。" & vbCrLf & folderPath, vbExclamation
        Exit Sub
    End If

    filePath = folderPath & "\" & FILE_PREFIX & Format(Now, "yyyymmdd_hhnnss") & ".csv"
    If Dir(filePath) <> "" Then
        MsgBox "同じ名前のファイルがあります。" & vbCrLf & filePath, vbExclamation
        Exit Sub
    End If

    recCount = DCount("*", SOURCE_NAME)
    If recCount = 0 Then
        If MsgBox("出力対象が0件です。このまま出力しますか?", _
                  vbYesNo + vbQuestion) = vbNo Then Exit Sub
    End If

    DoCmd.TransferText TransferType:=acExportDelim, _
                       SpecificationName:=SPEC_NAME, _
                       TableName:=SOURCE_NAME, _
                       FileName:=filePath, _
                       HasFieldNames:=True

    MsgBox recCount & " 件を出力しました。" & vbCrLf & filePath, vbInformation
    Exit Sub

ErrHandler:
    MsgBox "CSVの出力に失敗しました。" & vbCrLf & _
           "エラー番号:" & Err.Number & vbCrLf & Err.Description, vbCritical
End Sub

コードのポイント

  • 定義名・出力元・ファイル名の先頭を定数にまとめる:別のCSV用に複製するときは、冒頭の3行を書き換えるだけで済みます。
  • ファイル名に日付と時刻を入れる:Format(Now, "yyyymmdd_hhnnss") で「売上_20261006_093015.csv」のような名前になります。分は nn と書くと、月の mm と取り違えません。1日1回しか出さないなら Format(Date, "yyyymmdd") でも構いませんが、その場合は同じ日の2回目が下の重複チェックで止まります。
  • 出力先フォルダの有無を先に確かめる:フォルダがないと出力の段階でエラーになるので、分かりやすいメッセージで先に止めます。
  • 同じ名前のファイルがあれば止める:既存のファイルを上書きして前回分を失わないよう、出力前に止めています。上書きしてよい運用なら、この確認は外して構いません。
  • 件数を数えておく:DCount の件数を完了メッセージに出しておくと、CSVの行数と突き合わせられます。0件のときは、空のファイルを渡してしまわないように確認を挟みます。

フォームのボタンから実行する

  1. フォームをデザインビューで開き、コマンドボタンを配置します(ボタンウィザードが開いたらキャンセルします)。
  2. プロパティシートの「その他」タブで、名前を cmdExportCsv などに変えます。
  3. 「イベント」タブの「クリック時」で「[イベント プロシージャ]」を選び、「…」ボタンからコードを開きます。
  4. 次のように、標準モジュールのプロシージャを呼び出します。
Private Sub cmdExportCsv_Click()
    ExportSalesCsv
End Sub

出力の処理を標準モジュールに置いておくと、別のフォームやマクロから同じ処理を呼べます。ボタンごとにコードを複製せずに済みます。

出力元はクエリで作っておく

TableNameにテーブルを直接指定すると、すべての列が保存された順番のまま出力されます。取り込み先が求める列の並びや列名、並び順、出力するデータの範囲は、出力専用のクエリで決めておくのがおすすめです。

  • 列名を取り込み先の仕様に合わせたいときは、クエリで別名を付けます(例:取引先コード: 得意先ID)。
  • 実行のたびに期間などを入力させるパラメータクエリは、TransferText や DCount から呼ぶとエラーや入力画面が出る原因になります。出力用には、パラメータのないクエリを用意してください。
  • 定義を作ったあとにクエリの列を増やしたり減らしたりしたら、一度出力して、列の数と順番が取り込み先の仕様と合っているかを確認します。

出力後の確認チェックリスト

最初の数回と、クエリや定義を変えたあとは、次の項目を確認してから運用に乗せてください。

  • ファイル名に日付・時刻が入り、想定したフォルダに保存されている
  • 1行目が列名になっている(または、列名なしで想定どおり)
  • 区切り文字と引用符の付き方が定義どおりになっている
  • テキストエディターで開いて文字化けがなく、取り込み先が求める文字コードになっている
  • 行数が「完了メッセージの件数+見出しの1行」と合っている(セル内改行を含むデータでは行数が合わないので、取り込み先での件数で確認する)
  • 取り込み先で一度テスト用に取り込み、エラーにならない

うまく出力できないとき

症状 まず確認すること
定義が見つからないという趣旨のエラー 定義名の表記、保存済みのエクスポート操作の名前を書いていないか、別のaccdbで実行していないか
ファイルやパスに関するエラー 出力先フォルダがあるか、同じファイルを別のアプリで開いていないか、拡張子が .csv か .txt か
出力されたが件数が少ない 出力元クエリの抽出条件、DCount の件数とCSVの行数の差
列の並びや形式が想定と違う クエリの列の順番と、定義の内容

エラー番号は、上のコードのメッセージに表示されます。番号とメッセージを控えておくと、原因を切り分けやすくなります。

おすすめの記事