Сохранить текстовый файл UTF-8, закодированный с помощью 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
Есть ли какая-то настройка на уровне приложения?
Ответы
Ответ 1
Я нашел ответ на web:
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
Конечно, не так, как я ожидал...
Ответ 2
Вы можете использовать метод 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
Ответ 3
Это записывает знак байтового заказа в начале файла, что необязательно в файле UTF-8, а некоторые приложения (в моем случае, SAP) не нравятся.
Решение здесь: Можно ли экспортировать данные Excel с UTF-8 без спецификации?
Ответ 4
Вот еще один способ сделать это - с помощью функции 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
Ответ 5
Я заглянул в ответ от Маны, чье имя намекает на кодирование квалификаций и опыта. VBA docs говорят, что CreateTextFile(filename, [overwrite [, unicode]])
создает файл "как Unicode или ASCII файл. Значение True, если файл создается как Unicode file; False, если он создан как файл ASCII. Если этот параметр опущен, предполагается, что используется файл ASCII." Хорошо, что файл хранит символы Юникода, но в какой кодировке? Unencoded 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 байт/юникод, используя кодовую страницу ANSI для языкового стандарта. UnicodeEncoding
- UTF-16. Документы также описывают, что UTF-8 также является "кодировкой Unicode", что имеет смысл для меня. Но я еще не знаю, как указать UTF-8 для вывода VBA и не уверен, что данные, которые я пишу на диск с OpenTextFile (,, 1), кодируются в кодировке UTF-16. Сообщение Tamalek полезно.