How can I URL encode a string in Excel VBA?

后端 未结 15 1915
闹比i
闹比i 2020-11-22 11:39

Is there a built-in way to URL encode a string in Excel VBA or do I need to hand roll this functionality?

相关标签:
15条回答
  • 2020-11-22 12:14

    Since office 2013 use this inbuilt function here.

    If before 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
    

    Add Microsoft Script Control as reference and you are done.

    Same as last post just complete function ..works!

    0 讨论(0)
  • 2020-11-22 12:15

    No, nothing built-in (until Excel 2013 - see this answer).

    There are three versions of URLEncode() in this answer.

    • A function with UTF-8 support. You should probably use this one (or the alternative implementation by Tom) for compatibility with modern requirements.
    • For reference and educational purposes, two functions without UTF-8 support:
      • one found on a third party website, included as-is. (This was the first version of the answer)
      • one optimized version of that, written by me

    A variant that supports UTF-8 encoding and is based on ADODB.Stream (include a reference to a recent version of the "Microsoft ActiveX Data Objects" library in your project):

    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
    

    This function was found on 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
    

    I've corrected a little bug that was in there.


    I would use more efficient (~2× as fast) version of the above:

    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
    

    Note that neither of these two functions support UTF-8 encoding.

    0 讨论(0)
  • 2020-11-22 12:15

    I had problem with encoding cyrillic letters to URF-8.

    I modified one of the above scripts to match cyrillic char map. Implmented is the cyrrilic section of

    https://en.wikipedia.org/wiki/UTF-8 and http://www.utf8-chartable.de/unicode-utf8-table.pl?start=1024

    Other sections development is sample and need verification with real data and calculate the char map offsets

    Here is the script:

    Public Function UTF8Encode( _
       StringToEncode As String, _
       Optional UsePlusRatherThanHexForSpace As Boolean = False _
    ) As String
    
      Dim TempAns As String
      Dim TempChr As Long
      Dim CurChr As Long
      Dim Offset As Long
      Dim TempHex As String
      Dim CharToEncode As Long
      Dim TempAnsShort As String
    
      CurChr = 1
    
      Do Until CurChr - 1 = Len(StringToEncode)
        CharToEncode = Asc(Mid(StringToEncode, CurChr, 1))
    ' http://www.utf8-chartable.de/unicode-utf8-table.pl?start=1024
    ' as per https://en.wikipedia.org/wiki/UTF-8 specification the engoding is as follows
    
        Select Case CharToEncode
    '   7   U+0000 U+007F 1 0xxxxxxx
          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 0 To &H7F
                TempAns = TempAns + "%" + Hex(CharToEncode And &H7F)
          Case &H80 To &H7FF
    '   11  U+0080 U+07FF 2 110xxxxx 10xxxxxx
    ' The magic is in offset calculation... there are different offsets between UTF-8 and Windows character maps
    ' offset 192 = &HC0 = 1100 0000 b  added to start of UTF-8 cyrillic char map at &H410
              CharToEncode = CharToEncode - 192 + &H410
              TempAnsShort = "%" & Right("0" & Hex((CharToEncode And &H3F) Or &H80), 2)
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40) And &H1F) Or &HC0), 2) & TempAnsShort
              TempAns = TempAns + TempAnsShort
    
    '' debug and development version
    ''          CharToEncode = CharToEncode - 192 + &H410
    ''          TempChr = (CharToEncode And &H3F) Or &H80
    ''          TempHex = Hex(TempChr)
    ''          TempAnsShort = "%" & Right("0" & TempHex, 2)
    ''          TempChr = ((CharToEncode And &H7C0) / &H40) Or &HC0
    ''          TempChr = ((CharToEncode \ &H40) And &H1F) Or &HC0
    ''          TempHex = Hex(TempChr)
    ''          TempAnsShort = "%" & Right("0" & TempHex, 2) & TempAnsShort
    ''          TempAns = TempAns + TempAnsShort
    
          Case &H800 To &HFFFF
    '   16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
    ' not tested . Doesnot match Case condition... very strange
            MsgBox ("Char to encode  matched U+0800 U+FFFF: " & CharToEncode & " = &H" & Hex(CharToEncode))
    ''          CharToEncode = CharToEncode - 192 + &H410
              TempAnsShort = "%" & Right("0" & Hex((CharToEncode And &H3F) Or &H80), 2)
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000) And &HF) Or &HE0), 2) & TempAnsShort
              TempAns = TempAns + TempAnsShort
    
          Case &H10000 To &H1FFFFF
    '   21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    ''        MsgBox ("Char to encode  matched &H10000 &H1FFFFF: " & CharToEncode & " = &H" & Hex(CharToEncode))
    ' sample offset. tobe verified
              CharToEncode = CharToEncode - 192 + &H410
              TempAnsShort = "%" & Right("0" & Hex((CharToEncode And &H3F) Or &H80), 2)
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40000) And &H7) Or &HF0), 2) & TempAnsShort
              TempAns = TempAns + TempAnsShort
    
          Case &H200000 To &H3FFFFFF
    '   26  U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    ''        MsgBox ("Char to encode  matched U+200000 U+3FFFFFF: " & CharToEncode & " = &H" & Hex(CharToEncode))
    ' sample offset. tobe verified
              CharToEncode = CharToEncode - 192 + &H410
              TempAnsShort = "%" & Right("0" & Hex((CharToEncode And &H3F) Or &H80), 2)
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000000) And &H3) Or &HF8), 2) & TempAnsShort
              TempAns = TempAns + TempAnsShort
    
          Case &H4000000 To &H7FFFFFFF
    '   31  U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    ''        MsgBox ("Char to encode  matched U+4000000 U+7FFFFFFF: " & CharToEncode & " = &H" & Hex(CharToEncode))
    ' sample offset. tobe verified
              CharToEncode = CharToEncode - 192 + &H410
              TempAnsShort = "%" & Right("0" & Hex((CharToEncode And &H3F) Or &H80), 2)
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H1000000) And &H3F) Or &H80), 2) & TempAnsShort
              TempAnsShort = "%" & Right("0" & Hex(((CharToEncode \ &H40000000) And &H1) Or &HFC), 2) & TempAnsShort
              TempAns = TempAns + TempAnsShort
    
          Case Else
    ' somethig else
    ' to be developped
            MsgBox ("Char to encode not matched: " & CharToEncode & " = &H" & Hex(CharToEncode))
    
        End Select
    
        CurChr = CurChr + 1
      Loop
    
      UTF8Encode = TempAns
    End Function
    

    Good luck!

    0 讨论(0)
提交回复
热议问题