2014/09/29

Excel VBAでcsvファイルを作成する方法

カテゴリー:
タグ:

Excelで処理したデータをcsvファイル形式で保存する、ということはよくあると思います。ファイル全体をcsvで保存するのであれば、「名前を付けて保存」でファイル形式をcsvにすればできます。しかし、そのデータ処理をVBAで行っていた場合、csvファイルの保存だけ手作業というのはめんどうです。また、一部分だけcsvにするということもできません。ここでは、VBAを使って、Excel内のデータをcsvファイルに保存する方法を紹介します。

VBAでcsvファイルを作成する方法

VBAを使って、Excel内のデータをcsvファイルに保存する方法を紹介します。まずはベーシックな方法を紹介し、続いて応用例を挙げていきたいと思います。

前提として、csvファイルに保存しようとしているデータが、アクティブなシートに存在する、とします。また、A1セルから順番にデータが入っていて、行数は2以上、列数は3とします。列数が変わる可能性がある場合は後述します。

実は、csvファイルを保存するための特別なメソッドは、VBAにはありません。しかし、ファイルを読み書きするための一般的な仕組みがあるので、これを使用します。

Sub makeCsv1()

Dim lastRow As Long, row As Long
Dim fileNumber As Integer, csvFile As String

csvFile = ActiveWorkbook.Path & "\data.csv"

lastRow = Range("A1").End(xlDown).row

fileNumber = FreeFile

Open csvFile For Output As #fileNumber

For row = 1 To lastRow
    Write #fileNumber, Cells(row, 1), Cells(row, 2), Cells(row, 3)
Next

Close fileNumber

End Sub

あまり見慣れない、Open、Write、Closeの部分で、csvへのファイルの書き出しを行っています。このOpenやWriteやCloseは、ステートメントの一種です。それぞれ解説していきます。

まずは、Openについて。Openは、ファイルを開いて、ファイルへ入出力できるようにしてくれます。必須の項目だけ書くと、構文は次のようになります。

Open ファイル名 For ファイルモード As #ファイル番号

ファイル名は、これから作業をしようとしているファイル名です。ファイルモードは、そのファイルをどういうモードで開くかを指定します。ここでは「出力モード(Output)」としています。他にも、「読み込み(Input)」「追加書き込み(Append)」などを指定することができます。3つ目のファイル番号は、ファイルの識別番号です。今後読み書きするときには、ファイル名ではなく、このファイル番号を使用します。

ファイル番号は、1~511の範囲の数字を指定しますが、自分で数字を入力することも「FreeFile関数」を使うこともできます。FreeFile関数を使えば、適当なファイル番号が自動で設定されます。複数のファイルを同時に読み書きするときには重要ですが、1つのファイルしか操作しないのであれば、あまり気にすることはありません。上では、FreeFile関数を使って処理しています。

次にWriteについて。Writeは名前の通り、書きこみを実施します。次のような構文です。

Write #ファイル番号, 出力するデータ

ファイル番号は、Openで設定した数字です。出力するデータは、カンマ(,)で区切れば複数指定することができます。カンマで区切った各データは、ダブルクオテーション(”)で囲まれ、カンマで区切られて出力されます。また、最後には改行が追加されて出力されます。

最後のCloseは、ファイルを閉じるために実行します。

ファイルを開いて、書きこんで、閉じて終了です。書き方が少し特殊ですが、そんなに複雑なことをしているわけではありません。

列数が多い場合、列数が変わる場合の対応

さて、上で見たとおり、Writeは、各データをカンマで区切れば、出力値もカンマで区切られた形になり、Write文の最後の改行が、出力時にも改行として反映されます。しかし、これでは1行がとても長い場合に大変です。例えば6列あったとしましょう。

Write #ファイル番号, データ1, データ2, データ3, データ4, データ5, データ6

こういうふうに書くのでしょうか。めんどくさいです。でも、次のように書くのはダメなんですよね。

Write #ファイル番号, データ1, データ2, データ3
Write #ファイル番号, データ4, データ5, データ6

こうかくと、1行が2行に分割されたcsvファイルができあがってしまいます。

これには対応策があります。「セミコロン(;)」を使います。セミコロンを使うと、改行せずに次のデータが出力されるようになります。上の例であれば、次のようにすればちゃんと1行でcsvが作成されます。

Write #ファイル番号, データ1, データ2, データ3;
Write #ファイル番号, データ4, データ5, データ6

なので、上のマクロも、次のようにすれば、列数が多い場合や列数が変わりうる場合でも対応できます。

Sub makeCsv2()

Dim lastRow As Long, row As Long, lastCol As Integer, col As Integer
Dim fileNumber As Integer, csvFile As String

csvFile = ActiveWorkbook.Path & "\data.csv"

lastRow = Range("A1").End(xlDown).row
lastCol = Range("A1").End(xlToRight).Column

fileNumber = FreeFile

Open csvFile For Output As #fileNumber

For row = 1 To lastRow
    For col = 1 To lastCol - 1
        Write #fileNumber, Cells(row, col);
    Next
    Write #fileNumber, Cells(row, col)
Next

Close fileNumber

End Sub

最後の列以外にはセミコロンがついているので、途中で改行が入りません。最後の列にだけ改行が入ります。

保存時にcsvファイルの名前を指定する方法

csvに保存するときに、ファイル名をあらかじめ指定するのではなく、マクロを回した時にファイル名を指定したい場合があります。そのときには、GetSaveAsFilenameメソッドを使用して、ファイル取得の部分を次のようにします。

Dim csvFile As Variant

csvFile = Application.GetSaveAsFilename("data.csv", "CSV (*.csv),*.csv")
If csvFile = False Then End

GetSaveAsFilenameメソッドの1つ目の引数は、デフォルトのファイル名です。もちろん、ユーザーはファイル名を変更して保存することができます。2つ目の引数は、ファイルフィルターで、csvファイルを作成する場合は、上のように設定すればOKです。

返り値はVariant型です。ファイル名が指定された場合は、パスとファイル名が返ってきますが、キャンセルされれば、falseが返ってきます。そのため、ファイル名を取得する変数の型をStringからVariantに変え、もしfalseが返ってきたら、そこでマクロを終わらせるという処理をしています。結果的に、次のようなマクロになります。

Sub makeCsv3()

Dim lastRow As Long, row As Long, lastCol As Integer, col As Integer
Dim fileNumber As Integer, csvFile As Variant

csvFile = Application.GetSaveAsFilename("data.csv", "CSV (*.csv),*.csv")
If csvFile = False Then End

lastRow = Range("A1").End(xlDown).row
lastCol = Range("A1").End(xlToRight).Column

fileNumber = FreeFile

Open csvFile For Output As #fileNumber

For row = 1 To lastRow
    For col = 1 To lastCol - 1
        Write #fileNumber, Cells(row, col);
    Next
    Write #fileNumber, Cells(row, col)
Next

Close fileNumber

End Sub

ダブルクオテーションが不要な場合の対応

最後は、Writeで書き出した時に含まれるダブルクオテーションがいらない場合にどうするかを考えます。

上でも書いた通り、Writeを使ってデータを書きこむと、各データはダブルクオテーションで囲まれてしまいます。基本的に、これを取り除くことはできません。ダブルクオテーションが不要な場合は、別のPrintというものを使うようにします。

PrintもWriteも構文は同じですが、出力されるデータの処理が異なります。Writeを使うと、各データがダブルクオテーションで囲まれ、カンマで区切られます。一方Printは、データがそのまま出力されます。ダブルクオテーションで囲まれませんが、逆にカンマも追加されないので、自分でカンマを追加する必要があります。

次のようにすればOKです。

Sub makeCsv4()

Dim lastRow As Long, row As Long, lastCol As Integer, col As Integer
Dim fileNumber As Integer, csvFile As Variant

csvFile = Application.GetSaveAsFilename("data.csv", "CSV (*.csv),*.csv")
If csvFile = False Then End

lastRow = Range("A1").End(xlDown).row
lastCol = Range("A1").End(xlToRight).Column

fileNumber = FreeFile

Open csvFile For Output As #fileNumber

For row = 1 To lastRow
    For col = 1 To lastCol - 1
        Print #fileNumber, Cells(row, col) & ",";
    Next
    Print #fileNumber, Cells(row, col) & ""
Next

Close fileNumber

End Sub

「Print #fileNumber, Cells(row, col) & “”」については、理由はわからないのですが、「& “”」をしないと出力値に空白が含まれてしまうので、その対策として追加しています。また、Writeの時と同様、Printでもセミコロンで区切ることにより、改行を入れずにデータを書き出すことができます。

まとめ

今回は、VBAでcsvファイルを作成する方法を見てみました。一般的なテキストファイルへの出力と同じなので、ファイルの拡張子さえ変えればテキストファイルも同じように作成できます。csvファイルやテキストファイルをVBAで作成する場合は、ぜひ使ってみてください。

前の記事:
次の記事: