I want to remove and insert spaces after every byte in a hex string.
E.g.: if the hex string is
str = "0F0D3E"
then I want to insert spaces after every byte to obtain
str = "0F 0D 3E"
and also the reverse (remove spaces from the string so the string becomes "0F0D3E" again).
A quick and naïve approach would be:
Option Explicit
Private Sub Form_Load()
Dim sSrc As String
Dim sTgt As String
sSrc = "0F0D3E"
sTgt = SpaceIt(sSrc)
Debug.Print sTgt
sSrc = UnspaceIt(sTgt)
Debug.Print sSrc
End Sub
Private Function SpaceIt(sSrc As String) As String
Dim i As Long
Dim asSrc() As String
ReDim asSrc(0 To Len(sSrc) \ 2 - 1) As String
For i = 0 To Len(sSrc) - 1 Step 2
asSrc(i \ 2) = Mid$(sSrc, i + 1, 2)
Next i
SpaceIt = Join(asSrc, " ")
End Function
Private Function UnspaceIt(sSrc As String) As String
UnspaceIt = Replace(sSrc, " ", "")
End Function
You can harness the power of the Mid$ statement and the Mid$ function and a little arithmetic to write a function to do this pretty flexibly and efficiently:
Private Function Spacify( _
ByVal Text As String, _
ByVal StrideIn As Long, _
ByVal StrideOut As Long, _
Optional ByVal RTrim As Boolean) As String
Dim OutLen As Long
Dim CopyLen As Long
Dim OutPos As Long
Dim InPos As Long
If StrideIn <= StrideOut Then
OutLen = (Len(Text) \ StrideIn) * StrideOut
If RTrim Then OutLen = OutLen - (StrideOut - StrideIn)
CopyLen = StrideIn
Else
OutLen = ((Len(Text) + (StrideIn - StrideOut)) \ StrideIn) * StrideOut
CopyLen = StrideOut
End If
Spacify = Space$(OutLen)
OutPos = 1
For InPos = 1 To Len(Text) Step StrideIn
Mid$(Spacify, OutPos) = Mid$(Text, InPos, CopyLen)
OutPos = OutPos + StrideOut
Next
End Function
Example:
Private Sub Main()
Dim S As String
S = "0f030d"
Debug.Print """"; S; """"
S = Spacify(S, 2, 3)
Debug.Print """"; S; """"
S = Spacify(S, 3, 2)
Debug.Print """"; S; """"
S = Spacify(S, 2, 3, True)
Debug.Print """"; S; """"; " trimmed"
S = Spacify(S, 3, 2)
Debug.Print """"; S; """"
Debug.Print
S = "abc"
Debug.Print """"; S; """"
S = Spacify(S, 1, 2)
Debug.Print """"; S; """"
S = Spacify(S, 2, 1)
Debug.Print """"; S; """"
S = Spacify(S, 1, 2, True)
Debug.Print """"; S; """"; " trimmed"
S = Spacify(S, 2, 1)
Debug.Print """"; S; """"
Stop
End Sub
Result:
"0f030d"
"0f 03 0d "
"0f030d"
"0f 03 0d" trimmed
"0f030d"
"abc"
"a b c "
"abc"
"a b c" trimmed
"abc"
Try this:
Private Sub Form_Load()
Dim str As String
Dim newstr As String
str = "0F0D3E"
newstr = AddSpaces(str)
str = Replace(newstr, " ", "")
End Sub
Private Function AddSpaces(s As String) As String
Dim i As Integer
For i = 1 To Len(s) Step 2
AddSpaces = AddSpaces & Mid$(s, i, 2) & " "
Next
AddSpaces = Trim(AddSpaces)
End Function
Related
I am using vb6 and trying to generate a random number or String with this format
S1 = "378125649"
I have three requirements NO Duplicates Values & No Zeros & 9 charcters in length
I have approached This two very different ways the random number generator method is failing the FindAndReplace works but is too much code
The questions are
How to fix the GetNumber method code to meet the three requirement?
OR
How to simplify the FindAndReplace code to reflect a completely new sequence of numbers each time?
GetNumber code Below
Private Sub GetNumber()
Randomize
Dim MyRandomNumber As Long 'The chosen number
Dim RandomMax As Long 'top end of range to pick from
Dim RandomMin As Long 'low end of range to pick from
'Dim Kount As Long 'loop to pick ten random numbers
RandomMin = 1
RandomMax = 999999999
MyRandomNumber = Int(Rnd(1) * RandomMax) + RandomMin
lbOne.AddItem CStr(MyRandomNumber) & vbNewLine
End Sub
The FindAndReplace Code Below
Private Sub FindAndReplace()
Dim S4 As String
S4 = "183657429"
Dim T1 As String
Dim T2 As String
Dim J As Integer
Dim H As Integer
J = InStr(1, S4, 2)
H = InStr(1, S4, 8)
T1 = Replace(S4, CStr(J), "X")
T1 = Replace(T1, CStr(H), "F")
If Mid(T1, 8, 1) = "F" And Mid(T1, 2, 1) = "X" Then
T2 = Replace(T1, "F", "8")
T2 = Replace(T2, "X", "2")
End If
tbOne.Text = CStr(J) & " " & CStr(H)
lbOne.AddItem "Original Value " & S4 & vbNewLine
lbOne.AddItem "New Value " & T2 & vbNewLine
End Sub
Here's a way of generating 9-digit random numbers with no zeroes. The basic idea is to build a 9-character string position by position where each position is a random number between 1 and 9. Then each string is added to a collection to remove any duplicates. This code will generate 100,000 unique numbers:
Option Explicit
Private Sub Command1_Click()
Dim c As Collection
Set c = GetNumbers()
MsgBox c.Count
End Sub
Private Function GetNumbers() As Collection
On Error Resume Next
Dim i As Integer
Dim n As String
Randomize
Set GetNumbers = New Collection
Do While GetNumbers.Count < 100000
n = ""
For i = 1 To 9
n = n & Int((9 * Rnd) + 1)
Next
GetNumbers.Add n, n
Loop
End Function
In my testing, this code only generated 2 duplicates for the 100,000 unique numbers returned.
I don't have a VB6 compiler, so I winged it:
Function GetNumber(lowerLimit as Integer, upperLimit As Integer) As Integer
Dim randomNumber As String
Dim numbers As New Collection
Randomize
For i As Integer = lowerLimit To upperLimit
Call numbers.Add(i)
Next
For j As Integer = upperLimit To lowerLimit Step -1
Dim position As Short = Int(((j - lowerLimit)* Rnd) + 1)
randomNumber = randomNumber & numbers(position)
Call numbers.Remove(position)
Next
Return(CInt(randomNumber))
End Function
Use that function by calling for example:
GetNumber(1, 9)
I don't have VB6 on my machines anymore, so here's a solution written in Excel that shuffles the digits in 123456789 using an array.
You should be able to use it with little conversion:
Private Function RndNumber() As String
Dim i, j As Integer
Dim tmp As Variant
Dim digits As Variant
digits = Array("1", "2", "3", "4", "5", "6", "7", "8", "9")
For i = 0 To UBound(digits)
j = Int(9 * Rnd)
tmp = digits(i)
digits(i) = digits(j)
digits(j) = tmp
Next
RndNumber = Join(digits, "")
End Function
Here's a variation to play with that will shuffle an array you pass in and join them together with the specified separator. Note that the arrays being passed in are of variant type so anything can be shuffled. The first array has numbers while the second array has strings:
Private Sub Foo()
Dim digits As Variant
digits = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
Dim rndNnumber As String
RndNumber = ShuffleArrayAndJoin(digits, "")
Debug.Print RndNumber
Dim pets As Variant
pets = Array("cat", "dog", "fish", "hamster")
Dim rndPets As String
rndPets = ShuffleArrayAndJoin(pets, ", ")
Debug.Print (rndPets)
End Sub
Private Function ShuffleArrayAndJoin(ByVal sourceArray As Variant, ByVal separator As String) As String
Dim i, j As Integer
Dim tmp As Variant
For i = 0 To UBound(sourceArray)
j = Int(UBound(sourceArray) * Rnd)
tmp = sourceArray(i)
sourceArray(i) = sourceArray(j)
sourceArray(j) = tmp
Next
ShuffleArrayAndJoin = Join(sourceArray, separator)
End Function
Function GetNumber() As String
Dim mNum As String
Randomize Timer
Do While Len(mNum) <> 9
mNum = Replace(Str(Round(Rnd(Timer), 6)) + Str(Round(Rnd(Timer), 3)), " .", "")
Loop
GetNumber = mNum
End Function
Been clicking a button to load a text box for a couple of minutes, but so far no dupes, and I'd bet money there never will be any..
Well, it solves just 1 problem: it will never ever repeat number
but it has to be 15+ numbers long...
Function genRndNr(nrPlaces) 'must be more then 10
Dim prefix As String
Dim suffix As String
Dim pon As Integer
prefix = Right("0000000000" + CStr(DateDiff("s", "2020-01-01", Now)), 10)
suffix = Space(nrPlaces - 10)
For pon = 1 To Len(suffix)
Randomize
Randomize Rnd * 1000000
Mid(suffix, pon, 1) = CStr(Int(Rnd * 10))
Next
genRndNr = prefix + suffix
End Function
Trying to make the game "21" in visual basic 6, i have everything done but MsgBox is not displaying when its Bust, or Blackjack. Any ideas?
Private Sub cmdCheckScore_Click()
lblPC1.Visible = True
lblPC2.Visible = True
lblPC3.Visible = True
End Sub
Private Sub cmdDrawCard_Click()
If lblDraw1.Caption = "" Then 'Draws 3 random numbers with 3 button clicks
intDraw1 = Int(Rnd * 10 + 1)
lblDraw1.Caption = intDraw1
ElseIf lblDraw2.Caption = "" Then
intDraw2 = Int(Rnd * 10 + 1)
lblDraw2.Caption = intDraw2
ElseIf lblDraw3.Caption = "" Then
intDraw3 = Int(Rnd * 10 + 1)
lblDraw3.Caption = intDraw3
End If
intPlayerScore = intPlayer1 + intPlayer2 + intDraw1 + intDraw2 + intDraw3
intComputerScore = intPC1 + intPC2 + intPC3
If intPlayerScore > 21 Then
MsgBox "Bust!"
ElseIf intPlayerScore = 21 Then
MsgBox "Blackjack!"
End If
End Sub
Private Sub Form_Load()
Randomize
Dim intPlayer1 As Integer
Dim intPlayer2 As Integer
Dim intPlayer3 As Integer
Dim intPC1 As Integer
Dim intPC2 As Integer
Dim intPC3 As Integer
Dim intDraw1 As Integer
Dim intDraw2 As Integer
Dim intDraw3 As Integer
Dim PlayerScore As Integer
Dim ComputerScore As Integer
intDraw1 = 0
intDraw2 = 0
intDraw3 = 0
intPlayer1 = Int(Rnd * 10 + 1)
intPlayer2 = Int(Rnd * 10 + 1)
lblPlayer1.Caption = intPlayer1
lblPlayer2.Caption = intPlayer2
intPC1 = Int(Rnd * 10 + 1)
intPC2 = Int(Rnd * 10 + 1)
intPC3 = Int(Rnd * 10 + 1)
lblPC1.Caption = intPC1
lblPC2.Caption = intPC2
lblPC3.Caption = intPC3
End Sub
I've been trying to figure this out for 2 hours, and still no solution.
I believe your variables are getting created out of scope, and therefore when the click code runs, they're all variants.
Move your declares out of Form_Load to above cmdCheckScore
Dim intPlayer1 As Integer 'at the top of your FORM
Dim intPlayer2 As Integer
Dim intPlayer3 As Integer
Dim intPC1 As Integer
Dim intPC2 As Integer
Dim intPC3 As Integer
Dim intDraw1 As Integer
Dim intDraw2 As Integer
Dim intDraw3 As Integer
Dim PlayerScore As Integer
Dim ComputerScore As Integer 'at the top of your FORM
Private Sub cmdCheckScore_Click()
Next, click off to the left and set a breakpoint on this line to verify the values are getting there!
intPlayerScore = intPlayer1 + intPlayer2 + intDraw1 + intDraw2 + intDraw3
I've been searching Google for awhile and on this site but I can't figure out what &HF7 means? Can someone please explain? Sorry if its a dumb question. I'm very new to this stuff...
Here is the code I'm studying.
Set WshShell = CreateObject("WScript.Shell")
Key = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
DigitalID = WshShell.RegRead(key & "DigitalProductId")
ProductName = "Product Name: " & WshShell.RegRead(Key & "ProductName") & vbNewLine
ProductID = "Product ID: " & WshShell.RegRead(Key & "ProductID") & vbNewLine
ProductKey = "Installed Key: " & ConvertToKey(DigitalID)
ProductID = ProductName & ProductID & ProductKey
If vbYes = MsgBox(ProductId & vblf & vblf & "Save to a file?", vbYesNo + vbQuestion, "Windows Key Information") then
Save ProductID
End if
Function ConvertToKey(Key)
Const KeyOffset = 52
isWin8 = (Key(66) \ 6) And 1
Key(66) = (Key(66) And &HF7) Or ((isWin8 And 2) * 4)
i = 24
Chars = "BCDFGHJKMPQRTVWXY2346789"
Do
Cur = 0
X = 14
Do
Cur = Cur * 256
Cur = Key(X + KeyOffset) + Cur
Key(X + KeyOffset) = (Cur \ 24)
Cur = Cur Mod 24
X = X -1
Loop While X >= 0
i = i -1
KeyOutput = Mid(Chars, Cur + 1, 1) & KeyOutput
Last = Cur
Loop While i >= 0
If (isWin8 = 1) Then
keypart1 = Mid(KeyOutput, 2, Last)
insert = "N"
KeyOutput = Replace(KeyOutput, keypart1, keypart1 & insert, 2, 1, 0)
If Last = 0 Then KeyOutput = insert & KeyOutput
End If
a = Mid(KeyOutput, 1, 5)
b = Mid(KeyOutput, 6, 5)
c = Mid(KeyOutput, 11, 5)
d = Mid(KeyOutput, 16, 5)
e = Mid(KeyOutput, 21, 5)
ConvertToKey = a & "-" & b & "-" & c & "-" & d & "-" & e
End Function
Function Save(Data)
Const ForWRITING = 2
Const asASCII = 0
Dim fso, f, fName, ts
fName = "Windows Key.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile fName
Set f = fso.GetFile(fName)
Set f = f.OpenAsTextStream(ForWRITING, asASCII)
f.Writeline Data
f.Close
End Function
&HF7 is used as a mask here.
The byte in position 66 of the array Key is compared with the byte &HF7
Written in binary form &HF7 becomes 11110111. If you "And" the value of Key(66) with 11110111 then you'll get a new byte made up of all the bits in Key(66) except the bit in the 4th position from the right.
For example if Key(66) is 10101010 then 10101010 And 11110111 will be 10100010.
It's the number 247.
In VBScript, the &H prefix indicates a hexadecimal number, similar to the 0x prefix in C/C++. The number is F7, which is equivalent of the decimal value 247.
It's a public constant: http://www.vbforums.com/showthread.php?277384-VB-Key-COnsts
Typically used to detect modifier keys being held (ctrl, alt etc)
http://microsoft.public.word.vba.general.narkive.com/28vVYW5c/detect-modifier-keys-from-vba
That specific one is Public Const VK_CRSEL which I assume to be Ctrl select.
here is a script which convert string into hex code:
strString = "test"
strHex =""
For i=1 To Len(strString)
strHex = strHex & " " & Hex(Asc(Mid(strString,i,1)))
Next
strHex = Right(strHex,Len(strHex)-1)
WScript.Echo strHex
I want to do a reverse action which converts hex into string, is this possible using vbscript?
VBScript uses "&H" to mark numbers as hexadecimals. So
>> WScript.Echo Chr("&H" & "41")
>>
A
>>
demonstrates the strategy in principle. Demo code:
Option Explicit
Function s2a(s)
ReDim a(Len(s) - 1)
Dim i
For i = 0 To UBound(a)
a(i) = Mid(s, i + 1, 1)
Next
s2a = a
End Function
Function s2h(s)
Dim a : a = s2a(s)
Dim i
For i = 0 To UBound(a)
a(i) = Right(00 & Hex(Asc(a(i))), 2)
Next
s2h = Join(a)
End Function
Function h2s(h)
Dim a : a = Split(h)
Dim i
For i = 0 To UBound(a)
a(i) = Chr("&H" & a(i))
Next
h2s = Join(a, "")
End Function
Dim s : s = "test"
WScript.Echo 0, s
WScript.Echo 1, s2h(s)
WScript.Echo 2, h2s(s2h(s))
output:
0 test
1 74 65 73 74
2 test
Update wrt comment/unicode:
Use AscW/ChrW (VB ref) to deal with UTF 16.
Option Explicit
Function s2a(s)
ReDim a(Len(s) - 1)
Dim i
For i = 0 To UBound(a)
a(i) = Mid(s, i + 1, 1)
Next
s2a = a
End Function
Function s2h(s)
Dim a : a = s2a(s)
Dim i
For i = 0 To UBound(a)
a(i) = Right("0000" & Hex(AscW(a(i))), 4)
Next
s2h = Join(a)
End Function
Function h2s(h)
Dim a : a = Split(h)
Dim i
For i = 0 To UBound(a)
a(i) = ChrW("&H" & a(i))
Next
h2s = Join(a, "")
End Function
Dim s : s = "abcä" & ChrW("&H" & "d98a")
WScript.Echo 0, s
WScript.Echo 1, s2h(s)
WScript.Echo 2, h2s(s2h(s))
In VBScript I'm looking for a function that will return the numbers in the format 1000s or if 1000,000 or greater in millions as follows:
x = 100,000 then return 100k
y = 500,000 then return 500k
z = 5,000,000 then return 5m
q = 25,000,000 then return 25m
Where x, y, z, q are integers.
#van: Working example --
Option Explicit
Function NumFormat(ByRef iNumber, ByRef blnFixed)
Dim sNumber
If iNumber >= 1000000 Then
If NOT blnFixed Then
sNumber = (iNumber / 1000000) & "m"
Else
sNumber = Fix(iNumber / 1000000) & "m"
End If
ElseIf iNumber >= 100000 Then
If NOT blnFixed Then
sNumber = (iNumber / 1000) & "k"
Else
sNumber = Fix(iNumber / 1000) & "k"
End If
ElseIf iNumber >= 10000 Then
If NOT blnFixed Then
sNumber = (iNumber / 1000) & "k"
Else
sNumber = Fix(iNumber / 1000) & "k"
End If
ElseIf iNumber >= 1000 Then
If NOT blnFixed Then
sNumber = (iNumber / 1000) & "k"
Else
sNumber = Fix(iNumber / 1000) & "k"
End If
End If
NumFormat = sNumber
End Function
Response.Write NumFormat(56120000, True) & "<br>"
Response.Write NumFormat(25050000, False) & "<br>"
Response.Write NumFormat(255000, False) & "<br>"
Response.Write NumFormat(9009, True) & "<br>"
Response.Write NumFormat(3000, False) & "<br>"
Option Explicit
Public Function convertAmount(a)
a = CStr(a)
Dim re : Set re = new RegExp
' Replace millions
re.Pattern ="(,\d{3}){2}$"
a = re.replace(a, "m")
' Replace kilo's
re.Pattern =",\d{3}$"
a = re.replace(a, "k")
convertAmount = a
End Function
' Testcode
MsgBox convertAmount("1,234,567")
It could be it wouldn't work for integers, because I never have seen integers with thousand separator formatting. Just place a question mark in the regular expressions behind the comma, and it will also work for numbers without thousand separators. Like:
"(,?\d{3}){2}$" and ",?\d{3}$"
Limitations: No rounding, only trunking of the results