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 :)