Enregistrer le fichier texte UTF-8 encodé avec VBA

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 

Y a-t-il une configuration 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/ssortingng 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 atsortingbut “unicode” utile pour les parameters de codage.

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

Exemple: écraser:

 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 les documents MSDN

Cela é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 BOM?

Voici une autre manière de procéder: utiliser 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 Ssortingng, 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 Ssortingng 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 étudié la réponse de Máťa dont le nom évoque l’encodage des qualifications et de l’expérience. Les documents VBA disent 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 fichier Unicode; False s’il est créé en fichier ASCII. Si omis, un fichier ASCII est supposé. ” C’est bien qu’un fichier stocke des caractères Unicode, mais dans 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:

  • TriStateDefault 2 “ouvre le fichier en utilisant le système par défaut.”
  • TriStateTrue 1 “ouvre le fichier en Unicode.”
  • TriStateFalse 0 “ouvre le fichier au format ASCII.”

Máťa passe -1 pour cet argument.

À en juger par la documentation de VB.NET (pas VBA mais qui reflète les réalités sur la façon dont le système d’exploitation sous-jacent représente les chaînes Unicode et les échos dans MS Office), la valeur par défaut du système page de code pour les parameters régionaux. UnicodeEncoding est UTF-16. Les documents décrivent également UTF-8 est également un “encodage Unicode”, ce qui est logique pour moi. Mais je ne sais pas encore comment spécifier UTF-8 pour la sortie VBA ni être sûr que les données que j’écris sur le disque avec OpenTextFile (,,, 1) sont encodées en UTF-16. Le post de Tamalek est utile.