comment puis-je écrire des chaînes encodées en UTF-8 dans un fichier texte de vba, comme
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
Existe-t-il des paramètres au niveau de l'application?
J'ai trouvé la réponse sur le 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
Certainement pas comme je m'y attendais ...
Vous pouvez utiliser la méthode CreateTextFile ou OpenTextFile, les deux ayant un attribut "unicode" utile pour les paramètres de codage.
object.CreateTextFile(filename[, overwrite[, unicode]])
object.OpenTextFile(filename[, iomode[, create[, format]]])
Exemple: Ecraser:
CreateTextFile:
fileName = "filename"
Set fso = CreateObject("Scripting.FileSystemObject")
Set out = fso.CreateTextFile(fileName, True, True)
out.WriteLine ("Hello world!")
...
out.close
Exemple: Ajouter:
OpenTextFile Set fso = CreateObject("Scripting.FileSystemObject")
Set out = fso.OpenTextFile("filename", ForAppending, True, 1)
out.Write "Hello world!"
...
out.Close
Voir plus sur documents MSDN
Ceci écrit une marque d'ordre d'octet au début du fichier, ce qui est inutile dans un fichier UTF-8 et certaines applications (dans mon cas, SAP) ne l'aiment pas. Solution ici: Puis-je exporter des données Excel avec UTF-8 sans nomenclature?
Voici une autre façon de procéder: en utilisant la fonction 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
J'ai examiné la réponse de Máťa, dont le nom évoque des qualifications et de l'expérience en codage. Le documentation VBA dire CreateTextFile(filename, [overwrite [, unicode]])
crée un fichier "en tant que fichier Unicode ou ASCII. La valeur est True si le fichier est créé en tant que Unicode False s'il est créé sous la forme d'un fichier ASCII. S'il est omis, un fichier ASCII est supposé. ") quel encodage? Unicode non codé ne peut pas être représenté dans un fichier.
La page de documentation VBA pour OpenTextFile(filename[, iomode[, create[, format]]])
offre une troisième option pour le format:
Máťa passe -1 pour cet argument.
A en juger par documentation VB.NET (pas VBA mais je pense, reflète les réalités de la façon dont le système d'exploitation Windows sous-jacent représente les chaînes unicode et se répercute dans MS Office, je ne sais pas), la valeur par défaut du système est un codage utilisant 1 caractère octet/unicode utilisant une page de code ANSI pour les paramètres régionaux. UnicodeEncoding
est UTF-16. La documentation décrit également UTF-8 est également un "encodage Unicode", ce qui me semble logique. Mais je ne sais pas encore comment spécifier UTF-8 pour une sortie VBA, ni être sûr que les données que j'écris sur le disque avec OpenTextFile (, 1) sont codées en UTF-16. Le post de Tamalek est utile.