Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Keep in mind that just because you can solve a problem with recursion it doesn't mean that you should. Traversing a binary tree is a good example of where recursion is desirable, and actually produces clearer code than alternatives. Calculating factorials is a usual example to teach recursion. But that's all it is useful for. It is not a good idea to calculate factorials using recursion. Too much overhead for too little gain.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

In the classic sci-fi novel, The Shockwave Rider, John Brunner wrote

There are two kinds of fools. One says, "This is old, and therefore good." And one says, " This is new, and therefore better.”

My thoughts, exactly. I think I will take an existing app that I developed in WinForms and reproduce it in WPF and see what I think of the differences.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

It sucks (abandoning WinForms). I'm awfully tired of Microsoft pushing their "latest and greatest", then abandoning it for the next "latest and greatest". Because I develop apps only for my personal use I will likely just continue usinig WinForms under Visual Studio 2010 as long as it continues to run. I figure that when I finally make the move to WPF Microsoft will toss it in favour of the next next best thing.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Post your code. When I used the following code it worked fine.

    Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
        TextBox1.Text = ListBox1.SelectedIndex
    End Sub
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You can get the command line arguments in the collection My.Application.CommandLineArgs

Because you are passing the filename as an argument to your program, you would process it (open the file) in your form load event handler.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

There is no event that I am aware of that triggers when you open a file from within your program. You don't need an event triggered because you are already executing code, starting with the method you called to open the file. As for "open with", you can set your program as the default in the Open With dialog. If you don't want to set it as the default then clear the "Always Open With" checkbox.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Using a DLL does not decrease the speed of a process. Compiled code is compiled code whether it resides in a main module or a library. By putting common code into a DLL, however, you make it available to multiple projects without having to recompile it, and (as far as I know) if several active processes use the same DLL, it only has to be loaded into memory once. Furthermore, when you modify a DLL, you do not have to rebuild and reinstall the programs that use that DLL.

The downside is that you have to be very careful that any changes you make to the DLL do not break any of the programs that use it.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I suggest you have a look at TrueCrypt. It is open source and free and I have used it for years. You can create an encrypted file of a user-specified size. Once the file has been created you mount it (via TrueCrypt) as a virtual drive then copy files to/from that drive just like you would any other drive. Files are automatically encrypted/decrypted on the fly. If the TrueCrypt file is examined via a hex editor, the data is indistinguishable from noise. You can find it at http://www.truecrypt.org/

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

The how about

SELECT * FROM <table> WHERE DATEPART("YEAR",GETDATE()) - YEAR(<asset age column>) = 3

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

To make it more general you could replace

= 2009

with

DATEPART("YEAR",GETDATE())-3

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Can you zip and post the entire project or is it too large (or confidential)?

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Doesn't matter. I used an example with hard coded values. If instead of

"where UserName = 'Jim'"

you used

"where UserName = '" & txtUserName.Text & "'"

then it would do what you want. By specifying the username in the where clause you affect only records for that username. By also specifying DateOut = '' you further restrict to affect only the specific username who has not logged out.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Sleep is good. Coffee is better.

Let's say your audit table looks like

UserName    DateIn                 DateOut
--------    -------------------    -------------------
Jim         2012-03-27 11:30:23    2012-03-27 11:45:19
Jim         2012-03-29 08:15:12

And the current date is today. The reason that record two has no value for DateOut could be one of

  • The network failed
  • The server died
  • The user kicked out the power cord on his computer

Or several other reasons. In any case, when Jim goes to log back in he will end up with the following

UserName    DateIn                 DateOut
--------    -------------------    -------------------
Jim         2012-03-27 11:30:23    2012-03-27 11:45:19
Jim         2012-03-29 08:15:12
Jim         2012-04-01 13:24:17

This is not good because it looks like Jim has logged in twice without logging out. Come to think of it, if it is possible for a user to log in on two different machines at the same time then you might add a machine name field to the audit table (a good idea in any case). Let's keep it simple for now. When the app starts you will have to check for unclosed logins and put some value in to "close" them. Let's assume that has been done and the audit table now looks like

UserName    DateIn                 DateOut
--------    -------------------    -------------------
Jim         2012-03-27 11:30:23    2012-03-27 11:45:19
Jim         2012-03-29 08:15:12    2012-03-29 24:00:00
Jim         2012-04-01 13:24:17

If you were to use the query

UPDATE AuditTrail SET DateTimeOut = now() where Username ='Jim'

You would end up with

UserName    DateIn                 DateOut
--------    -------------------    -------------------
Jim         2012-03-27 …
poojavb commented: very nice explained.... +3
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You have to get your system or database admin to set up the database on the server and assign permissions. If you are going to allow multiple copies of your program to use the database concurrently then you will have to build in some sort of interlock to prevent multiple users from updating the same records at the same time. You will connect to the database using a connection string that incorporates the network name of the database server.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

If you are just saving it into the database then you don't need datasets and datatables. But I suggest you use a datetime field instead of separate date and time. To add the login record you can do

Dim con As New ADODB.Connection
con.Open("Driver={SQL Server};Server=.\SQLEXPRESS;Database=mydb;Trusted_Connection=yes;")

Dim query as String = "insert into AuditTrail (UserName,LevelOfAccess,DateIn,TimeIn) "
                    & "  Values(" & Quote(TextBox1.Text)      & "," 
                    &               Quote(LevelOfAccess.Text) & ","
                    &               Quote(Now())              & ")"

con.Execute(query)
con.Close

Private Function Quote( field As String) As String
    Return "'" & field & "'"
End Function

The query to update the audit trail when the user logs out is

Dim query as String = "update test1 set DateOut=getdate() where DateIn="
                    & "  (select MAX(DateIn) from Test1 where UserName = '" & username & "')"

Keep in mind that you may need cleanup code to resolve records where a DateOut is not inserted due to program, machine or network failure.

Begginnerdev commented: Nice formatting. +4
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I'll check it out. Thanks.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I checked a few sites for "standard Markdown language" and didn't see any references to "~~~". Can you provide a link? Just my two cents but it seems like a step back to expect posters to have to learn another "language". I am familiar with HTML and don't have a problem with using tags to format things like lists, bolding, etc but "~~~" is more than a little obscure. I see too many posters who couldn't even bother to use the old style CODE and /CODE format.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

That's somewhat different from the old style of code tags and definitely not intuitive. Is there any place that explains how the new system works? For example, as I am typing, the code tag in the first sentence is blue and underlined and everything following that is red. I don't know why. And the live preview shows absolutely no formatting changes.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You can't just post a page of code with no comments and expect us to tell you what is wrong with it. Tell us what it is supposed to do, then tell us what it is actually doing. Any error messages that pop up would be useful to know as well.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Usually, when you want to pause until a user has entered data, you display a modal form with the input fields. Because the form is displayed as modal, the calling form waits until it closes. You can always create a basic input form and dynamically create textboxes for the input data. If you don't want to create the controls at run time, and you know the maximum number of text entry fields then you can create them at design time and hide/show them as required.

Or, your input form could have one set of text boxes for data entry, and the user clicks an ADD button which adds the new fields to an array or collection. The only way to exit the form (other than CANCEL) is to enter the required number of items.

Again, no polling loop required.

No polling loop required.

If you want to zip and post the project I can have a look.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Try "\(\d{3}\) \d{3}-\d{4}" for the pattern. That requires a space between the area code and the number. Remove the space if you don't want it.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You'll have to be clearer as to what you want to do.

i loop a groupbox which contains other controls(label, radiobutton, textbox)

You can do anything you want in a loop. I can't offer a suggestion unless I have a clear idea what you are doing. The last suggestion was on how to display a sequence of forms without using a wait loop. That was a clearly defined goal. If you can be more specific I'd be glad to help.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Please try to explain this a little clearer.

i have two textboxs which have figues in them and need the 3rd textbox to display the figure

I have no idea what you want to display in the third textbox. I also have no idea why you are using a SQL query. An example of a clearer explanation would be:

I have two text boxes, TQTY and TUP. I want to multiply the numbers in these two text boxes and display the results in a third textbox, TCOST.

In which case I would reply:

First you have to determine that TQTY and TUP both contain numeric values. A simple way to do this is with the IsNumeric function. After that you can multiply them and display the result as follows:

TCOST.Text = Convert.ToSingle(TQTY.Text) * Convert.ToSingle(TUP.text)

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

We can probably give more help if you can be more specific as to the type of search. Lacking that, it looks as if you are on the right track. SQL uses "%" and "_" for wildcarding. A good explanation with examples can be found here.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You don't need to put the code into a timer. It can be put into the hadler for the zoom click event(s). In pseudo code it looks like

Private Sub zoom_IN
 
   'put zoom in processing code here

    toolBar_zoomOut.Enabled = zoom > 1
    toolbar_zoomIn.Enabled = zoom < 63

End Sub

Private Sub zoom_OUT
 
   'put zoom out processing code here

    toolBar_zoomOut.Enabled = zoom > 1
    toolbar_zoomIn.Enabled = zoom < 63

End Sub

"zoom > 1" evaluates to True if zoom is greater than 1 and False otherwise. This is a concise statement of

If zoom > 1 Then
   toolBar_zoomOut.Enabled = True
Else
   toolBar_zoomOut.Enabled = False
End If

In other words "If we aren't zoomed out as far as possible then enable the zoom out button".

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

The idea of event driven systems is to avoid polling/idling loops. Polling/idling uses CPU cycles unnecessarily and slows down anything else that may be running at the same time. One way to avoid this when you need to process several forms in succession and in a specific order is to daisy-chain the forms. When the user completes a form, either by clicking an "OK" or "NEXT" button, that form can call up the next form as part of its Close event handler. Another possibility is to create an array of form references and display them modally in a loop as in

Private myforms() as Form = {
   frmForm1,
   frmForm2,
   frmForm3
}

.
.
.

    For Each frm As Form In myforms
        If frm.ShowDialog() <> Windows.Forms.DialogResult.OK Then
            MsgBox("processing interrupted")
            Exit For
        End If
    Next

The second approach makes it easier to rearrange the order in which the forms are displayed as it decouples the forms.

A third approach is to use state transition logic in which you have a global state variable which determines which form is the next one to be displayed. The next form (or state) would be determined by the completion status of the previous form. This approach would be useful when the order of the forms is not fixed. There would be two possible "final" states - one in which all of the forms had been successfully completed, and one in which the user bailed out (or errored out).

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Your "Case zoom = 1" and "Case zoom > 1" may never get executed. If zoom = 1 then it will get processed by the "Case zoom < 63" clause. If zoom = 12 then "Case zoom < 63" will also trap it. You'll have to define your case clauses more precisely. Perhaps

toolBar_zoomOut.Enabled = zoom > 1
toolbar_zoomIn.Enabled = zoom < 63

would work better.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I suggest you reconsider connecting via the IP address. Let the infrastructure take care of name/address translation for you and just connect using the server name. Using the IP address could impact database access in a system where clustering/mirroring provides high availability.

ryklon commented: Thanks for the tip! +1
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You wouln't be able to use the ADO method because the fields aren't enclosed in quotes. The address field contains commas and these would be interpreted as field separators. I think the Filter option is your best bet. Read the entire file into a string array then filter on the ID plus a comma. Because this may also match something in the address portion you will still have to do a check on every line in the FIlters array to see if a line starts with the required string.

Dim alltext() As String = System.IO.File.ReadAllLines("d:\temp\test.txt")
Dim lookfor As String = "095" & ","

For Each line As String In Filter(alltext, lookfor)
    If line.StartsWith("095,") Then
        MsgBox("found " & line)
    End If
Next

I create the search string (lookfor) by concatenating an ID value with a comma. You will have to replace "095" with the variable (or textbox.Text object) containing the ID you are looking for. The "Filter" call reduces the array to only those lines containing <lookfor> in any position and the For loop find the line beginning with that value.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You relate two (or more) tables by having one or more columns in common. For example, a customer database would typically have a customer information table similar to

CUST_INFO
   Cust_ID
   Last_Name
   First_Name
   Address

where Cust_ID is a unique number generated by the app or the datbase system. Any other table that relates data to a customer would also contain a Cust_ID field. For example, an order table might look like

ORDER_INFO
    Order_No
    Cust_ID
    Order_Date
    Shipping_Date

If you had a query that required information from both tables you would use a join (implicit ot explicit) which refers to the requested fields and the field that relates the two tables. An explicit join looks like

select * from CUST_INFO inner join ORDER_INFO 
           on CUST_INFO.Cust_ID = ORDER_INFO.Cust_ID

An implicit join looks like

select * from  CUST_INFO,ORDER_INFO
         where CUST_INFO.Cust_ID = ORDER_INFO.Cust_ID

Using aliases can shorten the typing a little by

select * from  CUST_INFO As CI,ORDER_INFO As OI
         where CI.Cust_ID = OI.Cust_ID

A very good tutorial on joining SQL tables can be found here

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I don't have enough info to really understand your problem or to comment on a possible solution but I do have a suggestion as to your table design.

I strongly suggest that you create a separate table that contains (minimum) two columns. One column should be the patient's name, the other should be a unique ID. The remaining tables should refer to the patient only by ID. In the event that you have two patients with the same name then a third coolumn should be added to uniquely identify a patient (birth date, address, phone number, etc). It is not a good idea to duplicate information in a database. Let's assume that you have a patient named Joanne Johnson. With your current schema, that name would appear in multiple tables. If you were to acquire a second patient with the same name you would have to modify all of your table structures to distinquish them. Also, If Joanne Johnson changes her last name (marriage, divorce, etc) then you would have to modify all records in all tables that refer to her. However, if you store the name in only one table, only that one table needs to be updated.

Another reason is that a unique ID can be generated in four bytes of storage (more if a GUID is used). A name is typically stored as a varchar and will always require more than four bytes.

A further reason is that my suggested schema divides the patient …

adam_k commented: I agree +9
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Select the DataGridView in designer mode and examine the entries under the Events tab in the properties panel. You will see events like

CellClick
CellEnter
CellLeave
etc.

One of them should be what you are looking for.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Try

For Each i As String In My.Resources.TextFile1.Split(vbCrLf)

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

My mistake. The link in the email took me to the bottom of the thread and I mistook the post from Ge48 as a post from the OP. Anyway, if the OP can please post a sample of the file being searched, and a sample of the text to search for I can post some specific code.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

This won't work unless oldname is the only string on the line. According to your OP, the file format was " ID, Name, Address, Birthday, Pay-Roll Type". In the OP you said you were scanning for "ID". Now it appears you are scanning for "name", at least based on the comparison "if line = oldname Then". If you want to nail this down then I need you to be precise. Also, if you noticed I had suggested

Dim alltext() As String = System.IO.File.ReadAllLines(myfilename)

which reads all of the text file and splits it into an array of lines in one step. This works whether the lines are terminated by vbCrLf or just vbLf. Your way (using a streamreader and a Split) may not work for both cases.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

This piece of code won't work, I'm not sure why, it says string cannot be converted to 1 dimensional array of object and Include As Boolean = True, twice.

I'd have to see the actual code that you ran, the exact error message and the contents of the text variables you included in the Filter call.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I used the following code with the sample data I posted above.

Private Sub login_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles login.Click

        Dim con As New ADODB.Connection
        Dim rec As New ADODB.Recordset

        con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Temp;Extended Properties=""text;HDR=YES;FMT=Delimited""")
        rec.Open("select * from test.txt where ID='123'", con, CursorTypeEnum.adOpenForwardOnly)

        Do Until rec.EOF
            Debug.WriteLine(rec("ID").Value & " " & rec("Name").Value)
            rec.MoveNext()
        Loop

        rec.Close()
        con.Close()

It worked.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

If you want to use the file as a data source it can be done using ADO as follows

Imports ADODB

Public Class Form1
    .
    .
    .
 
'assuming the user clicks on btnLogin after entering a userid

   Private Sub login_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles login.Click

        Dim con As New ADODB.Connection
        Dim rec As New ADODB.Recordset

        con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & myFolder & ";Extended Properties='TEXT;HDR=YES;FMT=DELIMITED'")
        rec.Open("select * from " & myFile & " where ID='" & txtUsedID.Text & "'", con, CursorTypeEnum.adOpenForwardOnly)

        if rec.EOF Then
            'userID was not in the file
        else
            'userID was found
        End If
        
        rec.Close()
        con.Close()

    End Sub

Note the part of the connection string that states HDR=YES. This indicates that the first line of the file contains the names of the fields such as

"ID","Name","Address","Birthday","Pay-Roll Type"
"123","Ferguson, John","704 Hauser St.","1984-01-13","Hourly"
"902","Jefferson, George","East Side","1953-12-20","Salaried"

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You can replace the string with something like

Dim filtered() As String = Filter(text, txtUserID.text)

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

One easy way is to use a filter as in

Dim alltext() As String = System.IO.File.ReadAllLines(myfilename)
Dim filtered() As String = Filter(text, "12345")

You may have to include the field delimiters (commas, perhaps) in the filter string to prevent matches on the ID string if it should happen to occur in another field.

Another possibility, if the fields are regular and delimited is to open the text file as a data source and use a SQL query to select the records of interest. I can help with that if you want to go the SQL route.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I think the technique you want to use is called Gaussian Elimination. I must have written this code a half dozen times when I was back in university. I did versions with simple elimination, partial and full pivoting (actual and virtual). I hated it every time and I have long since forgotten how to do it but a walk-through with code can be found here. The technique can be used to solve for n equations in n unknowns.

And don't get me started on eigen values or linear diophantine equations. I don't recall what they are for but it is cool to be able to rattle off the names. Of course I didn't think so at exam time;)

Trivia - for matrices that are non-singular, the computer language, APL, has a single operator (quad divide) that does all that for you.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I like Mitja's idea of

Private pressedButton As Button

That way you have access to all of the button info for the last pressed button, not just the button name.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Using a common event handler will work as long as the buttons have similar functions. If they do not then to keep track of the last button pressed you should only have to declare a class level string such as

public partial class Form1 : Form
 
    Public lastButton As String
    .
    .
    .
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        lastButton = sender.Name

Just add the last line to each button handler.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Couldn't help but notice there is no "Handles" clause on

private void Button_Click(object sender, RoutedEventArgs e)

so perhaps nothing is happening because the code isn't attached to the button.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

You declared a bunch of doubles then you didn't use them. Your comparisons use redundant expressions in some cases and incorrect comparisons in others. Use intermediate variables to remove redundant conversions (and to allow checking in the debugger).

If chkOvertime.Checked = True           'bad  - *.Checked is already a boolean value
If chkOvertime.Checked                  'good - remove the unnecessary comparison

And txtHoursOvertime.Text = "" = False  'bad  - unnecessary comparison to boolean
And txtHoursOvertime.Text <> ""         'good - simplify comparison

And lstHourlyRate.SelectedItem = True   'bad  - *.SelectedItem is not a boolean
And lstHourlyRate.SelectedItem >= 0     'good - replace with comparison to same type (int)

And txtHoursOvertime.Text = True        'bad  - *.Text is not a boolean value
And txtHoursOvertime.Text <> ""         'good - replace with comparison to string

'use "&" to concatenate strings instead of "+"
'convert strings to numbers before doing calculations
'remove redundant conversions

If chkOvertime.Checked And txtHoursOvertime.Text <> "" And lstHourlyRate.SelectedItem >= 0 And txtHoursOvertime.Text <> "" Then

    Dim basicHours As Double = Double.Parse(txtHoursWorked.Text)
    Dim basicRate  As Double = Double.Parse(lstHourlyRate.SelectedItem)
    Dim otHours    As Double = Double.Parse(txtHoursOvertime.Text)
    Dim otRate     As Double = 2 * basicRate
    Dim basicPay   As Double = basicRate * basicHours
    Dim otPay      As Double = otRate * otHours 
    Dim totalPay   As Double = basicPay + otPay
    
    MessageBox.Show( _
        "Basic hours worked:   " & basicHours.ToString("$0.00") & vbCr & vbLf & _
        "Hourly rate of pay:   " & otRate.ToString("$0.00") & vbCr & vbLf & _
        "Basic pay:            " & basicPay.ToString("$0.00") & vbCr & vbLf & _
        "Overtime hourly rate: …
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Glad to help. Don't forget to mark as solved.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

tl;dr?

How about this

Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        Dim words() As String = Split("Some luck lies in not getting what you thought you wanted but getting what you have which once you have got it you may be smart enough to see is what you would have wanted had you known")

        For Each word As String In words
            ListBox1.Items.Add(word)
        Next

    End Sub

    Private Sub btnScan_Click(sender As System.Object, e As System.EventArgs) Handles btnScan.Click

        Dim unique As New Dictionary(Of String, Integer)

        For Each item As String In ListBox1.Items
            If unique.ContainsKey(item) Then
                unique(item) += 1
            Else
                unique(item) = 1
            End If
        Next

        For Each key As String In unique.Keys
            ListBox2.Items.Add(key & " (" & unique(key) & ")")
        Next

    End Sub

End Class

I set the Sorted property on ListBox2 to True.

powermatt commented: worked great +0
Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

I don't see that you need a custom control for that. Just seven multiline textboxes labeled with the corresponding date and possibly a calendar control to select a particular week.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Can you be more specific on the look and feel of the control you are looking for? "Some sort of calendar" is not a lot to go on. If you just want a datebook type program there are several free ones available. Several can be found here. There is also RedNoteBook available here but it might be a little more than you are looking for featurewise.

Reverend Jim 5,225 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

Got it (I think). Note that the variable names are different than the last example to reflect the more generic nature of the code.

Public Class Form1

    Public ctrlArray As New Dictionary(Of String, Label)
    Public curritem As Label

    Private Sub btnAddItem_Click(sender As System.Object, e As System.EventArgs) Handles btnAddItem.Click

        'create new listbox item and associated control

        Dim key As String = "item " & ctrlArray.Count
        Dim newitem As New Label

        newitem.Location = New System.Drawing.Point(140, 13)
        newitem.Size = New System.Drawing.Size(300, 260)
        newitem.Visible = False
        newitem.Text = key

        'add the new control to the control array, then add new listitem.

        Me.Controls.Add(newitem)
        ctrlArray.Add(key, newitem)
        ListBox1.Items.Add(key)

    End Sub

    Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged

        'hide the current visible control

        If Not curritem Is Nothing Then
            curritem.Visible = False
        End If

        'make the newly selected control visible

        If ListBox1.SelectedIndex >= 0 Then
            curritem = ctrlArray(ListBox1.SelectedItem)
            curritem.Visible = True
        End If

    End Sub

    Private Sub btnRemove_Click(sender As System.Object, e As System.EventArgs) Handles btnRemove.Click

        Dim key As String = ListBox1.SelectedItem
        curritem.Visible = False
        curritem = Nothing
        ctrlArray.Remove(key)
        ListBox1.Items.RemoveAt(ListBox1.SelectedIndex)

    End Sub

End Class

This one uses dynamic labels for testing. Replace "Label" with "PropertyGrid" or any other control. Don't forget to mark as solved if this is what you are looking for.