关于utf 8:保存使用VBA编码的文本文件UTF-8

Save text file UTF-8 encoded with VBA

我如何从VBA将UTF-8编码的字符串写入文本文件,例如

1
2
3
4
5
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

在应用程序级别上是否有设置?


我在网上找到了答案:

1
2
3
4
5
6
7
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

当然不是我所期望的...


您可以使用CreateTextFile或OpenTextFile方法,它们都具有" unicode"属性,可用于编码设置。

1
2
object.CreateTextFile(filename[, overwrite[, unicode]])        
object.OpenTextFile(filename[, iomode[, create[, format]]])

示例:覆盖:

1
2
3
4
5
6
7
CreateTextFile:
 fileName ="filename"
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set out = fso.CreateTextFile(fileName, True, True)
 out.WriteLine ("Hello world!")
 ...
 out.close

示例:追加:

1
2
3
4
5
 OpenTextFile Set fso = CreateObject("Scripting.FileSystemObject")
 Set out = fso.OpenTextFile("filename", ForAppending, True, 1)
 out.Write"Hello world!"
 ...
 out.Close

在MSDN文档上查看更多信息


这会在文件的开头写入字节顺序标记,这在UTF-8文件中是不必要的,并且某些应用程序(在我的情况下为SAP)不喜欢它。
这里的解决方案:我可以使用没有BOM的UTF-8导出Excel数据吗?


这是执行此操作的另一种方法-使用API??函数WideCharToMultiByte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 ="??ü?μ@€|~{}[]23\\ .." & _
   " 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文档说CreateTextFile(filename, [overwrite [, unicode]])创建一个文件"作为Unicode或ASCII文件。如果该文件被创建为Unicode文件,则值为True;如果被创建为ASCII文件,则值为False。如果省略,则假定为ASCII文件。"文件存储Unicode字符很好,但是用什么编码呢?未编码的unicode不能在文件中表示。

OpenTextFile(filename[, iomode[, create[, format]]])的VBA文档页面为格式提供了第三个选项:

  • TriStateDefault 2"使用系统默认值打开文件。"
  • TriStateTrue 1"以Unicode打开文件"。
  • TriStateFalse 0"以ASCII文件形式打开文件。"

玛阿(Máa)为此参数传递了-1。

从VB.NET文档(不是VBA)来看,但我认为反映了有关底层Windows OS如何表示unicode字符串并回显到MS Office的现实,我不知道)系统默认值是使用ANSI的1字节/ unicode字符的编码语言环境的代码页。 UnicodeEncoding是UTF-16。该文档还描述了UTF-8也是一种" Unicode编码",这对我来说很有意义。但是我还不知道如何为VBA输出指定UTF-8,也不确定我用OpenTextFile(,,, 1)写入磁盘的数据是UTF-16编码的。 Tamalek的帖子很有帮助。


将字符串转换为UTF-8字符串的传统方法如下:

1
StrConv("hello world",vbFromUnicode)

所以简单地说:

1
2
3
4
5
Dim fnum As Integer
fnum = FreeFile
Open"myfile.txt" For Output As fnum
Print #fnum, StrConv("special characters: ??ü?", vbFromUnicode)
Close fnum

不需要特殊的COM对象