第4回 直感！スグに使える業務向けVBA汎用プロシージャ(CSV保存)

第0回で配布しました汎用プロシージャのコードの紹介と簡単な解説をやっていきたいと思います！
以下のリンクから .bas ファイルをダウンロードできます（zipファイル）

https://drive.google.com/file/d/11qEUTsq87UItzoKu2okX5WgEopRercCb/view?usp=drive_link

今回ご紹介するプロシージャは
| プロシージャ名		| 概要						|
|-------------------------------|-----------------------------------------------|
| ArrayToCsv | 配列をCSV形式で保存(Shift_JIS、インデックスは1開始)		|
| ArrayToCsv_UTF8  | 配列をCSV形式で保存(UTF-8、インデックスは1開始)		|

今回は配列の中身をそのままCSVファイルに保存できてしまうというプロシージャです！Excelユーザーですと.xlsxファイルと.csvってなんとなく同じものみたいに扱うことが多いですが、簡単にCSVファイルと何かをおさらいしましょう。

## CSVファイルとは
CSVファイルは、英語で**C**omma **S**eparated **V**aluesの略で各項目がカンマ(,)で区切られたテキストファイルのことです。そう、テキストファイルなんです。テキストファイルでありながらカンマで区切られているためExcelのようなスプレッドシートでも取り扱うことができるというファイル形式です。

CSVファイルのメリットとしてExcelのみならず様々なツールで取り扱うことができる、データ容量が軽いなどが挙げられます。ロガーなどの測定器の出力ファイルなどがCSVファイルですね。(極稀にカンマ区切りではなく半角スペース区切りで.datファイルなんてパターンもありますね...)

そして今回、**Shift_JIS**版と**UTF-8**版と2種類の保存方式をご用意しました。文字コードというものをご存じない方向けに簡単に説明しますと、文字コードとはコンピュータが文字を処理するために特定のデータに文字をあてはめたもので、Shift_JISは日本語のシステムでよく使われる日本語処理に特化した文字コードになり、UTF-8は世界中の多くの言語に対応した国際標準の文字コードになります。

日本語ExcelなどはShift_JISが使われているのですが、PythonなどではUFT-8が使われており保存形式を揃えないと**文字化け**を起こしてしまします。

日本語Excelのみで完結するシステムであればShift_JIS版で大丈夫ですが、生成したCSVファイルをPythonなどの別のシステムで処理したい場合はUTF-8版をお使いください。

それではコードの紹介です！

## ArrayToCsv
~~~
Sub ArrayToCsv(dataArray As Variant, Optional csvPath As String = "")
'------------------------------------------------------------------------------------------------------------------------------
'　概要　　｜配列の内容をCSV形式で保存する
'------------------------------------------------------------------------------------------------------------------------------
'　引数１　｜dataArray - 保存対象の2次元配列(インデックスは1開始)
'　引数２　｜csvPath - 保存先のCSVファイルパス(省略時はダイアログ表示)
'------------------------------------------------------------------------------------------------------------------------------
'　実装　　｜Ver.1.0.0(2025/04/20:新規)
'------------------------------------------------------------------------------------------------------------------------------

    Dim vLoop       As Long '行ループカウンタ
    Dim hLoop       As Long '列ループカウンタ
    Dim fileNum     As Long 'ファイルハンドル
    Dim rowText     As String '行ごとのセル内容の文字列
    Dim csvSafe     As String 'セル内容変換用変数
    
    'ユーザー定義エラー
    If IsArray(dataArray) <> True Then
        Err.Raise vbObjectError + 1001, "ArrayToCsv", "第一引数は配列を指定してください"
    End If
    
    'ファイルパスが空なら保存先ダイアログ表示
    If csvPath = "" Then
        csvPath = Application.GetSaveAsFilename("output.csv", "CSVファイル (*.csv), *.csv")
        If csvPath = "False" Then Exit Sub 'キャンセル時
    End If
    
    'ファイル書き込み開始(Shift_JIS)
    fileNum = FreeFile
    Open csvPath For Output As #fileNum
    For vLoop = 1 To UBound(dataArray, 1)
        rowText = ""
        For hLoop = 1 To UBound(dataArray, 2)
            'セル内ダブルクオーテーション等の変換
            csvSafe = dataArray(vLoop, hLoop)
            csvSafe = Replace(csvSafe, """", """""")
            If InStr(csvSafe, ",") > 0 Or InStr(csvSafe, """") > 0 Or InStr(csvSafe, vbCr) > 0 Or InStr(csvSafe, vbLf) > 0 Then
                csvSafe = """" & csvSafe & """"
            End If
            rowText = rowText & csvSafe & ","
        Next hLoop
        rowText = Left(rowText, Len(rowText) - 1) '最後の区切り文字削除
        Print #fileNum, rowText
    Next vLoop
    
    Close #fileNum
    
End Sub

~~~

## ArrayToCsv_UTF8
~~~
Sub ArrayToCsv_UTF8(dataArray As Variant, Optional csvPath As String = "")
'------------------------------------------------------------------------------------------------------------------------------
'　概要　　｜配列の内容をUTF-8形式でCSV保存する
'------------------------------------------------------------------------------------------------------------------------------
'　引数１　｜dataArray - 保存対象の2次元配列(インデックスは1開始)
'　引数２　｜csvPath - 保存先のCSVファイルパス(省略時はダイアログ表示)
'------------------------------------------------------------------------------------------------------------------------------
'　実装　　｜Ver.1.0.0(2025/04/20:新規)
'------------------------------------------------------------------------------------------------------------------------------
    
    Dim vLoop       As Long '行ループカウンタ
    Dim hLoop       As Long '列ループカウンタ
    Dim rowText     As String '行ごとのセル内容の文字列
    Dim csvSafe     As String 'セル内容変換用変数
    Dim csvContent  As String 'CSVテキスト
    Dim stream      As Object
    
    'ユーザー定義エラー
    If IsArray(dataArray) <> True Then
        Err.Raise vbObjectError + 1001, "ArrayToCsv_UTF8", "第一引数は配列を指定してください"
    End If
    
    If csvPath = "" Then
        csvPath = Application.GetSaveAsFilename("output_utf8.csv", "CSVファイル (*.csv), *.csv")
        If csvPath = "False" Then Exit Sub
    End If
    
    'CSVテキストを構築
    For vLoop = 1 To UBound(dataArray, 1)
        rowText = ""
        For hLoop = 1 To UBound(dataArray, 2)
            'セル内ダブルクオーテーション等の変換
            csvSafe = CStr(dataArray(vLoop, hLoop))
            csvSafe = Replace(csvSafe, """", """""")
            If InStr(csvSafe, ",") > 0 Or InStr(csvSafe, """") > 0 Or InStr(csvSafe, vbCr) > 0 Or InStr(csvSafe, vbLf) > 0 Then
                csvSafe = """" & csvSafe & """"
            End If
            rowText = rowText & csvSafe & ","
        Next hLoop
        rowText = Left(rowText, Len(rowText) - 1) '最後の区切り文字削除
        csvContent = csvContent & rowText & vbCrLf
    Next vLoop
    
    'ADODB.StreamでUTF-8書き込み
    Set stream = CreateObject("ADODB.Stream")
    With stream
        .Charset = "utf-8"
        .Open
        .WriteText csvContent
        .SaveToFile csvPath, 2 '2=上書き保存
        .Close
    End With
    Set stream = Nothing
    
End Sub

~~~

## 動作解説
コードの中身はShift_JIS版とUTF-8版で違う部分がありますが、やっていることは文字コード以外同じであるため今回はShift_JIS版のみの解説とさせていただきます。

![Excel-4-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4046902/5be30f58-8c70-4298-9bdd-3ddbbdeb06c9.png)

では、第2回でも出てきたこの表をCSVファイルにしてみましょう！
第3回に出てきた**CellToArray**を使ってA1セルからF9セルまでを配列Aに格納してCSVファイルとして保存します。

~~~
Sub Main()
    
    Dim A As Variant
    
    A = CellToArray(1, 1, 9, 6)
    Call ArrayToCsv(A)
    
End Sub
~~~

実はこれだけで保存できてしまいます！また、ArrayToCsvの第2引数を指定しない場合はダイアログボックスが表示され任意のフォルダに任意のファイル名で保存ができます。(デフォルトは"output.csv")
また、第2引数にファイル名を含めたフルパスを指定するとダイアログボックスが表示されずそのまま保存されます。大量のCSVファイルを生成したい際はこちらの方法をオススメします。
では、生成されたoutput.csvを見てみましょう。

![Excel-4-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4046902/a4bbbcd7-0c07-47a1-b4d6-d4400a3a0f6b.png)

そしてメモ帳で開くと...

![Excel-4-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4046902/a5a8005b-95ec-4eed-bd4a-ef1788687a09.png)

しっかりカンマ区切りのテキストファイルになっていることが確認できました！
最終的に作りたいシステムに合わせてShift_JIS版とUTF-8版を使い分けてみてください！

## 直感！VBAシリーズ記事一覧
もしよろしければ他の記事もご覧ください！

https://qiita.com/Reko/items/3e482f9a73353e964f00

https://qiita.com/Reko/items/af042ae33cdc01e1dc96

https://qiita.com/Reko/items/9e211c9c496e12283f33

https://qiita.com/Reko/items/c2dab7b0e8207f8049df

https://qiita.com/Reko/items/3451339e723a34ac7897

https://qiita.com/Reko/items/40c66556ac51a8006ea6

https://qiita.com/Reko/items/0269b2bece07a675e797

https://qiita.com/Reko/items/e2d0d0bf2dea4feface1

https://qiita.com/Reko/items/b995c3da88d25f6e0104

https://qiita.com/Reko/items/bc97d79599cfd431b2f3

https://qiita.com/Reko/items/1731aaddfc6e50c209df

https://qiita.com/Reko/items/554a47f2aa944e2eec5e

https://qiita.com/Reko/items/e8253ac68ccafba44ad3