How to loop through text boxes and verify if there are duplicate values? - vb.net

I'm trying to setup a function that sends a mail to a defined list of recipients.
Each recipient is fetched from a textbox. The problem is that I want to identify if there are any duplicate values and exclude them when sending the email.
As an example, if textbox1 has the same value as textbox2, don't include textbox1 value in the recipients list.
I've tried with the following sub
Private Sub CheckDuplicates()
Dim x As Long
Dim y As Long
Dim User() As TextBox = {Mail_user1, Mail_user2, Mail_user3, Mail_user4, Mail_user5, Mail_user6, Mail_user7, Mail_user8, Mail_user9, Mail_user10, Mail_user11, Mail_user12, Mail_user13, Mail_user14, Mail_user15, Mail_user16, Mail_user17, Mail_user18, Mail_user19, Mail_user20, Mail_user21, Mail_user22, Mail_user23, Mail_user24, Mail_user25, Mail_user26, Mail_user27, Mail_user28, Mail_user29, Mail_user30}
For x = 1 To 30 - 1
For y = x + 1 To 30
If User(x).Text = User(y).Text Then
User(y).Text = ""
End If
Next
Next
End Sub
The issue is that I get the following error when I want to send the mail:
Index was outside the bounds of the array.
And the mail sub looks like this:
Public Function AddRecipients(mail As outlook.MailItem) As Boolean
Dim retValue As Boolean = False
Dim recipients As outlook.Recipients = Nothing
Dim recipientTo As outlook.Recipient = Nothing
Dim recipientCC As outlook.Recipient = Nothing
Dim recipientBCC As outlook.Recipient = Nothing
Try
recipients = mail.Recipients
' check if there are any recipients and remove them
While recipients.Count > 0
recipients.Remove(1)
End While
' new recipients list
CheckDuplicates()
'------------------CC section---------------------------
recipientCC = recipients.Add("someemail#test.com")
recipientCC.Type = outlook.OlMailRecipientType.olCC
'hidden recipients section
' recipientBCC = recipients.Add("")
' recipientBCC.Type = outlook.OlMailRecipientType.olBCC
retValue = recipients.ResolveAll()
Catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.Message)
Finally
If Not IsNothing(recipientBCC) Then Marshal.ReleaseComObject(recipientBCC)
If Not IsNothing(recipientCC) Then Marshal.ReleaseComObject(recipientCC)
If Not IsNothing(recipientTo) Then Marshal.ReleaseComObject(recipientTo)
If Not IsNothing(recipients) Then Marshal.ReleaseComObject(recipients)
End Try
Return retValue
End Function
Private Sub MailTime()
Dim OTmail As outlook.MailItem
Dim AppOutlook As New outlook.Application
Try
OTmail = AppOutlook.CreateItem(outlook.OlItemType.olMailItem)
'add users from AddRecipients
AddRecipients(OTmail)
OTmail.Subject = "Test OT mail"
OTmail.Body = "Test Ot mail"
OTmail.BodyFormat = outlook.OlBodyFormat.olFormatHTML
OTmail.Display()
Catch ex As Exception
MessageBox.Show("Could not send, resolve the errors !")
MessageBox.Show(ex.ToString)
Finally
OTmail = Nothing
AppOutlook = Nothing
End Try
End Sub

This will loop through all the TextBoxes and get a Distinct list for you.
Private Function uniqueRecipients() As List(Of String)
Dim recipients As List(Of String) = New List(Of String)
For Each ctrl As TextBox In Me.Controls.OfType(Of TextBox)
recipients.Add(ctrl.Text)
Next
Return recipients.Distinct.ToList
End Function
Private Sub Button26_Click(sender As Object, e As EventArgs) Handles Button26.Click
Try
Dim myRecips As List(Of String) = uniqueRecipients()
Dim oneLine As String = Strings.Join(myRecips.Where(Function(s) Not String.IsNullOrEmpty(s)).ToArray(), ";")
'send mail
Catch ex As Exception
MessageBox.Show(String.Concat("An error occurred: ", ex.Message))
End Try
End Sub

Use right tool type for the job - HashSet(Of String), Enumerable.ToHashSet Method
Private Function GenerateMailRecipientsFrom(textboxes As IEnumerable(Of TextBox)) As String
Dim uniqueRecipients = textboxes.
Select(Function(textbox) textbox.Text).
Where(Function(text) String.IsNullOrWhiteSpace(text) = False).
ToHashSet()
Return String.Join(";", uniqueRecipients)
End Function
HashSet accepts only unique values.
Then use a collection of all textboxes on the form
Dim mailTo As String = GenerateMailRecipientsFrom(Me.Controls.OfType(Of TextBox))
When you have predefined collection of textboxes you can still use the same method
Dim userMailTextBoxes As textBox() = { Mail_user1, Mail_user2, .. }
Dim mailTo As String = GenerateMailRecipientsFrom(userMailTextBoxes)

Nice one ! #Fabrio thanks for the code and explanation. As a side note, I have tried to load the unique values into a listbox and then insert them into outlook email while using this method:
Dim x As Long
For x = 0 To ListBox1.Items.Count - 1
If ListBox1.Items.Item(x) <> "" Then
recipientTo = recipients.Add(ListBox1.Items.Item(x))
recipientTo.Type = outlook.OlMailRecipientType.olTo
End If
Next
Worked like a charm :)

Related

How to check if Variable value is increaseing vb.net?

Hi I have listview and lable ,the lable is showing how many items in the listview
I want if the lable is increased will show msgbox
* may be it will increased alot such as 100 or 1 whatever
* It will execute the command just one if the value is increased
* it must be execute the msgbox any time if the value is increased
I'm sorry for my bad language
thank you
the code :
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim b As String = New WebClient().DownloadString(TextBox2.Text + "/Getinfo.php")
Dim mc As MatchCollection = Regex.Matches(b, "(\w+):")
For Each x As Match In mc
Dim infoName As String = x.Groups(1).Value
Try
Dim download As String = New WebClient().DownloadString(TextBox2.Text + "/sender/info/" & infoName & "/info.txt")
Dim f As String() = download.Split(":")
Dim ls As New ListViewItem
ls.Text = infoName
For Each _x As String In f
ls.SubItems.Add(_x)
Next
Dim hTable As Hashtable = New Hashtable()
Dim duplicateList As ArrayList = New ArrayList()
Dim itm As ListViewItem
For Each itm In ListView1.Items
If hTable.ContainsKey(itm.Text) Then 'duplicate
duplicateList.Add(itm)
Else
hTable.Add(itm.Text, String.Empty)
End If
Next
'remove duplicates
For Each itm In duplicateList
itm.Remove()
Next
ListView1.Items.Add(ls)
'here I want to excute the command if the value is increased but it's timer and the code will be execute every time
Catch
End Try
Next
End Sub
At the top of your function do
Dim oldlength = ListView1.Items.Count
At the bottom do
If oldlength < ListView1.Items.Count Then
'here I want to excute the command if the value is increased
End If
I'm pretty sure that your MessageBox isn't really what you want but a debugging example because you think if you can get the MessageBox at the right time you've solved one of your problems (which is true).

vba cast variant listbox / Objects

I got an issue with "casting" variants to defined objects.
At runtime my variant variable is of type "Variant/Object/Listbox", which i then want to set to a ListBox variable to route it as a parameter to another function (GetSelected) that requires a Listbox object.
But I get the error 13: types incompatible on command "Set lst = v".
Any ideas how to get it working?
Code:
Function GetEditableControlsValues(EditableControls As Collection) As Collection
'Gibt die Werte der editierbaren Felder zurück.
Dim v As Variant
Dim coll As New Collection
Dim lst As ListBox
For Each v In EditableControls
If TypeName(v) = "ListBox" Then
Set lst = v 'Fehler 13: Typen unverträglich. v zur Laufzeit: Variant/Object/Listbox.
coll.Add GetCollectionString(GetSelected(lst))
Else
coll.Add v.Value
End If
Next
End Function
This is what I have so far:
Imagine that you have a module with the following code in it:
Option Explicit
Public Sub TestMe()
Dim colInput As New Collection
Dim colResult As Collection
Dim lngCount As Long
Dim ufMyUf As UserForm
Set ufMyUf = UserForm1
Set colInput = GetListBoxObjects(ufMyUf)
For lngCount = 1 To colInput.Count
Debug.Print colInput(lngCount).Name
Next lngCount
End Sub
Function GetListBoxObjects(uf As UserForm) As Collection
Dim colResult As New Collection
Dim objObj As Object
Dim ctrCont As Control
For Each ctrCont In uf.Controls
If LCase(Left(ctrCont.Name, 7)) = "listbox" Then
Set objObj = ctrCont
colResult.Add objObj
End If
Next ctrCont
Set GetListBoxObjects = colResult
End Function
If you run TestMe, you would get a collection of the ListBox objects. Anyhow, I am not sure how do you pass them to the collection function, thus I have decided to iterate over the UserForm and thus to check all of the objects on it.
Cheers!
I had problems with casting controls myself and didn't find a general solution that I could use easy.
Eventually I found the way to do it: store as "Object" makes it easy to convert to whatever type the control actually is.
I tested (and use) it
The sub below shows that it works (here : 1 TextBox; 1 ListBox; 1 ComboBox; 1 CommandButton on a worksheet)
Sub Test_Casting()
Dim lis As MSForms.ListBox
Dim txt As MSForms.TextBox
Dim btn As MSForms.CommandButton
Dim com As MSForms.ComboBox
Dim numObjects As Integer: numObjects = Me.OLEObjects.Count
Dim obj() As Object
ReDim obj(1 To numObjects) As Object
Dim i As Integer: i = 0
Dim cttl As OLEObject
For Each ctrl In Me.OLEObjects
i = i + 1
Set obj(i) = ctrl.Object
Next ctrl
Dim result As String
For i = 1 To numObjects
If TypeOf obj(i) Is MSForms.ListBox Then
Set lis = obj(i): result = lis.Name
ElseIf TypeOf obj(i) Is MSForms.TextBox Then
Set txt = obj(i): result = txt.Name
ElseIf TypeOf obj(i) Is MSForms.CommandButton Then
Set btn = obj(i): result = btn.Name
ElseIf TypeOf obj(i) Is MSForms.ComboBox Then
Set ComboBox = obj(i): result = com.Name
Else
result = ""
End If
If (Not (result = "")) Then Debug.Print TypeName(obj(i)) & " name= " & result
Next i
For i = 1 To numObjects
Set lis = IsListBox(obj(i))
Set txt = IsTextBox(obj(i))
Set btn = IsCommandButton(obj(i))
Set com = IsComboBox(obj(i))
result = ""
If (Not (lis Is Nothing)) Then
result = "ListBox " & lis.Name
ElseIf (Not (txt Is Nothing)) Then
result = "TexttBox " & txt.Name
ElseIf (Not (btn Is Nothing)) Then
result = "CommandButton " & btn.Name
ElseIf (Not (com Is Nothing)) Then
result = "ComboBox " & com.Name
End If
Debug.Print result
Next i
End Sub
Function IsListBox(obj As Object) As MSForms.ListBox
Set IsListBox = IIf(TypeOf obj Is MSForms.ListBox, obj, Nothing)
End Function
Function IsTextBox(obj As Object) As MSForms.TextBox
Set IsTextBox = IIf(TypeOf obj Is MSForms.TextBox, obj, Nothing)
End Function
Function IsComboBox(obj As Object) As MSForms.ComboBox
Set IsComboBox = IIf(TypeOf obj Is MSForms.ComboBox, obj, Nothing)
End Function
Function IsCommandButton(obj As Object) As MSForms.CommandButton
Set IsCommandButton = IIf(TypeOf obj Is MSForms.CommandButton, obj, Nothing)
End Function
One use for it is a class for handling events in one class.
Private WithEvents intEvents As IntBoxEvents
Private WithEvents decEvents As DecBoxEvents
Private genEvents As Object
Private genControl as OLEobject
Public sub Delegate(ctrl As OLEObject)
set genControl = ctrl
' Code for creating intEvents or decEvents
if .... create intevents.... then set genEvents = new IntEvents ' pseudo code
if .... create decevents.... then set genEvents = new DecEvents ' pseudo code
end sub
I hope this helps others that struggle with casting controls

Page redirected too many times ASP.NET

Dear StackOverflow community,
I am still new with ASP.NET and playing have been playing around and I've encountered an error to authenticate my login where it shows up an error like "Page redirected too many times" and it happen something that are keep looping and I can't figure it out after 2 days.
I've implemented my login using header.acsx so it can be a global authentication to all page.
Here is the code of head.vb:
If String.IsNullOrEmpty(Session(GetSessionKey("UserName"))) Then
Dim userName As String = HttpContext.Current.User.Identity.Name.Split("\")(1)
SessionInitialiser(userName)
End If
Response.Redirect("~/EventRegistration.aspx")
Page_Load function:
Dim adserv As New ActiveDirectory()
Dim userDetails As WebServiceUserPrincipal = adserv.Getuser(userName)
Dim userGroups As String() = adserv.GetUserGroups(userName)
Dim _dt As New DataTable
_dt.Columns.Add("Group")
For Each item As String In userGroups
Dim _row As DataRow = _dt.NewRow()
_row("Group") = item
_dt.Rows.Add(_row)
Next
Session(GetSessionKey("FullName")) = userDetails.DisplayName
Session(GetSessionKey("Groups")) = _dt
Session(GetSessionKey("UserName")) = userName
Session(GetSessionKey("Switch")) = "OK"
Dim filter_auditGroup As String = ConfigurationSettings.AppSettings("FILTER_GROUP")
Dim _adt As New DataTable
_adt.Columns.Add("Group")
For Each item As String In userGroups
If (item = filter_auditGroup) Then
Dim _row As DataRow = _adt.NewRow()
_row("Group") = item
_adt.Rows.Add(_row)
End If
Next
'If _adt.Rows.Count > 0 Then
' Session(GetSessionKey("AuditGroups")) = _adt
'End If
End Sub
Check Access Function
If Not IsPostBack Then
Dim arr As Array = Request.Url.AbsolutePath.Split("/")
Dim page As String = arr(arr.Length - 1).ToString().Split(".")(0) '-- Ballot.aspx, remove .aspx and get Ballot only
Dim signOut As New List(Of String)
signOut.Add("SwitchUser")
signOut.Add("SignOut")
If (Not signOut.Contains(page, StringComparer.OrdinalIgnoreCase)) Then
If (String.IsNullOrEmpty(Session(GetSessionKey("UserName")))) Then
Response.Redirect("~/Default.aspx")
Else
Dim group As DataTable = Session(GetSessionKey("Groups"))
'Dim auditGroup As DataTable = Session(GetSessionKey("AuditGroups"))
Dim adminPage As New List(Of String)
adminPage.Add("BallotProcess")
adminPage.Add("CodeTablePage")
adminPage.Add("MaintainBallotItem")
adminPage.Add("MaintainCodeItem")
adminPage.Add("MaintainItemDetail")
If (adminPage.Contains(page, StringComparer.OrdinalIgnoreCase) And Not CheckAdmin(group)) Then
Response.Redirect("~/EventRegistration.aspx")
End If
'If (page.Equals("AuditPage", StringComparison.OrdinalIgnoreCase) And Not CheckAudit(group)) Then
' Response.Redirect("~/default.aspx")
'End If
End If
End If
End If
Check Admin Function
Private Function CheckAdmin(ByVal group As DataTable) As Boolean
Dim i As Integer
If Not IsNothing(group) Then
For i = 0 To group.Rows.Count - 1
If group.Rows(i)(0) = ConfigurationSettings.AppSettings("FILTER_GROUP") Then
CheckAdmin = True
Session(GetSessionKey("EventAdmin")) = 1
Exit Function
End If
Next
End If
End Function
I have found my answer through countless of debug and all I need to fix this code is just move the Response.Redirect("~/EventRegistration.aspx") into the If Else statement above. This is because when the if else statement execute to get the identity, after its if else statement the value will be Nothing, then it redirect to the page while the page will try to get the identity and it execute again the if else countless of times..
If String.IsNullOrEmpty(Session(GetSessionKey("UserName"))) Then
Dim userName As String = HttpContext.Current.User.Identity.Name.Split("\")(1)
SessionInitialiser(userName)
Response.Redirect("~/EventRegistration.aspx")
End If

vb.net select random folder name

Dose anybody know how I can select an existing random directory name (C:\ drive) using vb.net and store its location in a variable.
I had to googel this one but seem to only be able to find example in relation to files, not folders
Try this out, hope this will suits your requirement,
'----------------- Global Variables
Dim xCnter = 0
Dim xRndNo = 0
Dim xSubdirectory As String
Private Sub Basement()
Dim xGenerator As System.Random = New System.Random()
xRndNo = xGenerator.Next(1, 100)
AssignRndDirectory("C:\")
msgbox(subdirectory)
End Sub
Private Sub AssignRndDirectory(xPath as string)
For Each subdirectory In Directory.GetDirectories(xPath)
if xCnter = xRndNo then Exit sub
xCnter += 1
call AssignRndDirectory(subdirectory)
Next
End Sub
[Note: This code is not tested with IDE, Tell me if anything cause errors.]
EDIT: TESTED WITH IDE
Dim xCnter = 0
Dim xRndNo = 0
Dim xSubdirectory As String
Private Sub Basement()
Dim xGenerator As System.Random = New System.Random()
xRndNo = xGenerator.Next(1, 100)
AssignRndDirectory("C:\")
MsgBox(xSubdirectory)
xCnter = 0
End Sub
Private Sub AssignRndDirectory(ByVal xPath As String)
Try
For Each Subdirectory In Directory.GetDirectories(xPath)
If xCnter = xRndNo Then Exit Sub
xSubdirectory = Subdirectory
xCnter += 1
Call AssignRndDirectory(Subdirectory)
Next
Catch ex As Exception
Exit Sub
End Try
End Sub
Just make a list of directories, and select a random item from it.
Dim rnd As New Random()
Dim path As String = "C:\"
Dim dir = New DirectoryInfo(path)
Dim subDirs = dir.GetDirectories()
Dim randomDir = subdirs(rnd.[Next](subDirs.Length))
Or, if you prefer Linq, the last line can be:
Dim randomDirectory = subdirs.Skip(rnd.[Next](subdirs.Length)).First()

Enumeration in vb.net

while executing this below lines i got an error. Error:
Collection was modified; enumeration operation may not execute.
Help me to solve this.
Dim i As IEnumerator
Dim item As DataGridItem
Dim bChk As Boolean = False
i = dgOfferStatus.Items.GetEnumerator
For Each item In dgOfferStatus.Items
i.MoveNext()
item = i.Current
item = CType(i.Current, DataGridItem)
Dim chkItemChecked As New CheckBox
chkItemChecked = CType(item.FindControl("chkItemChecked"), CheckBox)
If chkItemChecked.Checked = True Then
Try
bChk = True
lo_ClsInterviewProcess.JobAppID = item.Cells(1).Text
lo_ClsInterviewProcess.candId = item.Cells(9).Text
Dim str, strSchedule1, strSchedule As String
Dim dspath As DataSet
Dim candidateId As Integer
''Moving the resume to Completed folder
ObjInterviewAssessment = New ClsInterviewAssessment
dspath = ObjInterviewAssessment.GetOffComPath(CInt(lo_ClsInterviewProcess.JobAppID), "GetHoldPath")
If dspath.Tables(0).Rows.Count > 0 Then
If Not IsDBNull(dspath.Tables(0).Rows(0).Item(0)) Then
str = dspath.Tables(0).Rows(0).Item(0)
strSchedule1 = str.Replace("Hold", "Completed")
End If
End If
Dim str1 As String
str1 = Server.MapPath(str).Trim
strSchedule = Server.MapPath(strSchedule1).Trim
Dim file1 As File
If file1.Exists(str1) Then
If file1.Exists(strSchedule) Then
file1.Delete(strSchedule)
End If
file1.Move(str1, strSchedule)
End If
''
intResult = lo_ClsInterviewProcess.UpdateApproveStatus(Session("EmployeeId"), strSchedule1)
BindHoldGrid()
If intResult > 0 Then
Alert.UserMsgBox("btnsearch", "Status Updated")
Else
Alert.UserMsgBox("btnsearch", "Status not Updated")
End If
Catch ex As Exception
ExceptionManager.Publish(ex)
Throw (ex)
End Try
End If
Next
If bChk = False Then
Alert.UserMsgBox("btnsearch", "Please Select any Candidate")
End If
'Catch ex As Exception
' ExceptionManager.Publish(ex)
'End Try
End Sub
Look at this part of your code. I think it's what causes your exception.
Dim i As IEnumerator
...
Dim item As DataGridItem
...
i = dgOfferStatus.Items.GetEnumerator
For Each item In dgOfferStatus.Items
i.MoveNext()
item = i.Current ' <-- here be dragons!? '
...
Next
What you're doing seems a little strange. You iterate through the same collection (dgOfferStatus.Items) twice, once with the For Each loop, and once manually using the i iterator. Then you modify items in your collection with item = i.Current. I believe it's this assignment that causes the exception.
(I also don't understand why you would do this. This assignment seems to be completeley superfluous, since i.Current and item should be identical since both iterators are at the same position in the collection.)
The exception basically tries to tell you that you may not modify a collection while you are iterating through it. But you seem to be doing exactly that.