XL 2021 Fichiers Txt en UTF8 ou ANSI

Marc Vanlindt

XLDnaute Nouveau
Bonjour à toutes et à tous.
Lorsque j'importe un fichier .txt dans une TextBox, ce fichier peut être encodé soit en ANSI, soit en UTF8 (sans BOM).
L'affichage dans une TextBox est toujours ANSI.
Comment déterminer l'encodage du fichier .txt afin de savoir si je dois le convertir ou non ?
Merci d'avance pour vos réponses ! (ChatGPT n'y parvient pas)
Marc
 
Solution
Bonjour,

Il y a quelques temps j'avais rencontré le même problème que toi et j'avais pondu un bout de code, qui ne vaut que ce qu'il vaut... mais qui fonctionnait avec les fichiers que j'utilisais.

Je t'ai construit un classeur-exemple avec les macros de l'époque, et ça a l'air de fonctionner avec tes trois fichiers qui sont bien détectés au format indiqué par leurs noms.
A toi de voir si tu peux en tirer quelque chose ou pas. ;)

Marc Vanlindt

XLDnaute Nouveau
Hello,
pour détecter l'encodage d'un fichier texte sous windows on peut utiliser le module powershell EncodingAnalyzer (licence GPL) qui se trouve dans la galerie powershell.
Voici comment l'utiliser en VBA.
1 - Il faut d'abord importer le module sur sa machine (il se télécharge automatiquement si présent dans la galerie):
Pour tous les utilisateurs :
Ouvrir une invite de commande Powershell en étant administrateur et lancer :
Code:
Install-Module -Name EncodingAnalyzer
Que pour l'utiliseur courant :
Ouvrir une invite de commande Powershell et lancer :
Code:
Install-Module -Name EncodingAnalyzer -Scope CurrentUser

Voici le code VBA pour utiliser la fonction Get-Encoding du module. Ce code utilise la fonction PS_GetOutput qui lance une commande powershell en utilisant la fonction de patricktoulon ShellAndwaitingEndProcess (lancer une commande et attendre qu'elle soit finie). La fonction PS_GetOutput renvoie le résultat de la commande (elle utilise le presse-papier pour récupérer ce résultat)

VB:
Sub DetectFileEncoding()
'Dim bm As New cBenchmark
Dim mesFichiers, Fichiers, Resultat As String, Lignes, Ligne
'bm.TrackByName "Init"
mesFichiers = Array("d:\temp\T1 UTF8.txt", "d:\temp\T2 UTF8-BOM.txt", "d:\temp\T3 ANSI.txt")
For Each Fichier In mesFichiers
    Resultat = PS_GetOutput("Get-Encoding '" & Fichier & "' | ConvertTo-Csv -NoTypeInformation ")
 '   bm.TrackByName "PowerShell Execute"
    Lignes = Split(Resultat, vbCrLf)
    For Each Ligne In Lignes
        Debug.Print Ligne
    Next Ligne
 '   bm.TrackByName "Affiche Résultat"
Next Fichier
End Sub

Public Function PS_GetOutput(ByVal sPSCmd As String) As String
    sPSCmd = "powershell -command " & sPSCmd & " | clip"
    ShellAndwaitingEndProcess sPSCmd
    With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .GetFromClipboard
        PS_GetOutput = .GetText(1)
    End With
End Function

Function ShellAndwaitingEndProcess(ByVal CheminComplet As String) As Long
    Dim ProcessHandle As Long
    Dim ProcessId As Long
    ProcessId = Shell(CheminComplet, vbHide)
    ProcessHandle = ExecuteExcel4Macro("CALL(""Kernel32"",""OpenProcess"",""JJJJ"",""" & 2031616 & """,""" & 0 & """,""" & ProcessId & """)")
    ShellAndwaitingEndProcess = ExecuteExcel4Macro("CALL(""Kernel32"",""WaitForSingleObject"",""JJJJJ"",""" & ProcessHandle & """,""" & &HF0000 & """)")
End Function
Les lignes en commentaires dans DetectFileEncoding ont été utilisées pour calculer le temps d'exécution pour traiter 3 fichiers textes. Voici le résultat :
IDnrNameCountSum of ticsPercentageTime sum
0​
Init
1​
78​
0,00%​
7800 ns
1​
PowerShell Execute
3​
22 655 101​
99,85%​
2,27 s
2​
Affiche Résultat
3​
45 397​
0,15%​
4,54 ms
TOTAL
7​
22 700 576​
100,00%​
2,27 s
Total time recorded:2,3 s

Et voici ce qui est retourné (en format csv) :


A noter que dans le PowerShell on peut lancer des commandes windows Exemple :
VB:
Resultat = PS_GetOutput("Dir")

Ami calmant, J.P
Bonjour J.P.
Merci pour cette réponse. Je ne connaissais pas ce module Powershell. Je vais faire quelques tests.
Amitiés,
Marc
 

Marc Vanlindt

XLDnaute Nouveau
Bonjour,

Il y a quelques temps j'avais rencontré le même problème que toi et j'avais pondu un bout de code, qui ne vaut que ce qu'il vaut... mais qui fonctionnait avec les fichiers que j'utilisais.

Je t'ai construit un classeur-exemple avec les macros de l'époque, et ça a l'air de fonctionner avec tes trois fichiers qui sont bien détectés au format indiqué par leurs noms.
A toi de voir si tu peux en tirer quelque chose ou pas. ;)
Ouiiii !! C'est intégré, testé et ça marche !
Ouf ! Même ChatGpt n'y était pas arrivé !
Merci beaucoup!
Marc
 

patricktoulon

XLDnaute Barbatruc
Bonjour
j'ai retrouvé mes deux fonctions dans les version beta du créatorRibbonx
je viens de les retester et elles fonctionnent
VB:
Sub test1()
     FileConvert_UTF8_To_Ansi "C:\Users\patricktoulon\Desktop\MacCustomUI.xml"
End Sub

Sub test2()
    FileConvert_Ansi_To_UTF8 "C:\Users\patricktoulon\Desktop\MacCustomUI.xml"
End Sub

Function FileConvert_UTF8_To_Ansi(fich)
   'patricktoulon creatorRibbonx V2.7
Dim lachaine As String, x, texte$: x = FreeFile
    'test lecture binnaire
    Open fich For Binary Access Read As #x: lachaine = String(LOF(x), " "): Get #x, , lachaine: Close #x
    If lachaine Like "*Ã*" Then 'si la chaine contient des carateres bizarres
        With CreateObject("ADODB.Stream"): .Charset = "utf-8": .Open: .LoadFromFile (fich): texte = .ReadText(): End With
        Kill fich
        x = FreeFile: Open fich For Output As #x: Print #x, texte: Close #x
        Else: MsgBox "ce fichier n'est pas encodé en utf-8"
    End If
End Function

Function FileConvert_Ansi_To_UTF8(fich)
     'patricktoulon creatorRibbonx V2.7
     Dim lachaine As String, x, texte$: x = FreeFile
    'test lecture binnaire
    Open fich For Binary Access Read As #x: lachaine = String(LOF(x), " "): Get #x, , lachaine: Close #x
    If Not lachaine Like "*Ã*" Then 'si la chaine ne contient pas de carateres sbizarre
        Kill fich
        Dim oStream
        Set oStream = CreateObject("ADODB.Stream")
        oStream.Charset = "utf-8"
        oStream.Open
        oStream.WriteText lachaine
        oStream.SaveToFile fich, 2
        Else: MsgBox "ce fichier est déjà encodé en utf-8"
    End If
End Function
edit:
je me souviens ca y est
je les avais abandonné car si le texte ne contient pas de caractères particulier le utf8 passe pour du ansi
c'est pour ça que j'ai opter pour les 3 premier caractères en lecture binaire
 
Dernière édition:

Marc Vanlindt

XLDnaute Nouveau
Bonjour
j'ai retrouvé mes deux fonctions dans les version beta du créatorRibbonx
je viens de les retester et elles fonctionnent
VB:
Sub test1()
     FileConvert_UTF8_To_Ansi "C:\Users\patricktoulon\Desktop\MacCustomUI.xml"
End Sub

Sub test2()
    FileConvert_Ansi_To_UTF8 "C:\Users\patricktoulon\Desktop\MacCustomUI.xml"
End Sub

Function FileConvert_UTF8_To_Ansi(fich)
   'patricktoulon creatorRibbonx V2.7
Dim lachaine As String, x, texte$: x = FreeFile
    'test lecture binnaire
    Open fich For Binary Access Read As #x: lachaine = String(LOF(x), " "): Get #x, , lachaine: Close #x
    If lachaine Like "*Ã*" Then 'si la chaine contient des carateres bizarres
        With CreateObject("ADODB.Stream"): .Charset = "utf-8": .Open: .LoadFromFile (fich): texte = .ReadText(): End With
        Kill fich
        x = FreeFile: Open fich For Output As #x: Print #x, texte: Close #x
        Else: MsgBox "ce fichier n'est pas encodé en utf-8"
    End If
End Function

Function FileConvert_Ansi_To_UTF8(fich)
     'patricktoulon creatorRibbonx V2.7
     Dim lachaine As String, x, texte$: x = FreeFile
    'test lecture binnaire
    Open fich For Binary Access Read As #x: lachaine = String(LOF(x), " "): Get #x, , lachaine: Close #x
    If Not lachaine Like "*Ã*" Then 'si la chaine ne contient pas de carateres sbizarre
        Kill fich
        Dim oStream
        Set oStream = CreateObject("ADODB.Stream")
        oStream.Charset = "utf-8"
        oStream.Open
        oStream.WriteText lachaine
        oStream.SaveToFile fich, 2
        Else: MsgBox "ce fichier est déjà encodé en utf-8"
    End If
End Function
edit:
je me souviens ca y est
je les avais abandonné car si le texte ne contient pas de caractères particulier le utf8 passe pour du ansi
c'est pour ça que j'ai opter pour les 3 premier caractères en lecture binaire
Merci beaucoup Patrick.
Mais entre-temps, TooFatBoy m'a apporté une solution qui marche parfaitement.
Quoi qu'il en soit, merci à toi d'avoir bien voulu te pencher sur ce cas et je garde sous la main ces codes que tu m'envoie "au cas où...".
Amicalement,
Marc
 

TooFatBoy

XLDnaute Barbatruc
Mais entre-temps, TooFatBoy m'a apporté une solution qui marche parfaitement.
Attention, c'est loin d'être parfait. Comme je l'ai dit, ça ne vaut que ce que ça vaut... :(

Par exemple, si le fichier est encodé en UTF-8 mais qu'il ne comporte aucun caractères spéciaux (accentués ou autres), il sera considéré comme étant encodé en ANSI et donc certains caractères pourraient être mal décodés.

De plus, la macro essaye de détecter si c'est de l'UTF-8, elle considère que c'est, soit de l'UTF-8 (avec possibilité de se tromper), soit (si ce n'est pas de l'UTF-8) de l'ANSI. Elle ne "gère" aucun autre encodage.

Elle ne regarde pas s'il y a le BOM, ce qui permettrait d'être sûr que le fichier est encodé en UTF-8.
Ceci dit, ce n'est pas très grave car d'après ce que j'ai compris le BOM n'est plus vraiment utilisé de nos jours.


Il faut donc que tu aies bien en tête que la macro peut se tromper, même si à mon avis les chances sont quasiment nulles, mais ça peut arriver.
 

Marc Vanlindt

XLDnaute Nouveau
Attention, c'est loin d'être parfait. Comme je l'ai dit, ça ne vaut que ce que ça vaut... :(

Par exemple, si le fichier est encodé en UTF-8 mais qu'il ne comporte aucun caractères spéciaux (accentués ou autres), il sera considéré comme étant encodé en ANSI et donc certains caractères pourraient être mal décodés.

De plus, la macro essaye de détecter si c'est de l'UTF-8, elle considère que c'est, soit de l'UTF-8 (avec possibilité de se tromper), soit (si ce n'est pas de l'UTF-8) de l'ANSI. Elle ne "gère" aucun autre encodage.

Elle ne regarde pas s'il y a le BOM, ce qui permettrait d'être sûr que le fichier est encodé en UTF-8.
Ceci dit, ce n'est pas très grave car d'après ce que j'ai compris le BOM n'est plus vraiment utilisé de nos jours.


Il faut donc que tu aies bien en tête que la macro peut se tromper, même si à mon avis les chances sont quasiment nulles, mais ça peut arriver.
Bonjour TooFatBoy.
J'ai bien vu que le test ne se faisait finalement que sur un seul caractère "Ã" mais étant donné que mes textes font en général plus de 1000 caractères, il faudrait un hasard immense pour que ce caractère ne s'y retrouve pas.
D'autre part, s'il arrive que le texte ne s'affiche pas correctement, je pourrai toujours le convertir avec Notepad++. Ce serait une opération supplémentaire mais étant donné la rareté des cas, ce n'est pas bien grave.
Bonne journée.
Marc
 

Discussions similaires

Réponses
18
Affichages
1 K

Statistiques des forums

Discussions
313 769
Messages
2 102 234
Membres
108 181
dernier inscrit
Chr1sD