make is.dev make it simple. development.
2024年9月22日

UTF-8 BOMなしでCSV保存

EXCELのCSV保存は、標準ではSJISかUTF-8(BOMあり)しか対応していない。
そのため、UTF-8(BOMなし)でCSV保存したい時は別ツールを使って変換することになる。
システムに取り込むファイルだとBOMなしが多かったりするので、これがなかなかに手間。

以下に、BOMなしのファイルも併せて作成出来るサンプルを紹介する。

使用環境

・ Windows 11
・ Microsoft EXCEL 2019

サンプルコード

'
' ブックをCSV(UTF-8)形式で名前を付けて保存する。
' その際、BOMなしのファイルも併せて作成する。
' 既にファイルがある場合は上書きするので注意。
'
Sub sample()

    ' アラートを消しておく(SaveAsの際、既にファイルがある場合に上書きになる)
    Application.DisplayAlerts = False


    ' FSO準備
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")


    ' ダイアログを表示して保存先ファイル名を取得
    Dim csvFileName As Variant
    
    csvFileName = Application.GetSaveAsFilename(FileFilter:="CSVファイル,*.csv")
    If csvFileName = False Then
        Exit Sub
    End If
    
    
    ' 一時ファイル用のファイル名を生成
    Dim tempFileName As String
    
    With fso
        tempFileName = .GetSpecialFolder(2) & "\" & .GetBaseName(.GetTempName) & ".csv"
    End With
    
    
    ' 一時ファイルとしてCSVファイルで保存(UTF-8 BOMあり)
    ActiveWorkbook.SaveAs Filename:=tempFileName, FileFormat:=xlCSVUTF8, CreateBackup:=False
    
    
    ' 続けて保存先ファイル名で保存しなおす(UTF-8 BOMあり)
    ActiveWorkbook.SaveAs Filename:=csvFileName, FileFormat:=xlCSVUTF8, CreateBackup:=False



    ' ここから一時ファイルを元にBOMなしのファイルを作っていく
    
    ' BOMなし用のファイル名を生成
    Dim csvFileNameNoBom As String
    With fso
        csvFileNameNoBom = .GetParentFolderName(csvFileName) & "\" & Replace(.GetFileName(csvFileName), ".csv", "(BOMなし).csv")
    End With


    ' Stream1 OPEN
    Dim stream1 As Object
    Set stream1 = CreateObject("ADODB.Stream")
    stream1.Type = 1             ' ファイルのタイプ(1:バイナリ 2:テキスト)
    stream1.Open
    
    
    ' Stream1 一時ファイルを開く
    stream1.LoadFromFile tempFileName
    
    
    ' Stream1 BOM分だけカーソルを進める
    stream1.Position = 3
    
    
    ' Stream2 OPEN
    Dim stream2 As Object
    Set stream2 = CreateObject("ADODB.Stream")
    stream2.Type = 1             ' ファイルのタイプ(1:バイナリ 2:テキスト)
    stream2.Open
    
    
    ' Stream1 から Stream2 にデータを流し込む
    ' この時点でBOMがない状態で写される
    stream2.Write stream1.Read
    
    
    ' Stream2 ファイルに出力する
    ' 第二引数 : 1.新規作成、2.上書き保存
    stream2.SaveToFile csvFileNameNoBom, 2
        
        
    ' Stream Close
    stream1.Close
    stream2.Close
    
    
    ' 一時ファイル削除
    Kill tempFileName

End Sub
VB

実行すると、アクティブなブックをCSV(UTF-8)形式で名前を付けて保存する。
BOMありのファイルが作られるのは標準機能での保存と同様だが、併せてBOMなしのファイルも作成する。

処理の中では、一度Tempフォルダに一時ファイルを作成した上で通常のCSV保存を行っている。
(2度SaveAsを実行している)

これは、EXCELがファイルを保存した際に対象のファイルを開いたままロックしてしまうため。
先に一時ファイルを保存した上で、指定したファイルを作成することでロックをそちら側に移している。

BOMなしへの変換は、一時ファイルを元に変換し、別途保存している。