Mac (Ventura) 上的 Excel VBA (365):确保使用 UTF-8 加载 UTF-8 csv 文件

Excel VBA (365) on Mac (Ventura): ensure UTF-8 csv-files are loaded using UTF-8

提问人:EFM 提问时间:4/30/2023 最后编辑:JosefZEFM 更新时间:11/1/2023 访问量:180

问:

每个月我都需要将数百个 UTF-8 格式的 csv 文件直接加载到 mac (Ventura) 上的 VBA 数组中。

使用 Open file 语句时,如何指定“UTF-8”或“代码页 65001”或“Unicode (UTF-8)”或类似内容? 我在以下位置找不到它: https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/open-statement#syntax

以下代码导致日语汉字乱码:

Open filePath For Input As #1
    fileContent = Input$(LOF(1), #1)
Close #1

(英语很好用)

我已经确认 csv 文件实际上是 UTF-8 格式的。

根据我发现的有关 mac 默认编码的信息,它应该是 UTF-8,但是,mac 上的 Excel 似乎不使用此默认值 (UTF-8)。无论我是在英语还是日语模式下运行 mac 都没有关系。

我尝试了不同的 Open 语句选项,如下所示。但它们不编译:

Open filePath For Input Mode As #1 Len = 100000, Format := "Unicode (UTF-8)"
    data = Input$(LOF(1), #1)
Close #1

此外,“”库在 mac 上不可用,所以我不能使用:Scripting.FileSystemObject

Set fso = CreateObject("Scripting.FileSystemObject")

我也不能使用CreateObject("ADODB.Stream")

到目前为止,唯一有效的方法是将 csv 文件加载到工作簿中。但是,我需要将 csv 文件直接加载到数组中。

With sh.QueryTables.Add("TEXT;" & FolderPath & Application.PathSeparator & Filename, Destination:=sh.Range("A" & lLastDataRow))
            .TextFilePlatform = 65001
            .TextFileCommaDelimiter = True
            .Refresh
            .Delete
        End With

显然,这里的关键是“”部分。如何为 Open file 语句指定此项?.TextFilePlatform = 65001

谢谢。

Excel VBA macOS CSV UTF-8

评论


答:

0赞 GWD 11/1/2023 #1

该语句无法处理 UTF-8 转换。Open

由于我们知道 VBA 和 Excel 内部使用 UTF-16LE,因此我们可以读取文件的二进制内容,稍后再进行 UTF-8 到 UTF-16 的转换。正如您已经指出的,这在 Mac 上有点棘手,因为缺少 和 .ADODB.StreamFileSystemObject

我编写了一个函数,仅使用跨平台可用的 VBA 内置函数和语句手动将 UTF-8 转码为 VBA 内部 UTF-16。我已经在不同的答案中发布了它,因此将在此处链接它以避免重复并使维护更容易。

使用此功能,您可以像这样轻松读取和解码文件:

Sub ReadUTF8FileDemo()
    Dim fileNum As Long: fileNum = FreeFile
    Dim path As String:  path = "C:\Users\username\Desktop\UTF-8_file.csv"
    
    Dim b() As Byte
    Open path For Binary Access Read As #fileNum
        ReDim b(0 To LOF(fileNum))
        Get fileNum, , b
    Close #fileNum: fileNum = 0
    
    Dim dataStr As String
    dataStr = DecodeUTF8(CStr(b))
    'DecodeUTF8 function available here:
    'https://stackoverflow.com/a/75787820/12287457
    
    Debug.Print dataStr 'Voilà
End Sub