I have 2 functions, one is SaveData() and the other is SendEmail()
in the SaveData() the radio buttons that are selected are saved, and the SendMail() is called at the end.
in the SendMail() the radio buttons are "tested" and then one of two emails is sent out based on the radio choices.
The problem I am having is passing the parameters correctly. I have tried several different method but the parameters are not being sent to SendMail()
The radio buttons are Yes/No questions
Any thoughts on why the parameters are not being passed?
Here is what I have:
Protected Function SaveData()
...
Q1 = Me.rblnewqst1.SelectedValue
Q2 = Me.rblnewqst2.SelectedValue
Q3 = Me.rblnewqst3.SelectedValue
Q4 = Me.rblnewqst4.SelectedValue
Q5 = Me.rblnewqst5.SelectedValue
....
and the SendEmail() is
Protected Sub SendEmail(ByVal rblnewqst1 As Object, ByVal rblnewqst2 As Object, ByVal rblnewqst3 As Object, ByVal rblnewqst4 As Object, ByVal rblnewqst5 As Object)
If rblnewqst1.SelectedValue = 2 Or rblnewqst2.SelectedValue = 2 Or rblnewqst3.SelectedValue = 2 Or rblnewqst4.SelectedValue = 2 Or rblnewqst5.SelectedValue = 2 Then
Dim sResponseFromName As String = "ex#example.com"
Dim sResponseToName As String = txtEmail.Text
Dim sResponseSubject As String = "Denied"
Dim sResponseBody As String = "Message>"
Try
Dim mm As New MailMessage(sResponseFromName, sResponseToName)
Dim SMTP As New SmtpClient
SMTP.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis
mm.Subject = sResponseSubject
mm.Body = sResponseBody
mm.IsBodyHtml = True
Try
SMTP.Send(mm)
Catch exSmtpException As SmtpException
Dim stemp As String = exSmtpException.Message.ToString
End Try
Catch ex As ApplicationException
Dim stemp As String = ex.InnerException.Message.ToString
End Try
Else
Dim sResponseFromName As String = "ex#example.com"
Dim sResponseToName As String = txtEmail.Text
Dim sResponseSubject As String = "Accepted"
Dim sResponseBody As String = "MESSAGE....."
Try
Dim mm As New MailMessage(sResponseFromName, sResponseToName)
Dim SMTP As New SmtpClient
SMTP.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis
mm.Subject = sResponseSubject
mm.Body = sResponseBody
mm.IsBodyHtml = True
Try
SMTP.Send(mm)
Catch exSmtpException As SmtpException
Dim stemp As String = exSmtpException.Message.ToString
End Try
Catch ex As ApplicationException
Dim stemp As String = ex.InnerException.Message.ToString
End Try
End If
End Sub
Like HardCode mentioned in his comments, I do recommend you always work with Option Explicit and Option Strict on.
The first thing I would do is alter the way the SendMail part works, to take the values from the radio buttons. Your If is checking against and integer value, so I would use Integer as the type.
So something more like:
Protected Sub SendEmail(ByVal q1 As Integer, ByVal q2 As Integer)
If q1 = 2 Or q2 = 2 Then
etc...
End IF
I shortened the list so I didn't have to type as much. In general I think it is better practice to send values than entire objects, unless you need the entire control for a specific reason. Also, sending object isn't something I recommend doing unless you have no other choice.
The other thing I would recommend, to test it, is setting a break point just inside the sendEmail Sub, use quick watch to see what the actual objects/types are that are being sent to your method that you are checking.
Related
so..
I have a txt file with hundreds of sentences or strings.
I also have 4 comboboxes with options that a user can select from and
each combobox is part of a different selection criteria. They may or may not use all the comboboxes.
When a user selects an option from any combobox I use a For..Next statement to run through the txt file and pick out all the strings that contain or match whatever the user selected. It then displays those strings for the user to see, so that if they wanted to they could further narrow down the search from that point by using the 3 remaining comboboxes making it easier to find what they want.
I can achieve this by using lots of IF statements within the for loop but is that the only way?
No, there are other ways. You can leverage LINQ to get rid of some of those if statements:
Private _lstLinesInFile As List(Of String) = New List(Of String)
Private Function AddClause(ByVal qryTarget As IEnumerable(Of String), ByVal strToken As String) As IEnumerable(Of String)
If Not String.IsNullOrWhiteSpace(strToken) Then
qryTarget = qryTarget.Where(Function(ByVal strLine As String) strLine.Contains(strToken))
End If
Return qryTarget
End Function
Public Sub YourEventHandler()
'Start Mock
Dim strComboBox1Value As String = "Test"
Dim strComboBox2Value As String = "Stack"
Dim strComboBox3Value As String = String.Empty
Dim strComboBox4Value As String = Nothing
'End Mock
If _lstLinesInFile.Count = 0 Then
'Only load from the file once.
_lstLinesInFile = IO.File.ReadAllLines("C:\Temp\Test.txt").ToList()
End If
Dim qryTarget As IEnumerable(Of String) = (From strTarget In _lstLinesInFile)
'Assumes you don't have to match tokens that are split by line breaks.
qryTarget = AddClause(qryTarget, strComboBox1Value)
qryTarget = AddClause(qryTarget, strComboBox2Value)
qryTarget = AddClause(qryTarget, strComboBox3Value)
qryTarget = AddClause(qryTarget, strComboBox4Value)
Dim lstResults As List(Of String) = qryTarget.ToList()
End Sub
Keep in mind this is case sensitive so you may want to throw in some .ToLower() calls in there:
qryTarget = qryTarget.Where(Function(ByVal strLine As String) strLine.ToLower().Contains(strToken.ToLower()))
I think a compound If statement is the simplest:
Dim strLines() As String = IO.File.ReadAllText(strFilename).Split(vbCrLf)
Dim strSearchTerm1 As String = "Foo"
Dim strSearchTerm2 As String = "Bar"
Dim strSearchTerm3 As String = "Two"
Dim strSearchTerm4 As String = ""
Dim lstOutput As New List(Of String)
For Each s As String In strLines
If s.Contains(strSearchTerm1) AndAlso
s.Contains(strSearchTerm2) AndAlso
s.Contains(strSearchTerm3) AndAlso
s.Contains(strSearchTerm4) Then
lstOutput.Add(s)
End If
Next
I have trouble rounding some cells from my datatable.
I want this round to 2 decimal places, as you can imagine. I will explain quickly how I charge data to the DataTable :
I have this function stored in a class:
Protected Friend Function cargarPref(ByVal id_Pref As String) As DataTable
Dim cmd As String = "Select Material,Cubicaje,SubTotal,ITBM,Total from Preferencia WHERE Id_Preferencia=#id_Pref"
Dim t As New DataTable
Try
con.Open()
comando = New OleDbCommand(cmd, con)
comando.Parameters.AddWithValue("#id_Pref", id_Pref)
adapter = New OleDbDataAdapter(comando)
adapter.Fill(t)
comando.Dispose()
adapter.Dispose()
con.Close()
Catch ex As Exception
MsgBox("Error en la consulta: " + ex.Message, MsgBoxStyle.Critical)
End Try
Return t
End Function
Ok, now I call it in my windows form:
Private Sub DataCliente_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataCliente.CellContentClick
If (Not IsNothing(DataMate)) Then
DataMate.DataSource = Nothing
mt.Clear()
End If
Dim index As Integer = 0
If (DataCliente.Columns(DataCliente.CurrentCell.ColumnIndex).Name.Equals("Empresa")) Then
index = Me.DataCliente.CurrentRow.Index
lblid.Text = DataCliente.Rows(index).Cells("Id_Cliente").Value
lblempresa.Text = DataCliente.Rows(index).Cells("Empresa").Value
lbldirecc.Text = DataCliente.Rows(index).Cells("Direccion").Value
lblcorreo.Text = DataCliente.Rows(index).Cells("Correo").Value
lbltel.Text = DataCliente.Rows(index).Cells("Telefono").Value
lblpreyd.Text = Math.Round(CDbl(DataCliente.Rows(index).Cells("PrecioYD").Value), 2).ToString("N2")
End If
mt = data.cargarPref(DataCliente.Rows(index).Cells("Id_Preferencia").Value) <--HERE!!!
DataMate.DataSource = mt
PanelMaterial.Enabled = True
End Sub
Now, watch as my values are in my database access, Along With the datagrid of the program!
For some strange reason ... the data I have taken from the database , the program treats them as if they were integers.
How I can then round off those values that are within the datatable, before printing in datagridview?
I finally discovered a solution , and I am going to show you how to solve this problem, if you need it (Before you do this , you must define all the columns you want to see on your datagridview !):
First, I create a class with public properties:
Public Class Preferencia
Public Property Material() As String
Public Property Cubicaje() As String
Public Property SubTotal() As String
Public Property ITBM() As String
Public Property Total() As String
End Class
Second , I create 2 functions and one procedural method :
Private Function setPreferencia(ByVal material As String, ByVal cubicaje As String, ByVal subtotal As String, ByVal itbm As String, ByVal total As String) As Preferencia
Dim item As New Preferencia
item.Material = material
item.Cubicaje = FormatNumber(cubicaje, 2)
item.SubTotal = FormatNumber(subtotal, 2)
item.ITBM = FormatNumber(itbm, 2)
item.Total = FormatNumber(total, 2)
Return item
End Function
Private Function registrarPreferencia() As List(Of Preferencia)
Dim lista As New List(Of Preferencia)
For Each itm In mt.Rows
lista.Add(setPreferencia(itm(0), itm(1), itm(2), itm(3), itm(4)))
Next
Return lista
Protected Friend Sub FillGrid()
DataMate.AutoGenerateColumns = False
DataMate.DataSource = registrarPreferencia()
DataMate.Columns("Material").DataPropertyName = "Material"
DataMate.Columns("Cubicaje").DataPropertyName = "Cubicaje"
DataMate.Columns("SubTotal").DataPropertyName = "SubTotal"
DataMate.Columns("ITBM").DataPropertyName = "ITBM"
DataMate.Columns("Total").DataPropertyName = "Total"
End Sub
Now the only thing is to call the method " FillGrid ()" when you want to print the data. And finaly, I resolved it!
Boy, learning something new can be a real headache if you can't find a solid source. I have been designing applications in a linear fashion for some time now and want to step up into a more powerful approach. I have been reading up on threading, and perhaps have gone to an larger level than I should. However, one usually steps up when the application calls for it and no better time than the present to learn something new.
My program is designed to do something that seems rather simple, but has become extremely difficult to create in a smooth running manor. The original design created object of each device on the network it wished to ping, in my real world environment they are Kindles. The goal was to ensure they were still connected to the network by Pining them. I used a For Loop and Obj Array to do this set on a Timer. This had unexpected results causing the ListView to flicker and load slowly after the ListView1.Items.Clear. I evolved into updating the List Items rather than clearing them and the flicker remained.
I assumed this was due to the slow process of the array and pings so I started hunting for solutions and came across Multi-Threading. I have known about this for some time, but have yet to dive into the practice. My program seemed to need more speed and smoother operation so I took a stab at it. The below code in its complete form is the result, however it crashes and throws errors. Clearly I have not used Threading as it was intended. Using it in simpler functions works fine and I feel I have the grasp. That is if i want my program to pointlessly run counters.
I don't know what to do next in my steps for getting this task done, and figure I am combining several different methods into a mush of dead program. I could really use some help getting back on track with this. All comments welcome and thank you for checking out my code.
Form1 Code
Public Class Form1
'Obj Array
Public Shared objDevice As New List(Of kDevice)
'Thread Array for each Obj
Public Shared thread() As System.Threading.Thread
Private Sub ipRefresh(objID, itemPos)
Dim objDev As kDevice = objID
If My.Computer.Network.Ping(objDev.kIP) Then
objDev.kStatus = "Online"
objDev.kPings = 0
Else
objDev.kPings += 1
End If
If objDev.kPings >= 8 Then
objDev.kStatus = "Offline"
objDev.kPings = 0
ListView1.Items(itemPos).BackColor = Color.Red
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = objDev.kName
str(1) = objDev.kIP
str(2) = objDev.kStatus
str(3) = objDev.kPings
itm = New ListViewItem(str)
ListView1.Items(itemPos) = itm
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.CheckForIllegalCrossThreadCalls = False
' Adding ListView Columns
ListView1.Columns.Add("Device", 100, HorizontalAlignment.Left)
ListView1.Columns.Add("IP Address", 150, HorizontalAlignment.Left)
ListView1.Columns.Add("Status", 60, HorizontalAlignment.Left)
ListView1.Columns.Add("Pings", 60, HorizontalAlignment.Left)
Dim ipList As New List(Of String)
Dim nameList As New List(Of String)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("kDevices.csv")
MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {","}
Dim currentRow As String()
Dim rowP As Integer = 1
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
Dim cellP As Integer = 0
Dim nTemp As String = ""
For Each currentField As String In currentRow
Select Case cellP
Case 0
nameList.Add(currentField.Replace("""", ""))
Case 1
ipList.Add(currentField.Replace("""", ""))
End Select
cellP += 1
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
rowP += 1
End While
End Using
Dim nameLAR As String() = nameList.ToArray
Dim ipLAR As String() = ipList.ToArray
ReDim Preserve thread(nameLAR.Length)
For i As Integer = 0 To nameLAR.Length - 1
Dim newDevice As New kDevice
Dim objNum = i
objDevice.Add(newDevice)
newDevice.kName = nameLAR(i)
newDevice.kIP = ipLAR(i)
If My.Computer.Network.Ping(newDevice.kIP) Then
newDevice.kStatus = "Online"
Else
newDevice.kStatus = "Loading"
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
thread(objNum) = New System.Threading.Thread(Sub() Me.ipRefresh(objDevice(objNum), objNum))
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
For i As Integer = 0 To objDevice.Count - 1
thread(i).Start()
Next
End Sub
End Class
kDevice Class
Public Class kDevice
Private strkName As String
Private strkIP As String
Private strkStatus As String
Private strkLastStatus As String
Private strkPings As Integer = 0
Public Property kName As String
Get
Return strkName
End Get
Set(value As String)
strkName = value
End Set
End Property
Public Property kIP As String
Get
Return strkIP
End Get
Set(value As String)
strkIP = value
End Set
End Property
Public Property kStatus As String
Get
Return strkStatus
End Get
Set(value As String)
strkStatus = value
End Set
End Property
Public Property kPings As Integer
Get
Return strkPings
End Get
Set(value As Integer)
strkPings = value
End Set
End Property
End Class
The Error / Crash on Line 32 of my code which is when it tries to pass the update to the ListView Item
An unhandled exception of type 'System.ArgumentException'
occurred in Microsoft.VisualBasic.dll
Additional information: InvalidArgument=Value of '18'
is not valid for 'index'.
or
An unhandled exception of type 'System.NullReferenceException'
occurred in Microsoft.VisualBasic.dll
Additional information: Object reference not set to an instance
of an object.
If my code does not make sense, or at lease the idea of what I was trying to make it do, please let me know and I will explain whichever parts are unclear. Again thank you for looking over my issue.
Just a possible issue I noticed:
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
In this bit here, you declare str(4) which would be 5 possible indexes (remember it starts at zero), where you should have 4 (str(3)) . I don't think this is the whole issue, but just a small bit you should probably fix. You also may want to look into other ways to update the listview without setting
Me.CheckForIllegalCrossThreadCalls = False
Here's an awesome guide that helped me when I did my first multi threaded application: http://checktechno.blogspot.com/2012/11/multi-thread-for-newbies.html
Well I get this error (The ID3v2TagVersions value of '4' (4) is not valid for this operation.) with UltraID3Lib on Visual Basic 2013. I want to use this library (dll) so i can edit my mp3 tags in a mp3 file. Although I achived changing the tags , when i use the Clear() sub and then retry to change the tags i get this error. Can anyone help me ?
My Code
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim Artist As String = ""
Dim Title As String = ""
Dim MP3TagEditor As New UltraID3
For Each Path In MP3List
MP3TagEditor.Read(Path)
Title = "Somthing"
Artist = "Somthing"
MP3TagEditor.ID3v2Tag.Title = Title
MP3TagEditor.ID3v2Tag.Artist = Artist
MP3TagEditor.Clear()
MP3TagEditor.Write()
Next
MsgBox("Tags Added", MsgBoxStyle.Information, "Success")
End Sub
Thanks
Try this
Dim sTitle As String = "No Name"
Dim sSinger As String = ""
Dim sAlbum As String = ""
Dim sYear As String = ""
Dim sComm As String = ""
Dim MP3Tag As New UltraID3
MP3Tag.Read(YOUR_PATH)
Try
Dim pics = MP3Tag.ID3v2Tag.Frames.GetFrames(CommonMultipleInstanceID3v2FrameTypes.Picture)
AlbumPic.Image = CType(pics(0), ID3v2PictureFrame).Picture
Catch ex As Exception
AlbumPic.Image = My.Resources.FlatCD
End Try
Try
sTitle = MP3Tag.Title
sSinger = MP3Tag.Artist
sAlbum = MP3Tag.Album
Catch ex As Exception
End Try
You cannot read ID3v2.4 tags from an MP3 file with UltraID3Lib. It doesn't support it yet. (As of 31/12/2015).
But there is an alternative, which, in my humble opinion is even better, stable and efficacious:
TagLib-Sharp
It supports many other tag types as well apart from ID3, i.e, MP3 Files.
A quick example to get you on the way:
Dim f As TagLib.File = TagLib.File.Create("someFile.mp3")
Dim artist As String = f.Tag.JoinedPerformers
Dim title As String = f.Tag.Title
More resources for TagLib-Sharp:
Where can I find tag lib sharp examples?
Set Bitmap as cover art for MP3
As you know we have a new syntax in vb.net with possibility to create inline tasks so we could run it asynchronously.
This is the correct code:
Dim testDeclaring As New Task(Sub()
End Sub)
testDeclaring.Start()
but now I need to pass a parameter in the subroutine and I can't find correct syntax for that.
Is it possible any way?
It's not possible. However, you could just use the parameters from the current scope:
Public Function SomeFunction()
Dim somevariable as Integer = 5
Dim testDeclaring As New Task(Sub()
Dim sum as integer = somevariable + 1 ' No problems here, sum will be 6
End Sub)
testDeclaring.Start()
End Function
If you want to pass a parameter you could do this
Dim someAction As Action(Of Object) = Sub(s As Object)
Debug.WriteLine(DirectCast(s, String))
End Sub
Dim testDeclaring As New Task(someAction, "tryme")
testDeclaring.Start()
Dont know if you looking for this:
Dim t As Task = New Task(Sub() RemoveBreakPages(doc))
Sub RemoveBreakPages(ByRef doc As Document)
Dim paragraphs As NodeCollection = doc.GetChildNodes(NodeType.Paragraph, True)
Dim runs As NodeCollection = doc.GetChildNodes(NodeType.Run, True)
For Each p In paragraphs
If CType(p, Paragraph).ParagraphFormat().PageBreakBefore() Then
CType(p, Paragraph).ParagraphFormat().PageBreakBefore = False
End If
Next
End Sub
Regards.