PDA

View Full Version : Add a time from a TextBox into a ListBox


dan28
May 6, 2009, 02:58 AM
I need to add a time from a textbox into a list box with a message after that time.
I've tried many different codes all with poor results. Either I can't change the time or when I changed the time it adds every move to the listbox e.g if the time is 10:00 and I want to change it to 2:00 when I click backspace it adds 10:0, 10:, 10, 1, etc to the list box.
I have to do this without using a button.
Please help!

Attached is an image of what should happen.

If you know how to do the times for the checkbox's that would help also. (numbers in brackets represent time in minutes)

Thanks

Perito
May 6, 2009, 04:50 AM
Can you post a code fragment that shows how you're trying to use it now? I think I've done this before and my recollection is that it wasn't all that hard.

dan28
May 6, 2009, 04:58 AM
This is the latest code I've tried

Private Sub tbxStart_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxStart.TextChanged

Dim dtmTurnOvenOn As Date = #12:00:00 AM#
Dim strStart As String = dtmTurnOvenOn.ToString("t")

strStart = tbxStart.Text
tbxStart.Text = Format(#12:00:00 PM#)

If rdbOven1.Checked = True Then
lbxOven1.Items.Add(strStart & (" Turn On, Heat (15) "))
End If

End Sub

Ive also tried formating the tbxStart.Text as Format("hh:mm) but that left hh:mm in the text box. This current code won't let me change the time at all. And when I try it just keeps producing cases of 12:00:00 AM Turn oven on.
Ive tried it without the Dim dtmTurnOvenOn and just used Strings but that also didn't work.

Perito
May 6, 2009, 05:46 AM
tbxStart is the "shift start time", from your label. Let's say you want to change the shift start time from 4:00 to 12:00 - the start of the next shift. Is this the proper scenario?

Your TextChanged subroutine will be called five times -- when you hit 1, 2, :, 0, and 0. This will add five lines to a listbox. You obviously need a way to check that and eliminate multiple entries. You might be able to use a different event (maybe the Leave or Validating event). You might also check the format of the time. If it's not complete, you exit out of the event before trying to add anything to the listbox. Finally, use a semaphore to make sure you don't "overrun" yourself:

Private Semaphore as Boolean = false ' class-level variable.

Private Sub...
if Semaphore then exit sub
try
Semaphore = true
finally
Semaphore = false
end try

I don't think it's the time formatting that's causing you problems. I think it's something having to do with adding multiple lines to the listbox.

You also mentioned something about changing the time. Do you wish to update all of the lines in the listbox? That's possible, but you have to re-parse each line, remove the current time from the line, update the time and rebuild the line and re-add it to the listbox.

Post back with your thoughts. I'll look in in an hour or so.

dan28
May 6, 2009, 06:04 AM
Yes tbxStart is the "Shift Start time."
When the time is changed the time next to "Turn oven on" in the selected listbox should be updated, therefore updating the times of the other things in the listbox.
ATM when I change the Start time instead of updated the "Turn oven on" Time it adds new ones under the data. Every time I change anything in the Start time textbox it adds a new "Turn oven on"

dan28
May 6, 2009, 06:09 AM
Sorry, "Turn on, Heat" not "Turn oven on"

Perito
May 6, 2009, 06:19 AM
tbxStart is the "Shift Start time."

When the time is changed the time next to "Turn oven on" in the selected listbox should be updated, therefore updating the times of the other things in the listbox.
ATM when i change the Start time instead of updated the "Turn oven on" Time it adds new ones under the data. Every time i change anything in the Start time textbox it adds a new "Turn oven on"

OK. Let me try this:

Private Sub tbxStart_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxStart.TextChanged

' don't process this line unless there are at least 4 characters in the text box.
If tbxStart.text.length < 4 then exit sub

Dim dtmTurnOvenOn As Date = #12:00:00 AM#
Dim strStart As String = dtmTurnOvenOn.ToString("t")

strStart = tbxStart.Text
tbxStart.Text = Format(#12:00:00 PM#)

' This code determines the oven.
If rdbOven1.Checked = True Then
' This adds an item to the checkbox. It doesn't modify anything already in there.
' lbxOven1.Items.Add(strStart & (" Turn On, Heat (15) "))

Dim tStr as string
Dim TimeStr as string
Dim OpStr as string
for i as integer = 0 to lbxOven1.Items.Count-1
tStr = lbxOven1.Items(i)
... ' parse the string into the time, TimeStr, and the operation, OpStr.
... Update the time string
TimeStr = something.
tStr = TimeStr & OpStr ' add them together again
lbxOven1.Items(i)=tStr ' put it back into the listbox
Next
lbxOven1.Update ' make the listbox repaint itself.
End If

End Sub

If you're unsure how to parse the string, I can show you that.

dan28
May 6, 2009, 06:36 AM
A few error messages from that code. From this part:

For I As Integer = 0 To lbxOven1.Items.Count - 1
tStr = lbxOven1.Items(I)
... ' parse the string into the time, TimeStr, and the operation, OpStr.
... Update the time string
TimeStr = something.
tStr = TimeStr & OpStr ' add them together again
lbxOven1.Items(I) = tStr ' put it back into the listbox
Next
lbxOven1.Update() ' make the listbox repaint itself.
End If

option strict on disallows implicit conversion from 'object' to 'string'.

and the rest were just from things like the... and = something.

I have no idea how to parse strings so if you could show me that would be great.

Thanks

Perito
May 6, 2009, 06:50 AM
To fix the option strict problem, change to

Dim tStr As String = lbxOven.Items(I).ToString

"Parse" means to break a sentence into its parts. In programming, it means to break down a string into pieces.

http://en.wikipedia.org/wiki/Parsing

Now, for parsing. If your times are always entered in the format "hh:mm text" with a two-digit hour, a colon, a two-digit minute, and a space, then we can parse it like this:

for I as integer = 0 to lbxOven1.Items.Count-1
Dim tStr As String = lbxOven.Items(I).ToString
TimeStr = tStr.SubString(0, 5) ' start at character 0, take 5 characters. Ignore the space.
Dim L as integer = tStr.length
OpStr = tStr.SubString(6, L-6) ' get the operation

Now update the time. The time in the listbox is in TimeStr. Replace TimeStr with whatever time you wish.
TimeStr =...
lbxOven1.Items(I) = TimeStr & " " & OpStr
Next
lbxOvem1.Update

Another option for parsing would be to insert a character, possibly a "-" between the time and the operation. The string could be parsed like this

Dim P As Integer = tStr.IndexOf("-"c) ' P is the position of the "-".
TimeStr = tStr.SubString(0, P-1).Trim ' Take everything before the "-", and delete leading and trailing spaces.
OpStr = tStr.SubString(P+1, tStr.Length - P - 1)
...
lbxOtem1.Items(I) = TimeStr & "-" & OpStr

Of course, if there is no "-", this code will fail so you need to make sure that there is always that character in the string.

dan28
May 7, 2009, 09:03 PM
Thanks for your help Perito.
I've managed to get the start time working.
My next problem is getting the bakery items to insert after the "Turn on, Heat" text in the list box and before the other 3 texts. ATM they are just going after everything.
I also need to work out how to get them to add the time that's in the brackets to the time shown next to them as shown in the image in Oven 2.
The start time text box is a string so will also need a way to avoid getting bad times such as 9:73 instead of 10:13.
All help is much appreciated.

Perito
May 8, 2009, 04:58 AM
My next problem is getting the bakery items to insert after the "Turn on, Heat" text in the list box and before the other 3 texts. ATM they are just going after everything.


I hope I understand this correctly. If you wish to insert them before other texts, you can't use lbxOven1.Items.Add() because that will simply put the new string at the end. You should make use of the lbxOven1.Items array to figure out where to put the next item. (but see my last idea, below).



I also need to work out how to get them to add the time that's in the brackets to the time shown next to them as shown in the image in Oven 2.
The start time text box is a string so will also need a way to avoid getting bad times such as 9:73 instead of 10:13.


One idea that would solve all of these problems is to keep the operations and times in either two arrays or an array of struct.

Private Structure OvenStruc
Public OvenOp As String
Public Optime As DateTime
End Structure
Private OvenOps() As OvenStruc

' This assumes that Op.Optime is properly set before calling this routine
' it adds a record to the OvenOps array.
Private Sub AddOperation(ByVal Op As OvenStruc)
Dim index As Integer
Dim found As Boolean = False
For i As Integer = 0 To OvenOps.GetUpperBound(0)
If Op.Optime > OvenOps(i).Optime Then
index = i
found = True
Exit For
End If
Next
ReDim Preserve OvenOps(OvenOps.GetUpperBound(0) + 1) ' enlarge the OvenOps array
If found Then ' add at index
For i As Integer = index To OvenOps.GetUpperBound(0) - 1
OvenOps(i + 1) = OvenOps(i)
Next
OvenOps(index) = Op ' insert the operation
Else ' add at the end
OvenOps(OvenOps.GetUpperBound(0)) = Op
End If
End Sub

' This deletes an operation from the OvenOps array.
Private Sub DeleteOperation(ByVal index As Integer)
If OvenOps.Length >= 1 Then
Dim Counter As Integer = OvenOps.GetUpperBound(0)
For i As Integer = index To Counter - 1
OvenOps(i) = OvenOps(i + 1)
Next
ReDim Preserve OvenOps(Counter - 1)
End If
End Sub

Private Sub Fill_Listbox()
Dim TimeStr As String
lbxOven1.Items.Clear() ' completely empty the listbox.
For i As Integer = 0 To OvenOps.GetUpperBound(0)
TimeStr = Format(OvenOps(i).Optime, "hh:mm tt ")
lbxOven1.Items.Add(TimeStr & OvenOps(i).OvenOp)
Next
lbxOven1.Refresh()
End Sub

When you wish to add an item to the array, you enter the time and the operation into the OvenOps array; then call AddOperation. If you wish to delete something, call DeleteOperation. Of course you'll still have to adjust some of the times somewhere, but it should be simpler since the times will be in the DateTime format. That format is easier to handle -- to add or subtract times from.

Instead of parsing strings from the listbox, simply fill the listbox each time there's a change. Fill_Listbox shows how this is done.

dan28
May 13, 2009, 03:47 AM
Thanks perito. With using your code and some others my partner and I have gathered we came up with this:



Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click

'adds ticked items to list boxes

Dim chkBakeItem As CheckBox
Dim intIndex As Integer = lbxOven1.Items.Count
Dim intIndex2 As Integer = lbxOven2.Items.Count
Dim intIndex3 As Integer = lbxoven3.Items.Count


If tbxStart.Text = "" Or tbxFinish.Text = "" Then
MessageBox.Show("Please enter Start and Finish times of shift before adding items")

Else : For Each chkBakeItem In gbxBakeryItems.Controls


If chkBakeItem.Checked = True And rdbOven1.Checked = True Then
lbxOven1.Items.Insert(intIndex - 3, (("00:00 ") + (chkBakeItem.Text)))

ElseIf chkBakeItem.Checked = True And rdbOven2.Checked = True Then
lbxOven2.Items.Insert(intIndex2 - 3, (("00:00 ") + (chkBakeItem.Text)))

ElseIf chkBakeItem.Checked = True And rdbOven3.Checked = True Then
lbxoven3.Items.Insert(intIndex3 - 3, (("00:00 ") + (chkBakeItem.Text)))


End If
Next

Dim intPosition, intBakeTime As Integer
Dim strCurrentString As String
Dim strBakeryItem As String
For i = 0 To lbxOven1.Items.Count

strCurrentString = lbxOven1.Items(i).ToString
strBakeryItem = strCurrentString.Substring(6, strCurrentString.Length - 6)

intPosition = strCurrentString.IndexOf("(")
intBakeTime = CInt(strCurrentString.Substring(intPosition + 1, 2))
'MessageBox.Show(intPosition & " " & intBakeTime)

If i = 0 Then

Else
'finds the space after the time in the string
Dim intspace As Integer = strCurrentString.IndexOf(" ")
'takes the string of the whole time
Dim strTime As String = strCurrentString.Substring(0, intspace)
'takes the string of the minutes
Dim strMinutes As String = strCurrentString.Substring(3, 2)
'finds position of ":"
Dim intColons As Integer = strCurrentString.IndexOf(":")
'takes string of the hrs
Dim strHours As String = strCurrentString.Substring(0, intColons - 1)
'take the previous time and add it to the beginning of the current item
Dim strPrevious As String = strMinutes(i - 1) ' This is where the error message comes up
'makes time of current item = previous time
Dim strNew As String = strPrevious
'edits string to add baking time
strMinutes = CStr(intBakeTime)

If CDbl(strMinutes) > 59 Then
strHours = CStr(CDbl(strHours) + 1)
strMinutes = CStr(60 - intBakeTime)

End If

The error message we get is "Index was outside the bounds of the array"

Any ideas on where we went wrong?