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

【VBA】ExcelデータをCSVファイルに書き出す方法の解説用アイキャッチ画像 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つに統合 を参照。出力元のファイルを事前に把握するには フォルダ内ファイル一覧を自動取得 が便利。

今回の検証条件とBefore/After

この記事では、Excelの表をCSVとして保存する流れを、通常のカンマ区切りデータと、文字化け・上書き・先頭ゼロが問題になりやすいデータを想定して整理しています。

確認したこと 起きやすい問題 記事内での対策
通常の一覧表をCSV出力 基本的にはSaveAsで対応できる 最小版で紹介
日本語を含むCSV 取り込み先によって文字化けする 文字コードを意識する実務版を使う
同じファイル名で再出力 既存ファイルを上書きする 日付付きファイル名や確認処理を入れる
商品コードや郵便番号 先頭ゼロが消えることがある 文字列として扱う前提で確認する

Beforeは、Excelファイルを手作業で「名前を付けて保存」してCSVを作る状態です。Afterは、決まった保存先とファイル名でCSVを書き出し、同じ作業を毎回同じ手順で実行できる状態です。

実行前の準備

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

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

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

シート構成を確認する

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

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

コード(最小版)– 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つで完了する。

SaveAs版と文字コード指定版の判断基準

CSV出力は、Excelの SaveAs だけでもできます。ただし、文字コードや上書き確認まで安定させたい場合は、少し丁寧な実務版にした方が安心です。

やりたいこと 向いている書き方 判断理由
自分用にCSVを作る SaveAs版 短く書けて、Excelの保存機能に任せられる
外部システムへ渡す 文字コード指定版 UTF-8やShift_JISなど、相手側の仕様に合わせる必要がある
毎日・毎月の定型出力 日付付きファイル名の実務版 過去ファイルを残しやすく、上書き事故を防げる
列数やヘッダーを制御したい 1行ずつ書き出す実務版 出力内容をコード側で明確に決められる

自分なら、社内で一度だけ使うならSaveAs版、他システムへ渡すCSVなら文字コード指定版にします。CSVは「作れた」だけでは不十分で、相手側で正しく読めることまで確認して完了です。

よくある落とし穴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出力時には必ずこのエスケープ処理を入れておくべきだ。

実務でCSV出力を使うときの文字コードと上書き対策

CSV出力は、会計ソフト、基幹システム、Webサービスへの取り込みでよく使います。ただし、CSVは見た目が単純なぶん、文字コード、カンマ、改行、先頭ゼロ、日付形式の違いで取り込みエラーになりやすい形式です。出力先のシステムがUTF-8を求めるのか、Shift_JISを求めるのかを先に確認し、テスト用データで読み込みまで確認しておくと安全です。

また、同名ファイルの上書きにも注意が必要です。日付付きファイル名にする、既存ファイルがある場合は確認する、出力後に件数を表示する、といった仕組みにすると、作業者が結果を確認しやすくなります。部署内で配布する場合は、保存先フォルダをセルで指定できるようにしておくと、PCごとのパス差にも対応しやすくなります。

確認項目起きやすい問題対策
文字コード取り込み先で文字化けするUTF-8/SJISの指定を確認する
カンマ・改行列ずれや行ずれが起きる値をダブルクォートで囲む
先頭ゼロコードが数値扱いで欠ける文字列として出力する
上書き前回ファイルを消してしまう既存ファイル確認や日付付き名にする

既存ファイルがあれば確認する例

Dim csvPath As String
csvPath = Range("B2").Value & "\export.csv"

If Dir(csvPath) <> "" Then
    If MsgBox("既存CSVを上書きしますか?", vbYesNo) <> vbYes Then
        Exit Sub
    End If
End If

CSV出力は、マクロ内だけで完結せず、出力後に別システムへ渡ることが多い処理です。そのため、Excel上で正しく見えるかだけでなく、取り込み先で正しく読めるかまで確認しておくと、実務での失敗を減らせます。

実務で試して分かった壊れやすいデータ

失敗例1: 住所や備考にカンマが入っている

CSVはカンマで列を区切るため、セルの中にカンマがあると列ズレの原因になります。実務版では、値をダブルクォーテーションで囲む処理を入れると壊れにくくなります。

失敗例2: 00123 のようなコードが 123 になる

CSVをExcelで開き直すと、数値として解釈されて先頭ゼロが消えることがあります。商品コードや郵便番号は、出力前のセル表示だけでなく、取り込み先でどう読まれるかまで確認します。

失敗例3: UTF-8で出したのに相手側では文字化けする

相手側システムがShift_JIS前提の場合、UTF-8の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ブックも自動保存する運用が作れる。マクロの実行結果を記録したい場合は実行ログの導入も検討してみてほしい。

関連記事

  • フォルダ内のファイルを日付フォルダに自動バックアップ — CSV出力前にバックアップ
  • ExcelファイルをPDFに一括変換 — CSV出力 vs PDF出力の使い分け
  • マクロをボタン1つで実行する方法 — CSV出力マクロをボタンに割り当て

次にやりたくなること

  • 複数Excelファイルを1つに統合: 複数ファイルのデータを統合してからCSV出力。散らばったデータを1つのCSVにまとめたいときに
  • フォルダ内ファイル一覧を自動取得: CSV出力先のファイル管理に。過去の出力ファイルを一覧化して整理できる
  • マクロをボタン1つで実行する方法: CSV出力をボタン化。毎週の定型作業を完全にワンクリック化

次に読みたい関連記事

コメント

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