How can I URL encode a string in Excel VBA?

后端 未结 15 1914
闹比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:01

    None of the solutions here worked for me out of the box, but it was most likely due my lack of experience with VBA. It might also be because I simply copied and pasted some of the functions above, not knowing details that maybe are necessary to make them work on a VBA for applications environment.

    My needs were simply to send xmlhttp requests using urls that contained some special characters of the Norwegian language. Some of the solutions above encode even colons, which made the urls unsuitable for what I needed.

    I then decided to write my own URLEncode function. It does not use more clever programming such as the one from @ndd and @Tom. I am not a very experienced programmer, but I had to make this done sooner.

    I realized that the problem was that my server didn't accept UTF-16 encodings, so I had to write a function that would convert UTF-16 to UTF-8. A good source of information was found here and here.

    I haven't tested it extensively to check if it works with url with characters that have higher unicode values and which would produce more than 2 bytes of utf-8 characters. I am not saying it will decode everything that needs to be decoded (but it is easy to modify to include/exclude characters on the select case statement) nor that it will work with higher characters, as I haven't fully tested. But I am sharing the code because it might help someone who is trying to understand the issue.

    Any comments are welcome.

    Public Function URL_Encode(ByVal st As String) As String
    
        Dim eachbyte() As Byte
        Dim i, j As Integer 
        Dim encodeurl As String
        encodeurl = "" 
    
        eachbyte() = StrConv(st, vbFromUnicode)
    
        For i = 0 To UBound(eachbyte)
    
            Select Case eachbyte(i)
            Case 0
            Case 32
                encodeurl = encodeurl & "%20"
    
            ' I am not encoding the lower parts, not necessary for me
            Case 1 To 127
                encodeurl = encodeurl & Chr(eachbyte(i))
            Case Else
    
                Dim myarr() As Byte
                myarr = utf16toutf8(eachbyte(i))
                For j = LBound(myarr) To UBound(myarr) - 1
                    encodeurl = encodeurl & "%" & Hex(myarr(j))
                Next j
            End Select
        Next i
        URL_Encode = encodeurl 
    End Function
    
    Public Function utf16toutf8(ByVal thechars As Variant) As Variant
        Dim numbytes As Integer
        Dim byte1 As Byte
        Dim byte2 As Byte
        Dim byte3 As Byte
        Dim byte4 As Byte
        Dim byte5 As Byte 
        Dim i As Integer  
        Dim temp As Variant
        Dim stri As String
    
        byte1 = 0
        byte2 = byte3 = byte4 = byte5 = 128
    
        ' Test to see how many bytes the utf-8 char will need
        Select Case thechars
            Case 0 To 127
                numbytes = 1
            Case 128 To 2047
                numbytes = 2
            Case 2048 To 65535
                numbytes = 3
            Case 65536 To 2097152
                numbytes = 4
            Case Else
                numbytes = 5
        End Select
    
        Dim returnbytes() As Byte
        ReDim returnbytes(numbytes)
    
    
        If numbytes = 1 Then
            returnbytes(0) = thechars
            GoTo finish
        End If
    
    
        ' prepare the first byte
        byte1 = 192
    
        If numbytes > 2 Then
            For i = 3 To numbytes
                byte1 = byte1 / 2
                byte1 = byte1 + 128
            Next i
        End If
        temp = 0
        stri = ""
        If numbytes = 5 Then
            temp = thechars And 63
    
            byte5 = temp + 128
            returnbytes(4) = byte5
            thechars = thechars / 12
            stri = byte5
        End If
    
        If numbytes >= 4 Then
    
            temp = 0
            temp = thechars And 63
            byte4 = temp + 128
            returnbytes(3) = byte4
            thechars = thechars / 12
            stri = byte4 & stri
        End If
    
        If numbytes >= 3 Then
    
            temp = 0
            temp = thechars And 63
            byte3 = temp + 128
            returnbytes(2) = byte3
            thechars = thechars / 12
            stri = byte3 & stri
        End If
    
        If numbytes >= 2 Then
    
            temp = 0
            temp = thechars And 63
            byte2 = temp Or 128
            returnbytes(1) = byte2
            thechars = Int(thechars / (2 ^ 6))
            stri = byte2 & stri
        End If
    
        byte1 = thechars Or byte1
        returnbytes(0) = byte1
    
        stri = byte1 & stri
    
        finish:
           utf16toutf8 = returnbytes()
    End Function
    
    0 讨论(0)
  • 2020-11-22 12:04

    Similar to Michael-O's code, only without need to reference (late bind) and with less one line .
    * I read, that in excel 2013 it can be done more easily like so: WorksheetFunction.EncodeUrl(InputString)

    Public Function encodeURL(str As String)
        Dim ScriptEngine As Object
        Dim encoded As String
    
        Set ScriptEngine = CreateObject("scriptcontrol")
        ScriptEngine.Language = "JScript"
    
        encoded = ScriptEngine.Run("encodeURIComponent", str)
    
        encodeURL = encoded
    End Function
    
    0 讨论(0)
  • 2020-11-22 12:05

    The VBA-tools library has a function for that:

    http://vba-tools.github.io/VBA-Web/docs/#/WebHelpers/UrlEncode

    It seems to work similar to encodeURIComponent() in JavaScript.

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

    If you also want it to work on MacOs create a seperate function

    Function macUriEncode(value As String) As String
    
        Dim script As String
        script = "do shell script " & """/usr/bin/python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' """ & Chr(38) & " quoted form of """ & value & """"
    
        macUriEncode = MacScript(script)
    
    End Function
    
    0 讨论(0)
  • 2020-11-22 12:10

    Same as WorksheetFunction.EncodeUrl with UTF-8 support:

    Public Function EncodeURL(url As String) As String
      Dim buffer As String, i As Long, c As Long, n As Long
      buffer = String$(Len(url) * 12, "%")
    
      For i = 1 To Len(url)
        c = AscW(Mid$(url, i, 1)) And 65535
    
        Select Case c
          Case 48 To 57, 65 To 90, 97 To 122, 45, 46, 95  ' Unescaped 0-9A-Za-z-._ '
            n = n + 1
            Mid$(buffer, n) = ChrW(c)
          Case Is <= 127            ' Escaped UTF-8 1 bytes U+0000 to U+007F '
            n = n + 3
            Mid$(buffer, n - 1) = Right$(Hex$(256 + c), 2)
          Case Is <= 2047           ' Escaped UTF-8 2 bytes U+0080 to U+07FF '
            n = n + 6
            Mid$(buffer, n - 4) = Hex$(192 + (c \ 64))
            Mid$(buffer, n - 1) = Hex$(128 + (c Mod 64))
          Case 55296 To 57343       ' Escaped UTF-8 4 bytes U+010000 to U+10FFFF '
            i = i + 1
            c = 65536 + (c Mod 1024) * 1024 + (AscW(Mid$(url, i, 1)) And 1023)
            n = n + 12
            Mid$(buffer, n - 10) = Hex$(240 + (c \ 262144))
            Mid$(buffer, n - 7) = Hex$(128 + ((c \ 4096) Mod 64))
            Mid$(buffer, n - 4) = Hex$(128 + ((c \ 64) Mod 64))
            Mid$(buffer, n - 1) = Hex$(128 + (c Mod 64))
          Case Else                 ' Escaped UTF-8 3 bytes U+0800 to U+FFFF '
            n = n + 9
            Mid$(buffer, n - 7) = Hex$(224 + (c \ 4096))
            Mid$(buffer, n - 4) = Hex$(128 + ((c \ 64) Mod 64))
            Mid$(buffer, n - 1) = Hex$(128 + (c Mod 64))
        End Select
      Next
    
      EncodeURL = Left$(buffer, n)
    End Function
    
    0 讨论(0)
  • 2020-11-22 12:13

    For the sake of bringing this up to date, since Excel 2013 there is now a built-in way of encoding URLs using the worksheet function ENCODEURL.

    To use it in your VBA code you just need to call

    EncodedUrl = WorksheetFunction.EncodeUrl(InputString)
    

    Documentation

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