VB time input, a better way to do it? - vb.net

Working on a handy program for my boss at work as a summer project in between semesters both to make life easier for her, and to practice and improve my skills. Intent is to allow her to quickly and easily calculate the hours and minutes the person worked. The form itself has a series of text boxes for the Clock in and Clock out time for each day that week. Currently it attempts to convert the txtbox text into a Date variable, then .Subtract()'s the start from the end and stores it in a rolling total variable which is displayed at the bottom of the form. I can't help but think there is a better way of going about doing this, and I'm absolutely certain that having the below block of code 21 times (7 days, 3 shifts) is inefficient.
Dim StartTime As Date
Dim EndTime As Date
Dim Worked As System.TimeSpan
Dim WorkedTotal As System.TimeSpan
If chkFirst.Checked = True Then
StartTime = CDate(txtMonStart.Text)
EndTime = CDate(txtMonEnd.Text)
EndTime = EndTime.AddHours(12)
Worked = EndTime.Subtract(StartTime)
lblMonWork.Text = Worked.ToString()
WorkedTotal += Worked
Currently it works, mostly. The user has to enter the ":" in the time input, and if the total exceeds 24 hours, it displays a day column (40 hour 12 min work week displays as 1.16:12). I'd like to eliminate both of these unplanned features and allow for my input validation to take place when the focus changes to another box. A changing bgcolor would indicate an invalid input.
Any bright ideas?

Instead of using TextBox for the time input, use DateTimePicker, just change the Format property to Time.
Handle the Validating event of the DateTimePicker and if it's invalid just set e.Cancel = False, that way they can't save changes unless it's valid. Or if you want them to be able to leave the DateTimePicker and just change the colour, just handle the ValueChanged event instead.
Regarding your code sample, I haven't really looked at the logic of it, but instead of having the same code 21 times, just move the code into a separate function and then call that function with the start and end times as parameters and it can return the workedtime as it's return value.
I'm not sure what your UI looks like but if you're repeating the start time and end time input control multiple times as well it might be worth looking at creating your own usercontrol that can contain one each of the start and end time controls, and then you could have the validation be inside that user control so you don't have to have lots of event handlers etc.

Related

Seeking suggestion to count time inside the loop

I am trying to measure/count the time inside the while loop, I tried a couple of methods but couldn't find the solution yet.
Here is my current VI.
 
In short, I am trying to measure the time as long as the "Boolean is on/true" and once it's off/false the time must be displayed.
If something is not clear then please let me know.
I may be repeating Fourier's answer, but typing it in two different forms may be helpful to you since I note you haven't accepted that answer yet.
Remove the outer While Loop. It is superfluous.
Then do this:
In the "turn on" frame, you gather the current Tick Count and stash it in a shift register. In the "turn off" frame, you gather the Tick Count again and subtract. In all the other frames, make sure you wire the two tunnels together so you don't lose your Tick Count. Side note: you probably want Boolean to be an indicator, not a control, so your user cannot click on it and toggle it directly.
You can reach your goal with simpler code. You should use one while loop only with the Event Structure:
When List of Conditions changes, intercept the event (as you are already doing) and register the time when this event happen (with the VI Tick count for example).
in two shift registers,"save" the time you registers in the previous point and the status of your count (a boolean should be enough: counting/not counting).
Then, in the Timeout event you calculate in real time the time passed with the following operation current time (Vi Tick count) - event time (save in the shift register).
You should count time only if your boolean Counting/not counting is True.
When you detect another event List of Conditions Value Change, you should check if you should stop count time or not.
Finally, in the Timeout event or in the List of Conditions Value change event, evaluate the stop condition for your while loop.

VB .net datetimepicker reporting wrong value

Ok, so I'm experiencing some strange behavior in datetimepicker fields in my program. I use Short format usually, and use a pair of them for date range selections.
The problem i'm experiencing is if a user is using the keyboard for input. they can tab and arrow through the field like normal to key in a date. However if the date part they are entering doesn't fill it's section of the mask and then they press enter to activate the formdefault without shifting focus away from that portion of the date, then the value of the DTP when the ok_button.click event is run is whatever value it had in it BEFORE they typed their change.
to give a specific example:
A user tabs into the date field. the default date in the field is today's date, 4/14/2015. They type in 1, arrow to the day, put in 1, then arrow to the year and type 14, then press enter. The reported value of the DTP is going to be 1/1/2015. Had they instead actually typed out 2015, or used the arrow to move to another date part or tab to shift focus to another control, the DTP will auto update to fill in the rest of the year.
The same problem would exist if they had typed in a 1 for the month and then hit enter, but would NOT happen if they put in a 12 for the month.
The only solution I can think of, and I haven't yet tried to implement it because it sounds like a real kludge and would require me to go through at TON of forms in the project, would be to change the keypress event for enter to shift focus to the OK button, and THEN invoke the formdefault.
I will say that most of the datetimepicker fields on my forms are actually contained within a user control, so if this is a property that can be changed in the control or tied to an event in the control, it would make updating much, MUCH easier.

vb Count Up From Time (Last Updated: ** Seconds/Minutes Ago)

Okay, I hate just posting a question with no code, but I literally have no idea how to get started other than to user a Timer. I have a Visual Basics program which works with an SQL Table. I'd like to have a label which shows the user how 'old' their display of the table is.
Each time they edit or refresh the table a label is refreshed with a current time stamp. Formatted as 03:19;27.
However, I'd like to show how many seconds or even just minutes the table was last updated.
For example: 'Last updated: 22 Seconds Ago' OR 'Last Updated: Less Than A Minute Ago'.
How could I do this?
The TimeSpan object provides all of the properties you need to format the message however you want. The formatting options in it's ToString method may also be very helpful to you. To get a TimeSpan object, you can simply subtract one Date from another, like this:
Dim span As TimeSpan = lastQueryDate - Date.Now
Dim message As String = String.Format("Last Updated: {0} Seconds Ago", span.TotalSeconds)
Or, if you want to use a Stopwatch object, you could get the span of time since the stopwatch was started by accessing its Elapsed property, which is also a TimeSpan object.

Adding two different dates in VB.net, without using 'Now'

I have been looking through a bunch of different posts on here and on other sites for adding two dates together, but for some reason everyone wants to use 'Now'
I would like to know how to add two different dates together when neither of which are now!
I have tried a few things but I am getting casting errors. Also worth noting I am setting it to the value of a dateTime picker on my page.
MaxDate.Value = MinDate.Value + TimeSpan.FromDays(1)
'does not work
MaxDate.Value = Now + TimeSpan.FromDays(1)
'does work!
If it is not obvious, I have two date pickers on my page and when a radio button is clicked I want to set the 'End date' (maxdate.value) to whatever the 'Start date' (mindate.value) is, and add one day to it.
Thanks for the help!
Just do this:
MaxDate.Value = MidDate.Value.AddDays(1)
You don't need create a TimeSpan object for that because the Date type has built-in methods for doing incrementation by day, month, year, minute, etc.
The AddDays method does not alter the original date, it just returns a new Date object with the offset value.
By the way, if you want to subtract a day, there is no MinusDays method, just do x.AddDays(-1).

Timing a simulation in a control loop

I have a labview vi which is in a control loop with PID . I want to insert a timer for the simulation. It should display the time of the simulation and also use that time to make changes in the control loop.
It is just a simple timer but I am not sure which one and how to use them. please help me
The simplest option, if it does what you need, is probably the 'Elapsed Time' Express VI.
Alternatively you can use the Get Date/Time in Seconds function. Read this function at the start of your simulation and pass the value in to your control loop (or read it on the first loop iteration and store the value in a shift register). Inside the loop, read the same function and subtract the value from the start value; that'll give you the elapsed time in seconds. If you want a display of this value just wire it to a numeric indicator. You can set the display format of the indicator to 'relative time' if you want to show hours, minutes and seconds.
The most natural option would be to use a Timed-loop, this allows you to detect whether your code can run in the supplied time and select a hardware time clock.