Count instances of specific string in Email - vba

I've looked for similar questions regarding this with no luck. I currently have working code that looks for a specific instance of string in the email body and subject. Upon finding this string, it has userform that takes it in another direction. My intentions are to have it run through the entire email and count how many times it finds this iteration and give that a callable variable for that userform(popup). Here is my code. It comes back with an error that says "InvalidCastException" so i'm guessing this is a conversion error. Any ideas? Thanks!
Ok so I added your comments together and came up with the following. I'm getting alot of errors, as the regex.Pattern I'm assuming doesn't exist. Any ideas? Also thank you for the literature.
Dim regEx ' Create variable.
Dim numfound As Integer
regEx = New RegExp ' Create a regular expression.
'Here it tells me that the regEx.Patter doesn't exist or Pattern is a member of the regex class
regEx.Pattern = "\*#{9}\*" ' Set pattern.
regEx.IgnoreCase = True ' Set case insensitivity.
regEx.Global = True ' Set global applicability.
If regEx.Execute(mailItem.Body) Then
' Getting a "not declared" runtime what should it be declared a Integer such as Dim numfound as Object
numfound = regEx.count
End If
Did some more digging and basically I'm back where I started with an InvalidCastException,
Conversion from string "111111111
123121233
" to type 'Long' is not valid.
Basically in the body of my test email I had those two strings of numbers and it can't convert them to a string to then run through the regexp iteration. Any ideas?
Dim sBody : sBody = (mailItem.Body) Or (mailItem.Subject) 'This is where is gives me the error
Dim Search : Search = New RegExp
Search.Global = True
Search.Pattern = "\*#{9}\*"
MsgBox(Search.Execute(sBody).Count, MsgBoxStyle.OkOnly)

To get you started, if you want to use a RegExp:
(1) Start your reading here and here
(2) Demo code to give you food for thought:
>> Dim sBody : sBody = "Three instances of ###: ### and a part of ####."
>> Dim Search : Set Search = New RegExp
>> Search.Global = True
>> Search.Pattern = "#{3,3}"
>> WScript.Echo Search.Execute(sBody).Count
>>
3
>>

The easiest way to do this would be just create an instance of RegEx and use it to parse the Item.Body.
Set Search = new RegExp
Search.IgnoreCase = True
Search.Global = True
Search.Pattern = "\*#{9}\*"
If Search.Test(Item.Body) Then
'will hold how many times it has been found
numFound = Search.Count
End If
Here is a link with a bit more information on RegExp http://msdn.microsoft.com/en-us/library/ms974570.aspx

Related

Block Finder - Like Function

I have a large string (more than 255 char) called strBlockText. This string includes random text and block numbers. The block numbers should to be in the format ###Block####-## (IE: 245Block6533-56) but sometimes someone enters the wrong block number format in the text - for example ##Block####-## or ###Block###-## or ##Block###-##...etc.
**Note, this is for plain text only.
I want to write a function that will be able to state, "Wrong block number format identified." when the block number is fat fingered.
This is the text I'm using as a sample:
This is a Test that we need to figure out why this isn’t working.
24Block1234-23 This is a Test that we need to figure out why this
isn’t working. 245Block4234-14 This is a Test that we need to figure
out why this isn’t working. This is a Test that 245Block6533-56 we
need to figure out why this isn’t working.
This is the code...that I feel should work but isn't:
Dim strBlockText As String
Dim strBlockCheck As String
If (((strBlockText Like "*##Block####-##*") or _
(strBlockText Like "*###Block###-##*") or _
(strBlockText Like "*##Block###-##*")) And _
(Not strBlockText Like "*###Block####-##*")) Then
strBlockCheck = "Wrong block number format identified."
Else
strBlockCheck = "Block number format acceptable."
End If
Would it be better to use a regex for this instead of like?...is there a reason like isn't working?
Consider this Sub using RegExp object with late binding:
Sub testRegExp2(strS)
Dim regexOne As Object, Matches As Object, Match As Object
'Set regexOne = New RegExp
Set regexOne = CreateObject("VBScript.RegExp")
regexOne.Pattern = "[0-9]+Block[0-9]+-[0-9]+"
regexOne.Global = True
Set Matches = regexOne.Execute(strS)
For Each Match In Matches
If Not Match Like "###Block####-##" Then
Debug.Print "Wrong block number format identified: " & Match
Else
Debug.Print "Block number format acceptable: " & Match
End If
Next
End Sub

Searching Strings from a split list

Attempting to split and store strings from a listbox and search then search the contents of the text file I have stored them to, hopefully sorting them in different categories,
firstly I am getting an "Object reference not set to an instance of an object." error with this
Dim variable As String = Nothing
If listArray.SelectedIndex > 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
Dim part As String() = variable.Split(New Char() {","c})
Dim line As String
For Each line In part
MessageBox.Show(line)
and secondly, would this be the right code to use for searching those separated strings?
For count As Integer = 0 To Logbook.listArray.Items.Count - 1
Dim searchIndex As String = Logbook.listArray.Items(count).ToString
If searchIndex.Contains(indexSearch.Text) Then
Logbook.listArray.SetSelected(0, True)
End If
Next
I'm pretty new to StackOverflow, my apologies if i'm not up to date with the website etiquette.
am getting an "Object reference not set to an instance of an object."
I guess you don't know that the first item is at index 0 and that SelectedIndex returns -1 if there is no item selected. That's why following code throws that exception:
Dim variable As String = Nothing
If listArray.SelectedIndex > 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
Dim part As String() = variable.Split(New Char() {","c}) ' <--- variable Nothing if first item selected
Then you just have to use <> -1 or >= 0:
Dim variable As String = Nothing
If listArray.SelectedIndex >= 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
According to the second part of the question(always ask only once), you haven't provided enough informations to understand what you want and what doesn't work with your code.

How to make string.contains work with a list

So I have this bot I'm making for someone that filters out curse words in a skype chat.
Instead of making it so my code is really long I want it so there is a huge list of curse words already loaded for example:
If Msg.Contains("swear1") Or Msg.Contains("swear2") Then
c.SendMessage("{---------Bot----------}" + vbNewLine + "DO NOT SWEAR!" + vbNewLine + "{-------------------------------------------}")
End If
I've tried creating an array and a string holding multiple values and didn't really work out too good as it didn't execute the function after someone said the trigger word. So I wanted to know if there is a way I can hold a huge list of curse words in one whatever without using
Msg.Contains("swear1")
Or
Msg.Contains("swear2")
etc etc, so everything would be held in one bit.
Any help would be appreciated :)
You use a Collection of Swear words and check the string against that. The .Any method takes the array and internally creates a For/loop with the word being the variable name for this loop and represents each string in the the array to test with our SwearWords.Contains(word) boolean expression, and if any of the expressions equates to True then it returns True.
Dim swearWordExists As Boolean = False
Dim msg As String = "swear1! has a swear word with extra text but still found"
Dim SwearWords As New List(Of String)
' fill it with your swear words
SwearWords.AddRange(New String() {"swear1", "swear2", "etc..."})
' then
If Not msg.Contains(" ") Then
' msg only has one word so check it
If SwearWords.Contains(msg) OrElse SwearWords.Any(Function(words) msg.Contains(words)) Then
swearWordExists = True
End If
Else
Dim words = Regex.Split(msg, "\W")
If Not words.Any(Function(word) SwearWords.Contains(word)) Then
If words.Any(Function(word) SwearWords.Any(Function(swear) word.Contains(swear))) Then
swearWordExists = True
End If
Else
swearWordExists = True
End If
End If
If swearWordExists Then
MessageBox.Show("Why are you swearing?")
End If
An easy but not super performant way would be to convert your string to a list then use the list intersect functionality
http://msdn.microsoft.com/en-us/library/vstudio/bb910215(v=vs.90).aspx
You could condense your code like this
Dim swears = New List(Of [String])() From {"swear1", "swear2"}
If Regex.IsMatch("[your message]", String.Format("({0})", String.Join("|", swears))) Then
MsgBox("Don't swear!")
End If
Where swears would be your list of all swears you don't want someone to say
What it does is it takes all strings in 'swears' and puts them into this format: (swear1|swear2) then regex will see if your message contains either 'swear1' or 'swear2' et cetera if you have more.

VBNET Reading a specific column on a line in a text file

I have saved written a text file and it currently reads:
"first","surname","pass"
I want to read the password column so the 3rd one and define that as a variable. Its basically for a login, if pass in text file matches the entered pass (from user).
I have searched for about an hour now and no luck. Could someone guide me to a correct path.
Thanks.
Simple example of reading a small file line by line and splitting each one into fields:
' get the values from the user somehow:
Dim first As String = "James"
Dim surname As String = "Bond"
Dim pass As String = "007"
Dim validated As Boolean = False ' assume wrong until proven otherwise
' check the file:
Dim fileName As String = "c:\some folder\path\somefile.txt"
Dim lines As New List(Of String)(System.IO.File.ReadAllLines(fileName))
For Each line As String In lines
Dim values() As String = line.Split(",")
If values.Length = 3 Then
If values(0).Trim(Chr(34)) = first AndAlso
values(1).Trim(Chr(34)) = surname AndAlso
values(2).Trim(Chr(34)) = pass Then
validated = True
Exit For
End If
End If
Next
' check the result
If validated Then
MessageBox.Show("Login Successful!")
Else
MessageBox.Show("Login Failed!")
End If
If this is a CSV file, as seems to be the case, then the easiest way to read it will be with the TextFieldParser class. The MSDN already provides an excellent example for how to use it to read a CSV file, so I won't bother reproducing it here.

Lowercase the first word

Does anybody know how to lowercase the first word for each line in a textbox?
Not the first letter, the first word.
I tried like this but it doesn't work:
For Each iz As String In txtCode.Text.Substring(0, txtCode.Text.IndexOf(" "))
iz = LCase(iz)
Next
When you call Substring, it is making a copy of that portion of the string and returning it as a new string object. So, even if you were successfully changing the value of that returned sub-string, it still would not change the original string in the Text property.
However, strings in .NET are immutable reference-types, so when you set iz = ... all you are doing is re-assigning the iz variable to point to yet another new string object. When you set iz, you aren't even touching the value of that copied sub-string to which it previously pointed.
In order to change the value of the text box, you must actually assign a new string value to its Text property, like this:
txtCode.Text = "the new value"
Since that is the case, I would recommend building a new string, using a StringBuilder object, and then, once the modified string is complete, then set the text box's Text property to that new string, for instance:
Dim builder As New StringBuilder()
For Each line As String In txtCode.Text.Split({Environment.NewLine}, StringSplitOptions.None)
' Fix case and append line to builder
Next
txtCode.Text = builder.ToString()
The solutions here are interesting but they are ignoring a fundamental tool of .NET: regular expressions. The solution can be written in one expression:
Dim result = Regex.Replace(txtCode.Text, "^\w+",
Function (match) match.Value.ToLower(), RegexOptions.Multiline)
(This requires the import System.Text.RegularExpressions.)
This solution is likely more efficient than all the other solutions here (It’s definitely more efficient than most), and it’s less code, thus less chance of a bug and easier to understand and to maintain.
The problem with your code is that you are running the loop only on each character of the first word in the whole TextBox text.
This code is looping over each line and takes the first word:
For Each line As String In txtCode.Text.Split(Environment.NewLine)
line = line.Trim().ToLower()
If line.IndexOf(" ") > 0 Then
line = line.Substring(0, line.IndexOf(" ")).Trim()
End If
// do something with 'line' here
Next
Loop through each of the lines of the textbox, splitting all of the words in the line, making sure to .ToLower() the first word:
Dim strResults As String = String.Empty
For Each strLine As String In IO.File.ReadAllText("C:\Test\StackFlow.txt").Split(ControlChars.NewLine)
Dim lstWords As List(Of String) = strLine.Split(" ").ToList()
If Not lstWords Is Nothing Then
strResults += lstWords(0).ToLower()
If lstWords.Count > 1 Then
For intCursor As Integer = 1 To (lstWords.Count - 1)
strResults += " " & lstWords(intCursor)
Next
End If
End If
Next
I used your ideas guys and i made it up to it like this:
For Each line As String In txtCode.Text.Split(Environment.NewLine)
Dim abc() As String = line.Split(" ")
txtCode.Text = txtCode.Text.Replace(abc(0), LCase(abc(0)))
Next
It works like this. Thank you all.