VB 6.0 - System.Uri.EscapeDataString in VB 6 - vb.net
I recently made an app in VB 2010 and in order to make it independent of the .Net Framework, I begun remaking the app in VB 6.0. There's supposed to be a button on the form that, when pressed, opens the default email client. Then it opens a new email and copies into its body the text generated by the application on a Textbox. The problem with it is that the copied text in the body gets pasted with the wrong encoding and completely different from how it's supposed to be. I also encountered that problem in VB 2010 but I was able to fix this by using System.Uri.EscapeDataString like this
Process.Start("mailto:test#email.com?subject= &body=" & System.Uri.EscapeDataString(TextBox1.Text))
Is there a way to do something like this in vb 6.0 ?
ShellExecute Me.hwnd, "open", "mailto:test#email.com?subject= &body=" & NoonText.Text, _
vbNullString, vbNullString, 1
P.S I've tried URL Encoding it but wherever there are supposed to be spaces, crosses ("+") are pasted instead.
OK. Here's the bulk of the code that should behave like System.Uri.EscapeUriString and System.Uri.EscapeDataString using, respectively, the methods named EscapeURI() and EscapeURIData() provided in the listing below. Like any random piece of code, consider it's provided as is and thoroughly test it before you ever consider using it.
I'm providing the code for two (2) reasons:
Although your motives are questionable, as people with more reputation than me have rightly noted, there may arise a case where somebody will be confronted with the same question but for different reasons. The answer to your problem remains "Don't do it", but I still consider the technical question, per se, not any less valid and on topic.
Hopefully, with this answer you'll realize it's utterly pointless to reinvent the wheel. VB.NET was created as the successor of VB6, with among other objectives to provide means to build solutions for current, "real-world" problems all the while using less code, so it's more manageable and easier to maintain. Also, the VB6 runtime (MSVBVM60.DLL) as a dependency is more problematic than the .NET Framework simply because its support is no longer guaranteed.
So, here's the code. It's basically an implementation of character escaping as described in RFC 3986 on top of a UTF-8 encoding routine. The code is not optimized but commented so as to be easy to understand. Also, it does not support Internationalized Domain Names (RFC 3987).
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, src As Any, ByVal cb As Long)
Private Declare Function MultiByteToWideChar Lib "Kernel32.dll" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpMultiByteStr As Long, _
ByVal cbMultiByte As Long, _
ByVal lpWideCharStr As Long, _
ByVal cchWideChar As Long _
) As Long
Private Declare Function WideCharToMultiByte Lib "Kernel32.dll" ( _
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
Private Enum VbStrConv2
vbUpperCase = VbStrConv.vbUpperCase
vbLowerCase = VbStrConv.vbLowerCase
vbProperCase = VbStrConv.vbProperCase
vbWide = VbStrConv.vbWide
vbNarrow = VbStrConv.vbNarrow
vbHiragana = VbStrConv.vbHiragana
vbUnicode = VbStrConv.vbUnicode
vbFromUnicode = VbStrConv.vbFromUnicode
vbUTF8 = &H100&
vbFromUTF8 = &H200&
End Enum
Private Const CP_ACP As Long = 0 ' Default ANSI code page.
Private Const CP_UTF8 As Long = 65001 ' UTF8.
Private Const CP_UTF16_LE As Long = 1200 ' UTF16 - little endian.
Private Const CP_UTF16_BE As Long = 1201 ' UTF16 - big endian.
Private Const CP_UTF32_LE As Long = 12000 ' UTF32 - little endian.
Private Const CP_UTF32_BE As Long = 12001 ' UTF32 - big endian.
Public Function EscapeURI(ByVal URI As String, Optional ByVal JSCompatible As Boolean = False) As String
' As per "RFC 1738: Uniform Resource Locators (URL) specification"
' 21-06-2010: Modified to conform to "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax"
Dim i As Long
Dim bAnsi() As Byte
Dim iAscii As Integer
Dim sEscapedUri As String
bAnsi = StrConv2(URI, VbStrConv2.vbUTF8)
sEscapedUri = vbNullString
For i = LBound(bAnsi) To UBound(bAnsi)
iAscii = bAnsi(i)
Select Case iAscii
' ASCII control caracters, always escape
Case 0 To 31, 127
If iAscii < 16 Then
sEscapedUri = sEscapedUri & "%0" & Hex$(iAscii)
Else
sEscapedUri = sEscapedUri & "%" & Hex$(iAscii)
End If
' Non-ASCII characters, always escape
Case 128 To 255
sEscapedUri = sEscapedUri & "%" & Hex$(iAscii)
' Reserved characters, don't escape with an URI
' RFC 3986 section 2.2 Reserved Characters (January 2005)
' ! # $ & ' ( ) * + , / : ; = ? # [ ]
Case 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 47, 58, 59, 61, 63, 64, 91, 93
If JSCompatible Then
Select Case iAscii
' [ ]
Case 91, 93
' ECMAScript's encodeURI() escapes those
' (since IPv6, hosts can be e.g. [::1/128] so we want to preserve them unescaped)
sEscapedUri = sEscapedUri & "%" & Hex$(iAscii)
Case Else
sEscapedUri = sEscapedUri & Chr$(iAscii)
End Select
Else
sEscapedUri = sEscapedUri & Chr$(iAscii)
End If
' Unreserved characters, never escape
' RFC 3986 section 2.3 Unreserved Characters (January 2005)
' - . 0 ... 9 A ... Z a .... z _ ~
Case 45, 46, 48 To 57, 65 To 90, 97 To 122, 95, 126
sEscapedUri = sEscapedUri & Chr$(iAscii)
' Unsafe characters, always escape
' " % < > \ ^ ` { | }
Case 34, 37, 60, 62, 92, 94, 96, 123, 124, 125
sEscapedUri = sEscapedUri & "%" & Hex$(iAscii)
' Space, escaped
Case 32
sEscapedUri = sEscapedUri & "%20"
Case Else
sEscapedUri = sEscapedUri & "%" & Hex$(iAscii)
End Select
Next i
EscapeURI = sEscapedUri
End Function
Public Function EscapeURIData(ByVal URIData As String, Optional ByVal JSCompatible As Boolean = False) As String
' As per "RFC 1738: Uniform Resource Locators (URL) specification"
' 21-06-2010: Modified to conform to "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax"
Dim i As Long
Dim bAnsi() As Byte
Dim iAscii As Integer
Dim sEscapedData As String
bAnsi = StrConv2(URIData, VbStrConv2.vbUTF8)
sEscapedData = vbNullString
For i = LBound(bAnsi) To UBound(bAnsi)
iAscii = bAnsi(i)
Select Case iAscii
' ASCII control caracters, always escape
Case 0 To 31, 127
If iAscii < 16 Then
sEscapedData = sEscapedData & "%0" & Hex$(iAscii)
Else
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
End If
' Non-ASCII characters, always escape
Case 128 To 255
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
' Reserved characters, always escape when treated as data
' RFC 3986 section 2.2 Reserved Characters (January 2005)
' ! # $ & ' ( ) * + , / : ; = ? # [ ]
Case 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 47, 58, 59, 61, 63, 64, 91, 93
If JSCompatible Then
Select Case iAscii
' ! ' ( ) *
Case 33, 39, 40, 41, 42
' ECMAScript's encodeURIComponent() doesn't escape those
sEscapedData = sEscapedData & Chr$(iAscii)
Case Else
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
End Select
Else
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
End If
' Unreserved characters, never escape
' RFC 3986 section 2.3 Unreserved Characters (January 2005)
' - . 0 ... 9 A ... Z a .... z _ ~
Case 45, 46, 48 To 57, 65 To 90, 97 To 122, 95, 126
sEscapedData = sEscapedData & Chr$(iAscii)
' Unsafe characters, always escape
' " % < > \ ^ ` { | }
Case 34, 37, 60, 62, 92, 94, 96, 123, 124, 125
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
' Space, escaped
Case 32
sEscapedData = sEscapedData & "%20"
Case Else
sEscapedData = sEscapedData & "%" & Hex$(iAscii)
End Select
Next i
EscapeURIData = sEscapedData
End Function
'
' Utilities
'
Private Function StrConv2(Expr As Variant, Conversion As VbStrConv2, Optional LocaleID As Long = 0)
Const METHOD_NAME = "StrConv2"
Dim sExpr As String, arr_bytInput() As Byte, lLBound As Long
Select Case Conversion
Case VbStrConv2.vbUTF8 ' LocaleID not used (no case changing, no code page mapping)
Dim lInputChars As Long
Dim lOutputBytes As Long, arr_bytOutputBytes() As Byte
' Expected input: Unicode (UCS-2)
Select Case VarType(Expr)
Case vbString
sExpr = CStr(Expr)
' Get length of input, in *characters*
lInputChars = Len(sExpr)
' Copy input string as-is
arr_bytInput = sExpr
Case (vbArray + vbByte)
' Get length of input, in *characters*
lInputChars = (UBound(Expr) - LBound(Expr) + 1) \ 2
' Copy array (same type)
arr_bytInput = Expr
Case Else
Err.Raise 13, METHOD_NAME, "Expr: Type mismatch (in " & METHOD_NAME & "())"
End Select
' Get size of output strings, in *bytes*
lOutputBytes = WideCharToMultiByte(CP_UTF8, 0, VarPtr(arr_bytInput(0)), lInputChars, 0, 0, 0, 0)
' Size appropriately
ReDim arr_bytOutputBytes(lOutputBytes - 1)
' Second call
lOutputBytes = WideCharToMultiByte(CP_UTF8, 0, VarPtr(arr_bytInput(0)), lInputChars, VarPtr(arr_bytOutputBytes(0)), lOutputBytes, 0, 0)
' Return as array of bytes
StrConv2 = arr_bytOutputBytes
Case VbStrConv2.vbFromUTF8 ' LocaleID not used (no case changing, no code page mapping)
Dim lInputBytes As Long
Dim lOutputChars As Long, arr_bytOutputChars() As Byte
' Expected input: UTF-8
Select Case VarType(Expr)
Case vbString
arr_bytInput = StrConv(Expr, vbFromUnicode)
' Get length of input, in *bytes*
lInputBytes = (UBound(arr_bytInput) - LBound(arr_bytInput) + 1)
Case (vbArray + vbByte)
' Copy array (same type)
arr_bytInput = Expr
' Get length of input, in *bytes*
lInputBytes = (UBound(arr_bytInput) - LBound(arr_bytInput) + 1)
Case Else
Err.Raise 13, METHOD_NAME, "Expr: Type mismatch (in " & METHOD_NAME & "())"
End Select
' Get size of output strings, in *chars*
lOutputChars = MultiByteToWideChar(CP_UTF8, 0, VarPtr(arr_bytInput(0)), lInputBytes, 0, 0)
' Size appropriately
ReDim arr_bytOutputChars(lOutputChars * 2 - 1)
' Second call
lOutputChars = MultiByteToWideChar(CP_UTF8, 0, VarPtr(arr_bytInput(0)), lInputBytes, VarPtr(arr_bytOutputChars(0)), lOutputChars)
' Return as string
sExpr = arr_bytOutputChars
StrConv2 = Left$(sExpr, lOutputChars)
Case Else
StrConv2 = StrConv(Expr, Conversion, LocaleID)
End Select
End Function
Related
VBA: Isolate a decimal number from a string so that I can add or subtract from it
I'm attempting to write a program that involves finding strings with numerical values that are +1 and -1 from the numerical value located within another string. (The rest of the program is fine, it's just this section that I'm having a difficult time with). For example: If I have the parent string: name[CE18.2]-abritraryinfo I need to find a way to isolate that 18.2 so that I can add 1 to it and subtract 1 from it to create two new numerical values of 19.2 and 17.2 I need to be able to do this in such a way that I can find this number in strings whose 'name' section and whose number after CE vary according to the different parent strings. What I've tried already is this: ''' Result = Empty 'Resets the value of the result after it changes to the next name f = InStr(c, "CE") 'Finds at which position in the string CE is located. The position is the C of CE z = Mid(c, f, 8) 'Pulls 8 units from the string starting at the position dictated by f stringLength = Len(z) 'Gives the Length of the section pulled by Z For i = 1 To stringLength 'From the first position to the final position If IsNumeric(Mid(z, i, 1)) Then Result = Result & Mid(z, i, 1) 'Gives the numbers in the string section pulled by Z End If Next i ''' but it doesn't work as it ignores the decimal point. Any advice would be incredibly helpful! Thanks in advance!
One of the simple solution is: Sub test1() inputS = "name[CE18.2]-abritraryinfo" pos = InStr(inputS, "[CE") If pos > 0 Then x = Val(Mid(inputS, pos + 3)) Debug.Print x, x - 1, x + 1 End If End Sub Output: 18,2 17,2 19,2
String Between Two Strings Option Explicit Sub gsbtsTEST() Const lStr As String = "CE" Const rStr As String = "]" Const sString As String = "name[CE18.2]-abritraryinfo" Dim ResString As String ResString = GetStringBetweenTwoStrings(sString, lStr, rStr) Dim ResValue As Double If IsNumeric(ResString) Then ResValue = Val(ResString) End If Debug.Print ResString, ResValue - 1, ResValue, ResValue + 1 End Sub Function GetStringBetweenTwoStrings( _ ByVal sString As String, _ ByVal lStr As String, _ ByVal rStr As String, _ Optional ByVal CompareMethod As VbCompareMethod = vbTextCompare) _ As String Dim lPos As Long: lPos = InStr(1, sString, lStr, CompareMethod) If lPos = 0 Then Exit Function Dim rPos As Long: rPos = InStr(1, sString, rStr, CompareMethod) If rPos = 0 Then Exit Function lPos = lPos + Len(lStr) If lPos < rPos Then GetStringBetweenTwoStrings = Mid(sString, lPos, rPos - lPos) End If End Function
How to get command line parameters of WinWord.exe inside the AutoExec macro?
Inside the AutoExec macro of Word, I would like to handle some features. For this, I need a Id, given by a command line parameter while starting WinWord.exe. Example: "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /MyParam:5 I need this 5 How can I get this?
VBA, natively, doesn't provide this kind of information. It's necessary to leverage the Windows API to get the command line arguments. The following code demonstrates how to use the GetCommandLineA and lstrcpynA APIs to extract get the full command line. This is then parsed to pick up each individual argument. Declare Function GetCommandLineA Lib "kernel32" () As Long Declare Function lstrcpynA Lib "kernel32" ( _ ByVal pDestination As String, ByVal pSource As Long, _ ByVal iMaxLength As Integer) As Long Function GetCmdLineInfo() As String ' Pointer to the command line ' Which will be passed as pSource to lstrcpynA Dim ptrCmdLine As Long ' Will hold the command line after the call to lstrcpynA ' Pointer to the destination; before being passed... ' must first be initialized with enough characters to hold that string Dim strCmdLine As String ' Get the pointer to the command line string ptrCmdLine = GetCommandLineA ' Fill the string with enough zeros to make sure there are enough ' characters available for the command string (which will replace the content). ' 300 is an arbitrary number, more might be necessary. strCmdLine = String$(300, vbNullChar) ' Copy from the pointer to a VBA-style string lstrcpynA strCmdLine, pCmdLine, Len(strCmdLine) ' Remove the extra vbNullChar characters at the end of the command line strCmdLine = left(strCmdLine, InStr(1, strCmdLine, _ vbNullChar) - 1) GetCmdLineInfo = strCmdLine End Function Function GetCmdLineArgs(strCmdLine As String) As String Dim lExePos As Long, lSpaceAfterExe As Long Dim strArgString As String 'Get the end of the path to the exe file... lExePos = InStr(LCase(strCmdLine), ".exe") strArgString = Mid(strCmdLine, lExePos + 4) 'Move beyond any quote characters and spaces after '.exe' 'The first argument may be the path to a file or 'an argument beginning with a forward slash, so get it all. lSpaceAfterExe = InStr(strArgString, " ") If lSpaceAfterExe > 0 Then strArgString = Mid(strArgString, lSpaceAfterExe + 1) Else strArgString = "No args" End If GetCmdLineArgs = Trim(strArgString) End Function Sub TestCmdLineargs() Dim strCmdLine As String Dim strCmdArgs strCmdLine = GetCmdLineInfo strCmdArgs = GetCmdLineArgs(strCmdLine) 'Debug.Print Len(strCmdLine), strCmdLine, strCmdArgs 'Extract the individual args to an array Dim strArgChar As String Dim lFirstArgPos As Long, lNextArgPos As Long Dim argsList() As String Dim strArgString As String Dim argsCounter As Long strArgChar = " /" argsCounter = 0 lFirstArgPos = InStr(strCmdArgs, strArgChar) 'If the first argument is a file path, store that in the array If left(strCmdArgs, 1) <> "/" Then ReDim Preserve argsList(argsCounter) strArgString = Trim(left(strCmdArgs, lFirstArgPos - 2)) argsList(argsCounter) = strArgString argsCounter = argsCounter + 1 End If 'Get the rest of the args, that start with a / Do While lFirstArgPos > 0 ReDim Preserve argsList(argsCounter) strArgString = Mid(strCmdArgs, lFirstArgPos + 1) lNextArgPos = InStr(lFirstArgPos + 2, strCmdArgs, strArgChar) 'If lNextArgPos is not greater than 0, then there are no more args If lNextArgPos <= 0 Then argsList(argsCounter) = strArgString Exit Do Else strArgString = Mid(strCmdArgs, lFirstArgPos + 1, lNextArgPos - lFirstArgPos) argsList(argsCounter) = strArgString argsCounter = argsCounter + 1 lFirstArgPos = lNextArgPos End If Loop Dim i As Long For i = LBound(argsList) To UBound(argsList) Debug.Print argsList(i) Next End Sub
How do you get the current label dimensions setting for a zebra printer
I am making an access application that prints two sizes of label, 3" width by 2" height, and then 1.5" width by 1" height. This application will run on several different computers that dont have the same sets of printers, for example, machine 1 might have a GC420d, a GK420d and a regular 8.5x11 printer, then machine 2 might have a LP 2844, a GC420d, and a regular 8.5x11 printer. The machines are spread out across the production environment and we cant standardize on printer type. So, this leaves me where i need to be able to determine which printer has the 3" x 2" settings and which has the 1.5" by 1" setting. EDIT: I know this looks like a "I havent tried anything and im too lazy to try" situation, but all of the code i had was lost when access crashed to desktop. I mostly tried Win API stuff like DeviceCapabilities, but i couldn't get it to give me anything useful. a paper type Enumeration of Custom is useless when i cant see what the actual dimensions of the custom paper type is. Then i tried DocumentProperties which required OpenPrinter to get the printer handle. Thats the stuff that nuked everything access side. i used this website to get the API calls for VBA. EDIT2: this is the return for the papertype according to access. ?application.Printers(0).DeviceName ZDesigner GC420d (EPL) ?application.Printers(0).PaperSize 256
You can use the below to list all supported paper names and their corresponding sizes: Private Enum DeviceCapabilitiesFlags DC_FIELDS = 1 DC_PAPERS = 2 DC_PAPERSIZE = 3 DC_MINEXTENT = 4 DC_MAXEXTENT = 5 DC_BINS = 6 DC_DUPLEX = 7 DC_SIZE = 8 DC_EXTRA = 9 DC_VERSION = 10 DC_DRIVER = 11 DC_BINNAMES = 12 DC_ENUMRESOLUTIONS = 13 DC_FILEDEPENDENCIES = 14 DC_TRUETYPE = 15 DC_PAPERNAMES = 16 DC_ORIENTATION = 17 DC_COPIES = 18 DC_BINADJUST = 19 DC_EMF_COMPLIANT = 20 DC_DATATYPE_PRODUCED = 21 DC_COLLATE = 22 DC_MANUFACTURER = 23 DC_MODEL = 24 DC_PERSONALITY = 25 DC_PRINTRATE = 26 DC_PRINTRATEUNIT = 27 DC_PRINTERMEM = 28 DC_MEDIAREADY = 29 DC_STAPLE = 30 DC_PRINTRATEPPM = 31 DC_COLORDEVICE = 32 DC_NUP = 33 DC_MEDIATYPENAMES = 34 DC_MEDIATYPES = 35 End Enum Private Type POINT x As Long y As Long End Type Private Declare Function DeviceCapabilities _ Lib "winspool.drv" _ Alias "DeviceCapabilitiesA" _ (ByVal lpDeviceName As String, _ ByVal lpPort As String, _ ByVal iIndex As Long, _ ByRef lpOutput As Any, _ ByRef lpDevMode As Any) _ As Long Private Declare Function StrLen _ Lib "kernel32.dll" _ Alias "lstrlenA" _ (ByVal lpString As String) _ As Long Public Sub ListSupportedPaperSizes() Dim defaultPrinter() As String Dim paperCount As Long Dim NameArray() As Byte Dim i As Long Dim paperNames() As String Dim paperName As String Dim ctr As Long defaultPrinter = Split(Application.ActivePrinter, " on ") paperCount = DeviceCapabilities(defaultPrinter(0), defaultPrinter(1), DC_PAPERSIZE, ByVal 0&, ByVal 0&) ReDim paperNames(1 To paperCount) ReDim NameArray(0 To paperCount * 64) As Byte ' Get paper names paperCount = DeviceCapabilities(defaultPrinter(0), defaultPrinter(1), DC_PAPERNAMES, NameArray(0), 0) 'convert the retrieved byte array to an ANSI string AllNames = StrConv(NameArray, vbUnicode) ReDim paperNames(1 To paperCount) 'loop through the string and search for the names of the papers For i = 1 To Len(AllNames) Step 64 ctr = ctr + 1 paperName = Mid(AllNames, i, 64) paperName = Left(paperName, StrLen(paperName)) If paperName <> vbNullString Then paperNames(ctr) = paperName End If Next i ReDim PaperSizes(1 To paperCount) As POINT paperCount = DeviceCapabilities(defaultPrinter(0), defaultPrinter(1), DC_PAPERSIZE, PaperSizes(1), 0) For i = 1 To paperCount Debug.Print paperNames(i) & " : " _ & Format(PaperSizes(i).x / 254, "0.00") & " x " _ & Format(PaperSizes(i).y / 254, "0.00") _ & " inch" Next End Sub
MS- Access VBA Converting multiple characters to Asc
For a homework project I am trying to enter characters in a single textbox as (eg:"AbC" no spaces) and have the output in a captioned label as the corresponding ASCII value written out with commas and spaces. (eg: 65, 98, 67) Private Sub cmdCode_Click() Dim codeInt As Integer strInput = txtInput.value codeInt = Asc(strInput) lblAnswer.Caption = codeInt & ", " End Sub I would like the result to look like: 65, 98, 67 I'm getting no errors but only receiving "65," as my output.
Here is my solution. It assumes that the input is always going to be three (3) characters long: Private Sub cmdCode_Click() Dim x As String Dim y As String Dim z As String strInput = txtInput.value x = Asc(Left(strInput, 1)) y = Asc(Mid(strInput, 2, 1)) z = Asc(Right(strInput, 1)) lblAnswer.Caption = x & ", " & y & ", " & z End Sub
This can be done for generic usage - and a little smarter: Public Function StrToAscList( _ ByVal Text As String) _ As String Dim Chars() As Byte Dim Item As Integer Dim List As String Chars() = StrConv(Text, vbFromUnicode) For Item = LBound(Chars) To UBound(Chars) If Item > 0 Then List = List & ", " List = List & CStr(Chars(Item)) Next StrToAscList = List End Function Then: Me!lblAnswer.Caption = StrToAscList(strInput)
VB6 How to decode Chinese Characters with the HTML code
I need to decode the following text (just partial of it) and it consists of Chinese traditional characters. I have tried some decoding code but it doesn't work. After decoded, it turned out to be ???? PART OF THE Encoded Text: %3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A20pt%3Btext-align%3Acenter%3Bfont-weight%3Abold%22%3E%0D%0A%09Genie%E7%93%B6%E4%B8%AD%E7%B2%BE%E9%9D%88%2010%25%E6%9D%8F%E4%BB%81%E9%85%B8%E4%BA%AE%E9%87%87%E7%85%A5%E8%86%9A%E7%B2%BE%E8%8F%AF%E6%B6%B2%20%E8%B2%B7%E4%B8%80%E9%80%81%E4%B8%80%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Acenter%22%3E%0D%0A%09%20%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2F3C8EF489980779600D2E2A95C5BB2E0C15859F8B%22%20%2F%3E%3C%2Fdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd After DECODED: You can see the Chinese characters being decoded as ???? <div align=center><TABLE width="100 <TBODY> <TR> <TD> <P style="FONT-SIZE: 20pt; FONT-WEIGHT: bold; COLOR: #000000; TEXT-ALIGN: center"> Genie???? 10???????? ???? </P> </TD> Please help how to decode it properly. Private Const CP_UTF8 As Long = 65001 ' UTF-8 Code Page 'Sys call to convert multiple byte chars to a char Private Declare Function MultiByteToWideChar Lib "kernel32" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpMultiByteStr As Long, _ ByVal cchMultiByte As Long, _ ByVal lpWideCharStr As Long, _ ByVal cchWideChar As Long) As Long Private Function URL8Decode(ByVal URLEncoded As String) As String On Error GoTo executeError Dim ANSI() As Byte Dim UTF8() As Byte Dim I As Long Dim B As Long URLEncoded = Replace$(URLEncoded, "+", " ") 'Optional, plus-encoding isn't always used. ANSI = StrConv(URLEncoded, vbFromUnicode) ReDim UTF8(UBound(ANSI)) 'Estimate. For I = 0 To UBound(ANSI) If ANSI(I) = &H25 Then UTF8(B) = FromHex(ANSI(I + 1)) * &H10 + FromHex(ANSI(I + 2)) 'Val("&H" & Mid$(URLEncoded, I + 2, 2)) I = I + 2 Else UTF8(B) = ANSI(I) End If B = B + 1 Next URL8Decode = FromUTF8(UTF8, B) Exit Function executeError: LogProcess "ProductDetailFrm URL8Decode - [Err=" & Err.description & "]" Resume 'HANG End Function Private Function FromHex(ByVal Char As Byte) As Byte On Error GoTo executeError If Char <= &H39 Then FromHex = Char - &H30 Else FromHex = Char - &H41 + &HA End If Exit Function executeError: LogProcess "ProductDetailFrm FromHex - [Err=" & Err.description & "]" End Function
See if this code help you. I am using the JavaScript capabilities to decode. Option Explicit Sub Test() Const sEncoded As String = "%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A20pt%3Btext-align%3Acenter%3Bfont-" & _ "weight%3Abold%22%3E%0D%0A%09Genie%E7%93%B6%E4%B8%AD%E7%B2%BE%E9%9D%88%2010%25%E6%9D%8F%E4%BB%81%E9%85%B8%E4%BA%AE%E9%87%87%E7%85%A5%E8%86%9A%E7%B2%BE%E8%8F%AF%E6%B6%B2%20%E8%B2%B7%E4%B8%80%E9%80%81%E4%B8%80%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd" & _ "%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Acenter%22%3E%0D%0A%09%20%0D%0A%3C%2" & _ "Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%" & _ "2F3C8EF489980779600D2E2A95C5BB2E0C15859F8B%22%20%2F%3E%3C%2Fdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%" & _ "20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd" ' I am writing the values to Range("A1") Cells(1, 1).Value = DecodeHTML(sEncoded) End Sub 'Decodes the string using a javasript object. Function DecodeHTML(ByVal strCharacters As String) As String Dim oScrip As Object Dim ret As String Set oScrip = CreateObject("MSScriptControl.ScriptControl") With oScrip .Language = "JScript" .AddCode "function decode(x) {return decodeURIComponent(x);}" ret = .Run("decode", strCharacters) End With 'Return the value DecodeHTML = ret End Function Just run the Test() procedure. Thanks I hope this helps :)