ExcelマクロでCSVファイルを自動的にインポート・エクスポートできれば、毎日の手作業を大幅に削減できます。本記事では、実務でそのまま使えるVBAコードを交えながら、CSVの読み込み・書き出し・エラー対処まで徹底解説します。「実行時エラー 1004」「実行時エラー 53」など現場でよく遭遇するエラー番号の原因と解決策も網羅しているため、初めてマクロに触れる方から中級者まで役立つ内容になっています。


目次


CSVとExcelマクロを組み合わせるメリット

CSVファイルはシステム間のデータ連携でもっとも広く使われるフォーマットです。基幹システムからのエクスポート、ECサイトの注文データ、経費精算ツールの出力など、業務の至るところにCSVが登場します。しかしExcelで手動インポートを繰り返すと、次のような問題が生じます。

  • テキストインポートウィザードを毎回操作する手間がかかる
  • 電話番号や商品コードなど先頭ゼロが自動で消えてしまう
  • 文字コードのミスマッチでデータが文字化けする
  • 複数ファイルを処理するとき、ヒューマンエラーが起きやすい

VBAマクロでCSV操作を自動化すると、これらの問題をまとめて解消できます。さらに「毎朝9時に所定フォルダのCSVを読み込んでレポートを生成する」といったスケジュール実行まで組み合わせれば、完全なノーオペレーション運用も実現可能です。


事前準備:VBAエディタの起動と設定

まず開発タブを表示させます。Excelの「ファイル」→「オプション」→「リボンのユーザー設定」で「開発」にチェックを入れてください。その後、Alt + F11 キーを押すとVBAエディタ(Visual Basic for Applications)が開きます。

メニューから「挿入」→「標準モジュール」を選択し、以下のコードを貼り付けて実行してください。

また、ファイルシステム操作(フォルダ存在確認など)を行う場合は、VBAエディタの「ツール」→「参照設定」から Microsoft Scripting Runtime にチェックを入れておくと便利です。


CSVをExcelに自動インポートする基本コード

もっともシンプルなインポート方法は、Open ステートメントを使ってCSVをテキストとして読み込む方法です。ウィザードを使わないため、先頭ゼロが消えないという大きなメリットがあります。

' ========================================
' 基本CSVインポートマクロ
' 対象: UTF-8またはShift-JIS のカンマ区切りCSV
' ========================================
Sub ImportCSV_Basic()

    Dim filePath As String
    Dim fileNo   As Integer
    Dim lineText As String
    Dim cols()   As String
    Dim ws       As Worksheet
    Dim rowIndex As Long

    ' --- インポート先シートの準備 ---
    Set ws = ThisWorkbook.Sheets(1)
    ws.Cells.Clear
    rowIndex = 1

    ' --- ファイル選択ダイアログ ---
    filePath = Application.GetOpenFilename( _
        FileFilter:="CSVファイル (*.csv),*.csv", _
        Title:="インポートするCSVを選択してください")

    If filePath = "False" Then
        MsgBox "キャンセルされました。", vbInformation
        Exit Sub
    End If

    ' --- ファイルを開いて1行ずつ読み込む ---
    fileNo = FreeFile()
    Open filePath For Input As #fileNo

    Do While Not EOF(fileNo)
        Line Input #fileNo, lineText

        ' カンマで分割
        cols = Split(lineText, ",")

        Dim i As Integer
        For i = 0 To UBound(cols)
            ' 先頭ゼロ保持のため文字列として貼り付け
            ws.Cells(rowIndex, i + 1).NumberFormat = "@"
            ws.Cells(rowIndex, i + 1).Value = cols(i)
        Next i

        rowIndex = rowIndex + 1
    Loop

    Close #fileNo

    MsgBox "インポート完了! " & rowIndex - 1 & " 行を読み込みました。", vbInformation

End Sub

ポイント解説

  • FreeFile():使用可能なファイル番号を自動取得する。ハードコードすると競合するため必ず使用する。
  • NumberFormat = "@":セル書式を文字列に設定してから値を入れることで、先頭ゼロや日付の自動変換を防ぐ。
  • EOF(fileNo):ファイル末尾に達したらループを終了する。

実務向け:文字コード・区切り文字に対応したインポート

基幹システムによっては UTF-8(BOM付き)タブ区切り(TSV) で出力されることがあります。Open ステートメントのみではUTF-8を正しく扱えないケースがあるため、ADODB.Stream オブジェクトを使う方法が安全です。

' ========================================
' UTF-8 CSV インポートマクロ(ADODB.Stream使用)
' 参照設定不要・Windows標準コンポーネントで動作
' ========================================
Sub ImportCSV_UTF8()

    Dim filePath  As String
    Dim stream    As Object
    Dim lineText  As String
    Dim cols()    As String
    Dim ws        As Worksheet
    Dim rowIndex  As Long
    Dim delimiter As String

    delimiter = ","   ' タブ区切りの場合は vbTab に変更

    Set ws = ThisWorkbook.Sheets(1)
    ws.Cells.Clear
    rowIndex = 1

    filePath = Application.GetOpenFilename( _
        FileFilter:="CSVファイル (*.csv),*.csv,テキストファイル (*.txt),*.txt", _
        Title:="インポートするファイルを選択")

    If filePath = "False" Then Exit Sub

    ' ADODB.Stream でUTF-8読み込み
    Set stream = CreateObject("ADODB.Stream")
    With stream
        .Type    = 2          ' テキストモード
        .Charset = "UTF-8"    ' 文字コード指定
        .Open
        .LoadFromFile filePath
    End With

    Do While Not stream.EOS
        lineText = stream.ReadText(-2)   ' -2 = adReadLine(1行ずつ)

        ' BOMが先頭行に混入する場合の除去
        If rowIndex = 1 Then
            lineText = Replace(lineText, Chr(239) & Chr(187) & Chr(191), "")
        End If

        cols = Split(lineText, delimiter)

        Dim i As Integer
        For i = 0 To UBound(cols)
            ws.Cells(rowIndex, i + 1).NumberFormat = "@"
            ws.Cells(rowIndex, i + 1).Value = cols(i)
        Next i

        rowIndex = rowIndex + 1
    Loop

    stream.Close
    Set stream = Nothing

    MsgBox "UTF-8インポート完了! " & rowIndex - 1 & " 行を処理しました。", vbInformation

End Sub

文字コードの判断基準

  • Windowsの旧システム・日本語基幹パッケージ → Shift-JIS(CP932).Charset = "CP932" を指定
  • 新しいクラウド系SaaS・Googleスプレッドシートエクスポート → UTF-8.Charset = "UTF-8"
  • BOM付きUTF-8(Excel出力に多い)→ BOM除去処理を追加(上記コード参照)

ExcelシートをCSVとして自動エクスポートするコード

Excelの「名前を付けて保存」でCSV保存すると確認ダイアログが出て手間がかかります。マクロを使えばダイアログなしで指定フォルダにCSVを自動保存できます。

' ========================================
' アクティブシートをCSVエクスポートするマクロ
' 文字コード: UTF-8 BOM付き(Excelで開いたとき文字化けしない)
' ========================================
Sub ExportCSV_UTF8BOM()

    Dim ws         As Worksheet
    Dim savePath   As String
    Dim fileNo     As Integer
    Dim rowIndex   As Long
    Dim colIndex   As Long
    Dim lastRow    As Long
    Dim lastCol    As Long
    Dim lineBuffer As String
    Dim cellVal    As String

    Set ws = ActiveSheet

    ' 保存先フォルダとファイル名を指定(必要に応じて変更)
    savePath = ThisWorkbook.Path & "\output_" & _
               Format(Now(), "yyyymmdd_HHmmss") & ".csv"

    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column

    fileNo = FreeFile()
    Open savePath For Output As #fileNo

    ' UTF-8 BOM を先頭に書き込む
    Print #fileNo, Chr(239) & Chr(187) & Chr(191);

    For rowIndex = 1 To lastRow
        lineBuffer = ""
        For colIndex = 1 To lastCol
            cellVal = CStr(ws.Cells(rowIndex, colIndex).Value)

            ' カンマ・ダブルクォート・改行を含む場合はダブルクォートで囲む
            If InStr(cellVal, ",") > 0 Or _
               InStr(cellVal, """") > 0 Or _
               InStr(cellVal, vbLf) > 0 Then
                cellVal = """" & Replace(cellVal, """", """""") & """"
            End If

            If colIndex = lastCol Then
                lineBuffer = lineBuffer & cellVal
            Else
                lineBuffer = lineBuffer & cellVal & ","
            End If
        Next colIndex

        Print #fileNo, lineBuffer
    Next rowIndex

    Close #fileNo

    MsgBox "CSVエクスポート完了!" & vbCrLf & savePath, vbInformation

End Sub

ポイント解説

  • ファイル名にタイムスタンプを付与することで上書き防止になる。
  • セル値にカンマやダブルクォートが含まれるとき、RFC 4180に従ってダブルクォートで囲む処理を入れることで破損を防ぐ。
  • BOM(Chr(239)&Chr(187)&Chr(191))を先頭に付けることで、Excelで開いたとき文字化けしない。

フォルダ内の複数CSVを一括取り込む方法

月次レポートや日次データなど、同じ形式のCSVが大量にある場合は、フォルダをループして全ファイルを一気に処理するマクロが有効です。

' ========================================
' 指定フォルダ内の全CSVを縦に積み上げてインポート
' ========================================
Sub ImportAllCSVInFolder()

    Dim folderPath As String
    Dim fileName   As String
    Dim fileNo     As Integer
    Dim lineText   As String
    Dim cols()     As String
    Dim ws         As Worksheet
    Dim rowIndex   As Long
    Dim isFirst    As Boolean
    Dim skipHeader As Boolean

    skipHeader = True   ' 2ファイル目以降のヘッダー行をスキップするか

    Set ws = ThisWorkbook.Sheets(1)
    ws.Cells.Clear
    rowIndex = 1

    ' フォルダ選択ダイアログ
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "CSVファイルが入ったフォルダを選択"
        If .Show = False Then Exit Sub
        folderPath = .SelectedItems(1) & "\"
    End With

    isFirst = True
    fileName = Dir(folderPath & "*.csv")

    If fileName = "" Then
        MsgBox "CSVファイルが見つかりませんでした。", vbExclamation
        Exit Sub
    End If

    Do While fileName <> ""
        Dim isHeaderRow As Boolean
        isHeaderRow = True

        fileNo = FreeFile()
        Open folderPath & fileName For Input As #fileNo

        Do While Not EOF(fileNo)
            Line Input #fileNo, lineText

            ' 2ファイル目以降のヘッダーをスキップ
            If skipHeader And Not isFirst And isHeaderRow Then
                isHeaderRow = False
                GoTo NextLine
            End If
            isHeaderRow = False

            cols = Split(lineText, ",")
            Dim i As Integer
            For i = 0 To UBound(cols)
                ws.Cells(rowIndex, i + 1).NumberFormat = "@"
                ws.Cells(rowIndex, i + 1).Value = cols(i)
            Next i
            rowIndex = rowIndex + 1

NextLine:
        Loop

        Close #fileNo
        isFirst = False
        fileName = Dir()   ' 次のファイルへ
    Loop

    MsgBox "一括インポート完了! 合計 " & rowIndex - 1 & " 行を処理しました。", vbInformation

End Sub

実行時エラー番号一覧と解決策

VBAでCSV操作をするときに遭遇しやすいエラーをまとめました。エラー番号でそのまま検索してもこの一覧が役に立つよう、原因と修正方法を丁寧に記載しています。

実行時エラー 1004:アプリケーション定義またはオブジェクト定義のエラー

  • 主な原因:存在しないシート名・範囲への書き込み、保護されたシートへの操作、ファイルが既に開いている状態でのSaveAs
  • 解決策:シート名のスペルミスを確認。シートを Sheets(1) のようにインデックスで指定する。保護がかかっている場合は ws.Unprotect を先に実行する。

実行時エラー 53:ファイルが見つかりません

  • 主な原因Open ステートメントで指定したファイルパスが間違っている。ファイルが別のフォルダに移動された。
  • 解決策Dir(filePath) で事前に存在確認を行い、空文字だったら処理を中断する。
' ファイル存在確認の書き方
If Dir(filePath) = "" Then
    MsgBox "ファイルが見つかりません: " & filePath, vbCritical
    Exit Sub
End If

実行時エラー 70:書き込みできません(パーミッションエラー)

  • 主な原因:出力先のCSVファイルがExcelや他のアプリで既に開かれている。読み取り専用属性が付いている。管理者権限が必要なフォルダへの書き込み。
  • 解決策:対象ファイルを閉じてから実行する。保存先を ThisWorkbook.Path 配下にして権限問題を回避する。

実行時エラー 75:パス名が無効です

  • 主な原因:ファイルパスに使用できない文字(: * ? " < > |)が含まれている。パスの末尾に余分な \ が付いている。
  • 解決策:パスをデバッグウィンドウに Debug.Print filePath で出力して確認する。

実行時エラー 9:インデックスが有効範囲にありません

  • 主な原因Sheets("Sheet1") のように名前で参照しているが、シート名が日本語や別の名前になっている。配列の UBound を超えたアクセス。
  • 解決策:シートを番号(Sheets(1))またはコード名(Sheet1)で参照する。

実行時エラー 13:型が一致しません

  • 主な原因:CSV内の空白行・空セルを数値型変数に代入しようとした。CInt() などの変換関数に非数値文字列を渡した。
  • 解決策IsNumeric()IsEmpty() で値を検証してから変換する。
' 型チェックの書き方
If IsNumeric(cols(2)) Then
    ws.Cells(rowIndex, 3).Value = CDbl(cols(2))
Else
    ws.Cells(rowIndex, 3).Value = cols(2)
End If

実行時エラー 91:オブジェクト変数またはWithブロック変数が設定されていません

  • 主な原因Set を使わずにオブジェクト変数に代入しようとした。Nothing のオブジェクトにメソッドを呼び出した。
  • 解決策:オブジェクト変数には必ず Set キーワードを使う。処理前に If Not obj Is Nothing Then でガード処理を入れる。

実行時エラー 5:プロシージャの呼び出し、または引数が不正です

  • 主な原因Split 関数に空文字を渡した。Open ステートメントのモード指定が間違っている(InputモードでOutputしようとするなど)。
  • 解決策:引数の型と値を見直す。空行の場合は If Len(Trim(lineText)) = 0 Then GoTo NextLine でスキップする。

実務で使えるテクニック集

画面更新を止めて高速化する

大量行の処理では画面描画がボトルネックになります。処理の前後で次のコードを追加するだけで劇的に速くなります。

' 処理前(高速化設定)
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False

' --- メイン処理 ---

' 処理後(必ず元に戻す)
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True

エラーハンドリングをつけてロバストにする

本番運用するマクロには必ずエラーハンドリングを実装してください。ファイルが開きっぱなしになるのを防ぐために Close を確実に実行する構造が重要です。

Sub SafeImport()
    Dim fileNo As Integer
    fileNo = FreeFile()

    On Error GoTo ErrorHandler

    Open "C:\data\sample.csv" For Input As #fileNo
    ' --- 処理 ---
    Close #fileNo
    Exit Sub

ErrorHandler:
    If fileNo > 0 Then Close #fileNo
    MsgBox "エラーが発生しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical
End Sub

今日の日付のCSVを自動的に読み込む

「毎朝、日付が付いたCSVを取り込む」という業務に対応するパターンです。

Dim todayFile As String
todayFile = "C:\daily_data\" & Format(Date, "yyyymmdd") & "_sales.csv"

If Dir(todayFile) = "" Then
    MsgBox "本日分のファイルが存在しません: " & todayFile, vbExclamation
    Exit Sub
End If
' 以降インポート処理へ

インポート後に自動でピボットテーブルを更新する

' 全ピボットテーブルを更新
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
    pt.RefreshTable
Next pt

Outlookと連携してCSVをメール添付で送信する

' 参照設定: Microsoft Outlook XX.X Object Library が必要
Sub SendCSVByMail()
    Dim olApp  As Object
    Dim olMail As Object
    Dim csvPath As String

    csvPath = ThisWorkbook.Path & "\report.csv"

    Set olApp  = CreateObject("Outlook.Application")
    Set olMail = olApp.CreateItem(0)

    With olMail
        .To      = "[email protected]"
        .Subject = "日次レポート " & Format(Date, "yyyy/mm/dd")
        .Body    = "本日のレポートをお送りします。"
        .Attachments.Add csvPath
        .Send
    End With

    MsgBox "メール送信完了", vbInformation
End Sub

まとめ

本記事では、ExcelマクロによるCSVの自動インポート・エクスポートについて、基本コードから実務向けの応用まで解説しました。要点を整理すると次のとおりです。

  • Open ステートメントを使ったインポートは先頭ゼロを守れる・シンプルで速い
  • UTF-8対応には ADODB.Stream が有効で、BOM除去処理もセットで実装する
  • エクスポート時は RFC 4180 に沿ったダブルクォート囲み処理を入れてデータ破損を防ぐ
  • フォルダループで複数CSVを一括処理するとき、2件目以降のヘッダー行スキップを忘れずに
  • 実行時エラー 1004・53・70・75・9・13・91・5 の原因と対策を覚えておくとデバッグが格段に速くなる
  • ScreenUpdating = FalseOn Error GoTo によるエラーハンドリングは本番マクロの必須実装

マクロは一度作れば何度でも再利用できます。まず「毎日手作業でやっているCSV処理」を1つピックアップし、本記事のコードをベースにカスタマイズすることから始めてみてください。業務の自動化は、小さな一歩の積み重ねで大きな時間削減につながります。