【VBA】ExcelデータをCSVファイルに書き出す方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

完成イメージ(Before / After)

Before(手作業でCSV保存)

Before(実行前)のExcel画面
A B C
1 ロット番号 スペック名 測定値
2 001 ラインA 15.2
3 002 ラインA 14.8
4 003 ラインB 15.0

毎回「名前を付けて保存→CSV」を手動で実行。文字コードの指定ができず文字化けリスクあり。

After(VBAで自動CSV出力)

After(実行後)のExcel画面
A B C
1 ロット番号 スペック名 測定値
2 001 ラインA 15.2
3 002 ラインA 14.8
4 003 ラインB 15.0

ボタン1つでUTF-8のCSVが出力される。日付付きファイル名(例: 検査データ_20260418.csv)で自動保存。

他システムにデータを渡すたびに、手作業でCSVに変換していた。文字化けして戻されることもあって地味にストレスだった。VBAでUTF-8対応のCSV出力を作ってからは、一発で完了。「また文字化けしてるよ」と言われる日々から解放された。

「名前を付けて保存」でCSVを作ると、文字コードの制御ができない。VBAなら文字コードもファイル名も自由自在。

なお、複数ファイルのデータを1つにまとめてからCSV出力する場合は 複数Excelファイルを1つに統合 を参照。出力元のファイルを事前に把握するには フォルダ内ファイル一覧を自動取得 が便利。

実行前の準備

CSV保存先のフォルダを確認する

CSVを保存するフォルダのパスを確認しておく。エクスプローラーでフォルダを開き、アドレスバーからパスをコピーするのが確実。

例: C:\Users\tanaka\Documents\CSV出力

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロが保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

シート構成を確認する

このコードは以下のシート構成を前提としている:

  • シート名「データ」に出力対象のデータがある
  • 1行目はヘッダー(CSVにも出力される)
  • A列〜D列がデータ範囲(書き換え可能)

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」

ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。

コード(最小版)– ExcelデータをCSVに書き出し


'============================================================
' ■ ExcelデータをCSVに書き出し(最小版)
'   → 指定シートのデータ範囲をカンマ区切りで出力
'   → 文字コードは Shift_JIS(Windows標準)
'============================================================
Sub ExportToCSVMinimal()

    '--- ★書き換えポイント ---
    Dim sheetName As String
    sheetName = "データ"           '← 出力対象のシート名

    Dim startCol As Long
    startCol = 1                   '← 開始列(1=A列)

    Dim endCol As Long
    endCol = 4                     '← 終了列(4=D列)

    Dim filePath As String
    filePath = "C:\Users\tanaka\Documents\CSV出力\data.csv"  '← 保存先
    '--- ★ここまで ---

    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets(sheetName)

    '--- 最終行を取得
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, startCol).End(xlUp).Row

    If lastRow < 1 Then
        MsgBox "出力するデータがありません。", vbExclamation
        Exit Sub
    End If

    '--- CSVファイルを開く
    Dim fileNum As Integer
    fileNum = FreeFile
    Open filePath For Output As #fileNum

    '--- 1行ずつ書き出し
    Dim i As Long, j As Long
    Dim line As String
    Dim cellValue As String

    For i = 1 To lastRow
        line = ""
        For j = startCol To endCol
            cellValue = CStr(ws.Cells(i, j).Value)

            '--- カンマやダブルクォートを含む場合の処理
            If InStr(cellValue, ",") > 0 Or _
               InStr(cellValue, """") > 0 Or _
               InStr(cellValue, vbLf) > 0 Then
                cellValue = """" & Replace(cellValue, """", """""") & """"
            End If

            If j > startCol Then line = line & ","
            line = line & cellValue
        Next j
        Print #fileNum, line
    Next i

    Close #fileNum

    MsgBox lastRow & " 行のデータをCSVに書き出しました。" & vbCrLf & _
           "保存先: " & filePath, vbInformation

End Sub

書き換えポイント

変数 説明 初期値
sheetName 出力対象のシート名 "データ"
startCol / endCol 出力する列範囲(列番号) 1(A列)〜 4(D列)
filePath CSVの保存先フルパス "C:\Users\tanaka\Documents\CSV出力\data.csv"

コードの流れ

  1. 対象シートの最終行を取得
  2. Open ... For Output でCSVファイルを新規作成
  3. 1行ずつループし、各セルの値をカンマで連結
  4. カンマ・ダブルクォート・改行を含むセルはダブルクォートで囲む
  5. Print # で1行ずつ書き込み
  6. Close でファイルを閉じる

最小版のコードで注目してほしいのは、カンマ・ダブルクォート・改行を含むセルの処理だ。CSVはカンマで列を区切る形式なので、セルの値自体にカンマが含まれていると列がずれてしまう。そこで、カンマや改行を含む値はダブルクォートで囲む(RFC 4180準拠)。さらに値の中にダブルクォートがある場合は "" にエスケープする。なぜこの処理が必要かというと、これを省略すると取り込み先のシステムでCSVが正しくパースされず、データが壊れるからだ。

FreeFile はVBAが空いているファイル番号を自動で割り当ててくれる関数だ。固定の番号(#1 など)を使うと、他の処理でファイルを開いている場合に競合する。FreeFile を使う癖をつけておけば安全だ。

重要: Open ... For Output は既存ファイルを上書きする。追記したい場合は For Append に変更する。Dir関数でファイル操作する方法は フォルダ内ファイル一覧を自動取得 も参照。

コード(実務版)– 文字コード指定+日付付きファイル名で保存

実務では「基幹システムがUTF-8を要求する」「毎回異なるファイル名で保存したい」ケースが多い。ADODB.Streamで文字コードを指定し、日付付きファイル名で保存する。

ADODB.StreamでUTF-8出力に統一してからは、文字化けトラブルがゼロになった。システム担当に怒られることもなくなった。CSV出力先のファイル管理には フォルダ内ファイル一覧を自動取得 も役立つ。


'============================================================
' ■ CSV書き出し — UTF-8対応+日付付きファイル名(実務版)
'   → ADODB.Stream で文字コードを指定(UTF-8 BOM付き)
'   → ファイル名に日付を入れて上書き防止
'============================================================
Sub ExportToCSVAdvanced()

    '--- ★書き換えポイント ---
    Dim sheetName As String
    sheetName = "データ"           '← 出力対象のシート名

    Dim startCol As Long
    startCol = 1                   '← 開始列(1=A列)

    Dim endCol As Long
    endCol = 4                     '← 終了列(4=D列)

    Dim saveFolderPath As String
    saveFolderPath = "C:\Users\tanaka\Documents\CSV出力\"  '← 保存先フォルダ

    Dim filePrefix As String
    filePrefix = "data"            '← ファイル名の先頭部分

    Dim charSet As String
    charSet = "UTF-8"              '← 文字コード("UTF-8" or "Shift_JIS")
    '--- ★ここまで ---

    '--- パスの末尾に \ を付ける
    If Right(saveFolderPath, 1) <> "\" Then saveFolderPath = saveFolderPath & "\"

    '--- 保存先フォルダの存在確認
    If Dir(saveFolderPath, vbDirectory) = "" Then
        MsgBox "保存先フォルダが見つかりません。" & vbCrLf & _
               saveFolderPath, vbExclamation
        Exit Sub
    End If

    '--- 日付付きファイル名を生成
    Dim filePath As String
    filePath = saveFolderPath & filePrefix & "_" & Format(Date, "yyyyMMdd") & ".csv"

    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets(sheetName)

    '--- 最終行を取得
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, startCol).End(xlUp).Row

    If lastRow < 1 Then
        MsgBox "出力するデータがありません。", vbExclamation
        Exit Sub
    End If

    '--- ADODB.Stream でCSV書き出し
    Dim stream As Object
    Set stream = CreateObject("ADODB.Stream")

    stream.Type = 2          '← adTypeText(テキストモード)
    stream.charSet = charSet
    stream.Open

    '--- 1行ずつ書き出し
    Dim i As Long, j As Long
    Dim line As String
    Dim cellValue As String

    For i = 1 To lastRow
        line = ""
        For j = startCol To endCol
            cellValue = CStr(ws.Cells(i, j).Value)

            '--- カンマ・ダブルクォート・改行を含む場合の処理
            If InStr(cellValue, ",") > 0 Or _
               InStr(cellValue, """") > 0 Or _
               InStr(cellValue, vbLf) > 0 Then
                cellValue = """" & Replace(cellValue, """", """""") & """"
            End If

            If j > startCol Then line = line & ","
            line = line & cellValue
        Next j
        stream.WriteText line, 1   '← 1 = adWriteLine(改行付き)
    Next i

    '--- ファイルに保存
    stream.SaveToFile filePath, 2  '← 2 = adSaveCreateOverWrite
    stream.Close
    Set stream = Nothing

    MsgBox lastRow & " 行のデータをCSVに書き出しました。" & vbCrLf & _
           "保存先: " & filePath & vbCrLf & _
           "文字コード: " & charSet, vbInformation

End Sub

書き換えポイント

変数 説明 初期値
sheetName 出力対象のシート名 "データ"
startCol / endCol 出力する列範囲 14
saveFolderPath 保存先フォルダ "C:\Users\tanaka\Documents\CSV出力\"
filePrefix ファイル名の先頭部分 "data"
charSet 文字コード "UTF-8""Shift_JIS" に変更可)

コードの流れ

  1. 保存先確認: フォルダの存在をチェック
  2. 日付付きファイル名: data_20260308.csv 形式で自動生成
  3. ADODB.Stream生成: CreateObject で参照設定不要
  4. 文字コード指定: .Charset = "UTF-8" で指定
  5. 行ごとの書き出し: カンマ・ダブルクォート・改行の特殊処理付き
  6. ファイル保存: SaveToFile で書き出し

CSV出力マクロをボタン(マクロをボタン1つで実行する方法)に割り当てれば、毎週のCSV作成がボタン1つで完了する。

よくある落とし穴5選

1. 文字コード違いで文字化けする

自分もこれで30分溶かした。Shift_JISで出力したCSVをUTF-8前提のシステムに取り込んだら、全角文字が全部文字化け。原因に気づくまで「データが壊れた?」と焦った。

対策: 取り込み先のシステムが要求する文字コードを確認し、実務版コードの charSet を合わせる。迷ったらUTF-8が無難。

2. セル内のカンマでCSVの列がずれる

原因: セルの値に , が含まれていると、CSVのカラム区切りと誤認される。

対策: コード内でカンマを含む値をダブルクォートで囲む処理を入れている。この処理を外すと列ずれが発生する。

3. 同名ファイルが上書きされる

原因: 最小版では filePath が固定のため、実行するたびに上書きされる。

自分も過去のCSVを上書きしてしまい、先週分のデータを失ったことがある。それ以来、日付付きファイル名を使うようにした。

対策: 実務版のように日付付きファイル名にする。同日に複数回出力する場合は時刻も追加する:Format(Now, "yyyyMMdd_HHmmss")

4. 数値の先頭ゼロが消える

原因: CSVをExcelで開くと、00011 に変換される。これはExcelの仕様でVBA側の問題ではない。

対策: VBAでの出力時には先頭ゼロは保持される。CSVを確認するときはメモ帳やテキストエディタで開くと正確に見える。

5. 保存先フォルダが存在せずエラーになる

原因: filePath に指定したフォルダが存在しない。

対策: 実務版では Dir でフォルダの存在を確認している。存在しない場合はメッセージを出して処理を止める。

VBAでCSV出力すると文字化けするときの対処法

「VBAで書き出したCSVを基幹システムに取り込んだら全角文字が文字化けした」という場合、原因は文字コードの不一致だ。最小版の Open ... For Output はShift_JIS(Windows標準)で出力するが、取り込み先がUTF-8を要求していると文字化けする。対処法は実務版の ADODB.Stream を使い、.Charset = "UTF-8" で文字コードを明示的に指定すること。逆にShift_JISが必要な場合は .Charset = "Shift_JIS" にすればよい。自分もShift_JISで出力したCSVをUTF-8前提のWebシステムに取り込んで全滅した経験がある。取り込み先の仕様書で文字コードを確認してから出力するのが鉄則だ。

VBAのCSV出力でカンマを含むデータが壊れるときの対処法

「セルの値にカンマが入っていると、CSV取り込み時に列がずれてデータが壊れる」という場合、原因はカンマを含む値をダブルクォートで囲んでいないことだ。CSVはカンマで列を区切るフォーマットなので、値自体にカンマがあるとカラム区切りと誤認される。対処法はカンマ・ダブルクォート・改行を含む値を """" & Replace(cellValue, """", """""") & """" でダブルクォートで囲みエスケープすること。最小版・実務版のコードにはこの処理が組み込み済みなので、そのままコピペすれば安全にCSV出力できる。住所や備考欄にカンマが入りがちなので、CSV出力時には必ずこのエスケープ処理を入れておくべきだ。

FAQ

Q1: ヘッダー行を出力しない場合

ループの開始行を変更する:


For i = 2 To lastRow   '← 1 を 2 に変えるとヘッダーをスキップ

Q2: タブ区切り(TSV)で出力したい

カンマの代わりにタブ文字 vbTab を使う:


If j > startCol Then line = line & vbTab   '← "," を vbTab に変更

Q3: 特定の列だけ出力したい

出力する列番号を配列で指定する:


Dim cols As Variant
cols = Array(1, 3, 5)   '← A列, C列, E列だけ出力

For j = LBound(cols) To UBound(cols)
    cellValue = CStr(ws.Cells(i, cols(j)).Value)
    '--- 以降同様
Next j

Q4: CSV出力後にメールで送りたい

CSV添付でメールを作成できる。Excelからメール自動作成(Outlook連携) を参照。

Q5: ボタン1つでCSV出力を実行したい

マクロをボタン1つで実行する方法ExportToCSVAdvanced をボタンに割り当てる。

まとめ

  • Open/Print# でExcelデータをCSVに書き出せる(最小版・Shift_JIS)
  • ADODB.Stream で文字コードを指定してCSV出力できる(実務版・UTF-8対応)
  • カンマ・ダブルクォート・改行を含むセルの処理が重要
  • 日付付きファイル名で上書きを防止する

CSV出力は「他システムとの橋渡し」になる重要な処理だ。最小版で基本的な書き出しの仕組みを理解したら、実務版でUTF-8対応と日付付きファイル名を導入してほしい。一度セットアップすれば、毎回の「名前を付けて保存→CSV→文字コード確認」という手作業がゼロになる。自分の場合、毎週金曜に在庫データをCSV出力して基幹システムに取り込む作業があったが、VBA化してからは出力ボタンを押すだけで文字コード指定済みのCSVが生成されるようになった。取り込み先で文字化けしないかヒヤヒヤする必要もない。CSV出力は地味だが、一度仕組みを作れば毎週・毎月の定型作業が確実に楽になる処理だ。なお、CSV出力先のフォルダが存在しない場合にエラーで止まるのはよくあるトラブルだ。実務版のようにDir関数で事前チェックする方法に加えて、ファイルやフォルダの存在確認で紹介しているMakeDirパターンを組み込めば、フォルダがなければ自動作成→CSVを出力、という流れが作れる。出力するデータに空白行が混ざっている場合は、空白行の一括削除で事前にクリーニングしておくとCSVの品質が上がる。ブックの保存と組み合わせれば、CSV出力後にExcelブックも自動保存する運用が作れる。マクロの実行結果を記録したい場合は実行ログの導入も検討してみてほしい。

関連記事

次にやりたくなること

コメント

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