📢 パソコン学習の決定版、「オンライン学習」「ベテラン講師によるマンツーマンサポート」の『PCHack』でパソコンスキルを劇的に向上!《詳しくはこちらをクリック》

エクセルVBAでCSV読み込み基本の5ステップ!

紬ちゃん

エクセルVBAのCSV読み込みが失敗しちゃう……

ライクさん

CSV読み込みマクロを作る前に、基礎知識を押さえておくと失敗しにくくなるよ!

簡単なようで意外と失敗しがちなCSVファイルの読み込みは、この記事の5ステップで基本をマスターしましょう。

エクセルVBAでCSVを読み込む基本の5ステップ
  1. まずはエクセルとCSVの違いを知る
  2. CSV読み込みマクロを段階を追って学ぶ
  3. よくある読み込みトラブルと解消法をマスター
  4. 大量データは高速読み込みの工夫をする
  5. CSV読み込みの便利ワザを活用

CSVが1行ずつの文字列で作られていることと、エクセルとCSVには違いがあることを理解できれば、VBAの失敗を防げます。

コピペでそのまますぐに使えるサンプルコードもご活用ください。

エクセルマクロの有効化の設定など、マクロの基本について以下の記事にまとめました。

こちらの記事もおすすめなので、ぜひご覧ください。

目次

エクセルVBAでCSV読み込みをする際の基礎知識

エクセルVBAでCSVファイルを読み込む前に、まず知っておきたいことがあります。

それは、「CSVはエクセル専用のファイルではない」ということです。

ライクさん

CSVファイルは、エクセルの他にアクセスやGoogleスプレッドシート、メモ帳など様々なアプリケーションで開いたり編集できたりするよ!

CSVは「Comma Separated Values」の略です。

日本語に訳すると「カンマで区切られた値たち」であるとおり、ファイルの中身はただの文字列です。

エクセルが持っているようなセルの色や罫線などといった見た目の情報は一切含まれていません。

エクセルとCSVの主な違いを表にすると次のとおりです。

CSVファイルエクセルファイル
ファイルの中身テキストのみデータ・書式・数式など
情報量少ない多い
桁や日付の扱い何も判断しない自動で判断しようとする
改行やカンマ記号としてそのまま挿入される自動で判断しようとする
文字コードUTF-8やShift_JISなど指定できるWindows版のエクセルではShift_JISが標準
ライクさん

文字コードとは、コンピュータが文字をデータとして扱うためのルールのことだよ。

これらの差が、CSVファイルをエクセルに読み込みする際のトラブルの素です。

CSVファイルをダブルクリックしてエクセルで開いた場合、エクセルは「これは数字?文字?日付?」など、エクセルなりに判断しながら表示させます。

この「自動判断」が原因で、以下のようなトラブルが発生してしまうのです。

  • 郵便番号や商品番号の「先頭の0」が消える
  • ただの数字が日付や金額として表示される
  • 本来は複数行なのに1行で表示される
  • 文字化けして読めなくなる
紬ちゃん

どうして勝手に0が消えたり、住所の番地が日付になったりするの?って、ずっと思ってた!

ライクさん

エクセルが、良かれと思って自動で変換してたんだね……

このように、CSVファイルをエクセルに読み込む際は、エクセルの自動判断をどのように対策するかがポイントです。

VBAで正しい読み込み方を指定することで、CSVのトラブルは一気に減ります。

これから解説する0落ち対策、文字化け対策なども、すべてこの「エクセルとCSVの違い」を理解することが基本です。

この章はぜひ、何度も読み返してください。

初心者向けのエクセルでCSVを取り込むマクロ

エクセルVBAでCSVの読み込みをするマクロを作るときは、まずは基本パターンを覚えておきましょう。

最初に次の3つの基本を押さえておくことで、後ほど解説するトラブル解決法や応用がぐっと楽になります。

  • 基本の読み込みコード
  • 実務でよく使う「ファイル選択ダイアログ」でCSVを選ぶコード
  • テキストとして1行ずつ読み込むコード

とりあえずマクロを動かすことから始めて、現場で使えるように段階を踏んで理解していきましょう。

作例では、デスクトップ上にある「47都道府県の県庁所在地のCSVファイル」をエクセルファイルに読み込みます。

メモ帳で開いた場合は次の構成となっています。

県庁所在地一覧
県庁所在地一覧

一番シンプルなCSV読み込みマクロ

まずはCSVファイルのはじめの1行だけをマクロで読み込んでみましょう。

エクセルVBAを挫折する原因の一番が、難しいコードよりも「コードを書いても動かなかった……」という経験です。

ご紹介するCSV読み込みマクロは、CSVの読み込みを手動で行うときの以下の基本要素がすべて含まれています。

  • ファイルを指定する
  • ファイルを読み込む
  • エクセルに書き込む
  • ファイルを閉じる

まずはCSV読み込みマクロの骨格を理解し、実務レベルへ発展させていきましょう。

エクセルファイルを開き、「開発」→「Visual Basic」をクリックしてからVBAコードを書いていきます。

STEP
標準モジュールを挿入する
標準モジュールをクリック
標準モジュールをクリック
  • 「挿入」タブをクリック
  • 「標準モジュール」を選択
STEP
プロシージャを挿入
プロシージャをクリック
プロシージャをクリック
  • 「挿入」タブを選択
  • 「プロシージャ」をクリック
STEP
マクロ名を入力
分かりやすい名前を付ける
分かりやすい名前を付ける
  • マクロ名を入力
  • 「OK」ボタンを押す
STEP
プロシージャが追加されたことを確認
プロシージャが追加された
プロシージャが追加された

Public SubCSVを1行だけ開く()End Subの間にコードを記述していきます。

STEP
コードをコピペする
Public Subマクロ名()とEnd Subの間にコピペ
Public Subマクロ名()とEnd Subの間にコピペ

以下のコードをCtrl+CCtrl+Vでコピペします。

    Dim f As Integer
    Dim line As String

    f = FreeFile
    Open "CSVファイルのフルパス" For Input As #f  ' 読み込みたいCSVのパス

    Line Input #f, line  ' 1行だけ読み込む
    Range("A1").Value = line

    Close #f

コードの詳しい解説は後で行います。

STEP
CSVファイルのフルパスを取得
右クリックで選択
右クリックで選択
  • 読み込みたいCSVファイルを右クリック
  • 「パスのコピー」をクリック
STEP
CSVのパスを差し替える
赤く囲まれた箇所を差し替える
赤く囲まれた箇所を差し替える

「"CSVファイルのフルパス"」部分を削除し、STEP6でコピーしたCSVファイルのフルパスを貼り付けます。

ライクさん

パスの最初と最後に「"」ダブルクォーテーションが付いていることを確認しよう!

STEP
マクロを動かしてみる
F5キーでも実行できる
F5キーでも実行できる

「▶」ボタンを押し、マクロを実行してみましょう。

STEP
実行するマクロを選ぶ
先ほど作成したマクロを選択
先ほど作成したマクロを選択
  • 「マクロ名」から、先ほど作成したマクロを選択
  • 「実行」ボタンを押す
STEP
エクセルで結果を確認
VBAエディターはいったん最小化しておく
VBAエディターはいったん最小化しておく

マクロを登録したエクセルファイルを表示させ、A1セルにCSVファイルの1行目が読み込まれていることを確認しましょう。

今回のマクロでは区切り位置の指定をしていないため、A1セル内に1行目の内容がカンマごと入力されていることも併せてご確認ください。

また、必要に応じてこのエクセルファイルを「マクロ有効ファイル」として保存しておきましょう。

ご紹介したコードの解説は次のとおりです。

Dim f As Integer

fをファイル番号を入れるための変数として設定しています。

VBAでCSVファイルを開くときは、番号を振って管理するルールとなっているため、変数fのデータの型はInteger数字であることを宣言しています。

Dim line As String

lineをCSVファイルの1行分の文字列を入れる変数として設定しています。

CSVの1行はカンマ区切りの文字列のため、変数lineのデータの型はString文字列であることを宣言しています。

f = FreeFile

FreeFileとは、「ファイル番号のうち、今空いている番号」を返す関数です。

変数fに入る番号は「今空いているファイル番号」であることを示しています。

Open "CSVファイルのフルパス" For Input As #f

CSVファイルを読み込み専用で開く命令です。

  • For Inputは読み込みモードであることを指定
  • As #fこのCSVファイルを先ほどのf = FreeFileで取得したファイル番号で管理することを指定
Line Input #f, line

Line Input はファイルから1行だけ読み込む命令です。

  • 読み込んだ文字列が変数lineに格納される
  • カンマ区切りのCSVの場合でも、カンマが含まれた状態のままで1行分が取り込まれる
Range("A1").Value = line

A1セルに変数lineに格納された内容を書きこむ命令です。

Close #f

変数fで指定されたファイル番号のCSVファイルを閉じる命令です。

Closeを書かないとファイルが開きっぱなしの状態になり、データ破損などのリスクが生じます。

CSV読み込みの場合は、OpenCloseをセットで使うことを覚えておきましょう。

CSVファイルを読み込むマクロは何種類かありますが、この記事では基本的にLine Inputを紹介します。

このコードが最も分かりやすく、CSV読み込みの本質が理解できるからです。

あとはアレンジするだけで実務レベルに近づいていきますので、まずはこの「基本のコード」をマスターしましょう。

ファイル選択ダイアログでCSVを読み込む方法

実務レベルでエクセルVBAでCSVファイルの読み込みを考えた場合、事前にファイルパスを指定するよりは、CSVファイルをその都度選んで読み込むほうが実用的です。

CSVの保存場所やファイル名は毎回異なるため、固定パスでは対応できないからです。

ファイル選択ダイアログを使って「ファイルを選ぶ→読み込む」流れを作ることで、実務への応用がぐっと近づきます。

前説の「一番シンプルなCSV読み込みマクロ」をアレンジして、選択したファイルの1行目をA1セルに読み込むマクロを作成してみましょう。

サンプルコードは以下のとおりです。

Public Sub ファイルを選択して1行読み込む()

    Dim fPath As String  '※追加①
    Dim f As Integer
    Dim line As String

    ' CSVを選ぶ※追加②
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    ' キャンセル対応※追加③
    If fPath = "False" Then Exit Sub 

    ' 読み込み
    f = FreeFile
    Open fPath For Input As #f
    Line Input #f, line  '最初の1行を読み込み
    Range("A1").Value = line
    Close #f

End Sub

前節とのコードの違いは次の3つのみです。

  • ファイルのフルパスを格納する変数fPathが追加
  • CSVファイルをファイル選択ダイアログで選ぶためのコードが追加
  • ファイル選択ダイアログをキャンセルした場合のキャンセル対策用コードが追加

コードの後半部分は前節とほぼ同じであることを確認しましょう。

後半はほぼ同じ
後半はほぼ同じ
歩君

段階を踏んで理解するのって大事だね!

作例では、マクロ実行ボタンに上記のマクロを登録してみました。

実際の業務をイメージしながら一緒に作業してみてください。

STEP
サンプルコードをコピー&ペーストする
すでにあるコードの下にコピー&ペーストする
すでにあるコードの下にサンプルコードをコピー&ペーストする

前節で作成したコードの下に、サンプルコードをコピー&ペーストしましょう。

Public Sub ファイルを選択して1行読み込む()からEnd Subまですべてをコピーします。

STEP
コピー後にいったんVBAエディターを最小化する
End Subまでコピーされていることを確認
End Subまでコピーされていることを確認

サンプルコードを貼り付けたら、いったんVBAエディターを最小化し、エクセルを表示させましょう。

STEP
フォームコントロールのボタンを選択する
エクセルの画面から作業を開始する
エクセルの画面から作業を開始する
  • 「開発」タブをクリック
  • 「挿入」を押す
  • 「ボタン」を選択
STEP
ボタンにマクロを登録する
ボタンの位置はどこでもOK
ボタンの位置はどこでもOK
  1. マウスをドラッグしてボタンを作成
  2. 登録するマクロを選択
  3. 「OK」ボタンを押す
ライクさん

マクロ名を分かりやすくしておくと作業が楽だよ!

STEP
ボタン名を変更
実務を想定して名前をつけよう
実務を想定して名前をつけよう

CSVファイルを読み込むマクロであることが分かるようにボタン名をつけましょう。

STEP
ボタンを押してマクロを実行
マウスポインタが指マークになることを確認
マウスポインタが指マークになることを確認

ボタンを押し、マクロを実行したときの挙動を確認してみましょう。

STEP
ファイル選択ダイアログが表示されることを確認
ダイアログからCSVファイルを選択する
ダイアログからCSVファイルを選択する
  • ファイル選択ダイアログより読み込むCSVファイルをクリック
  • 「開く」を押す
STEP
CSVファイルが読み込まれた
1行目のみ読み込まれることを確認
1行目のみ読み込まれることを確認

A1セルにCSVファイルの1行目が読み込まれたことを確認しましょう。

前節と同様、マクロで区切り位置の指定をしていないため、A1セル内に1行目の内容がカンマごと入力されていることも併せてご確認ください。

コードのポイントは次のとおりです。

fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")

変数fPathに、ファイル選択ダイアログで選択したファイルのフルパスを格納するよう指示しています。

引数でCSVファイルを表示させるよう指定しています。

If fPath = "False" Then Exit Sub

ファイル選択ダイアログでファイルを選ばずにキャンセルした場合に、マクロを終了するよう指示しています。

このコードが無かった場合、ファイルを選ばずにキャンセルするとマクロがエラーとなります。

CSV読み込みマクロを実務に活用する場合、基本構造の理解の次に優先すべきなのは、この「ファイル選択する方法」を理解することです。

実務に役立つマクロを作成するためにも、ぜひ、活用してください。

CSVをテキストとして1行ずつ読み込む方法

初心者向けのエクセルでCSVを取り込むマクロの仕上げとして、CSVファイルの最終行まで読み込むVBAコードを紹介します。

今まではLine Inputで最初の1行のみを読み込んでいましたが、この、「1行を読み込む処理」をCSVファイルの最後まで繰り返します。

併せて、Splitという関数を使って、1行ずつ読み込んだCSVをカンマで分割させましょう。

サンプルコードは以下のとおりです。

Public Sub ファイルを1行ずつ読み込む()
    Dim fPath As String
    Dim f As Integer
    Dim line As String
    Dim row As Long  '※追加①
    Dim arr As Variant  '※追加②

    ' CSVを選ぶ
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    
    ' キャンセル対応
    If fPath = "False" Then Exit Sub

    ' ファイル読み込み
    f = FreeFile
    Open fPath For Input As #f


    '1行ずつ繰り返し読み込み※追加③
    
    row = 1
    
    Do Until EOF(f)
    
        Line Input #f, line          ' 1行読み込む
        arr = Split(line, ",")       ' カンマで分割

        Range("A" & row).Resize(1, UBound(arr) + 1).Value = arr
        row = row + 1
    Loop

    Close #f
    
End Sub

コードが長くなるとモチベーションが下がってしまいそうですが、前半部分は前節の「ファイル選択ダイアログでCSVファイルを選ぶコード」と同じです。

前半部分は前節と同じ
前半部分は前節と同じ
ライクさん

ここでは、後半部分だけを理解しよう!

前節とのコードの違いは次の3つのみです。

  • セルの行数を格納する変数rowが追加
  • カンマ区切りで分割したデータを格納する変数arrが追加
  • row = 1以下のCSVを読み込むコードが複雑になった

また、row = 1以下のマクロが行っている動作は次の4つに分解されます。

  • CSVを1行のテキストとして読み込む:Line Input
  • 1行のテキストをカンマ位置で分割:Split
  • 分割したテキストをセルに書き込む:.Value = arr
  • ①~④をCSVファイルの最終行まで繰り返す:Do UntilLoop

一つずつを見てみるとそれほど難しくないことが分かります。

紬ちゃん

動作を分解しただけで難易度が下がった気がする!

作例では、前節で作成したボタンの登録マクロを、上記のマクロに変更してみました。

上記のコードをVBAエディターに貼り付けたうえでエクセルファイルを表示させ、一緒に作業してみてください。

STEP
作成済みのマクロ実行ボタンを選択
右クリックで作業を始める
右クリックで作業を始める
  • マクロ実行ボタンを右クリック
  • 「マクロの登録」を押す
STEP
ボタンに登録するマクロを変更
新たにVBAエディターに貼り付けたマクロを選ぶ
新たにVBAエディターに貼り付けたマクロを選ぶ
  • マクロを選び直す
  • 「OK」ボタンを押す
STEP
ボタンを押して動作を確認する
動きは前節と同じ
動きは前節と同じ
  • マクロ実行ボタンを押す
  • ファイル選択ダイアログが表示されるので、読み込むCSVファイルを選択
  • 「開く」を押す
STEP
CSVファイルがすべて読み込まれた
今度は47都道府県すべてが読み込まれた
今度は47都道府県すべてが読み込まれた

前節までは最初の1行だけが読み込みされていましたが、今回は47都道府県すべての行がカンマ区切りで読み込まれていることを確認しましょう。

なお、数字も文字列として読み込まれていることを併せて確認してください。

コードのポイントは次のとおりです。

row = 1

行数を格納する変数rowの初期値が1であることを指定しています。

「読み込んだCSVデータをエクセルの1行目から書き始める」という意味です。

Do Until EOF(f)~Loop

CSVファイルの終わりになるまで処理を繰り返すことを命令しています。

なお、EOFとはEnd Of File、「ファイルの終わり」を意味しています。

Line Input #f, line
arr = Split(line, ",")

CSVから1行だけ読み取った文字列を、変数lineに格納しています。

その上で、変数lineに格納した文字列をカンマで分割して変数arrに格納しています。

分割したデータはarr(0)arr(1)arr(2)…と0から順に一つずつ格納されます。

ライクさん

変数arrの中に小部屋があるイメージだよ!

文字列を分割する関数SplitはCSVファイルの読み込み以外でも様々な場面で使いますので、知っておくと便利です。

Range("A" & row).Resize(1, UBound(arr) + 1).Value = arr

配列を利用して1行分をまとめてセルに書き込む操作をしています。

それぞれのコードの意味は次のとおりです。

  • Range("A" & row):A列の row 行目
  • Resize(1, UBound(arr) + 1) :配列の要素数だけ横に広げる
  • .Value = arr:セル範囲に配列をまとめて書き込む

Resize とはセル範囲を広げたり縮めたりする命令です。

また、UBound(arr)では、Splitで分割したデータの最大要素数を調べています。

分割したデータはarr(0)arr(1)arr(2)…と0から順に格納されるため、データの数を調べたい場合は最大要素数に1をプラスする必要があります。

ここの箇所は配列を理解していないと難しい内容であり、初心者向けではないため、「配列という機能がある」と知っておくだけで構いません。

row = row + 1

次の行へ進むことを命令しています。

このコードがあることで、A1、A2、A3…と1つ下の行に連続して書き込めます。

最後のコードは配列が登場したため少し難しくなってしまいましたが、ここでは以下のCSVの本質3点さえ理解できればOKです。

  • CSVは1行ごとにデータが入っている
  • 行の中はカンマで区切られている
  • 1行ずつ読み込む→カンマ位置で区切る→セルに入れるが基本の流れ

この3点を理解することが、CSV読み込みでよくある「0落ち」「データの区切り位置がおかしい」「文字化け」の対策につながります。

エクセルのCSV読み込みマクロでよくあるトラブルと解消法

前の章ではCSVを読み込む一番確実な方法を解説しました。

データを1行ずつ読み込み、カンマ位置でデータを区切り、文字列としてセルに貼り付けました。

CSVの読み込み動作自体はシンプルですが、実際の業務では以下のようなデータの崩れが非常によく起こります。

  • 郵便番号や商品コードなど、数字の先頭の0が消える
  • 全部1行になる、行がズレる
  • 文字化けして読めない

これは読み込み方法が良くないのではなく、エクセルとCSVのファイル形式の違いが原因です。

ここではエクセルVBAでCSVを読み込む際によくあるトラブルを紹介し、その解消法を解説します。

ご自身がゼロからマクロを作成する場合はもちろん、前任者が作ったCSV読み込みマクロを補正する際にもご活用ください。

数字の先頭の0が消えるトラブルを防ごう

エクセルVBAでCSVファイルを読み込むと「先頭の0」が消えることがあるのは、セルに書き込む際の自動変換が原因です。

つまり、先頭が0の数字は自動的に「数値」扱いされてしまうのです。

前の章で作成したCSV読み込みマクロは、「配列」という仕組みを使って複数セルに一括で書き込むという少し特殊な方法を取ったため、0落ち問題は発生しません。

ただし、他の書き込み方法を使うとエクセルが自動変換してしまい、00123が123で読み込まれるなど、正しく読み取れない場合があります。

例えば以下のコードについて考えてみましょう。

※以下のコードは0落ち対策前のコードです

Public Sub ゼロ落ち対策前()
    Dim fPath As String
    Dim f As Integer
    Dim line As String
    Dim row As Long
    Dim arr As Variant
    Dim i As Long


    ' CSVを選ぶ
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    
    ' キャンセル対応
    If fPath = "False" Then Exit Sub

    ' ファイル読み込み
    f = FreeFile
    Open fPath For Input As #f


    '1行ずつ繰り返し読み込み
    
    row = 1
    
    Do Until EOF(f)
    
        Line Input #f, line          ' 1行読み込む
        arr = Split(line, ",")       ' カンマで分割
        
 
 '▼▼▼ 1セルずつ書き込むコードに変更 ▼▼▼
        
        For i = LBound(arr) To UBound(arr)
            Cells(row, i + 1).Value = arr(i)
        Next i
        
 '▲▲▲ この場合はゼロ落ちが発生する ▲▲▲
 
        
        row = row + 1
    Loop

    Close #f
    
End Sub

基本的に前章のCSVをテキストとして1行ずつ読み込む方法と同じですが、セルに書き込むときのコードを変えています。

配列を活用して複数セルに一括で書き込む方法から、1セルずつ書き込む方法に変更しました。

コードのポイントは次のとおりです。

For i = LBound(arr) To UBound(arr)~Next i

区切られたデータの数だけ処理を繰り返すコードです。

変数iにデータの数が順番に格納されます。

Cells(row, i + 1).Value = arr(i)

カンマ区切りで分割したCSVデータを、Cells(row, i + 1).Value = arr(i)で1セルずつ書き込んでいます。

Cells(行番号,列番号)でセルを一つずつ指定しています。

このマクロを実行すると、以下の図のようにCSVデータが読み込まれます。

0落ちや日付判断が発生
0落ちや日付判断が発生

エクセルが1セルずつデータを受け取った場合、エクセルの自動変換が発生し、0落ちや日付変換が起きてしまうのです。

この場合、書き込む前にセルを文字列に設定することが有効です。

具体的に、セルに書き込むコードの前に次のコードを追加します。

Cells(row, i + 1).NumberFormat = "@" '※追加

コードの追加位置は以下の図より確認してください。

読み込む前に書式設定
読み込む前に書式設定

このコードは、「このセルは文字列として扱って」とエクセルに命令しているコードです。

エクセルの内部ルールにより、"@"は文字列書式のことを表しています。

0落ち対策後のコードの完成版はこちらです。

対策前後のコードを実行し、それぞれの違いを確認してください。

Public Sub ゼロ落ち対策後()
    Dim fPath As String
    Dim f As Integer
    Dim line As String
    Dim row As Long
    Dim arr As Variant
    Dim i As Long


    ' CSVを選ぶ
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    
    ' キャンセル対応
    If fPath = "False" Then Exit Sub

    ' ファイル読み込み
    f = FreeFile
    Open fPath For Input As #f


    '1行ずつ繰り返し読み込み
    
    row = 1
    
    Do Until EOF(f)
    
        Line Input #f, line          ' 1行読み込む
        arr = Split(line, ",")       ' カンマで分割
        
 
 '▼▼▼ 1セルずつ書き込むコードに変更 ▼▼▼
        
        
        For i = LBound(arr) To UBound(arr)
            Cells(row, i + 1).NumberFormat = "@"  '※追加
            Cells(row, i + 1).Value = arr(i)
        Next i
        
 '▲▲▲ この場合はゼロ落ちが発生しない ▲▲▲
 
        
        row = row + 1
    Loop

    Close #f
    
End Sub
0落ち対策ができた
0落ち対策ができた

前章のコードが0落ち対策として最も安全ですが、すでに他の方法でCSV読み込みマクロが作成されている場合は、NumberFormat = "@" を追加することで0落ちを防げます。

前任者のマクロを修正する場合や、他の読み込み方法を使う場合に備えて、0落ち対策方法を理解しておきましょう。

列ズレが起きた場合の解消ポイント

CSVファイルを読み込んだ際、意図しない位置でデータが区切られてしまい、列がズレてしまうことがあります。

以下のCSVデータを使って考えてみましょう。

都道府県と市の間にカンマがあるデータ
都道府県と市の間にカンマがあるデータ

これはCSVファイルをダブルクリックでエクセルとして開いたものです。

E列に所在地が書かれてありますが、都道府県と市の間にカンマがあります。

あとで分けやすいようにカンマを挿入したものと思われますが、これを前節「数字の先頭の0が消えるトラブルを防ごう」のマクロで読み込みをすると次のようになります。

E列がカンマ位置で分割されている
E列がカンマ位置で分割されている

エクセルは、途中にカンマを含む値をCSVに変換する場合、「ここからここまでが1データ」であることが分かるよう、データにダブルクォーテーション「""」を付けます。

ですが、前節のマクロで使用したSplit(line, ",")では、ダブルクォーテーションの有無に関わらず「カンマ位置で区切る」ことだけを行ってしまいます。

紬ちゃん

SplitはCSVのルールが理解できないのね……

データ内にカンマを使わないのが一番ですが、実務ではなかなかそうもいきません。

対策としては、次のことが考えられます。

  • Split(line, ",")でカンマ位置で区切られた状態で一度CSVファイルを読み込み、そのあと手動で結合させる
  • CSVファイルをメモ帳で開き、該当するカンマを手動で別の記号に直す
ライクさん

カンマ位置があらかじめ予測できて、なおかつ件数が少ない場合は「手動で別の記号に修正」が確実だよ。

また、マクロ初心者向けではありませんが、以下にサンプルデータとして「カスタム関数」を使った「列ズレ防止CSV読み込みマクロ」をご紹介します。

Split の弱点である途中のカンマ問題を補うために作成したものであり、エクセルVBAに元々用意されている関数ではありません。

VBA内でSafeSplitと書かれているものが「カスタム関数」です。

Public Sub CSV読み込みカスタム関数版()
    Dim fPath As String
    Dim f As Integer
    Dim line As String
    Dim row As Long
    Dim arr As Variant
    Dim i As Long

    ' CSVを選ぶ
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    If fPath = "False" Then Exit Sub

    ' ファイル読み込み
    f = FreeFile
    Open fPath For Input As #f

    row = 1

    Do Until EOF(f)

        Line Input #f, line          ' 1行読み込む
        arr = SafeSplit(line)        ' 行ズレ防止版 Split(カスタム関数)


        For i = 0 To UBound(arr)
            Cells(row, i + 1).NumberFormat = "@"
            Cells(row, i + 1).Value = arr(i)
        Next i


        row = row + 1
    Loop

    Close #f
End Sub




Function SafeSplit(ByVal line As String) As Variant  ' カスタム関数の設定
    Dim insideQuote As Boolean
    Dim i As Long
    Dim ch As String
    Dim temp As String
    Dim result As Collection
    Dim arr() As String
    
    Set result = New Collection
    
    For i = 1 To Len(line)
        ch = Mid(line, i, 1)
        
        If ch = """" Then
            insideQuote = Not insideQuote
        ElseIf ch = "," And Not insideQuote Then
            result.Add temp
            temp = ""
        Else
            temp = temp & ch
        End If
    Next i
    
    result.Add temp
    
    ReDim arr(0 To result.Count - 1)
    
    For i = 1 To result.Count
        arr(i - 1) = result(i)
    Next i
    
    SafeSplit = arr
End Function

Public Sub CSV読み込みカスタム関数版()End SubでCSVファイルを読み込むコードが書かれています。

Function SafeSplit(ByVal line As String) As VariantEnd Functionの部分では、カスタム関数SafeSplitを定義しています。

コードを使用する際は、少量のデータで検証したうえで、自己責任でお使いください。

エクセルで文字化け表示した場合の対処法

CSVファイルをエクセルVBAで読み込んだとき、データが文字化けすることがあります。

文字化けにより判読不能
文字化けにより判読不能

これはCSVの文字コードが影響しています。

文字コードとは、コンピュータが文字をデータとして扱うためのルールのことです。

CSVファイルの文字コードは、「メモ帳」を使って調べるのが最も簡単です。

CSVファイルを右クリック→プログラムから開く→「メモ帳」をクリックし、文字コードを確認してみましょう。

画面右下に文字コードが書かれている
画面右下に文字コードが書かれている

CSV読み込みで日本語が文字化けする原因は、CSV側の文字コードがUTF-8である場合がほとんどです。

Windows版のエクセルではShift_JISが標準となるため、CSVファイルとエクセルの解釈が異なり、文字化けが生じるのです。

本記事で解説してきたVBAコードを使って最も速く文字化け対策をする方法は、「メモ帳で文字コードを変換する方法」です。

CSVファイルをメモ帳で開き、「名前を付けて保存」→エンコードを「UTF-8」から「ANSI」に変換して、新しいCSVファイルとして保存するだけです。

ANSIに変更して保存
ANSIに変更して保存

ここでの「ANSI」とは、Windows環境においてShift_JISに相当する文字コードを指します。

これで、コードを修正することなく簡単に文字化け対策ができます。

紬ちゃん

これならマクロ初心者でも確実に文字化け対策できる!

ライクさん

だけど、この方法にはデメリットもあるんだ。

CSVファイルをUTF-8からShift_JISへ変換する方法は最も簡単で再現性も高いですが、一方で、変換することで問題が生じる場合もあります。

Shift_JISには、特殊文字や外字など表現できない文字があるからです。

Shift_JISには対応していない文字が入ったCSVファイルをUTF-8からShift_JISへ変換した場合、文字が消えたり別の文字に置き換わるなど、データ破損が起こる可能性があります。

その場合は、件数が少ない場合は手動で修正しましょう。

なお、文字コード問題に詳しいマクロ中級者向けの内容ですが、今までデータの読み込みに使っていたLine Inputではなく、UTF-8に対応したADODB.Streamコードを使う方法があります。

ADODB.Streamは文字コードの指定ができる賢い仕組みです。

以下にADODB.Streamを使って作成した「0落ち・列ズレ・文字化け」対策をしたサンプルコードをご紹介します。

Public Sub CSV読み込み_UTF8対応版()

    Dim fPath As String
    Dim stm As Object
    Dim text As String
    Dim lines As Variant
    Dim one As Variant
    Dim arr As Variant
    Dim row As Long
    Dim i As Long

    'CSVを選択
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    If fPath = "False" Then Exit Sub


    'UTF-8対応 ADODB.Stream
    Set stm = CreateObject("ADODB.Stream")
    With stm
        .Type = 2                  ' adTypeText
        .Charset = "utf-8"         ' UTF-8を指定
        .Open
        .LoadFromFile fPath
        text = .ReadText(-1)       ' 全文読み込み
        .Close
    End With

    '改行統一(CRLF/LFどちらでも対応)
    text = Replace(text, vbCrLf, vbLf)
    text = Replace(text, vbCr, vbLf)

    '行ごとに分割
    lines = Split(text, vbLf)


    row = 1

    '行ループ
    For Each one In lines
        If Trim(one) <> "" Then

            'SafeSplitで列崩れ対策
            arr = SafeSplit(one)
            

            '0落ち防止+書き込み
            For i = 0 To UBound(arr)
                Cells(row, i + 1).NumberFormat = "@"
                Cells(row, i + 1).Value = arr(i)
            Next i

            row = row + 1
        End If
    Next one

End Sub




Function SafeSplit(ByVal line As String) As Variant  ' カスタム関数の設定
    Dim insideQuote As Boolean
    Dim i As Long
    Dim ch As String
    Dim temp As String
    Dim result As Collection
    Dim arr() As String
    
    Set result = New Collection
    
    For i = 1 To Len(line)
        ch = Mid(line, i, 1)
        
        If ch = """" Then
            insideQuote = Not insideQuote
        ElseIf ch = "," And Not insideQuote Then
            result.Add temp
            temp = ""
        Else
            temp = temp & ch
        End If
    Next i
    
    result.Add temp
    
    ReDim arr(0 To result.Count - 1)
    
    For i = 1 To result.Count
        arr(i - 1) = result(i)
    Next i
    
    SafeSplit = arr
End Function

VBAが行っている主な内容は前節までと変わりませんが、順番と内容が若干変わっています。

  • ファイルを指定する:変更なし
  • ファイルを読み込む:読み込み方法をLine Inputから変更
  • ファイルを閉じる:エクセルに書き込む前にファイル全文を読み込んでいる
  • エクセルに書き込む:変更なし

カスタム関数の内容は前節と同じです。

なお、文字コードUTF-8の場合で、「セル内に改行が含まれるCSVファイル」を読み込むのは、コードが煩雑となります。

そのため、上記のコードでは対応していません。

その点も踏まえて、コードを使用する際は、少量のデータで検証したうえで自己責任でお使いください。

大量データのCSVでも固まらない高速読み込みの工夫

エクセルVBAで大量のCSVを読み込むと、エクセルが固まったり遅くなったりすることがあります。

これは、パソコンが弱いからではなく、エクセルの仕組み上、重くなる原因があるからです。

この章では、大量のCSVを読み込むと遅くなる理由と対策法、固まらない読み込み方法について解説します。

データを扱う量が多い方はぜひ、参考にしてください。

エクセルが遅くなる理由と改善方法

大量のCSVファイルの読み込みが遅くなるのは、エクセルの3つのクセが原因です。

  • データを1セルずつ書き込むたびに画面表示を更新する
  • セルを変更するたびに全シートの計算をチェックする
  • 書き込み回数が多いほど負荷が増える

これらのクセを対策し、エクセルVBAを高速化するコードは次のとおりです。

Application.ScreenUpdating = False      ' 画面の更新を止める
Application.Calculation = xlCalculationManual   ' 自動計算を止める
Application.EnableEvents = False        ' イベント停止(安全策)

' --- ここに読み込み処理を書く ---

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True

処理前にエクセルのクセを止め、処理後に元に戻すことがエクセル高速化の基本です。

また、「③書き込み回数が多いほど負荷が増える」について、これまで紹介したコードで解説します。

CSV読み込みを以下の「配列」を使って1行分を一度に書き込むため処理が速いです。

100行×100列の場合、作業回数は100回です。

Range("A" & row).Resize(1, UBound(arr) + 1).Value = arr

一方で、次のように1セルずつ書き込む方法はセルの数だけエクセルに仕事をさせるため遅くなります。

For i = LBound(arr) To UBound(arr)
Cells(row, i + 1).Value = arr(i)
Next i

このコードの場合、100行×100列=10,000回処理が走るため、確実に遅くなります。

大量のデータを扱うときには、このような対策も取り入れてマクロを作りましょう。

エクセルの高速取り込み機能の活用で効率よく読み込もう

大量のCSVデータを取り込むときは、VBAですべて処理させるよりも、エクセルに最初の取り込みを任せてしまうほうが圧倒的に速く済みます。

エクセルの高速取り込みエンジンであるQueryTablesを活用して、安全に速くCSVの読み込みをしましょう。

QueryTablesの特徴は次のとおりです。

  • 外部データを高速で読み込む機能
  • 行が多くてもフリーズしにくい
  • UTF-8などの文字コードを判定
  • ただし列データの書式を自動判断してしまう

以下にQueryTablesを使ったサンプルコードをご紹介します。

QueryTablesの短所である「列データの書式を自動判断してしまう=0落ちする」をカバーした内容です。

Public Sub QueryTablesでCSV読み込み()

    Dim fPath As String
    Dim colCount As Long
    Dim types() As Long
    Dim i As Long

    'CSVファイルを選ぶ
    fPath = Application.GetOpenFilename("CSVファイル (*.csv), *.csv")
    If fPath = "False" Then Exit Sub

    '想定する最大列数を決める(例:30列)
    colCount = 30   ' ※CSVの列数に合わせて調整してください

    ReDim types(1 To colCount)
    For i = 1 To colCount
        types(i) = xlTextFormat   ' 各列を「文字列」として扱う
    Next i

    'QueryTables で CSV を読み込む
    With ActiveSheet.QueryTables.Add( _
        Connection:="TEXT;" & fPath, _
        Destination:=Range("A1"))

        .TextFileParseType = xlDelimited          ' 区切り形式
        .TextFileCommaDelimiter = True            ' カンマ区切り
        .TextFilePlatform = 65001                 ' UTF-8想定※Shift-JISの場合は65001を932に変更

        .TextFileColumnDataTypes = types          ' 全列を文字列扱いに固定

        .Refresh BackgroundQuery:=False           ' 実際に読み込む
        .Delete                                   ' 読み込み後にQueryTable自体は削除
    End With

End Sub

コードのポイントは次のとおりです。

colCount = 30
ReDim types(1 To colCount)
For i = 1 To colCount
types(i) = xlTextFormat
Next i

この箇所で0落ち対策として、列の数の分だけ「書式は文字列である」ことを指示しています。

colCount = 30で、読み込むCSVの列数を30と仮定して変数colCountに格納しています。

仮に列数が50の場合はcolCount = 50と入力します。

With ActiveSheet.QueryTables.Add( _
Connection:="TEXT;" & fPath, _
Destination:=Range("A1"))

ActiveSheet現在使用しているシートに対して、QueryTablesでCSVファイルを高速に読み込むよう指示しています。

  • Connectionで読み込むファイルがテキストファイルであることとフルパスを指定
  • Destinationで読み込み開始位置を指定

WithEnd Withで同じオブジェクト名を省略しています。

.TextFileParseType = xlDelimited
.TextFileCommaDelimiter = True
.TextFilePlatform = 65001
.TextFileColumnDataTypes = types

読み込み方法をそれぞれ指定しています。

コード内の解説をご覧ください。

.TextFilePlatform = 65001は読み込むCSVファイルの文字コードがUTF-8であることを指定しています。

もしもShift-JISの場合は.TextFilePlatform = 932としてください。

.Refresh BackgroundQuery:=False
.Delete

Refreshで読み込みを開始しています。

DeleteはQueryTableの仕組みを削除しています。

CSVファイルの列数とファイルの文字コードを手修正したうえで、データの高速読み込みに役立ててください。

初心者でも使える!CSV読み込みの便利ワザ

エクセルVBAでCSVを扱う際、読み込み以外にも知ってくと実務で便利なワザがあります。

今回は以下の3つの便利技をご紹介します。

  • CSV書き出し
  • 複数のCSVをまとめて読み込み
  • 大量データを安定的に稼働させる

この3つを抑えることで、CSVの扱いがよりラクになりますので、ぜひマスターしてください。

エクセルの内容をCSVとして書き出す基本方法

エクセルの内容をCSVで出力する際は「ファイル」→「保存」→「ファイル形式をCSVに指定して保存」を行いますが、VBAで出力したい場合もあります。

手動の場合はファイル保存を行う
手動の場合はファイル保存を行う

その場合でも、手動で保存するときと同様に「1行ずつ文字列として整えてから出力する」という基本構造を押さえておけばOKです。

そのため、以下の3点を踏まえてVBAコードを作る必要があります。

  • セルや文字の書式、罫線などは保存されない
  • セル内にカンマがあれば、読み込みの際に区切り位置として誤認される
  • セル内に改行やダブルクォーテーションがあると列ズレする可能性がある

以下のサンプルコードは、エクセルの表の内容を「Shift-JIS形式のCSVファイル」として出力するコードです。

マクロの繰り返し処理を使い、セルひとつずつの値を変数に格納し、1行ずつ文字列として整えてから出力しています。

Public Sub CSVを書き出すShiftJIS版()

    Dim fPath As String
    Dim f As Integer
    Dim lastRow As Long, lastCol As Long
    Dim r As Long, c As Long
    Dim line As String
    Dim cellValue As String
    

    '保存先を選択
    fPath = Application.GetSaveAsFilename("output.csv", _
              "CSVファイル (*.csv), *.csv")
    If fPath = "False" Then Exit Sub
    
    
    '上書き対策
    If Dir(fPath) <> "" Then
        If MsgBox("同じファイルが存在します。" & vbCrLf & _
              "上書きしてもよろしいですか?", _
              vbYesNo + vbExclamation) = vbNo Then
        Exit Sub
        End If
    End If
    

    '表のサイズを取得
    lastRow = Cells(Rows.Count, 1).End(xlUp).row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

    f = FreeFile
    Open fPath For Output As #f


    '1行ずつ書き出し
    For r = 1 To lastRow

        line = ""

    '列の最後まで処理を繰り返す
        For c = 1 To lastCol

            cellValue = Cells(r, c).value

            ' セル内にCSVが壊れる原因がある場合(セル内にカンマ・ダブルクォーテーション・改行がある)
            If InStr(cellValue, ",") > 0 Or _
               InStr(cellValue, """") > 0 Or _
               InStr(cellValue, vbLf) > 0 Or _
               InStr(cellValue, vbCr) > 0 Then

                ' ダブルクォーテーションをつける
                cellValue = Replace(cellValue, """", """""""")
                cellValue = """" & cellValue & """"
            End If

            line = line & cellValue

            If c < lastCol Then line = line & ","

        Next c

        Print #f, line

    Next r

    Close #f

End Sub

コードのポイントは次のとおりです。

fPath = Application.GetSaveAsFilename("output.csv", "CSVファイル (*.csv), *.csv")
If fPath = "False" Then Exit Sub

Application.GetSaveAsFilenameは「名前を付けて保存」のダイアログです。

"output.csv"はファイル名の初期設定です。別のファイル名が良い場合は、ここを修正しましょう。

また、*.csvだけを選択するようフィルターをかけています。

If fPath = "False" Then Exit Subで、ダイアログをキャンセルした場合にマクロが終了するよう、エラー対策をしています。

If Dir(fPath) <> "" Then
If MsgBox("同じファイルが存在します。" & vbCrLf & _ "上書きしてもよろしいですか?", _ vbYesNo + vbExclamation) = vbNo Then
Exit Sub
End If
End If

同じファイル名がある場合は、上書きしてよいか確認するメッセージボックスが表示されるよう指示しています。

If文が2つの入れ子になっており、ファイル名とメッセージボックスの選択が条件になっています。

メッセージボックスで上書き保存に対してNOを選択した場合、マクロが終了します。

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

変数lastRowにA列の最終行、lastColに1行目の最終列を格納しています。

これにより、表全体を漏れなく書き出せます。

Open fPath For Output As #f

Open~For Outputは、書き込み専用で開くことを指示しています。

For r = 1 To lastRow
line = ""
For c = 1 To lastCol
cellValue = Cells(r, c).value

For r = 1 To lastRowで最終行まで処理を繰り返すこと、For c = 1 To lastColで最終列まで処理を繰り返すことを指示しています。

CSVファイルは文字列が1行ずつ存在しているため、まずは行を指定→1行内にあるそれぞれのセルの値をcellValue = Cells(r, c).valueで取得する流れです。

If InStr(cellValue, ",") > 0 Or _
InStr(cellValue, """") > 0 Or _
InStr(cellValue, vbLf) > 0 Or _
InStr(cellValue, vbCr) > 0 Then
cellValue = Replace(cellValue, """", """""""")
cellValue = """" & cellValue & """"

セル内にカンマやダブルクォーテーションやセル内改行がある場合は、次の2つの作業を指示しています。

  • セル内のダブルクォーテーションをすべて二重にする
  • セル全体をダブルクォーテーションで囲む
ライクさん

セル内にダブルクォーテーションがある場合は、ダブルクォーテーションを2つに増やして記述するルールがあるんだよ。

line = line & cellValue
If c < lastCol Then line = line & ","

セルの値をつなぎ合わせて、最後の列以外は値の後ろにカンマを挿入します。

変数lineにセルの値をどんどんつぎ足しているイメージです。

Print #f, line

行を書き込んでいます。

また、参考として、CSVファイルを書き出すVBAの文字コードUTF-8版もご紹介します。

Public Sub CSVを書き出すUTF8版()

    Dim fPath As String
    Dim lastRow As Long, lastCol As Long
    Dim r As Long, c As Long
    Dim line As String
    Dim cellValue As String
    Dim utf8Text As String
    Dim stm As Object

    ' 保存先の選択
    fPath = Application.GetSaveAsFilename("output.csv", _
              "CSVファイル (*.csv), *.csv")
    If fPath = "False" Then Exit Sub

    ' 上書き確認
    If Dir(fPath) <> "" Then
        If MsgBox("同名ファイルがあります。上書きしますか?", _
                  vbYesNo + vbExclamation) = vbNo Then
            Exit Sub
        End If
    End If

    ' 表のサイズ取得
    lastRow = Cells(Rows.Count, 1).End(xlUp).row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

    utf8Text = ""   ' 一旦すべて文字列として作る

    'CSV組み立て
    For r = 1 To lastRow

        line = ""

        For c = 1 To lastCol

            cellValue = Cells(r, c).value

           ' セル内にCSVが壊れる原因がある場合(セル内にカンマ・ダブルクォーテーション・改行がある)
            If InStr(cellValue, ",") > 0 Or _
               InStr(cellValue, """") > 0 Or _
               InStr(cellValue, vbLf) > 0 Or _
               InStr(cellValue, vbCr) > 0 Then

                ' ダブルクォーテーションをつける
                cellValue = Replace(cellValue, """", """""""")
                cellValue = """" & cellValue & """"
            End If

            line = line & cellValue
            If c < lastCol Then line = line & ","

        Next c

        utf8Text = utf8Text & line & vbCrLf
    Next r

    'UTF-8 書き出し(BOMあり)
    Set stm = CreateObject("ADODB.Stream")
    With stm
        .Type = 2                    ' テキストモード
        .Charset = "utf-8"           ' UTF-8指定
        .Open
        .WriteText utf8Text
        .SaveToFile fPath, 2
        .Close
    End With

End Sub

Shift-JIS版と途中まではほぼ同じですが、書き出す際のコードがShift-JIS版よりも複雑になっています。

エクセルで文字化け表示した場合の対処法でご紹介したADODB.Streamを使っています。

少量のデータで検証したうえで、自己責任でご活用ください。

複数のCSVをまとめて読み込もう

支店ごとの売上データをひとつのエクセルファイルに読み込むなど、同じレイアウトのCSVファイルを複数読み込む場合、同じ作業を繰り返すのは面倒です。

ファイル数が多い場合は、どこまで読み込んだのか途中で分からなくなることも考えられます。

そこで、フォルダ内のCSVファイルをまとめて読み込むマクロをご紹介します。

フォルダを選ぶだけで、その中にあるCSVファイルを順番に読み込み、ひとつ読み込むごとに下に追加していきます。

サンプルコードは次のとおりです。

なお、Shift-JISに対応しています。

Public Sub 複数CSVをまとめて読み込む()

    Dim folderPath As String
    Dim fileName As String
    Dim f As Integer
    Dim line As String
    Dim row As Long

    'フォルダを選ぶ
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Sub
        folderPath = .SelectedItems(1) & "\"
    End With

    '最初のCSVファイルを取得
    fileName = Dir(folderPath & "*.csv")
    row = 1

    'CSVを1つずつ処理
    Do While fileName <> ""

        f = FreeFile
        Open folderPath & fileName For Input As #f

        Do Until EOF(f)
            Line Input #f, line

            'カンマで分割※行ズレ防止版にしたい場合はarr = SafeSplit(line)にし、このコードの下にカスタム関数の定義を追加
            arr = Split(line, ",")

            '1列ずつ書き込み
            For i = 0 To UBound(arr)
                Cells(row, i + 1).NumberFormat = "@"
                Cells(row, i + 1).value = arr(i)
            Next i

            row = row + 1
        Loop

        Close #f

        ' 次のCSVへ
        fileName = Dir()

    Loop


End Sub

CSVをテキストとして1行ずつ読み込む方法の章でご紹介したコードがベースのため、変更点のみポイントを解説します。

With Application.FileDialog(msoFileDialogFolderPicker)
If .Show <> -1 Then Exit Sub
folderPath = .SelectedItems(1) & "\"
End With

フォルダの中のCSVを全部読み込むため、今までのファイル選択からフォルダ選択ダイアログに変更されています。

フォルダパスを変数folderPathに格納しています。

Do While fileName <> ""~Loop

Do WhileLoopで、フォルダ内のCSVの読み込みが終わるまで処理を繰り返します。

row = row + 1

CSVファイルの読み込みが終わった次の行から、次のCSVファイルを読み込むために行番号はファイルをすべて読み込むまで通算にしています。

なお、このコードは、CSVファイルの1行目に項目がある場合に、ファイルを読み込むたびに1行目の項目も読み込まれます。

次のデータの一番上に項目が読み込まれている
次のデータの一番上に項目が読み込まれている

すべての読み込みが終わったあとに、手作業で項目を削除してください。

また、文字コードがUTF-8のCSVファイルをまとめて読み込むVBAコードもご参考までにご紹介します。

Public Sub CSV複数読み込み_UTF8版()

    Dim folderPath As String
    Dim fileName As String
    Dim fPath As String

    Dim stm As Object
    Dim text As String
    Dim lines As Variant
    Dim one As Variant
    Dim arr As Variant

    Dim row As Long, i As Long



    'CSVフォルダを選択する
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Sub
        folderPath = .SelectedItems(1) & "\"
    End With


    '取り込み開始位置
    row = 1


    'フォルダ内のCSVを順番に取得
    fileName = Dir(folderPath & "*.csv")

    Do While fileName <> ""

        fPath = folderPath & fileName


        ' ADODB.Stream で UTF-8 読み込み
        Set stm = CreateObject("ADODB.Stream")
        With stm
            .Type = 2                   ' adTypeText
            .Charset = "utf-8"
            .Open
            .LoadFromFile fPath
            text = .ReadText(-1)        ' 全文取得
            .Close
        End With
        

        '改行を統一
        text = Replace(text, vbCrLf, vbLf)
        text = Replace(text, vbCr, vbLf)

        lines = Split(text, vbLf)


        '行ループ
        For Each one In lines
            If Trim(one) <> "" Then

            'カンマで分割※行ズレ防止版にしたい場合はarr = SafeSplit(one)
            arr = Split(one, ",")

                '0落ち防止+書き込み
                For i = 0 To UBound(arr)
                    Cells(row, i + 1).NumberFormat = "@"
                    Cells(row, i + 1).value = arr(i)
                Next i

                row = row + 1
            End If
        Next one

        ' 次のCSVへ
        fileName = Dir()

    Loop


End Sub

前節と同様、CSVファイルを読み込む際にADODB.Streamを使っています。

少量のデータで検証したうえで、自己責任でご活用ください。

エクセルのメモリ不足やエラー中断を回避しよう

大量のCSVを扱う時に重要なのは次の2点です。

  • メモリを使いすぎないこと
  • 止まらないこと

小さなCSVなら問題ない場合でも、大きいとメモリを圧迫したりフリーズしたり、最悪の場合はファイルを壊してしまう場合があります。

そこで、手順は変えずに負荷だけ減らす工夫をして、安心して読み込めるようにしましょう。

マクロ初心者でも扱える実用的な工夫を2つご紹介します。

1万行以上のCSVの場合は行ごとにメモリをクリアすると安心

今回ご紹介したCSV読み込みコードは主に「配列」を使ったものです。

Splitやカスタム関数のSafeSplitを使ったコードが該当します。

大きなCSVの場合、この配列がメモリをどんどん使うので、行ごとにクリアしてメモリを節約しましょう。

追加するコードは以下のとおりです。

Erase 配列名
ライクさん

配列名は、今回の記事だと変数arrが該当するよ!

Eraseは配列を初期化したりメモリを解放したりするコードです。

コードの挿入位置は、1行の処理が終わった直後が最も安全で効果的です。

行ループの最後がベストな位置
行ループの最後がベストな位置

目安として、CSVファイルが1万行以上の場合はEraseを付けておくと安心です。

CSV読み込みが途中で止まるのを防ぐ最低限のエラー処理

CSVを読み込む際、途中でおかしい行が混ざってエラーが出た場合でも、次の行へ進むコードを入れておけます。

読み込みが終わった後に件数を確認したり、あらかじめ行ごとにIDを付けたりするなど、読み込めなかった行を特定する工夫をしておきましょう。

サンプルコードは次のとおりです。

On Error GoTo SkipLine

For Each one In lines

    ' データの読み込み
    arr = SafeSplit(one)

    For i = 0 To UBound(arr)
        Cells(row, i + 1).NumberFormat = "@"
        Cells(row, i + 1).Value = arr(i)
    Next i

    row = row + 1

ContinueLoop:
    On Error GoTo SkipLine
Next one

Exit Sub

SkipLine:
    ' この行はスキップして次へ
    row = row + 1
    Resume ContinueLoop

このコードの流れは次のとおりです。

繰り返し処理を止めない工夫
繰り返し処理を止めない工夫
  • 処理の途中でエラーが発生した場合は、ForNextの繰り返し処理をいったん抜け出してSkipLineへ移動
  • row = row + 1で1行スキップし、ContinueLoopに戻る
  • 再びOn Error GoTo SkipLineでエラー時の処理内容を指示したうえで、Next oneで次の行の処理に戻る
ライクさん

ContinueLoopを中継地点にしているんだよ!

この2つの対策をしておくことで、大きなCSVでも読み込み時の安定感が大幅にアップします。

今までのコードに若干手を加えるだけでOKですので、お困りの際はぜひ一度、試してみてください。

エクセルVBAのCSV読み込みに関するQ&A

エクセルVBAでCSVを開かずに読み込む方法は?

エクセルVBAでCSVを読み込む方法はいくつかありますが、Line Inputというコードを使って、1行ずつ読み込む方法が初心者向けで確実です。

詳しい内容は「初心者向けのエクセルでCSVを取り込むマクロ」の章をご覧ください。

CSVファイルを文字化けせずに開くにはどうすればいいですか?

CSVの文字コードがUTF-8の場合はCSVを読み込む際に文字化けすることがあります。

UTF-8に対応したコードを使えば文字化けを防げます。

エクセルで文字化け表示した場合の対処法」の章で詳細をご確認ください。

VBAでCSVを一括で読み込みする方法を教えてください。

フォルダ内のCSVファイルを順番に読み込むコードをご紹介してますので、「複数のCSVをまとめて読み込もう」の章をご覧ください。

エクセルVBAのCSV読み込みはこれだけ知ればOK!

エクセルVBAでCSVファイルを読み込む基本を解説しました。

次の5ステップで段階を踏んで学ぶことで、初心者でも無理なくCSV読み込みマクロを作れます。

おさらい
  1. まずはエクセルとCSVの違いを知る
  2. CSV読み込みマクロを段階を追って学ぶ
  3. よくある読み込みトラブルと解消法をマスター
  4. 大量データは高速読み込みの工夫をする
  5. CSV読み込みの便利ワザを活用

CSVは読み込み方の工夫次第で、業務の効率化にも反対に手間を増やすことにもつながります。

この記事を活用して、ぜひ、スムーズなCSV読み込みをしましょう!

CSV読み込み以外にも、マクロを作成する上で知っておきたい基本の内容について、以下の記事にまとめました。

マクロ初心者から一歩踏み出したい方は、ぜひご覧ください。

よかったらシェアしてね!
  • URLをコピーしました!
目次