vb.net DatePicker not setting value when new date is selected - sql

I'm working on a vb.net application (I'm very new to vb.net), and have just added a DatePicker to a field on a form- PostDate (the field was previously just a text box).
The date picker appears to work visually- when the user clicks inside the form field, the date picker calendar appears, and they can select a date from the current month, or switch months to select a date from another month. Once the user has selected a date, the calendar disappears, and the newly selected date is displayed in the field in the format mm/dd/yyyy.
However, while debugging my application, when I reach the UpdateButton_Click() function that is handling the updates to fields in the form (i.e. checking to see if any of their values have changed, and updating them in the database if they have), I see that in the line I have added to check for changes to the date field that I have just added the DatePicker to, the date variable still holds the previous value (i.e. the original date, rather than the newly selected date).
The UpdateButton_Click() function is defined with:
Protected Sub UpdateButton_Click(sender As Object, e As EventArgs) Handles UpdateButton.Click
If Page.IsPostBack Then
...
Dim mypostdate As String = HttpUtility.HtmlEncode(PostDate.Text & " " & theTime.Text)
...
C.updateCaseByCaseID(... mypostdate, ...)
...
Next
End If
End Sub
If I put a break point on this function, and step through it, I can see that the value of PostDate.Text is always its original value (i.e. it has a previously saved value when the page loads). Even if I change the value of the field to a new date, using the date picker, although the field shows the new date in the browser, when I step through this function, the value of PostDate.Text is always the original date value.
The call to C.updateCaseByCaseID(...) appears to be what is handling the database updates, and was originally defined in cases.vb with:
Public Function updateCaseByCaseID(ByVal Caseid As String, ...) As String
Dim con As New SqlConnection(connectionString)
Dim sql As String = "UPDATE tableName SET "
sql = sql & " ReportNumber=#ReportNumber, ... "
If status = "" Then
Else
sql = sql & " ,status=status "
End If
...
If PostDate = "" Then
Else
sql = sql & ", PostDate=#PostDate"
End If
' Other similar If Else statements for the other parameters '
...
Dim cmd As New SqlCommand(sql, con)
cmd.Parameters.AddWithValue("#CID", Cid)
...
cmd.Parameters.AddWithValue("#PostDate", PostDate)
' Other similar AddWithValue statements '
...
If state = "" Then
Else
cmd.Parameters.AddWithValue("#State", State)
End If
' Other similar If statements for the other parameters '
...
con.Open()
cmd.ExecuteNonQuery()
con.Close()
Dim myaction As String = "Done"
Return myaction
End Function
I added the postdate parameter to the sql variable by changing that line to:
sql = sql & " ReportNumber=#ReportNumber, ..., PostDate=#PostDate, ...
However, although this does now update the value of the post date field, it appears to update it to today's date, rather than the date selected by the DatePicker. This seems to be because although the PostDate field displays the newly selected date in the browser, in the UpdateButton_Click(...) function, in the line
Dim mypostDate As String = HttpUtility.HtmlEncode(PostDate.Text + " " + theTime.Text)
the variable PostDate.Text, i.e. the form field that is displaying the newly selected date in the browser, appears to have the value of today's date... I don't understand why this is happening...? Surely it should contain the value of the date selected in the DatePicker? Especially given that that is what's being displayed in the browser...
Anyone have any suggestions what I'm doing wrong with this?
Edit
As mentioned in the comments, I have updated the UpdateButton_Click() function as follows:
Protected Sub UpdateButton_Click(sender As Object, e As EventArgs) Hanles UpdateButton.Click
If Page.IsPostBack Then
...
Dim mypostdate As String = HttpUtility.HtmlEncode(PostDateTxt.Text & " " & theTime.Text)
Dim postDateAndTimeParts = mypostdate.Split("/")
Dim postTime = postDateAndTimeParts(2).Split("/")
Dim postDay = postDateAndTimeParts(1)
Dim postMonth = postDateAndTimeParts(0)
Dim postYear = postDateAndTimeParts(2).Split(" ")(0)
Dim postHour = postTime.Split(":")(0)
Dim postMin = PostTime.Split(":")(1)
DateTime PostDate = New DateTime(postYear, postMonth, postDay, postHour, postMin, 0);
...
C.updateCaseByCaseID(...)
End If
End Sub
My intention is to pass the new PostDate DateTime object that I'm reconstructing from the String into the C.updateCaseByCaseId(...) call, however on the line where I'm constructing that object, I'm currently getting a compile error that says:
Method arguments must be enclosed in parentheses
I'm not sure why this is? I can't see where I'm missing any parentheses...

Related

vb.net option strict on convert string to date

I am trying to convert a string from a database to a Date type with this format "yyyy-M-d"
The string is stored in this format "yyyy-M-d"
So I can execute this code with the Date variables in this format "yyyy-M-d"
Because Option Strict is ON Visual Studio 2019 ver 16.7.5 is UN-happy
If gvTorF = "False" And varToday > varFTue Then
First I am not sure it is necessary but the posts I read about comparing Dates makes this suggestion
Here are my variables
Dim varToday As Date
Dim varFTue As Date
Dim varStr As String
Next I click a Button to get the data from the Database With this code below
Public Sub GetDateInfo()
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;")
conn.Open()
Using cmd As SQLiteCommand = New SQLiteCommand($"SELECT * FROM DateInfoTable WHERE DID = '1'", conn)
Using rdr As SQLite.SQLiteDataReader = cmd.ExecuteReader
While rdr.Read()
varTorF = rdr("ditORf").ToString
'varFTue = CDate(rdr("diTESTdate")) 'shows as 10/26/2021
'varFTue = Date.ParseExact(varStr, "yyyy-M-d", provider As IFormatProvider, As Date)
'Tried line of code above this can NOT format correct
varTESTdate = CType(rdr("diTESTdate"), String) 'shows as 2021-10-26
End While
rdr.Close()
End Using
End Using
End Using
End Sub
Other than turning Option Strict OFF or just use the format "M-d-yyyy" to run my test
Where varToday > varFTue which seems to work
The Question is what are my other options to make the conversion from String to Date?
The function below will convert the two Strings varTESTdate & varTodayStr
The varTESTdate is from the database and varTodayStr is created in the function bothDates
Here is the Function and the call made behind a Button Click event
bothDates(varTESTdate, varTodayStr)
Public Function bothDates(ByVal varTESTdate As String, ByVal varTodayStr As String) As Object
result1 = Date.ParseExact(varTESTdate, "yyyy-M-d", provider:=Nothing)
Dim dateToday = Date.Today
varTodayStr = dateToday.ToString("yyyy-M-d")
result2 = Date.ParseExact(varTodayStr, "yyyy-M-d", provider:=Nothing)
Return (result1, result2)
End Function
You appear to have the conversion in your code already
Dim d = DateTime.ParseExact("2026-10-26", "yyyy-M-d", Nothing) 'or provide a culture instead of Nothing..
Though I'm not sure what the trailing "As IFormatProvider, As Date" is there for
'varFTue = Date.ParseExact(varStr, "yyyy-M-d", provider As IFormatProvider, As Date)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a syntax error in this context in vb, and looks like a remnant artifact of a conversion from C# where we use "as X" to perform casts. Don't assume that converters get all code perfect all the time; you nearly always have to fix up their output, especially if pasting in only parts of a program where they can't see all the declared variables (your code appears to not contain provider as a variable)

Check if multiple control types are empty inside groupbox and display tags of empty controls

As mentioned i need to check if all fields in a groupbox are empty and if they are then display a messagebox showing the tags of the empty fields.
Issue is i have multiple types of controls on this box including: TextBox, NumericUpDown and DatePicker.
I am wondering if there is an easier way than what i am doing below.
If BenchQtyCombo.Text = 1 Then
Dim B1emptyTextBoxes =
From txt In Bench1_Combo.Controls.OfType(Of TextBox)()
Where txt.Text.Length = 0
Select txt.Tag
Dim B1emptyNumericBox =
From num In Bench1_Combo.Controls.OfType(Of NumericUpDown)()
Where num.Value = 0
Select num.Tag
If B1emptyTextBoxes.Any Or B1emptyNumericBox.Any Then
MessageBox.Show(String.Format("Please Complete the Following Required Fields:" & vbCrLf & vbCrLf & "{0}", String.Join(", ", B1emptyTextBoxes, B1emptyNumericBox)))
End If
End If
Im also having an issue with B1emptyTextBoxes, B1emptyNumericBox displaying the tags in the messagebox as i get this string instead of the tags
Im yet to include the code for the datepicker which will be something like Where DatePicker.Date > Today code yet until i get this working.
Any suggestions would be greatly appreciated.
To begin with, a group box's text property can never equal 1. 1 is a numeric type. Normally a text property contains a string.
If GroupBox1.Text = "1" Then
Next, a .Tag property is of datatype Object. You can throw anything you want into it. However, you will get an object when you reference it. When you call .ToString on an Object (which is what your String.Format is doing) you will get the fully qualified name of the Object.
The CStr() changes it back to the underlying type String. If you hold your cursor over B1emptyTextBoxes and B1emptyNumericBox befor adding the CStr() you will see that the datatype is IEnumerable of Object. After adding CStr() you will see IEnumerable of String.
Then add the 2 IEnumerables together with the Concat() method and Bob's your uncle.
Private Sub OPCode()
If GroupBox1.Text = "GroupBox1" Then
Dim B1emptyTextBoxes = From txt In GroupBox1.Controls.OfType(Of TextBox)()
Where txt.Text.Length = 0
Select CStr(txt.Tag)
Dim B1emptyNumericBox = From num In GroupBox1.Controls.OfType(Of NumericUpDown)()
Where num.Value = 0
Select CStr(num.Tag)
If B1emptyTextBoxes.Any Or B1emptyNumericBox.Any Then
Dim BothEnumerables = B1emptyTextBoxes.Select(Function(s) s).Concat(B1emptyNumericBox.Select(Function(s) s))
MessageBox.Show(String.Format("Please Complete the Following Required Fields:" & vbCrLf & vbCrLf & "{0}", String.Join(", ", BothEnumerables)))
End If
End If
End Sub
You are joining the 2 lists to display them in the MessageBox. You need to join the contents of those lists separately instead & then join those strings.
Your MessageBox string will need:
String.Join(", ", String.Join(", ", B1emptyTextBoxes), String.Join(", ", B1emptyNumericBox))

String.Format for Integer is Incorrect in VB.Net

This should not happen, so I must be missing something simple.
In the below VB function, I am trying to generate a list of part numbers to display on the screen using this format statement:
ticket = String.Format("{0:000}-{1:00000}-{2:00}", storeNumber, order, release)
With that, ticket should have the format xxx-yyyyy-zz so that the ticket is human readable and the other parts of my application can parse this data.
Public Shared Function GetShipTickets(storeNumber As Integer, auditor As String, startDate As DateTime) As ShipTickets
Dim list As New ShipTickets(auditor)
list.Display = String.Format("Since {0:MMMM d}.", startDate)
Const sqlCmd As String =
"SELECT TICKET_STORE, TICKET_ORDER, TICKET_RELEASE " &
"FROM TBLRELHDR " &
"WHERE TICKET_STORE=#TICKET_STORE AND STATUS='C' AND #CREATE_DATE<=CREATE_DATE " &
"ORDER BY TICKET_ORDER, TICKET_RELEASE, CREATE_DATE; "
Dim table As New DataTable()
Using cmd As New DB2Command(sqlCmd, Db2CusDta)
cmd.Parameters.Add("TICKET_STORE", DB2Type.SmallInt).Value = storeNumber
cmd.Parameters.Add("CREATE_DATE", DB2Type.Char, 8).Value = String.Format("{0:yyyyMMdd}", startDate)
table.Load(cmd.ExecuteReader())
End Using
If 0 < table.Rows.Count Then
For Each row As DataRow In table.Rows
Dim order As String = String.Format("{0}", row("TICKET_ORDER")).Trim().ToUpper()
Dim release As String = String.Format("{0}", row("TICKET_RELEASE")).Trim().ToUpper()
Dim ticket As String = String.Format("{0:000}-{1:00000}-{2:00}", storeNumber, order, release)
list.Add(ticket)
Next
End If
list.Sort()
Return list
End Function
It is not working, though.
Also, when I view my data on the screen, it is not displaying correctly either:
What is going on?
VB is not my strongest programming language. Either there is some nuance of VB that I am unaware of or the compiler is messing up.
Using Visual Studio 2012
The format "{2:00}" works on integers, not strings. It won't automatically convert a string consisting of digits into an integer. Manually convert the strings to integers:
Dim ticket As String = String.Format("{0:000}-{1:00000}-{2:00}",
CInt(storeNumber),
CInt(order),
CInt(release))

Migration from vba to vb.net - correct logic for using Iserror

I'm trying to use this code:
If Not IsError(Convert.ToDateTime(DatiBase(i).innertext.substring(DatiBase(i).innertext.indexof(":") + 1).trim(), New CultureInfo("it-IT"))) Then
MyString = "'" & Convert.ToDateTime(DatiBase(i).innertext.substring(DatiBase(i).innertext.indexof(":") + 1).trim(), New CultureInfo("it-IT")).ToString("yyyy-MM-dd") & "'"
Else
'Do something else
End If
My goal is to assign value to "MyString" only if "Convert.ToDateTime" gives a valid value but the code doesn't do that: It stops when the String isn't recognized as a valid DateTime instead of execute the "else" code.
You should use DateTime.TryParse:
https://msdn.microsoft.com/en-us/library/9h21f14e%28v=vs.110%29.aspx
If you don't know exactly what is the format in which you receive your string then you need to provide a set of possible formats to the DateTime.TryParseExact.
This example below is a simplified test version of your code above
Sub Main
Dim dateConverted as DateTime
Dim testDate = "asdfasldka:08/05/2015 13:10"
Dim yourWannaBeDate = testDate.Substring(testDate.IndexOf(":") + 1).Trim()
Dim possibleFormats = new string() {"d/M/yyyy", "d/M/yyyy H:m", "d/M/yy", "d/M/yy H:m"}
if DateTime.TryParseExact(yourWannaBeDate, possibleFormats, CultureInfo.CurrentCulture, DateTimeStyles.None, dateConverted) then
Console.WriteLine(dateConverted.ToString("yyyy-MM-dd"))
else
Console.WriteLine("Not a date")
End if
End Sub
The above code will match "08/05/2015", "8/5/2015", "08/05/15" and the same strings with the time part in two or one digit format
The trick consists in passing an array of possible formats that could be used to interpret the date in your CurrentCulture (I am assuming that your PC has the culture that match the formats above, however, if this is not the case just initialize a new CultureInfo variable and use it in the TryParseExact)
I wanna thank Leonardo for the tip. This is the code I successfully used:
Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture("it-IT")
Dim DateResult As DateTime
Dim styles As DateTimeStyles = DateTimeStyles.None
Dim mTmpDate As String
mTmpDate = DatiBase(i).innertext.substring(DatiBase(i).innertext.indexof(":") + 1).trim()
If DateTime.TryParse(mTmpDate, culture, styles, DateResult) Then
MyString = "'" & DateResult.ToString("yyyy-MM-dd HH:mm") & "'"
Else
'Do something else
End If
The code works with any kind of date in "italian style" and in "MyString" I get a date/time formatted as mySql needs (for a timestamp field).

How do I make the closest future date to today's date the default dropdownlist value?

We dynamically populate our dropdownlist with several event dates from the database.
Currently, all dates less than today's date are disabled and can't be viewed by our users.
The next available date greater than today's date becomes the default dropdownlist value and all future dates are avaiable and visible in the dropdownlist.
For instance, if we have the following dates on our datebase:
2/12/2013
12/20/203
5/21/2014
8/8/2014
10/22/2014
since three of the dates (2/12/2013,12/20/203,5/21/2014) are less than today's date, these dates are disabled and not viewable.
The closest available date greater than today's date is 8/8/2014 and this becomes the default dropdownlist value.
Finally all future dates like 10/22/2014 are also available in the dropdownlist.
Here are the code snips that make this happen:
//the markup
<asp:DropDownList id="txtEventDate" runat="server">
</asp:DropDownList>
//Code that dynamically populates dropdownlist
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("Events").ConnectionString))
cmd.Connection.Open()
Dim ddlValues As SqlDataReader
ddlValues = cmd.ExecuteReader()
txtEventDate.DataSource = ddlValues
txtEventDate.DataValueField = "dates"
txtEventDate.DataTextField = "datelist"
txtEventDate.DataBind()
cmd.Connection.Close()
cmd.Connection.Dispose()
//Code that displays only future dates with next available future date as default dropdownlist value
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) < 0 Then
items.Enabled = False
End If
Next
Our users would like to change the process so they would be allowed to go back to an older date and make some changes if they needed to.
Any ideas how to address this problem?
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
lstDates = lstDates.OrderBy(Function(x) x.[Date]).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
txtEventDate.DataSource = lstDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
Per your comment it seems like you want to let the user change the older dates. So remove your For Each that disables the older dates.
First you need to find the nearest date equal or closer to current date like below
Dim nearestDate = ddlValues.OrderBy(Function(t) Math.Abs((t.dates - DateTime.Now).Ticks)).First()
Then after you do the data binding keep the nearest date default selected using FindByValue or FindByText
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
Side Note: always try using using statements for your db connection objects like SqlConnection, SqlCommad etc so the resources used by these objects are freed up after usage.
UPDATE 1: Based on what you reported in your comment, I made few changes as to the date format ( it was not part of your initial question) etc and here is the complete code for PopulateDates(). Also make sure you don't run the foreach you earlier had to set the nearest date because it might set wrong values. If you get wrong values then better put breakpoint and see which object returns unexpected data.
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select dates from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
Dim stDates As List(Of [String]) = lstDates.OrderBy(Function(o) o.[Date]).[Select](Function(x) x.[Date].ToString("MMM dd, yyyy")).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
// Dim nearestDate = lstDates.First(Function(x) x >= DateTime.Now.[Date]) // this does the trick too
txtEventDate.DataSource = stDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString("MMM dd, yyyy")))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
Here is the link to the DEMO (unfortunately it's in C#) I set up to show how it return me the correct data.
UPDATE 2: Here is your complete working version (hopefully it works). I tried this locally to load the data from database and retrieving through the DataReader and everything works the way you wanted.
You reported in your comment saying only one item was returned when accessing from the DataReader, it's because your original code had If rdr.Read() Then which will exit after the first record but rather we need to use while to iterate the complete list.
Regarding Value field and Text of the dropdownlist holding different date format, I've created a Dictionary collection to achieve this. Here is your complete code for PopulateDates().
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select dates from events order by dates", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim list As New Dictionary(Of String, DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
Dim dt As DateTime
While rdr.Read()
dt = DateTime.Parse(rdr("dates").ToString())
list.Add(dt.ToString("MM/dd/yyyy"), dt)
End While
End Using
txtEventDate.DataSource = list
txtEventDate.DataTextField = "Value"
txtEventDate.DataValueField = "key"
txtEventDate.DataTextFormatString = "{0:MMM dd, yyyy}"
txtEventDate.DataBind()
Dim nearestDate = list.First(Function(x) x.Value >= DateTime.Now.[Date]).Key
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
And the HTML markup looks like the format you wanted.
Totally untested, but would something like the following do what you want? Your list of items will need to be sorted, if it's not already, but this should find the first item that is for today or later and set it as the selected item in the drop-down.
Update - try SelectedValue instead!
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) >= 0 Then
txtEventDate.SelectedValue = items.Value
Exit For
End If
Next