78 votes

Comment coder en URL une chaîne de caractères dans Excel VBA ?

Existe-t-il un moyen intégré d'encoder une chaîne de caractères URL dans Excel VBA ou dois-je développer manuellement cette fonctionnalité ?

100voto

Tomalak Points 150423

Non, rien d'intégré ( jusqu'à Excel 2013 - voir cette réponse ).

Il existe trois versions de URLEncode() dans cette réponse.

  • Une fonction avec le support UTF-8. Vous devriez probablement utiliser celui-ci (ou la mise en œuvre alternative par Tom) pour la compatibilité avec les exigences modernes.
  • À des fins de référence et d'éducation, deux fonctions sans support UTF-8 :
    • une réponse trouvée sur un site web tiers, incluse telle quelle. (C'était la première version de la réponse)
    • une version optimisée de cela, écrite par moi

Une variante qui supporte l'encodage UTF-8 et qui est basée sur ADODB.Stream (inclure une référence à une version récente de la bibliothèque "Microsoft ActiveX Data Objects" dans votre projet) :

Public Function URLEncode( _
   ByVal StringVal As String, _
   Optional SpaceAsPlus As Boolean = False _
) As String
  Dim bytes() As Byte, b As Byte, i As Integer, space As String

  If SpaceAsPlus Then space = "+" Else space = "%20"

  If Len(StringVal) > 0 Then
    With New ADODB.Stream
      .Mode = adModeReadWrite
      .Type = adTypeText
      .Charset = "UTF-8"
      .Open
      .WriteText StringVal
      .Position = 0
      .Type = adTypeBinary
      .Position = 3 ' skip BOM
      bytes = .Read
    End With

    ReDim result(UBound(bytes)) As String

    For i = UBound(bytes) To 0 Step -1
      b = bytes(i)
      Select Case b
        Case 97 To 122, 65 To 90, 48 To 57, 45, 46, 95, 126
          result(i) = Chr(b)
        Case 32
          result(i) = space
        Case 0 To 15
          result(i) = "%0" & Hex(b)
        Case Else
          result(i) = "%" & Hex(b)
      End Select
    Next i

    URLEncode = Join(result, "")
  End If
End Function

Cette fonction a été trouvé sur freevbcode.com :

Public Function URLEncode( _
   StringToEncode As String, _
   Optional UsePlusRatherThanHexForSpace As Boolean = False _
) As String

  Dim TempAns As String
  Dim CurChr As Integer
  CurChr = 1

  Do Until CurChr - 1 = Len(StringToEncode)
    Select Case Asc(Mid(StringToEncode, CurChr, 1))
      Case 48 To 57, 65 To 90, 97 To 122
        TempAns = TempAns & Mid(StringToEncode, CurChr, 1)
      Case 32
        If UsePlusRatherThanHexForSpace = True Then
          TempAns = TempAns & "+"
        Else
          TempAns = TempAns & "%" & Hex(32)
        End If
      Case Else
        TempAns = TempAns & "%" & _
          Right("0" & Hex(Asc(Mid(StringToEncode, _
          CurChr, 1))), 2)
    End Select

    CurChr = CurChr + 1
  Loop

  URLEncode = TempAns
End Function

J'ai corrigé un petit bug qui était là.


J'utiliserais une version plus efficace (~2× plus rapide) de ce qui précède :

Public Function URLEncode( _
   StringVal As String, _
   Optional SpaceAsPlus As Boolean = False _
) As String

  Dim StringLen As Long: StringLen = Len(StringVal)

  If StringLen > 0 Then
    ReDim result(StringLen) As String
    Dim i As Long, CharCode As Integer
    Dim Char As String, Space As String

    If SpaceAsPlus Then Space = "+" Else Space = "%20"

    For i = 1 To StringLen
      Char = Mid$(StringVal, i, 1)
      CharCode = Asc(Char)
      Select Case CharCode
        Case 97 To 122, 65 To 90, 48 To 57, 45, 46, 95, 126
          result(i) = Char
        Case 32
          result(i) = Space
        Case 0 To 15
          result(i) = "%0" & Hex(CharCode)
        Case Else
          result(i) = "%" & Hex(CharCode)
      End Select
    Next i
    URLEncode = Join(result, "")
  End If
End Function

Notez qu'aucune de ces deux fonctions ne prend en charge l'encodage UTF-8.

5 votes

J'ai utilisé votre "version plus efficace (~2× plus rapide)" et cela fonctionne à merveille ! Merci.

0 votes

@Chris Merci. :) Notez que vous pouvez probablement faire une version conforme à l'UTF-8 si vous utilisez un fichier de type ADODB.Stream qui peut effectuer la conversion nécessaire des chaînes de caractères. Des exemples de la façon de produire UTF-8 avec VBA ou VBScript sont partout sur Internet.

0 votes

Si les performances sont un problème, envisagez une refactorisation pour utiliser "replace" en parcourant les entiers de 0 à 255 et en faisant quelque chose comme ça : Cas 0 à 36, 38 à 47, 58 à 64, 91 à 96, 123 à 255 str_Input = Replace(str_Input, Chr(int_char_num), "%" & Right("0" & Hex(255), 2))

65voto

Jamie Bull Points 1370

Pour mettre à jour cette information, depuis Excel 2013, il y a maintenant une façon intégrée d'encoder les URLs en utilisant la fonction de la feuille de calcul ENCODEURL .

Pour l'utiliser dans votre code VBA, il vous suffit d'appeler

EncodedUrl = WorksheetFunction.EncodeUrl(InputString)

Documentation

0 votes

Il échoue pour moi lorsque je dois encoder des données csv avec des virgules consécutives dans le champ. J'ai dû utiliser la version utf8 ci-dessus dans la réponse.

0 votes

@SalmanSiddique bon de connaître les limites. Il serait peut-être utile de dire laquelle des versions utf8 vous avez utilisée car il y en a plusieurs.

0 votes

Application.WorksheetFunction.EncodeUrl(myString) a parfaitement fonctionné pour mes besoins - j'espère que cette réponse sera suffisamment upvoted pour remplacer la version précédente, méga ancienne.

35voto

Tom Points 221

Version du produit ci-dessus supportant UTF8 :

Private Const CP_UTF8 = 65001

#If VBA7 Then
  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
#Else
  Private Declare Function WideCharToMultiByte Lib "kernel32" ( _
    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
#End If

Public Function UTF16To8(ByVal UTF16 As String) As String
Dim sBuffer As String
Dim lLength As Long
If UTF16 <> "" Then
    #If VBA7 Then
        lLength = WideCharToMultiByte(CP_UTF8, 0, CLngPtr(StrPtr(UTF16)), -1, 0, 0, 0, 0)
    #Else
        lLength = WideCharToMultiByte(CP_UTF8, 0, StrPtr(UTF16), -1, 0, 0, 0, 0)
    #End If
    sBuffer = Space$(lLength)
    #If VBA7 Then
        lLength = WideCharToMultiByte(CP_UTF8, 0, CLngPtr(StrPtr(UTF16)), -1, CLngPtr(StrPtr(sBuffer)), LenB(sBuffer), 0, 0)
    #Else
        lLength = WideCharToMultiByte(CP_UTF8, 0, StrPtr(UTF16), -1, StrPtr(sBuffer), LenB(sBuffer), 0, 0)
    #End If
    sBuffer = StrConv(sBuffer, vbUnicode)
    UTF16To8 = Left$(sBuffer, lLength - 1)
Else
    UTF16To8 = ""
End If
End Function

Public Function URLEncode( _
   StringVal As String, _
   Optional SpaceAsPlus As Boolean = False, _
   Optional UTF8Encode As Boolean = True _
) As String

Dim StringValCopy As String: StringValCopy = IIf(UTF8Encode, UTF16To8(StringVal), StringVal)
Dim StringLen As Long: StringLen = Len(StringValCopy)

If StringLen > 0 Then
    ReDim Result(StringLen) As String
    Dim I As Long, CharCode As Integer
    Dim Char As String, Space As String

  If SpaceAsPlus Then Space = "+" Else Space = "%20"

  For I = 1 To StringLen
    Char = Mid$(StringValCopy, I, 1)
    CharCode = Asc(Char)
    Select Case CharCode
      Case 97 To 122, 65 To 90, 48 To 57, 45, 46, 95, 126
        Result(I) = Char
      Case 32
        Result(I) = Space
      Case 0 To 15
        Result(I) = "%0" & Hex(CharCode)
      Case Else
        Result(I) = "%" & Hex(CharCode)
    End Select
  Next I
  URLEncode = Join(Result, "")

End If
End Function

Profitez-en !

4 votes

Se référer à "ce qui précède" dans une réponse qui peut augmenter ou diminuer en fonction du nombre de votes, n'est pas utile.

0 votes

Maintenant, il faut VBA7 les en-têtes avec PtrSafe y LongPtr .

18voto

Michael-O Points 6715

Bien que celui-ci soit très ancien. J'ai trouvé une solution basée sur este réponse :

Dim ScriptEngine As ScriptControl
Set ScriptEngine = New ScriptControl
ScriptEngine.Language = "JScript"

ScriptEngine.AddCode "function encode(str) {return encodeURIComponent(str);}"
Dim encoded As String
encoded = ScriptEngine.Run("encode", "€ömE.sdfds")

Ajoutez le contrôle Microsoft script comme référence et vous avez terminé.

Juste une note en passant, à cause de la partie JS, c'est entièrement compatible avec UTF-8. VB convertira correctement d'UTF-16 en UTF-8.

1 votes

Génial, je ne savais pas qu'on pouvait utiliser du code JS dans VBA. Mon monde entier s'ouvre maintenant.

1 votes

Super. C'était juste ce dont j'avais besoin. Remarque : Si vous ne voulez pas ajouter une référence, vous pouvez le faire : A) Dim ScriptEngine As Object B) Set ScriptEngine = CreateObject("scriptcontrol"). A propos, au lieu de créer une fonction en JS, il semble que vous pouvez appeler le composant encodeURIC directement comme suit : encoded = ScriptEngine.Run("encodeURIComponent", str)

0 votes

@ElScripto, allez-y et postez une réponse améliorée qui fait référence à la mienne.

13voto

ozmike Points 583

Depuis qu'Office 2013 utilise cette fonction intégrée aquí .

Si avant office 2013

Function encodeURL(str As String)
Dim ScriptEngine As ScriptControl
Set ScriptEngine = New ScriptControl
ScriptEngine.Language = "JScript"

ScriptEngine.AddCode "function encode(str) {return encodeURIComponent(str);}"
Dim encoded As String

encoded = ScriptEngine.Run("encode", str)
encodeURL = encoded
End Function

Ajoutez le contrôle Microsoft script comme référence et vous avez terminé.

Même chose que le dernier message, mais la fonction complète fonctionne !

0 votes

Fait. Ok, je ne savais pas que je pouvais modifier et vous n'obtenez pas de points pour les modifications malheureusement !

1 votes

Pour info, j'ai essayé de mettre à jour l'autre message mais mes modifications sont modérées ! Par exemple, Micha a revu ce message il y a 18 heures : Reject This edit is incorrect or an attempt to reply to or comment on the existing post. alex2410 reviewed this 18 hours ago : Reject Cette modification est incorrecte ou constitue une tentative de réponse ou de commentaire sur le message existant. bansi a commenté ceci il y a 18 heures : Rejeter Cette modification est incorrecte ou constitue une tentative de réponse ou de commentaire sur le message existant. -

0 votes

ScriptControl ne fonctionne pas sur les versions 64 bits d'Office, vérifiez les points suivants solution via htmlfile ActiveX y solution pour faire fonctionner ScriptControl avec Excel x64 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X