Converting characters to numbers - vbscript

In a program I am currently making, I need to convert a certain set of characters to numbers. This set of characters is prone to change and also includes CaPiTaL letters in the conversion, of which the capitals will be converted to a different number as with special characters (such as "#", "&", "$", etc). The numbers follow a simple pattern; a = 1, b = 2, c = 3, etc.
The current method I am using to do this is using a separate:
If letter = "a" then
number = 1
End If
This method however is a chore to write up and also seems to be a bit inefficient (in terms of running continuous/bulk amounts of letters through it). Is there any function, sub, etc. that can be used to perform an action like this in VBScript (specifically in VB Express 2010)?

When in doubt, read the documentation. The Asc() function returns the character code of a given ASCII character:
>>> WScript.Echo Asc("a")
97
>>> WScript.Echo Asc("A")
65
Another option is to create a dictionary with the desired mappings:
Set map = CreateObject("Scripting.Dictionary")
map.Add "a", 1
map.Add "b", 2
...
which can be used like this:
>>> WScript.Echo map("a")
1
>>> WScript.Echo map("b")
2

Step 0: Using positional mapping:
Option Explicit
' Start with a function working on a string that calls
' a character decode function
Function decodeS(s)
ReDim aTmp(Len(s) - 1)
Dim i
For i = 0 To UBound(aTmp)
aTmp(i) = decodeC(Mid(s, i + 1, 1))
Next
decodeS = aTmp
End Function
' naive decode via InStr/Index/Position
Function decodeC(c)
decodeC = InStr("abc", c)
End Function
WScript.Echo "acbbca", Join(decodeS("acbbca"))
Step 1: guarded positional mapping:
' guarded decode via InStr/Index/Position
Function decodeC(c)
decodeC = -1
Dim p : p = InStr("abcdefghiA", c)
If p Then decodeC = p
End Function
WScript.Echo "acbbcAx", Join(decodeS("acbbcAx"))
Step 2: positional mapping 'doesn't work', switch to lookup:
' decode via parallel array and InStr/Index/Position
Dim gsC : gsC = "aAbBcC"
Dim gaC : gaC = Split("-1 1 10 2 20 3 30")
Function decodeC(c)
decodeC = CLng(gaC(InStr(gsC, c)))
End Function
WScript.Echo "CcBxbAa", Join(decodeS("CcBxbAa"))
Step 3: you prefer dictionary lookup:
' decode via dictionary
Dim gdC : Set gdC = CreateObject("Scripting.Dictionary")
gdC("a") = 1
gdC("A") = 10
Function decodeC(c)
decodeC = -1
If gdC.Exists(c) Then decodeC = gdC(c)
End Function
WScript.Echo "CcBxbAa", Join(decodeS("CcBxbAa"))

Related

Randomly rearrange letters in a word

Using this SO question / answer as a starting point: Splitting a single word into an array of the consituent letters
I have this simple bit of code to take a word and split the word into single letters:
<%
Dim word1, i
word1 = "particle"
For i = 1 To Len(word1)
Response.Write "<p>" & Mid(word1, i, 1) & "</p>"
Next
%>
I would like to know how to take a word (variable length, rather than a word that is 8 characters long as in the example above), and randomly rearrange the letters of the word - so that e.g. particle could be e.g.:
alpreict
lircpaet
ctelaipr
teapclir
raeitclp
This is an example of what I'd like to achieve: https://onlinerandomtools.com/shuffle-letters
However, I realise that is easier said than done.
I wondered if anyone has any advice about how it might be possible to achieve this using Classic ASP please?
Thanks
Here's one way to do it:
Function ShuffleText(p_sText)
Dim iLength
Dim iIndex
Dim iCounter
Dim sLetter
Dim sText
Dim sShuffledText
' Copy text passed as parameter
sText = p_sText
' Get text length
iLength = Len(sText)
For iCounter = iLength To 1 Step -1
' Get random index
iIndex = 1 + Int(Rnd * (iCounter))
' Get character at that index
sLetter = Mid(sText, iIndex, 1)
' Remove character from string
sText = Left(sText, iIndex - 1) & Mid(sText, iIndex + 1)
' Add character to shuffled string
sShuffledText = sShuffledText & sLetter
Next
' Return shuffled text
ShuffleText = sShuffledText
End Function
This code selects a random character in the string, removes it and adds it to a shuffled string. It repeats this process until it has gone through all characters.
There are probably more efficient ways to do this by randomizing an array of numbers first and using those numbers as iIndex, without manipulating the sText string.

How capitalize fullname in vb6

hi all i have this question as bellow
how capitalize full in one vb6 Vb6 string variable
‘example
‘my fullname
Dim fullname as string
Fullname = “abdirahman abdirisaq ali”
Msgbox capitalize(fullname)
it prints abdirahmanAbdirisaq ali that means it skips the middle name space even if I add more spaces its same .
this is my own code and efforts it takes me at least 2 hours and still .
I tired it tired tired please save me thanks more.
Please check my code and help me what is type of mistakes I wrote .
This is my code
Private Function capitalize(txt As String) As String
txt = LTrim(txt)
temp_str = ""
Start_From = 1
spacing = 0
For i = 1 To Len(txt)
If i = 1 Then
temp_str = UCase(Left(txt, i))
Else
Start_From = Start_From + 1
If Mid(txt, i, 1) = " " Then
Start_From = i
spacing = spacing + 1
temp_str = temp_str & UCase(Mid(txt, Start_From + 1, 1))
Start_From = Start_From + 1
Else
temp_str = temp_str & LCase(Mid(txt, Start_From, 1))
End If
End If
Next i
checkName = temp_str
End Function
It's far simpler than that. In VB6 you should use Option Explicit to properly type your variables. That also requires you to declare them.
Option Explicit
Private Function capitalize(txt As String) As String
Dim temp_str as String
Dim Names As Variant
Dim Index As Long
'Remove leading and trailing spaces
temp_str = Trim$(txt)
'Remove any duplicate spaces just to be sure.
Do While Instr(temp_str, " ") > 0
temp_str = Replace(temp_str, " ", " ")
Loop
'Create an array of the individual names, separating them by the space delimiter
Names = Split(temp_str, " ")
'Now put them, back together with capitalisation
temp_str = vbnullstring
For Index = 0 to Ubound(Names)
temp_str = temp_str + Ucase$(Left$(Names(Index),1)) + Mid$(Names(Index),2) + " "
Next
'Remove trailing space
capitalize = Left$(temp_str, Len(temp_str) - 1)
End Function
That's the fairly easy part. If you are only going to handle people's names it still needs more work to handle names like MacFarland, O'Connor, etc.
Business names get more complicated with since they can have a name like "Village on the Lake Apartments" where some words are not capitalized. It's a legal business name so the capitalization is important.
Professional and business suffixes can also be problematic if everything is in lower case - like phd should be PhD, llc should be LLC, and iii, as in John Smith III, would come out Iii.
There is also a VB6 function that will capitalize the first letter of each word. It is StrConv(string,vbProperCase) but it also sets everything that is not the first letter to lower case. So PhD becomes Phd and III becomes Iii. Where as the above code does not change the trailing portion to lower case so if it is entered correctly it remains correct.
Try this
Option Explicit
Private Sub Form_Load()
MsgBox capitalize("abdirahman abdirisaq ali")
MsgBox capitalize("abdirahman abdirisaq ali")
End Sub
Private Function capitalize(txt As String) As String
Dim Names() As String
Dim NewNames() As String
Dim i As Integer
Dim j As Integer
Names = Split(txt, " ")
j = 0
For i = 0 To UBound(Names)
If Names(i) <> "" Then
Mid(Names(i), 1, 1) = UCase(Left(Names(i), 1))
ReDim Preserve NewNames(j)
NewNames(j) = Names(i)
j = j + 1
End If
Next
capitalize = Join(NewNames, " ")
End Function
Use the VB6 statement
Names = StrConv(Names, vbProperCase)
it's all you need (use your own variable instead of Names)

Convert a value with a regex to a real value

I have a huge file containing values with a regex in it, like this:
LGP0041_\d{4}\.dta
objd135a_\S{3}.txt
Now I need to convert these to a valid example value, like this:
LGP0041_1234.dta
objd135a_abc.txt
I know of the RegExp object to check if there is a match, but is there also a way to create valid values?
A regular grammar can be used to recognize or produce words of its language, but the VBScript regexp engine does not implement producing. So you have to roll your own.
Your sample does not contain contain regular patterns. \S can't mean 'non-whitespace' because you won't like characters illegal in a file name and a representative sample of file names should contain elements with spaces. The fact that the first sample escapes the extension dot and the second one doesn't makes me think that your syntax specs aren't really thought out. If you come up with a (regular) grammar of your inputs, I'm willing to give your problem further thought.
Some code to base the thinking on:
Option Explicit
Function rndInt(lowerbound, upperbound)
rndInt = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
End Function
Sub shuffleAD(aX)
' Durstenfeld's Permutation Algorithm
Dim J, K, Temp
For J = UBound(aX) To 1 Step -1
K = Int((J + 1) * Rnd) ' random number 0 - J
Temp = aX(J)
aX(J) = aX(K)
aX(K) = Temp
Next
End Sub ' shuffleAD
Class cRGen
Private m_
Public Function init(s)
Set init = Me
ReDim m_(Len(s) - 1)
Dim i
For i = 0 To UBound(m_)
m_(i) = Mid(s, i + 1, 1)
Next
End Function
Public Function getNext(mi, ma)
shuffleAD m_
getNext = Mid(Join(m_, ""), 1, rndInt(mi, ma))
End Function
End Class
Dim goRpl : Set goRpl = Nothing
Function magic(m, w, mi, ma, p, src)
If IsEmpty(ma) Then ma = mi
magic = goRpl.m_dicGens(w).getNext(mi, ma)
End Function
Class cRpl
Private m_fRpl
Private m_r
Public m_dicGens
Private Sub Class_Initialize()
Set m_fRpl = GetRef("magic")
Set m_r = New RegExp
m_r.Pattern = "\\(\w){(\d+)(?:,(\d+))?}"
Set m_dicGens = CreateObject("Scripting.Dictionary")
Set m_dicGens("d") = New cRGen.init("0123456789")
Set m_dicGens("S") = New cRGen.init("abcdefghij")
End Sub
Public Function rpl(s)
Set goRpl = me
rpl = m_r.Replace(s, m_fRpl)
End Function
End Class
Randomize
Dim aTests : aTests = Array( _
"LGP0041_\d{4}.dta" _
, "objd135a_\S{3}.txt" _
, "x_\S{3,8}.txt" _
)
Dim oRpl : Set oRpl = New cRpl
Dim sTest
For Each sTest In aTests
WScript.Echo sTest, "=>", oRpl.rpl(sTest)
Next
output:
cscript 28936688.vbs
LGP0041_\d{4}.dta => LGP0041_4317.dta
objd135a_\S{3}.txt => objd135a_cea.txt
x_\S{3,8}.txt => x_jgcfidh.txt
cscript 28936688.vbs
LGP0041_\d{4}.dta => LGP0041_8054.dta
objd135a_\S{3}.txt => objd135a_eci.txt
x_\S{3,8}.txt => x_ahfgd.txt
This should at least identify the needed components:
generators that deliver strings of specific character sets
a (sorry: global) replace function that maps 'type letters' to generators, handles 'width specs', and build the output
a regular pattern to parse the specs from your inputs

Type Mismatch when trying to duplicate an array

This code
07: ReDim newArray(0)
08: ReDim oldArray(0)
'populating newArray
40: wscript.echo "redimming oldArray to length of " & UBound(newArray)
41: ReDim oldArray(UBound(newArray))
42: wscript.echo UBound(oldArray)
43: oldArray = newArray
results in the following output:
redimming oldArray to length of 19
19
D:\Scripts\test.vbs(43, 2) Microsoft VBScript runtime error: Type mismatch
How can I make a copy of "newArray()"? (Created via this question)
In VBScript, array assignment copies the right hand side value:
>> Dim a : a = Array(1,2,3)
>> Dim b : b = a
>> b(0) = 17
>> WScript.Echo Join(a), Join(b)
>>
1 2 3 17 2 3
(as opposed to other languages where array assignment often means to make an alias of/a reference to the r-value).
So: don't create an array for the l-value, just Dim the name (to allow Option Explicit).
Attempt II:
If you want a copy of a dynamic array, just assign it to a clean/new variable.
BTW: ReDim newArray(0) - creates an array containing one (empty) element; reflect on the difference between size/Num of Elms vs. UBound/Last Index.
Attempt III:
ReDim a(n) ' create array for/with n+1 elements
... fill a ...
Dim b ' plain variant variable
b = a ' copy a (in)to b

vbs execute another vbs script with dictionary as parameter

i am trying to execute a vbscript from another vbscript. The think is, i have to pass a dictionary as parameter, but i always get the same error message.
Here is my code so far:
dim objShell
Set objShell = Wscript.CreateObject("WScript.Shell")
dim dicExp
Set dicExp = CreateObject("Scripting.Dictionary")
dic.add 0, 10
objShell.Run "C:\Users\groeschm\Desktop\ODBCAktuell.vbs " & dicString
But i always get this error message:
Error 800A01C2 - Wrong number of arguments of invalid property assignment.
Greetings,
Michael
You cannot pass an object reference to WScript.Shell.Run. See http://msdn.microsoft.com/en-us/library/d5fk67ky(v=vs.84).aspx, it says the command line argument is a string, and nothing else.
You cannot pass a Scripting.Dictionary reference, nor can you encode that reference into the string argument.
It´s as simple as that!
And even if you could, this would be useless because the called VBS does not share the same global scope as the caller code.
You should consider alternatives to Run. You could put the ODBCAktuell.vbs code into a function, and call that instead. Or you consider ExecuteFile or one of the related intrinsics.
(Without knowing what ODBCAktuell.vbs contains, and without knowing what exactly you are trying to accomplish, it is difficult to advise you further than that.)
There is a similar question based on the same brainbug: Create instance for a class(resides in B.vbs) from another .VBS file
The OT's code is messed up. dicString is undefined. It does not throw the error claimed, but an "Object Required", because the dictionary is named dicExp, not dic.
While TheBlastOne is right to state that you can't pass anything except strings via the command line, the wish to communicate other (more complex) types of data is legitimate. Making numbers or dates from command line args is standard procedure. And: wanting to re-use code via some kind of import/using/include mechanism isn't a brainbug but essential for good programming.
A general approach to serialisation (via strings) is JSON, but it's not easy to use it in VBScript (cf).
The starting point(s) for a 'roll your own' approach for simple cases (dictionaries with numbers/scalars/simple strings as keys and values) is trivial:
Stringify:
cscript passdic.vbs
cscript recdic.vbs "1 2 3 4"
1 => 2
3 => 4
passdic.vbs:
Option Explicit
Function d2s(d)
ReDim a(2 * d.Count - 1)
Dim i : i = 0
Dim k
For Each k In d.Keys()
a(i) = k
i = i + 1
a(i) = d(k)
i = i + 1
Next
d2s = Join(a)
End Function
Function qq(s)
qq = """" & s & """"
End Function
Dim d : Set d = CreateObject("Scripting.Dictionary")
d(1) = 2
d(3) = 4
Dim c : c = "cscript recdic.vbs " & qq(d2s(d))
WScript.Echo c
Dim p : Set p = CreateObject("WScript.Shell").Exec(c)
WScript.Echo p.Stdout.ReadAll()
recdic.vbs:
Option Explicit
Function s2d(s)
Set s2d = CreateObject("Scripting.Dictionary")
Dim a : a = Split(s)
Dim i
For i = 0 To UBound(a) Step 2
s2d.Add a(i), a(i + 1)
Next
End Function
Dim d : Set d = s2d(WScript.Arguments(0))
Dim k
For Each k In d.Keys()
WScript.Echo k, "=>", d(k)
Next
Code re-use:
cscript passdic2.vbs
cscript recdic2.vbs
1 => 2
3 => 4
passdic2.vbs
Option Explicit
Function d2s(d)
ReDim a(d.Count - 1)
Dim i : i = 0
Dim k
For Each k In d.Keys()
a(i) = "cd.Add " & k & "," & d(k)
i = i + 1
Next
d2s = "Function cd():Set cd=CreateObject(""Scripting.Dictionary""):" & Join(a, ":") & ":End Function"
End Function
Dim d : Set d = CreateObject("Scripting.Dictionary")
d(1) = 2
d(3) = 4
CreateObject("Scripting.FileSystemObject").CreateTextFile("thedic.inc").Write d2s(d)
Dim c : c = "cscript recdic2.vbs"
WScript.Echo c
Dim p : Set p = CreateObject("WScript.Shell").Exec(c)
WScript.Echo p.Stdout.ReadAll()
thedic.inc
Function cd():Set cd=CreateObject("Scripting.Dictionary"):cd.Add 1,2:cd.Add 3,4:End Function
recdic2.vbs
Option Explicit
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile("thedic.inc").ReadAll()
Dim d : Set d = cd()
Dim k
For Each k In d.Keys()
WScript.Echo k, "=>", d(k)
Next

Resources