IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VBA Discussion :

fonctions de codage et décodage de texte en utf-8 avec VBA


Sujet :

VBA

  1. #1
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut fonctions de codage et décodage de texte en utf-8 avec VBA
    Salut.

    Voici deux fonctions qui permettent de coder une chaine textuelle en utf-8 et de récupérer une chaine textuelle à partir de utf-8


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Function Uni2Utf(Text As String) As String
      Dim v As Long
      Dim i As Long
     
      For i = 1 To Len(Text)
        v = AscW(Mid(Text, i, 1))
        Select Case v
          Case Is < 128
            Uni2Utf = Uni2Utf & Mid(Text, i, 1)
          Case Is < 2048
            Uni2Utf = Uni2Utf & Chr(((v And 1984) / 64) Or 192)
            Uni2Utf = Uni2Utf & Chr((v And 63) Or 128)
          Case Else
            Uni2Utf = Uni2Utf & Chr(((v And 61440) / 4096) Or 224)
            Uni2Utf = Uni2Utf & Chr(((v And 4032) / 64) Or 128)
            Uni2Utf = Uni2Utf & Chr((v And 63) Or 128)
        End Select
      Next
    End Function
     
    Function Utf2Uni(Text As String) As String
      Dim v As Long
      Dim i As Long: i = 1
     
      Do While i <= Len(Text)
        v = Asc(Mid(Text, i, 1))
        Select Case v
          Case Is < 128
            Utf2Uni = Utf2Uni & Mid(Text, i, 1)
            i = i + 1
          Case Is < 224
            Utf2Uni = Utf2Uni & ChrW((v And 63) * 64 + (Asc(Mid(Text, i + 1, 1)) And 63))
            i = i + 2
          Case Else
            Utf2Uni = Utf2Uni & ChrW(((v And 31) * 4096) + _
              ((Asc(Mid(Text, i + 1, 1)) And 63) * 64) + _
              (Asc(Mid(Text, i + 2, 1)) And 63))
            i = i + 3
        End Select
      Loop
    End Function

    Si vous voulez comprendre ces fonctions, j'ai écrit 3 billets:
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  2. #2
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 1 009
    Par défaut
    Bonjour Pierre.

    Merci pour ces billets qui sont très intéressants.
    J'ai appris beaucoup de choses.
    Jusqu'à présent j'utilisais bêtement les APi "WideCharToMultiByte" et "MultiByteToWideChar" sans savoir ce qu'elles faisaient.
    Maintenant je comprends mieux et je vais adopter tes fonctions.

    Cordialement.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Bonjour Laurent,

    Merci pour ton appréciation.

    Cela dit, je pense que sur de grands textes, l'api sera plus rapide puisque compilée. Il faudrait tester avec une très longue chaine pour voir, et tant qu'à faire, comparer les résultats...
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  4. #4
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 1 009
    Par défaut
    Citation Envoyé par Pierre Fauconnier Voir le message
    … je pense que sur de grands textes, l'api sera plus rapide puisque compilée. Il faudrait tester avec une très longue chaîne pour voir, et tant qu'à faire, comparer les résultats...
    Je pense que le plus important est de monter que le VBA sait, aussi, faire cela (comme les "vrais" langages de programmation) et être indépendant des API (et peut-être le plus important, savoir ce qui se passe en cuisine).

    Quant à ceux qui veulent se lancer dans les comparaisons, voici les fonctions basées sur les API en question :
    - Public Function ConvertStringToUTF8(StrInput As String) As String
    - Public Function ConvertUTF8ToString(UTF8String As String) As String

    Code VBA : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    Private Const CP_UTF8 = 65001
     
    Private Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, _
                                                                         ByVal dwFlags As Long, ByVal lpMultiByteStr As LongPtr, _
                                                                         ByVal cchMultiByte As Long, ByVal lpWideCharStr As LongPtr, _
                                                                         ByVal cchWideChar As Long) As Long
     
    Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, _
                                                                         ByVal lpWideCharStr As LongPtr, ByVal cchWideChar As Long, _
                                                                         ByVal lpMultiByteStr As LongPtr, ByVal cbMultiByte As Long, _
                                                                         ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
     
    '------------------------------------------------------------------------------------------------
    Public Function ConvertStringToUTF8(StrInput As String) As String
    '------------------------------------------------------------------------------------------------
    Dim nBytes As Long, abBuffer() As Byte, i As Long
     
    If Len(StrInput) > 0 Then
        ' Get length in bytes *including* terminating null
        nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(StrInput), -1, 0&, 0&, 0&, 0&)
        ' We don't want the terminating null in our byte array, so ask for `nBytes-1` bytes
        ReDim abBuffer(nBytes - 2)  ' NB ReDim with one less byte than you need
        nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(StrInput), -1, ByVal VarPtr(abBuffer(0)), nBytes - 1, 0&, 0&)
        ' Génèration d'une chaîne à partir du tableau:
        For i = LBound(abBuffer) To UBound(abBuffer)
            ConvertStringToUTF8 = ConvertStringToUTF8 & Chr(abBuffer(i))
        Next i
    End If
     
    End Function
     
    '------------------------------------------------------------------------------------------------
    Private Function sUTF8ToUni(bySrc() As Byte) As String
    '------------------------------------------------------------------------------------------------
    ' Converts a UTF-8 byte array to a Unicode string
    Dim lBytes As Long, lNC As Long, lRet As Long
     
    lBytes = UBound(bySrc) - LBound(bySrc) + 1
    lNC = lBytes
    sUTF8ToUni = String$(lNC, Chr(0))
    lRet = MultiByteToWideChar(CP_UTF8, 0, VarPtr(bySrc(LBound(bySrc))), lBytes, StrPtr(sUTF8ToUni), lNC)
    sUTF8ToUni = Left$(sUTF8ToUni, lRet)
     
    End Function
     
    '------------------------------------------------------------------------------------------------
    Public Function ConvertUTF8ToString(UTF8String As String) As String
    '------------------------------------------------------------------------------------------------
    Dim bData() As Byte, sData As String, lSize As Long, i As Long
     
    sData = UTF8String
    lSize = Len(sData)
     
    If lSize > 0 Then
        ReDim bData(0 To lSize - 1)
        For i = 1 To lSize
         bData(i - 1) = Asc(Mid(sData, i, 1))
        Next i
        ' Convert all the data to Unicode
        sData = sUTF8ToUni(bData)
    Else
        sData = ""
    End If
     
    ConvertUTF8ToString = sData
    End Function
    '------------------------------------------------------------------------------------------------

    Cordialement.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Merci du complément d'info. Il a son importance car je n'avais pas regardé ce que faisaient les api. Je pensais qu'elles recevaient une adresse de chaine pour retourner une chaine complète adaptée.

    Or, de ce que j'en vois, elles traitent caractère par caractère. Du coup, je pense que le gain de passer par l'api est quasi nul, puisque l'on boucle de toute façon en VBA.

    Quoi qu'il en soit, je suis entièrement d'accord avec tes conclusions: Comprendre comment ça se passe sous le capot (ou le couvercle de la marmite ) et, effectivement, utiliser VBA qui est un vrai langage pro et qui permet de belles choses.

    Bon weekend
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  6. #6
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 178
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 178
    Par défaut
    Hello,
    Citation Envoyé par Pierre Fauconnier Voir le message
    Cela dit, je pense que sur de grands textes, l'api sera plus rapide puisque compilée. Il faudrait tester avec une très longue chaine pour voir, et tant qu'à faire, comparer les résultats...
    j'ai réalisé un test des 2 types de méthodes sur un très grand texte (Notre-Dame de Paris de Victor Hugo) pour une conversion UTF8 vers unicode.
    Voici le code du test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Sub TestPerformance()
        Dim ContenuFichier As String
        Dim MonFichier As String
        Dim deb As Double, fin As Double
        Debug.Print "Test Conversion Notre Dame de Paris UTF8 en Unicode"
        deb = Timer * 1000#
        MonFichier = "D:\Temp\notre_dame_de_paris.txt" 'l'emplacement et le nom du fichier texte
        ContenuFichier = LireFichierTexte(MonFichier) 'appelle la fonction "LireFichierTexte"
        Debug.Print "Nombre de mots : " + CStr(Number_of_Words(ContenuFichier))
        deb = Timer * 1000#
        ContenuConverti = Utf2Uni(ContenuFichier)
        fin = Timer * 1000#
        Debug.Print "Temps de Conversion Utf2Uni : " + CStr(fin - deb) + " ms"
        deb = Timer * 1000#
        ContenuConverti = ConvertUTF8ToString(ContenuFichier)
        fin = Timer * 1000#
        Debug.Print "Temps de Conversion ConvertUTF8ToString : " + CStr(fin - deb) + " ms"
    End Sub
    et voici le résultat :
    Test Conversion Notre Dame de Paris UTF8 en Unicode
    Nombre de mots : 172354
    Temps de Conversion Utf2Uni : 249562,5 ms
    Temps de Conversion ConvertUTF8ToString : 156,25 ms
    Le résultat est sans équivoque.

    Ami calmant, J.P

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Salut JP

    Merci pour ce test. Il ne me surprend pas, maintenant que j'ai regardé exactement comment fonctionne l'api. Un code compilé sera toujours plus rapide qu'un code interprété, surtout sur un nombre aussi grand de boucles.

    Perso, j'ai rarement à coder la bible en utf8, ceci dit De mon utilisation sur des chaines relativement courtes, les performances d'une fonction "tout vba" restent pour moi tout à fait acceptables...
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

Discussions similaires

  1. [XL-2010] Excel - Extraire le texte d'un SmartArt avec VBA
    Par maximelocatelli dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 11/05/2017, 08h38
  2. [AC-2010] Insertion texte dans un champ avec VBA
    Par redojackson dans le forum VBA Access
    Réponses: 6
    Dernier message: 21/07/2014, 08h08
  3. [XL-2007] Utiliser plusieurs couleurs au texte d'une cellule avec vba
    Par CRC dans le forum Excel
    Réponses: 2
    Dernier message: 21/08/2009, 14h37
  4. fonction combinée: liste de choix + input text
    Par jflebegue dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 01/09/2005, 18h38
  5. Fonction LEFT sur champ de type "text" : méthodes
    Par MatthieuQ dans le forum Langage SQL
    Réponses: 4
    Dernier message: 08/06/2004, 11h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo