提问人:Karsten W. 提问时间:3/27/2010 最后编辑:Karsten W. 更新时间:11/14/2023 访问量:226625
保存使用 VBA 编码的 UTF-8 文本文件
Save text file UTF-8 encoded with VBA
问:
如何将 UTF-8 编码的字符串从 vba 写入文本文件,例如
Dim fnum As Integer
fnum = FreeFile
Open "myfile.txt" For Output As fnum
Print #fnum, "special characters: äöüß" 'latin-1 or something by default
Close fnum
应用程序级别是否有一些设置?
答:
我在网上找到了答案:
Dim fsT As Object
Set fsT = CreateObject("ADODB.Stream")
fsT.Type = 2 'Specify stream type - we want To save text/string data.
fsT.Charset = "utf-8" 'Specify charset For the source text data.
fsT.Open 'Open the stream And write binary data To the object
fsT.WriteText "special characters: äöüß"
fsT.SaveToFile sFileName, 2 'Save binary data To disk
当然不是我预料的......
评论
Ã
这会在文件的开头写入一个字节顺序标记,这在 UTF-8 文件中是不必要的,并且某些应用程序(在我的情况下是 SAP)不喜欢它。 解决方案:我可以在没有 BOM 的情况下使用 UTF-8 导出 excel 数据吗?
评论
您可以使用 CreateTextFile 或 OpenTextFile 方法,两者都具有用于编码设置的属性“unicode”。
object.CreateTextFile(filename[, overwrite[, unicode]])
object.OpenTextFile(filename[, iomode[, create[, format]]])
示例:覆盖:
CreateTextFile:
fileName = "filename"
Set fso = CreateObject("Scripting.FileSystemObject")
Set out = fso.CreateTextFile(fileName, True, True)
out.WriteLine ("Hello world!")
...
out.close
示例:追加:
'OpenTextFile
Set fso = CreateObject("Scripting.FileSystemObject")
Set out = fso.OpenTextFile("filename", ForAppending, True, 1)
out.Write "Hello world!"
...
out.Close
在 MSDN 文档上查看详细信息
评论
FileSystemObject
.Write
这是执行此操作的另一种方法 - 使用 API 函数 WideCharToMultiByte:
Option Explicit
Private Declare Function WideCharToMultiByte Lib "kernel32.dll" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpWideCharStr As Long, _
ByVal cchWideChar As Long, _
ByVal lpMultiByteStr As Long, _
ByVal cbMultiByte As Long, _
ByVal lpDefaultChar As Long, _
ByVal lpUsedDefaultChar As Long) As Long
Private Sub getUtf8(ByRef s As String, ByRef b() As Byte)
Const CP_UTF8 As Long = 65001
Dim len_s As Long
Dim ptr_s As Long
Dim size As Long
Erase b
len_s = Len(s)
If len_s = 0 Then _
Err.Raise 30030, , "Len(WideChars) = 0"
ptr_s = StrPtr(s)
size = WideCharToMultiByte(CP_UTF8, 0, ptr_s, len_s, 0, 0, 0, 0)
If size = 0 Then _
Err.Raise 30030, , "WideCharToMultiByte() = 0"
ReDim b(0 To size - 1)
If WideCharToMultiByte(CP_UTF8, 0, ptr_s, len_s, VarPtr(b(0)), size, 0, 0) = 0 Then _
Err.Raise 30030, , "WideCharToMultiByte(" & Format$(size) & ") = 0"
End Sub
Public Sub writeUtf()
Dim file As Integer
Dim s As String
Dim b() As Byte
s = "äöüßµ@€|~{}[]²³\ .." & _
" OMEGA" & ChrW$(937) & ", SIGMA" & ChrW$(931) & _
", alpha" & ChrW$(945) & ", beta" & ChrW$(946) & ", pi" & ChrW$(960) & vbCrLf
file = FreeFile
Open "C:\Temp\TestUtf8.txt" For Binary Access Write Lock Read Write As #file
getUtf8 s, b
Put #file, , b
Close #file
End Sub
我研究了 Máťa 的答案,他的名字暗示了编码资格和经验。VBA文档说,创建一个文件“作为Unicode或ASCII文件。如果文件创建为 Unicode 文件,则该值为 True;如果创建为 ASCII 文件,则为 False。如果省略,则假定为 ASCII 文件。文件存储 unicode 字符很好,但以什么编码?未编码的 unicode 不能在文件中表示。CreateTextFile(filename, [overwrite [, unicode]])
VBA 文档页面为以下格式提供了第三个选项:OpenTextFile(filename[, iomode[, create[, format]]])
- TriStateDefault 2“使用系统默认值打开文件”。
- TriStateTrue 1“以 Unicode 格式打开文件”。
- TriStateFalse 0 “以 ASCII 格式打开文件。”
Máťa 为此参数传递 -1。
从 VB.NET 文档来看(不是 VBA,但我认为反映了底层 Windows 操作系统如何表示 unicode 字符串并回显到 MS Office,我不知道)的现实,系统默认值是使用 1 字节/unicode 字符的编码,使用区域设置的 ANSI 代码页。 是 UTF-16。文档还描述了 UTF-8 也是一种“Unicode 编码”,这对我来说很有意义。但是我还不知道如何为 VBA 输出指定 UTF-8,也不确定我使用 OpenTextFile(,,,1) 写入磁盘的数据是 UTF-16 编码的。Tamalek 的帖子很有帮助。UnicodeEncoding
将字符串转换为 UTF-8 字符串的传统方法如下:
StrConv("hello world",vbFromUnicode)
所以简单地说:
Dim fnum As Integer
fnum = FreeFile
Open "myfile.txt" For Output As fnum
Print #fnum, StrConv("special characters: äöüß", vbFromUnicode)
Close fnum
不需要特殊的 COM 对象
评论
StrConv(vbFromUnicode)
返回一个字节数组,该数组包含将给定的 Unicode 字符串(所有字符串在 VBA 中都是 Unicode)转换为非 Unicode 程序的当前系统代码页的结果。此时,字符串中不在该代码页上的“特殊字符”将丢失(并不是说您首先可以将它们包含在原始文本中,因为 VBA 代码编辑器不是 Unicode)。
Print
TypeName(StrConv("hello world",vbFromUnicode))
String
Byte()
StrConv(...,vbFromUnicode)
UTF-16
UTF-8
Dim b() as byte: b = strconv(...,vbFromUnicode)
我不想仅仅为了支持几个 UTF8 字符串而更改我的所有代码,所以我让我的代码做这件事,在保存文件后(在 ANSI 代码中,因为它是 excel 的默认值),然后我使用以下代码将文件转换为 UTF-8:
Sub convertTxttoUTF(sInFilePath As String, sOutFilePath As String)
Dim objFS As Object
Dim iFile As Double
Dim sFileData As String
'Init
iFile = FreeFile
Open sInFilePath For Input As #iFile
sFileData = Input$(LOF(iFile), iFile)
sFileData = sFileData & vbCrLf
Close iFile
'Open & Write
Set objFS = CreateObject("ADODB.Stream")
objFS.Charset = "utf-8"
objFS.Open
objFS.WriteText sFileData
'Save & Close
objFS.SaveToFile sOutFilePath, 2 '2: Create Or Update
objFS.Close
'Completed
Application.StatusBar = "Completed"
End Sub
我像这样使用这个潜艇(这是一个例子):
Call convertTxttoUTF("c:\my.json", "c:\my-UTF8.json")
我在这里找到了这段代码: VBA 将文件编码 ANSI 更改为 UTF8 – 文本转 Unicode
由于这是用 BOM 标记编写的,为了删除 BOM,我将 Sub 更改为:
Sub convertTxttoUTF(sInFilePath As String, sOutFilePath As String)
Dim objStreamUTF8 As Object
Dim objStreamUTF8NoBOM As Object
Dim iFile As Double
Dim sFileData As String
Const adSaveCreateOverWrite = 2
Const adTypeBinary = 1
Const adTypeText = 2
'Init
iFile = FreeFile
Open sInFilePath For Input As #iFile
sFileData = Input(LOF(iFile), iFile)
Close iFile
'Open files
Set objStreamUTF8 = CreateObject("ADODB.Stream")
Set objStreamUTF8NoBOM = CreateObject("ADODB.Stream")
' wrute the fules
With objStreamUTF8
.Charset = "UTF-8"
.Open
.WriteText sFileData
.Position = 0
.SaveToFile sOutFilePath, adSaveCreateOverWrite
.Type = adTypeText
.Position = 3
End With
With objStreamUTF8NoBOM
.Type = adTypeBinary
.Open
objStreamUTF8.CopyTo objStreamUTF8NoBOM
.SaveToFile sOutFilePath, 2
End With
' close the files
objStreamUTF8.Close
objStreamUTF8NoBOM.Close
End Sub
我用这个答案解决了文件开头的BOM未知字符
评论