Randomly rearrange letters in a word - vbscript

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.

Related

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)

Excel copy/sort data while counting/removing duplicates

Ok so I've searched and searched and can't quite find what I'm looking for.
I have a workbook and what I'm basically trying to do is take the entries from certain ranges (Sheet1 - E4:E12, E14:E20, I4:I7, I9:I12, I14:I17, & I19:I21) and put them in a separate list on Sheet2. I then want the new list on Sheet2 to be sorted by how many times an entry appeared on Sheet1 as well as display the amount.
example http://demonik.doomdns.com/images/excel.png
Obviously as can be seen by the ranges I listed above, this sample is much smaller lol, was just having trouble trying to figure out how to describe everything and figured an image would help.
Basically I am trying to use VBA (the update would be initialized by hitting a button) to copy data from Sheet1 and put all the ranges into one list in Sheet2 that is sorted by how many times it appeared on Sheet1, and then alphabetically.
If a better discription is needed just comment and let me know, I've always been horrible at trying to describe stuff like this lol.
Thanks in advance!
Another detail: I cant have it search for specific things as the data in the ranges on Sheet1 may change. Everything must be dynamic.
I started out with this data
and used the following code to read it into an array, sort the array, and count the duplicate values, then output the result to sheet2
Sub Example()
Dim vCell As Range
Dim vRng() As Variant
Dim i As Integer
ReDim vRng(0 To 0) As Variant
Sheets("Sheet2").Cells.Delete
Sheets("Sheet1").Select
For Each vCell In ActiveSheet.UsedRange
If vCell.Value <> "" Then
ReDim Preserve vRng(0 To i) As Variant
vRng(i) = vCell.Value
i = i + 1
End If
Next
vRng = CountDuplicates(vRng)
Sheets("Sheet2").Select
Range(Cells(1, 1), Cells(UBound(vRng), UBound(vRng, 2))) = vRng
Rows(1).Insert
Range("A1:B1") = Array("Entry", "Times Entered")
ActiveSheet.UsedRange.Sort Range("B1"), xlDescending
End Sub
Function CountDuplicates(List() As Variant) As Variant()
Dim CurVal As String
Dim NxtVal As String
Dim DupCnt As Integer
Dim Result() As Variant
Dim i As Integer
Dim x As Integer
ReDim Result(1 To 2, 0 To 0) As Variant
List = SortAZ(List)
For i = 0 To UBound(List)
CurVal = List(i)
If i = UBound(List) Then
NxtVal = ""
Else
NxtVal = List(i + 1)
End If
If CurVal = NxtVal Then
DupCnt = DupCnt + 1
Else
DupCnt = DupCnt + 1
ReDim Preserve Result(1 To 2, 0 To x) As Variant
Result(1, x) = CurVal
Result(2, x) = DupCnt
x = x + 1
DupCnt = 0
End If
Next
Result = WorksheetFunction.Transpose(Result)
CountDuplicates = Result
End Function
Function SortAZ(MyArray() As Variant) As Variant()
Dim First As Integer
Dim Last As Integer
Dim i As Integer
Dim x As Integer
Dim Temp As String
First = LBound(MyArray)
Last = UBound(MyArray)
For i = First To Last - 1
For x = i + 1 To Last
If MyArray(i) > MyArray(x) Then
Temp = MyArray(x)
MyArray(x) = MyArray(i)
MyArray(i) = Temp
End If
Next
Next
SortAZ = MyArray
End Function
End Result:
Here is a possible solution that I have started for you. What you are asking to be done gets rather complicated. Here is what I have so far:
Option Explicit
Sub test()
Dim items() As String
Dim itemCount() As String
Dim currCell As Range
Dim currString As String
Dim inArr As Boolean
Dim arrLength As Integer
Dim iterator As Integer
Dim x As Integer
Dim fullRange As Range
Set fullRange = Range("E1:E15")
iterator = 0
For Each cell In fullRange 'cycle through the range that has the values
inArr = False
For Each currString In items 'cycle through all values in array, if
'values is found in array, then inArr is set to true
If currCell.Value = currString Then 'if the value in the cell we
'are currently checking is in the array, then set inArr to true
inArr = True
End If
Next
If inArr = False Then 'if we did not find the value in the array
arrLength = arrLength + 1
ReDim Preserve items(arrLength) 'resize the array to fit the new values
items(iterator) = currCell.Value 'add the value to the array
iterator = iterator + 1
End If
Next
'This where it gets tricky. Now that you have all unique values in the array,
'you will need to count how many times each value is in the range.
'You can either make another array to hold those values or you can
'put those counts on the sheet somewhere to store them and access them later.
'This is tough stuff! It is not easy what you need to be done.
For x = 1 To UBound(items)
Next
End Sub
All that this does so far is get unique values into the array so that you can count how many times each one is in the range.

How to Remove Specific Special Characters

I have a string like X5BC8373XXX. Where X = a special character equals a Square.
I also have some special characters like \n but I remove them, but I can't remove the squares...
I'd like to know how to remove it.
I Found this method:
Dim Test As String
Test = Replace(Mscomm1.Input, Chr(160), Chr(64) 'Here I remove some of the special characters like \n
Test = Left$(Test, Len(Test) -2)
Test = Right$(Test, Len(Test) -2)
This method DOES remove those special characters, but it's also removing my first character 5.
I realize that this method just remove 2 characters from the left and the right,
but how could I work around this to remove these special characters ?
Also I saw something with vblF, CtrlF something like this, but I couldn't work with this ;\
You can use regular expressions. If you want to remove everything that's not a number or letter, you can use the code below. If there are other characters you want to keep, regular expressions are highly customizable, but can get a little confusing.
This also has the benefit of doing the whole string at once, instead of character by character.
You'll need to reference Microsoft VBScript Regular Expressions in your project.
Function AlphaNum(OldString As String)
Dim RE As New RegExp
RE.Pattern = "[^A-Za-z0-9]"
RE.Global = True
AlphaNum = RE.Replace(OldString, "")
End Function
Cleaning out non-printable characters is easy enough. One brute-force but easily customizable method might be:
Private Function Printable(ByVal Text As String) As String
Dim I As Long
Dim Char As String
Dim Count As Long
Printable = Text 'Allocate space, same width as original.
For I = 1 To Len(Text)
Char = Mid$(Text, I, 1)
If Char Like "[ -~]" Then
'Char was in the range " " through "~" so keep it.
Count = Count + 1
Mid$(Printable, Count, 1) = Char
End If
Next
Printable = Left$(Printable, Count)
End Function
Private Sub Test()
Dim S As String
S = vbVerticalTab & "ABC" & vbFormFeed & vbBack
Text1.Text = S 'Shows "boxes" or "?" depending on the font.
Text2.Text = Printable(S)
End Sub
This will remove control characters (below CHR(32))
Function CleanString(strBefore As String) As String
CleanString = ""
Dim strAfter As String
Dim intAscii As Integer
Dim strTest As String
Dim dblX As Double
Dim dblLen As Double
intLen = Len(strBefore)
For dblX = 1 To dblLen
strTest = Mid(strBefore, dblX, 1)
If Asc(strTest) < 32 Then
strTest = " "
End If
strAfter = strAfter & strTest
Next dblX
CleanString = strAfter
End Function

vb6 split space delimited string at every nth space

I have a space delimited string variable. I would like to store the contents of the variable into an array. Using split, I can store every space delimited value in an array. I would prefer if I could separate the string variable at every 7th space. For example, the text could read:
"hello hello hello hello hello hello hello hi hi hi hi hi hi hi hey hey hey hey hey hey hey"
This isn't the actual content of the string, but a simpler version that is easier to read. I want to separate at the places where the words change, or every 7th space. Any help would be greatly appreciated. My current code looks like this, which splits at every space.
ReDim StatsArray(ArrInc)
StatsArray = Split(Stats)
For i = 0 To UBound(StatsArray())
If i > UBound(StatsArray()) Then
ReDim Preserve StatsArray(i + ArrInc)
End If
' MsgBox StatsArray(i) ' When not commented out, this help me check the array
Next
There isn't any built-in function that will do this for you. A couple of solutions come to mind: (1) Do your split, then iterate your array. Concatenate seven array elements in a string variable. Write the result to a new array. Rinse and repeat. (2) Create an Array. Iterate through the string character by character, pushing each character into a variable and keeping track of the spaces you encounter; when you reach the seventh space add an element to your array, copy the variable to it, and clear the variable. Rinse and repeat.
The first one strikes me as a bit faster, but I could be quite wrong about that.
If I understand what you're trying to do, a string of "1234 12345678 123" would get split into 1234, 1234567, 8, 123. Is this correct?
If so, then you can use Regular Expressions to do the split for you.
Function Split7(S As String)
Dim regex As New RegExp
regex.Pattern = "[^ ]{7}"
regex.Global = True
Split7 = Split(regex.Replace(S, "$& "), " ")
End Function
This will insert a space after every 7th character that is not a space. Then use the split function to get the whole thing into an array.
Another stab at it, though I'd probably optimize the ReDim Preserves, doing them in chunks:
Option Explicit
Private Function SplitN( _
ByRef Source As String, _
ByVal Delim As String, _
ByVal N As Long) As String()
'Delim can be multi-character.
'Always returns at least 1-element result,
'even if Source = "".
Dim SearchPos As Long
Dim PartPos As Long
Dim DelimPos As Long
Dim Parts() As String
Dim DelimCount As Long
Dim PartsCount As Long
SearchPos = 1
PartPos = SearchPos
Do
DelimPos = InStr(SearchPos, Source, Delim)
If DelimPos > 0 Then
DelimCount = DelimCount + 1
If DelimCount = N Then
DelimCount = 0
ReDim Preserve Parts(PartsCount)
Parts(PartsCount) = _
Mid$(Source, PartPos, DelimPos - PartPos)
PartsCount = PartsCount + 1
PartPos = DelimPos + Len(Delim)
End If
SearchPos = DelimPos + Len(Delim)
End If
Loop While DelimPos > 0
ReDim Preserve Parts(PartsCount)
Parts(PartsCount) = Mid$(Source, PartPos)
SplitN = Parts
End Function
Private Sub Form_Load()
Dim S As String
Dim Parts() As String
Dim P As Long
S = "hello hello hello hello hello hello hello " _
& "hi hi hi hi hi hi hi " _
& "hey hey hey hey hey hey hey"
Text1.SelStart = 0
Text1.SelText = S & vbNewLine & vbNewLine
Parts = SplitN(S, " ", 7)
Text1.SelText = "Ubound() = " & UBound(Parts) & vbNewLine
For P = 0 To UBound(Parts)
Text1.SelText = Parts(P) & vbNewLine
Next
End Sub

I want to read the last 400 lines from a txt file

I know how to do it in VB.Net but not an idea in vb6.
What I what to achieve is to avoid reading the whole file.
Is that possible?
You could open the file using Random access. Work your way backward a byte at a time, counting the number of carriage return line feed character pairs. Store each line in an array, or something similar, and when you've read your 400 lines, stop.
Cometbill has a good answer.
To open file for Random access:
Open filename For Random Access Read As #filenumber Len = reclength
To get the length of the file in Bytes:
FileLen(ByVal PathName As String) As Long
To read from Random access file:
Get [#]filenumber,<[recnumber]>,<varname>
IMPORTANT: the <varname> from the Get function must be a fixed length string Dim varname as String * 1, otherwise it will error out with Bad record length (Error 59) if the variable is declared as a variable length string like this Dim varname as String
EDIT:
Just wanted to point out that in Dim varname as String * 1 you are defining a fixed length string and the length is 1. This is if you wish to use the read-1-byte-backwards approach. If your file has fixed length records, there is no need to go 1 byte at a time, you can read a record at a time (don't forget to add 2 bytes for carriage return and new line feed). In the latter case, you would define Dim varname as String * X where X is the record length + 2. Then a simple loop going backwards 400 times or untill reaching the beginning of the file.
The following is my take on this. This is more efficient than the previous two answers if you have a very large file, since we don't have to store the entire file in memory.
Option Explicit
Private Sub Command_Click()
Dim asLines() As String
asLines() = LoadLastLinesInFile("C:\Program Files (x86)\VMware\VMware Workstation\open_source_licenses.txt", 400)
End Sub
Private Function LoadLastLinesInFile(ByRef the_sFileName As String, ByVal the_nLineCount As Long) As String()
Dim nFileNo As Integer
Dim asLines() As String
Dim asLinesCopy() As String
Dim bBufferWrapped As Boolean
Dim nLineNo As Long
Dim nLastLineNo As Long
Dim nNewLineNo As Long
Dim nErrNumber As Long
Dim sErrSource As String
Dim sErrDescription As String
On Error GoTo ErrorHandler
nFileNo = FreeFile
Open the_sFileName For Input As #nFileNo
On Error GoTo ErrorHandler_FileOpened
' Size our buffer to the number of specified lines.
ReDim asLines(0 To the_nLineCount - 1)
nLineNo = 0
' Read all lines until the end of the file.
Do Until EOF(nFileNo)
Line Input #nFileNo, asLines(nLineNo)
nLineNo = nLineNo + 1
' Check to see whether we have got to the end of the string array.
If nLineNo = the_nLineCount Then
' In which case, flag that we did so, and wrap back to the beginning.
bBufferWrapped = True
nLineNo = 0
End If
Loop
Close nFileNo
On Error GoTo ErrorHandler
' Were there more lines than we had array space?
If bBufferWrapped Then
' Create a new string array, and copy the bottom section of the previous array into it, followed
' by the top of the previous array.
ReDim asLinesCopy(0 To the_nLineCount - 1)
nLastLineNo = nLineNo
nNewLineNo = 0
For nLineNo = nLastLineNo + 1 To the_nLineCount - 1
asLinesCopy(nNewLineNo) = asLines(nLineNo)
nNewLineNo = nNewLineNo + 1
Next nLineNo
For nLineNo = 0 To nLastLineNo
asLinesCopy(nNewLineNo) = asLines(nLineNo)
nNewLineNo = nNewLineNo + 1
Next nLineNo
' Return the new array.
LoadLastLinesInFile = asLinesCopy()
Else
' Simply resize down the array, and return it.
ReDim Preserve asLines(0 To nLineNo)
LoadLastLinesInFile = asLines()
End If
Exit Function
ErrorHandler_FileOpened:
' If an error occurred whilst reading the file, we must ensure that the file is closed
' before reraising the error. We have to backup and restore the error object.
nErrNumber = Err.Number
sErrSource = Err.Source
sErrDescription = Err.Description
Close #nFileNo
Err.Raise nErrNumber, sErrSource, sErrDescription
ErrorHandler:
Err.Raise Err.Number, Err.Source, Err.Description
End Function

Resources