Ctrl+Backspace in VB6? - vb6

I use the following VB6 code to Ctrl+Backspace words, but it only works if the words are separated by spaces. I need it to work if the words are separated by any special character: . - #, etc.
Public Sub DelLastWord(tb As TextBox)
Dim WordStart As String
Dim Trimmed As String
Dim curpos As Long
curpos = tb.SelStart
Trimmed = Trim$(Left$(tb.Text, curpos))
If LenB(Trimmed) Then
WordStart = InStrRev(Trimmed, Space$(1), Len(Trimmed))
tb.SelStart = WordStart
tb.SelLength = curpos - WordStart
tb.SelText = vbNullString
End If
End Sub
Any suggestions or code someone can give me to take care of special characters?

I would loop backwards from the insertion point until I found a separator character. Something like this:
Public Sub DelLastWord(tb As TextBox)
Dim i As Long
Dim curpos As Long
curpos = tb.SelStart
For i = curpos To 1 Step -1
If isSeparator(Mid(tb.Text, i, 1)) Or i = 1 Then
tb.SelStart = i - 1
tb.SelLength = curpos - i + 1
tb.SelText = vbNullString
Exit Sub
End If
Next
End Sub
Private Function isSeparator(char As String) As Boolean
'if the character is not a letter or number
'then it is a separator
If Asc(char) >= 48 And Asc(char) <= 57 Then Exit Function
If Asc(char) >= 65 And Asc(char) <= 90 Then Exit Function
If Asc(char) >= 97 And Asc(char) <= 122 Then Exit Function
isSeparator = True
End Function

Just replace your InStrRev call with something that finds what you want. Go to the end of the string, loop backwards, and stop at the first "special" character.
Something like this is basic, but it would do the job. I'm sure there's optimizations available, like not using the NonSpecial string and instead checking the ASCII code with math, but you get the point. This way has the benefit that it is easy to read and/or change which characters are special or not.
Public Function FindLastSpecialChar(ByVal Str As String) As Long
Const NonSpecial As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim I As Long
For I = Len(Str) To 1 Step -1
If InStr(NonSpecial, Mid(Str, I, 1)) = 0 Then
FindLastSpecialChar = I
Exit Function
End If
Next
End Function
The above returns 4 for each of the following in the immediate window:
?findlastspecialchar("abc john")
?findlastspecialchar("abc;john")
?findlastspecialchar("abc.john")
?findlastspecialchar("abc+john")

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)

array.slice(start, end) in vbscript?

Anyone have a favorite implementation of the standard (e.g. jscript, javascript) array.slice(start,end) function in vbscript?
It seems to be commonly missed (among vbscript programmers anyway) and sharing a good implementation would help. If one doesn't show up, I guess I'll have to answer my own question and write something.
For completeness, this might be a better version:
Function Slice (aInput, Byval aStart, Byval aEnd)
If IsArray(aInput) Then
Dim i
Dim intStep
Dim arrReturn
If aStart < 0 Then
aStart = aStart + Ubound(aInput) + 1
End If
If aEnd < 0 Then
aEnd = aEnd + Ubound(aInput) + 1
End If
Redim arrReturn(Abs(aStart - aEnd))
If aStart > aEnd Then
intStep = -1
Else
intStep = 1
End If
For i = aStart To aEnd Step intStep
If Isobject(aInput(i)) Then
Set arrReturn(Abs(i-aStart)) = aInput(i)
Else
arrReturn(Abs(i-aStart)) = aInput(i)
End If
Next
Slice = arrReturn
Else
Slice = Null
End If
End Function
This avoids a number of issues with the previous answer:
No consideration of objects in the array
Negative start and end values are allowed; they count backwards from the end
If start is higher than end gives a reversed array subset
The (expensive) redim preserve is not necessary since the array is empty
A defined result is returned (Null) if the input is not an array
Uses the built-in function IsArray instead of string manipulation/comparison on the input
This is one I've used in the past:
Function Slice(arr, starting, ending)
Dim out_array
If Right(TypeName(arr), 2) = "()" Then
out_array = Array()
ReDim Preserve out_array(ending - starting)
For index = starting To ending
out_array(index - starting) = arr(index)
Next
Else
Exit Function
End If
Slice = out_array
End Function
Function Slice(arr, starting, ending)
Dim out_array
If Right(TypeName(arr), 2) = "()" Then
out_array = Array()
If ending=UBound(arr)+1 Then
actending=ending-1
ReDim Preserve out_array(actending - starting)
For index = starting To actending
out_array(index - starting) = arr(index)
Next
Else
ReDim Preserve out_array(ending - starting)
For index = starting To ending
out_array(index - starting) = arr(index)
Next
End If
Else
Exit Function
End If
Slice = out_array
End Function

do while condition vb6

I have a little vb6 program:
Private Sub Form_Load()
Dim varTemp As Variant
Dim string1 As String
Dim x As Integer
x = 0
dialog.Filter = "toate fisierele(*.*) | *.*"
dialog.Flags = cdlOFNAllowMultiselect Or cdlOFNLongNames Or cdlOFNExplorer
'open the window to select files
dialog.ShowOpen
varTemp = Split(dialog.FileName, vbNullChar)
Do While (varTemp(x) <> "")
string1 = varTemp(x)
x = x + 1
Loop
Unload Form1
End
End Sub
I want the Do While to loop until it reaches the end of varTemp. However, when I choose two files from the dialog and "Do While" is hit with x = 3 I get "Run-time error '9': Subscript out of range". What condition should the "Do While" loop have to loop until the end of varTemp? Thank you.
You can use this instead:
Do While x <= UBound(varTemp)
Since varTemp will be an array, this will loop until you hit the last element in the array.
In case the user cancels the selection, and varTemp is empty, you may check for an empty string before looping, like this:
If varTemp <> vbNullString Then
Do While x <= UBound(varTemp)
string1 = varTemp(x)
x = x + 1
Loop
End If

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

How to reduce the decimal length

I want to reduce the decimal length
text1.text = 2137.2198231578
From the above, i want to show only first 2 digit decimal number
Expected Output
text1.text = 2137.21
How to do this.
Format("2137.2198231578", "####.##")
I was about to post use Format() when I noticed p0rter comment.
Format(text1.text, "000.00")
I guess Int() will round down for you.
Been many years since I used VB6...
This function should do what you want (inline comments should explain what is happening):
Private Function FormatDecimals(ByVal Number As Double, ByVal DecimalPlaces As Integer) As String
Dim NumberString As String
Dim DecimalLocation As Integer
Dim i As Integer
Dim LeftHandSide As String
Dim RightHandSide As String
'convert the number to a string
NumberString = CStr(Number)
'find the decimal point
DecimalLocation = InStr(1, NumberString, ".")
'check to see if the decimal point was found
If DecimalLocation = 0 Then
'return the number if no decimal places required
If DecimalPlaces = 0 Then
FormatDecimals = NumberString
Exit Function
End If
'not a floating point number so add on the required number of zeros
NumberString = NumberString & "."
For i = 0 To DecimalPlaces
NumberString = NumberString & "0"
Next
FormatDecimals = NumberString
Exit Function
Else
'decimal point found
'split out the string based on the location of the decimal point
LeftHandSide = Mid(NumberString, 1, DecimalLocation - 1)
RightHandSide = Mid(NumberString, DecimalLocation + 1)
'if we don't want any decimal places just return the left hand side
If DecimalPlaces = 0 Then
FormatDecimals = LeftHandSide
Exit Function
End If
'make sure the right hand side if the required length
Do Until Len(RightHandSide) >= DecimalPlaces
RightHandSide = RightHandSide & "0"
Loop
'strip off any extra didgits that we dont want
RightHandSide = Left(RightHandSide, DecimalPlaces)
'return the new value
FormatDecimals = LeftHandSide & "." & RightHandSide
Exit Function
End If
End Function
Usage:
Debug.Print FormatDecimals(2137.2198231578, 2) 'outputs 2137.21
Looks fairly simple, but I must be missing something subtle here. What about:
Option Explicit
Private Function Fmt2Places(ByVal Value As Double) As String
Fmt2Places = Format$(Fix(Value * 100#) / 100#, "0.00")
End Function
Private Sub Form_Load()
Text1.Text = Fmt2Places(2137.2198231578)
End Sub
This also works in locales where the decimal point character is a comma.

Resources