CountFields is a very slow function. It’s also possible that it’s doing it every time through the For Next loop. So at a minimum do that before the loop.
On another note though, I’m confused on why you do the split on chr(13) and then use CountFields on the TextArea. It seems redundant.
dim myArray() as string = TextArea1.Text.split(chr(13))
for each s as string in myArray
if s.instr(TextField1.text) > 0 then
ItemFound = true
exit
next
That should be faster. There’s probably an even faster way.
I have a list of strings about 2500, that consists of names, email addresses and Telephone numbers in a TextArea.
I have a pushbutton with the following code to search for the string that contains, lets say, the email address.
Dim ItemFound as Boolean
Dim i as Integer
Dim myArray() as String
myArray = Split(TextArea1.Text, Chr(13))
For i = 0 to CountFields(TextArea1.Text, Chr(13))
if Instr(myArray(i), TextField1.Text) > 0 then
ItemFound = True
exit
end if
next
If ItemFound = True then
TextField1.Text = myArray(i)
else
TextField1.Text = TextField1.Text + " was not found"
end if
It takes about 60 seconds to find a string that is close to the bottom of the TextArea, how can I speed this up?
Thanks Lennox[/quote]
Instant :
dim Position as integer = instr(TextArea1.Text,"Needle")
if Position = 0 then return // Not found
dim Endline as integer = instr( instr(TextArea1.Text,"Needle"),TextArea1.Text,chr(13)) // End of line
//Find preceding EndOfLine
While mid(TextArea1.Text,Position,1) <> chr(13)
Position = Position-1
system.DebugLog str(Position)
Wend
Position = Position+1
dim result as string = Mid(TextArea1.Text,Position,Endline-Position)
Msgbox str(Position)+" "+str(Endline)+" "+Result
This displays the line in which is the term searched for.
dim pattern as string = _
"^.*\\Q" + TextField1.Text.ReplaceAllB( "\\E", "\\\\EE\\Q" ) + "\\E.*$"
dim rx as new RegEx
rx.SearchPattern = pattern
dim match as RegExMatch = rx.Search( TextArea1.Text )
if match is nil then
TextField1.Text = TextField1.Text + " was not found"
else
TextField1.Text = match.SubExpressionString( 0 )
end if
If you are on PC the EndOfLine in TextArea is probably not chr(13), so the routine that seeks the previous line end indeed never ends. If Kem’s code works for you that is perfect.
I created what I posted on Mac, and verified it worked.
chr(13)+chr(10) will certainly not work, since there is no chr(10) in a Mac TextArea.
I slightly modified the code so it does not go into an endless loop, and also placed a beep if for some reason the TextArea does not contain any carriage return, which may very well be the issue you have. What I posted was based on the description of the OP, who has thousand of lines, all separated by chr(13). Incidentally, that is also the case for Bob’s code.
[code] if instr(TextArea1.Text,chr(13)) = 0 then beep
dim Position as integer = instr(TextArea1.Text,“Needle”) // We are looking for Needle, case insensitive
if Position = 0 then return // Not found
dim Endline as integer = instr( instr(TextArea1.Text,“Needle”),TextArea1.Text,chr(13)) // End of line
//Find preceding EndOfLine
While mid(TextArea1.Text,Position,1) <> chr(13) and Position > 0
Position = Position-1
system.DebugLog str(Position)
Wend
Position = Position+1
dim result as string = Mid(TextArea1.Text,Position,Endline-Position)
Msgbox str(Position)+" “+str(Endline)+” "+Result[/code]
You got to understand this was in no way intended as a bullet proof method, but rather a principle to apply to have the fastest result possible. Placing error checking like making sure the Position variable does not go negative or making sure there are chr(13) in the text are just examples of what needs to be done to get to a polished result.
This works on Windows
modified Michel Bujardet Code
TextArea1.Text = ReplaceAll(TextArea1.Text, EndOfLine, Chr(13))
dim Position as integer = instr(TextArea1.Text, TextField1.Text)
if Position = 0 then return // Not found
dim Endline as integer = instr( instr(TextArea1.Text, TextField1.Text), TextArea1.Text, Chr(13)) // End of line
//Find preceding EndOfLine
While mid(TextArea1.Text, Position,1) <> chr(13)
Position = Position-1
system.DebugLog str(Position)
Wend
Position = Position+1
dim result as string = Mid(TextArea1.Text, Position, Endline-Position)
TextField1.Text = Result
If Keyboard.AsyncControlKey or IsContextualClick then
// from Kem Tekinay’s Code
'MsgBox “KT”
// https://forum.xojo.com/17526-help-speeding-up-a-search/0#p145182
dim pattern as string = _
"^.*\\Q" + TextField1.Text.ReplaceAllB( "\\E", "\\\\EE\\Q" ) + "\\E.*$"
dim rx as new RegEx
rx.SearchPattern = pattern
dim match as RegExMatch = rx.Search( TextArea1.Text )
if match is nil then
TextField1.Text = TextField1.Text + " was not found"
else
TextField1.Text = match.SubExpressionString( 0 )
end if
else
// modified Michel Bujardet’s Code
'MsgBox “MB”
// https://forum.xojo.com/17526-help-speeding-up-a-search/0#p145182
TextArea1.Text = ReplaceAll(TextArea1.Text, EndOfLine, Chr(13))
dim Position as integer = instr(TextArea1.Text, TextField1.Text)
if Position = 0 then return // Not found
dim Endline as integer = instr( instr(TextArea1.Text, TextField1.Text), TextArea1.Text, Chr(13)) // End of line
//Find preceding EndOfLine
While mid(TextArea1.Text, Position,1) <> chr(13)
Position = Position-1
system.DebugLog str(Position)
Wend
Position = Position+1
dim result as string = Mid(TextArea1.Text, Position, Endline-Position)
TextField1.Text = Result
[quote=145403:@Kem Tekinay]If the found text is on the first line, this will go into an endless loop, won’t it? Seems like it should be:
//Find preceding EndOfLine
While Position > 0 and mid(TextArea1.Text, Position,1) <> chr(13)
Position = Position-1
system.DebugLog str(Position)
Wend
[/quote]