Ok so I'm working on a program that parses input in the textbox and finds a delimiter such as a comma, space, or a line pressed using enter key and extracting each word before each delimiter and posting it in the listbox. I keep getting errors though.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim delimiter As String = ""
Dim oldIndex As Integer = 0
Dim newIndex As Integer = 0
Dim length As Integer = 0
Dim tempString As String = ""
Dim tempWord As String = ""
Dim advanceSize As Integer = 0
If RadioButton1.Checked = True Then
delimiter = ","
advanceSize = 1
tempString = TextBox1.Text
length = tempString.Length
Do While oldIndex < length
newIndex = tempString.IndexOf(delimiter)
tempWord = Mid(tempString, oldIndex, newIndex)
tempWord.Trim()
oldIndex = newIndex + advanceSize
ListBox1.Items.Add(tempWord)
Loop
ElseIf RadioButton2.Checked = True Then
delimiter = vbCrLf
advanceSize = 2
tempString = TextBox1.Text
length = tempString.Length
Do While oldIndex < length
newIndex = tempString.IndexOf(delimiter)
newIndex = tempString.IndexOf(delimiter)
tempWord = Mid(tempString, oldIndex, newIndex)
tempWord.Trim()
oldIndex = newIndex + advanceSize
ListBox1.Items.Add(tempWord)
Loop
ElseIf RadioButton3.Checked = True Then
delimiter = " "
advanceSize = 1
tempString = TextBox1.Text
length = tempString.Length
Do While oldIndex < length
newIndex = tempString.IndexOf(delimiter)
newIndex = tempString.IndexOf(delimiter)
tempWord = Mid(tempString, oldIndex, newIndex)
tempWord.Trim()
oldIndex = newIndex + advanceSize
ListBox1.Items.Add(tempWord)
Loop
Else
Exit Sub
In the first line read, the value of oldindex is zero. The Mid function requires a number greater than zero for the second parameter because, unlike the string.substring method, it is one-based rather than zero-based. The error will be resolved if you initialize oldindex to 1.
Incidentally, the third parameter of mid (and .substring) is length, not an ending index.
May I suggest an alternative which achieves the goal of your question? There is a String.Split function which you can use. It's a bit fiddly, as to split on a string you need to use an array of strings (there can be just one in the array, which is all we need) and you have to specify a StringSplitOptions value, but apart from that it is easy to use:
Private Sub bnSplitData_Click(sender As Object, e As EventArgs) Handles bnSplitData.Click
Dim txt = tbDataToSplit.Text
Dim delimiter As String() = Nothing
' select case true is an easy way of looking at several options:
Select Case True
Case rbCommas.Checked
delimiter = {","}
Case rbNewLines.Checked
delimiter = {vbCrLf}
Case rbSpaces.Checked
delimiter = {" "}
Case Else ' default value
delimiter = {","}
End Select
Dim parts = txt.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
' get rid of the old entries
ListBox1.Items.Clear()
' add the new entries all in one go
ListBox1.Items.AddRange(parts)
End Sub
Please note how I gave the controls (except ListBox1) meaningful names - it makes referring to the correct one much easier.
Related
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)
Below code works great as expected the only downside is its slow because I am using this to search for all the instances of the substring and delete the Entire row if found in any cell of the whole workbook.
Aim is simple just delete the entirerow if the entered string is found in any cell string
Dim wo As Worksheet, ws As Worksheet
Dim I As Long, j As Long, m As Long
Dim toFind As String, testStr As String
Dim pos As Long
Dim lstRow As Long, cutRow As Long
Dim WS_Count As Integer
Dim Cell As Range
Option Compare Text
Option Explicit
Sub SearchDelete()
toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
toFind = Trim(toFind)
j = 0
If toFind = "" Then
MsgBox "Empty String Entered.Exiting Sub Now."
Exit Sub
Else
WS_Count = ActiveWorkbook.Worksheets.Count
'Begin the loop.
For I = 1 To WS_Count
Label1:
For Each Cell In Worksheets(I).UsedRange.Cells
If Trim(Cell.Text) <> "" Then
pos = 0
pos = InStr(1, Trim(Cell.Text), toFind, vbTextCompare)
If pos > 0 Then 'match Found'
cutRow = Cell.Row
Worksheets(I).Rows(cutRow).EntireRow.Delete
j = j + 1
GoTo Label1
Else: End If
Else: End If
Next Cell
Next I
End If
MsgBox "Total " & j & " Rows were deleted!"
End Sub
Individual operations are pretty much always slower than bulk operations and the Range.Delete method is no exception. Collecting the matching rows with a Union method and then performing the removal en masse will significantly speed up the operation.
Temporarily suspending certain application environment handlers will also help things along. You do not need Application.ScreenUpdating active while you are removing rows; only after you have completed the operation.
Option Explicit
Option Compare Text
Sub searchDelete()
Dim n As Long, w As Long
Dim toFind As String, addr As String
Dim fnd As Range, rng As Range
toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
toFind = Trim(toFind)
If Not CBool(Len(toFind)) Then
MsgBox "Empty String Entered.Exiting Sub Now."
GoTo bm_Safe_Exit
End If
'appTGGL bTGGL:=False 'uncomment this line when you have finsihed debugging
With ActiveWorkbook
For w = 1 To .Worksheets.Count
With .Worksheets(w)
Set fnd = .Cells.Find(what:=toFind, lookat:=xlPart, _
after:=.Cells.SpecialCells(xlCellTypeLastCell))
If Not fnd Is Nothing Then
Set rng = .Rows(fnd.Row)
n = n + 1
addr = fnd.Address
Do
If Intersect(fnd, rng) Is Nothing Then
n = n + 1
Set rng = Union(rng, .Rows(fnd.Row))
End If
Set fnd = .Cells.FindNext(after:=fnd)
Loop Until addr = fnd.Address
Debug.Print rng.Address(0, 0)
rng.Rows.EntireRow.Delete
End If
End With
Next w
End With
Debug.Print "Total " & n & " rows were deleted!"
bm_Safe_Exit:
appTGGL
End Sub
Public Sub appTGGL(Optional bTGGL As Boolean = True)
Application.ScreenUpdating = bTGGL
Application.EnableEvents = bTGGL
Application.DisplayAlerts = bTGGL
Application.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
Debug.Print Timer
End Sub
The answer to your question: "How to speed up this code to find and delete rows if a substring is found" is - DON'T repeat the search from the top of the sheet after you found and removed the row!
I would like to replace a comma in between two double quotes.
EXAMPLE:
Replace:
11/18/2015,15:27,1,103,3,,,197179,"Petco, Inc.",Amy,Jr,187.061,452.5,0,0,0,2.419,0,0,37.38,489.88`
With:
11/18/2015,15:27,1,103,3,,,197179,"Petco Inc.",Amy,Jr,187.061,452.5,0,0,0,2.419,0,0,37.38,489.88
NOTE: I still want to keep the bare commas I just want to replace any commas that are inside of the double quote "
I know I can replace the commas by doing this: strText = Replace(strText, ",", "")
but how do I do that in between the two double quotes only and not affect the other commas that are outside of the double quotes.
Tried this thanks to pee2pee but getting an error: Expected identifier
.Pattern = "/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g"
-------------------^
dim re
Set re = New RegExp
With re
.Pattern = "/(""".*?"""|[^""",\s]+)(?=\s*,|\s*$)/g"
.IgnoreCase = False
.Global = False
End With
Set re = Nothing
Thanks
1 - Classic one:
csv = "..." ' your lines
ReDim chars(Len(csv) - 1) 'array for output
wearein = False
For i = 1 To Len(csv)
chars(i-1) = Mid(csv, i, 1)
Select Case chars(i-1)
Case Chr(34) 'we're in
wearein = Not wearein
Case ","
If wearein Then chars(i-1) = ""
End Select
Next
newstr = Join(chars, "")
Response.Write newstr
2 - By using RegExp and a callback function :
Function ReplaceCallback(match, position, all)
ReplaceCallback = Replace(match, ",", "")
End Function
Set re = New RegExp
re.Pattern = """[^""]*,[^""]*"""
re.Global = True
csv = "..." 'your lines
newstr = re.Replace(csv, GetRef("ReplaceCallback")) 'replace done
Response.Write newstr
3 - By mixing MS JScript and VBScript:
<script language="JScript" runat="server">
function removeCommas(text){
return text.replace(/"[^"]*,[^"]*"/g, function(){return arguments[0].replace(/,/g, "")});
}
</script>
<%
csv = "..." 'your lines
Response.Write removeCommas(csv)
%>
The regex pattern you need would be something like
/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g
ONLY and ONLY in this case, you can use:
strText = Replace(strText, ", ", " ")
because you have just a space after the comma you need to replace.
An easy (but probably not that efficient) solution could be going one char at a time changing the comma if you passed an uneven amount of double quotes, finishing after the last double quote.
string origin = ""; //Your string to convert
int lastIndex = origin.LastIndexOf('"');
bool betweenQuotes = false;
for(int i = 0; i < lastIndex; i++)
{
if(origin[i] == '"')
betweenQuotes = !betweenQuotes;
if(origin[i] == ',' && betweenQuotes)
origin[i] = ' ';
}
Edit: You can't set a char like I did in the last row
origin[i] = ' ';
it won't work in c#.
put in that line this instead
origin = origin.Substring(0, i) + " " + origin.Substring(i + 1);
That solution was for C#, so I made a code in VB that does the same thing since as I understood online ASP works (or at least can work) with VB. (Sorry, but it's my first time working with classic asp and VB). But this code in VB is working for me.
Dim origin As String = "11/18/2015,15:27,1,103,3,,,197179,fPetco, Inc.f,Amy,Jr,187.061,452.5,0,0,0,2.419,0,0,37.38,489.88"
Dim lastIndex As Integer = 0
Dim betweenQuotes As Boolean = False
For i As Integer = 0 To origin.Length - 1
If origin(i) = "f" Then
lastIndex = i
End If
Next
For i As Integer = 0 To lastIndex
If origin(i) = "f" Then
betweenQuotes = Not betweenQuotes
End If
If origin(i) = "," AndAlso betweenQuotes Then
origin = origin.Substring(0, i) + " " + origin.Substring(i + 1)
End If
Next
I just replaced the double quotes with the f char since I have no idea how to put special chars in a string in VB. but this code replaces the comma only between the Fs, so it should be ok.
I also made a JS version, cause that would work everywhere on the web doesn't matter what language you used to create the page.
var origin = "";
var lastIndex = 0;
var betweenQuotes = false;
for (var i = 0; i < origin.length ; i++)
if (origin[i] == '"')
lastIndex = i;
for(i = 0; i < lastIndex; i++)
{
if (origin[i] == '"')
betweenQuotes = !betweenQuotes;
if (origin[i] == ',' && betweenQuotes) {
origin = origin.substr(0, i) + " " + origin.substr(i + 1, origin.length - i - 1);
}
}
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.
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.