DEVTOME.COM HOSTING COSTS HAVE BEGUN TO EXCEED 115$ MONTHLY. THE ADMINISTRATION IS NO LONGER ABLE TO HANDLE THE COST WITHOUT ASSISTANCE DUE TO THE RISING COST. THIS HAS BEEN OCCURRING FOR ALMOST A YEAR, BUT WE HAVE BEEN HANDLING IT FROM OUR OWN POCKETS. HOWEVER, WITH LITERALLY NO DONATIONS FOR THE PAST 2+ YEARS IT HAS DEPLETED THE BUDGET IN SHORT ORDER WITH THE INCREASE IN ACTIVITY ON THE SITE IN THE PAST 6 MONTHS. OUR CPU USAGE HAS BECOME TOO HIGH TO REMAIN ON A REASONABLE COSTING PLAN THAT WE COULD MAINTAIN. IF YOU WOULD LIKE TO SUPPORT THE DEVTOME PROJECT AND KEEP THE SITE UP/ALIVE PLEASE DONATE (EVEN IF ITS A SATOSHI) TO OUR DEVCOIN 1M4PCuMXvpWX6LHPkBEf3LJ2z1boZv4EQa OR OUR BTC WALLET 16eqEcqfw4zHUh2znvMcmRzGVwCn7CJLxR TO ALLOW US TO AFFORD THE HOSTING.

THE DEVCOIN AND DEVTOME PROJECTS ARE BOTH VERY IMPORTANT TO THE COMMUNITY. PLEASE CONTRIBUTE TO ITS FURTHER SUCCESS FOR ANOTHER 5 OR MORE YEARS!

Programming Microsoft Word - 10 - Working With A Collection (Part 1)

What are we going to do in this tutorial?

In the previous tutorial, we covered the topic of include a database in your project. A great way to leverage work. The user (of your program)

One drawback of that program is the inability to process multiple sets of data. Once one set of information (the details of an individual or company) has been loaded, the program can only put out this set of information. A bit of a hassle if your user wants to process more parties to insert in a Word document.

In this tutorial, we are going to expand on the program made in the previous tutorial. Because of the length, the tutorial is divided over two parts. This first part consists of building the infrastructure in the program to handle the details of multiple 'parties'.

In the second part, the program will be tested with showing data to be processed through message boxes. Once this works, the use of message boxes is changed to inserting the data into a Word document. The goal is to add versatility to the program, so it can add the details of one party to a Word document (e.g., a contract) but also multiple parties. This is going to be a long tutorial, so please make some coffee and stretch your fingers…

Step 1

Before diving in the code, I will give a description of the general concept here. The first part of the coding is pretty cryptic and can be though to understand. It is helpful to understand what we are trying to do here so you do not lose sight of the big picture. You may remember that the program build so far takes data from the main form (Form1) from the user or from a database in your project. This data comprises of the details of one party (an individual or a company) and is contained in textboxes on the main form. The output is generated by taking the contents of these textboxes and showing them in a message box. You are going to change this.

Data of each party will not be stored in textboxes on the main form anymore, but in a separate container (a 'Class'). The details of each party that needs to be part of the program's output (in the first part of this tutorial: showing info on the screen through a message box), will be stored as a Class (a 'party' class). Subsequently, each class (holding the information of one party; either an individual or a company) will be stored in one single collection, holding the information of each party that the user wants to output. This collection will serve as one block of information that will be the output of the program.

Taking this step in the code will greatly advance your options to add additional features for the user, such as sorting or deleting data in the collection before going to the output stage. Classes are incredibly powerful in .NET. Let's get started with this part.

Start Visual Basic and open the project made in the previous tutorial (in my case named 'MyFirstFormWithDatabase'): File → Open Project. Alternatively, if you want to save the original program made in the previous tutorial, you can work in a new copy of the program. In Windows Explorer find the folder “MyFirstFormWithDatabase” in the Visual Studio Projects folder. This folder should be located in (Win 8) “C:\Users\[your username]\Documents\Visual Studio 2013\Projects\”. Copy the folder with the program, paste the folder at the same location and rename the new folder ” MyFirstFormWithDatabase02”. Now open the project in the new folder in Visual Studio.

Add a class named 'Party' by right-clicking the project name in the Solution Explorer: Add → Class

Between the lines 'Public Class Party … End Class', enter the following code:

Public Class PartyCompany


        Public Property Name As String
        Public Property Seat As String
        Public Property Address As String
        Public Property City As String
        Public Property Country As String
    End Class

    Public Class PartyIndividual


        Public Property Name As String
        Public Property PlaceOfBirth As String
        Public Property Address As String
        Public Property City As String
        Public Property Country As String
    End Class

That's it: you created a class 'Party' that holds two (sub)classes. Looks very simple, isn't it? Later on, we are going to expand this class but for now the class is sufficient to hold all data we need. Please note the two separate (sub)classes; one for Individuals and one for Companies.

Step 2

Next step is adding the collection class. The collection class will be used to store each instance of a party. In normal words; the collection will hold one or mulitple boxes, each called a 'party', and each box called 'party' will hold the details of that party. All of this is arranged neatly in your code, using the party class written above and the collection class you are going to code right now.

Add a class named 'PartiesCollection' by right-clicking the project name in the Solution Explorer: Add → Class

Between 'Public Class PartijCollection….. End Class', insert the code shown below. I have cut this code in pieces to give a little background. The code reflects is a custom collection class. The program would also function using a standard Visual Basic Collection class, but customizing that code later on would be difficult. I suggest to use a custom collection right from the start.

Private col As Collection = New Collection

When the code calls the PartyCollection Class, this class will call a new Collection class. The next lines make this collection ('col') perform the basic stuff.

    Public Sub Remove(ByVal index As Integer)
        col.Remove(index)
    End Sub

A few lines of code to remove an item from the collection ('col'). Please note that this code takes in the 'index' as input. The 'index' will be a number. In Visual Basic, a collection is numbered as of 1 upwards.

    Public Function Contains(ByVal item As String) As Boolean
        Return col.Contains(item)
    End Function

Code to look whether the Collection contains an item. This code is not used in our program, but added as a standard regardless because it belongs to the basics of a collection. Please note that the input is not a number of the index, but a string (a piece of text).

    Public Function Count() As Integer
        Return col.Count
    End Function

Code to count the number of items in the Collection. Mandatory to build code to cycle through a collection as you will see later on.

    Public Function Item(ByVal index As Integer)
        Return col.Item(index)
    End Function

Code to return an item from the collection (in this case a 'party') by providing an index number of the collection.

    Public Sub Add(ByVal party As Object, Optional ByVal before As Integer = -1, Optional ByVal after As Integer = -1)
        If before = -1 And after = -1 Then
            col.Add(party)
        ElseIf before = -1 Then
            col.Add(party, , after)
        ElseIf after = -1 Then
            col.Add(party, before)
        End If
    End Sub

This code could have been very simple. The minimum required would be adding an object 'party' (an instance of our 'party' class) with the command 'col.Add(partij)'. This code is more elaborate. Normally, the command 'Add()' inserts the object to be inserted as new item at the very end of the collection. Remember, Visual Basic counts all elements of a collection from 1 upwards. In order to provide sorting options or - in this tutorial - options to rearrange the list of items held in the collections, additional code is needed. The collection does not know a command to move an element in the collection: doing this requires a mix of deleting and reinserting items again. Instead of building this logic in the main form, we build it in the PartiesCollection class. Don't worry about this now, just insert the code.

    Public Function GetData(ByVal index As Integer) As Object
        Dim party As Object = Item(index)
        Return party
    End Function

Finally, a piece of code to get an item from the collection (in this case a 'party') by providing an index number of the collection. Note that this function is quite similar to the function 'Item()' mentioned above. The difference is that the function GetData() returns the item 'party' as an Object.

This is the code for the PartiesCollection Class for now. Time to put both classes created (Party and PartiesCollection) to work.

Step 3

The main form needs some work. Add a listbox (named 'lstParties') to the Form from the Toolbox.

Furthermore, add two small buttons (named 'btnAdd' with text 'Add' and named 'btnRemove' with text 'Remove') (see picture below). Resize Form1 and move buttons if necessary. The end result should look like this.

Step 4

Go to the main form's code (Form1) (if necessary ,double-click one of the buttons in Form1 in the design view to get to the code view). Just under 'Public Class Form1', insert the following line of code:

Public MyPartiesCollection As New PartiesCollection

This is an important piece of code. The program takes the PartiesCollection class and creates a new instance of it in the Form1's code. Remember that the PartiesCollection class creates a new 'collection' (named 'col' in that class)? The code in Form1 can now work with data in this newly created collection. It can do all that without having to write extensive code; the basics are all in the classes you wrote already…

The MyPartiesCollection (again, an instance of the PartiesCollection class) will drive the data in our Form1. This collection is invisible to the user. It is possible to add and remove items to this collection while the user has no idea what is going on and what is collected in that collection. To avoid this, the data in this collection will be shown to the user in the listbox.

Let's add code for the Add and Remove button. First, the Add button.

Select Case TcParties.SelectedTab.Name

            Case TbNP.Name
                'object "partij vullen met data
                Dim party As New Party.PartyIndividual

                party.Name = txtNPName.Text
                party.PlaceOfBirth = txtNPPlaceOfBirth.Text
                party.Address = txtNPAddress.Text
                party.City = txtNPCity.Text
                party.Country = txtNPCountry.Text


                If party.Name IsNot "" Then
                    'Visual Basic Generic Collection vullen
                    MyPartiesCollection.Add(party)

                    'textboxen clearen zodat user begrijpt dat het is ingevoerd
                    txtNPName.Text = Nothing
                    txtNPPlaceOfBirth.Text = Nothing
                    txtNPAddress.Text = Nothing
                    txtNPCity.Text = Nothing
                    txtNPCountry.Text = Nothing

                    'listbox updaten met alle partij namen
                    AddPartiesToListBox(MyPartiesCollection)

                Else
                    MsgBox("Please fill out a name of this party before " & _
                           "adding it to the list")
                    party = Nothing
                End If

            Case TbRP.Name

                'object "partij vullen met data
                Dim party As New Party.PartyCompany

                party.Name = txtRPName.Text
                party.Seat = txtRPSeat.Text
                party.Address = txtRPAddress.Text
                party.City = txtRPCity.Text
                party.Country = txtRPCountry.Text


                If party.Name IsNot "" Then
                    'Visual Basic Generic Collection vullen

                    MyPartiesCollection.Add(party)

                    'textboxen clearen zodat user begrijpt dat het is ingevoerd
                    txtRPName.Text = Nothing
                    txtRPSeat.Text = Nothing
                    txtRPAddress.Text = Nothing
                    txtRPCity.Text = Nothing
                    txtRPCountry.Text = Nothing

                    'listbox updaten met alle partij namen
                    AddPartiesToListBox(MyPartiesCollection)

                Else
                    MsgBox("Please fill out a name of this party before " & _
                           "adding it to the list")
                    party = Nothing

                End If


        End Select

You will notice that the whole code block is enclosed by the 'Select … End Select' routine. This routine is used to run a specific block of code depending on which tab is selected in the form (Individuals or Companies). Let's run to such a specific block of code to see what's happening.

In case the tab for Individuals is chosen, first 'party' is declared as a Party class of the sub type 'PartyIndividual'. This object 'party' is created in order to put it away in the collection (the MyPartiesCollection which was declared at the top of the main form). But first, the 'party' object (let's call it the party class) must be filled with data. This data is taken from the textboxes on the main form. Because we know the Individuals tab is selected on the main form, the data from the textboxes on that tabpage are inserted in the relevant elements of the party class (name, address, etc).

After the party class has been loaded up with the data from the textboxes, the code performs an additional check. We want the party to have a name. If the party class element 'Name' is empty (IsNot ””), the code will not add the party class to the collection but show a messagebox with a warning. If the party.name element does have contents, the code calls the 'Add' procedure that is part of the MyPartiesCollection class and adds the party class to the collection. Next, the code clears the textboxes so the user gets a visual confirmation that the information in the textboxes was processed.

Finally, the code calls the procedure 'AddPartiesToLIstBox' with the MyPartiesCollection as input. Ignore the error message for now: this procedure indeed does not exist yet. You will insert this procedure in the code of the main form. Add the following procedure to the main form (between 'Public Class Form1 …. End Class').

Private Sub AddPartiesToListBox(ByRef partiescollection As PartiesCollection)

        Dim i As Integer = 1
        Dim partyname As String
        Dim party As Object

        lstParties.Items.Clear()

        For i = i To partiescollection.Count

            party = partiescollection.Item(i)
            partyname = party.Name
            lstParties.Items.Add(partyname)



        Next i


    End Sub

Let's analyse this code.

The MyPartiesCollection is fed into the procedure. 'i' is defined as an integer to be used to iterate through all elements of this collection. The 'partyname' variable is used to hold a party name and party will hold instances of our party class. Now the execution part. First, the listbox on the form is fully cleared. Next, the code cycles to the first record in the collection (with index 1) to the end of the records (the final number is provided by the 'Count' procedure, part of the MyPartiesCollection class). For each record, the program takes the party class from the collection associated with that index number and looks up the 'Name' element for that party class. Subsequently, that name is added to the listbox.

As an alternative, we could also code a Function in the original PartiesCollection class file to retrieve the 'Name' element of a party by giving the index number of the collection. The benefit would be more elegant code. Now that we speak of this let's enhance our code in this manner.

First amend the sub procedure AddPartiesToListBox as follows.

Private Sub AddPartiesToListBox(ByRef partiescollection As PartiesCollection)

        Dim i As Integer = 1
        Dim partyname As String


        lstParties.Items.Clear()

        For i = i To partiescollection.Count


            partyname = partiescollection.ReturnPartyName(i)
            lstParties.Items.Add(partyname)



        Next i


    End Sub  

Ignore the error message for 'ReturnPartyName(i)' for now. Notice how the code becomes leaner. We do not need the 'party' variable anymore, and the code do assign a party class to this variable. Instead, the partyname variable is filled by a Function that will be added to the PartiesColllection class.

In the PartiesCollection class, add the following Function:

Public Function ReturnPartyName(ByVal index As Integer) As String
        Dim party As Object = Item(index)
        Dim partyname As String

        partyname = party.Name
        Return partyname
    End Function

This function takes an integer as input, being the index number of the collection. With the command 'Item', the code retrieves the party class that is held in the collection that is stored with that index number. Subsequently, the variable partyname is filled with data from the element 'Name' in the party class retrieved, and returned as the output of the function. Remember that this works because both types of 'party' classes have an element called 'Name'. This code does not check which type of party class is called so please be aware that this may be a potential place for bugs. If the Party class is changed so that one or more of the sub party classes (PartyIndividual or PartyCompany) no longer as a 'Name' element, the code will start throwing errors. But for now, this works.

Run the code and notice that it funtions as intended.

Finally - in this step - add code for the Remove button in the main form (Form1). Double-click on the remove button in the main form to get to the code and insert the following code.

Dim i As Integer

        Try
            i = lstParties.SelectedIndex + 1
            MyPartiesCollection.Remove(i)
            AddPartiesToListBox(MyPartiesCollection)
        Catch ex As Exception
            MsgBox("Please select a name in the listbox to remove")
        End Try

The code to remove an entry from the listbox contains a 'Try … End Try' block. This is done to ensure that the code only calls the 'Remove' functin from the MyPartiesCollection class if it does not return an error. An error could easily occur if the user has not selected an item in the listbox for removal before pressing the remove button. If nothing is selected when the user clicks the remove button, a message box shows with a warning. If something is selected, the code retrieves the integer 'i' to use as index number for the 'Remove' function of the MyPartiesCollection. Items in a listbox in Visual Basic starts at number 0 whereas a collection in Visual Basic starts with number 1. Therefore, the index number 'i' is increased with 1. Subsequently, the 'remove' function of the MyPartiesCollection class is called and finally the listbox is updated with the AddPartiesToListBox command.

Now, run the code. Add a few parties to the collection. Make use of the data in the database to do this. This data can be accessed by bringing up the lookup forms (button '…'). The parties added will show up by their names in the listbox. Now, select one of the names in the listbox: the name will be removed from the listbox. More important, the party as a whole is also removed from the collection. It is no longer there. If no name is selected when clicking the remove button, the program warns with a message box that no party was selected.

Time to wrap this part of the code up with buttons to shift a party up or down in the listbox (and the collection that is hidden from view).

Add a button 'Up' (btnUp) and 'Down' (btnDown) to the main form (Form1). Rearrange the 'Add' and 'Remove' button if necessary. The four buttons can be aligned by the inbuilt align tools of Visual Studio. To ensure that the vertical distance between the four buttons is equal, select all four buttons and use: Format → Vertical Spacing → Make Equal.

Click the newly created 'Up' button and insert the following code.

Dim i As Integer
        Dim obj As Object

        i = lstParties.SelectedIndex + 1

        If i = 1 Then
            MsgBox("Item is already on top!")
        ElseIf i > 1 Then
            obj = MyPartiesCollection.Item(i)
            MyPartiesCollection.Remove(i)
            MyPartiesCollection.Add(obj, , (i - 1))

            AddPartiesToListBox(MyPartiesCollection)

        End If

Let's analyse what this code does.

The code needs a variable i as Integer to work with the collection (by means of the index number of the rows in the collection). The 'obj' Object is used to work with a 'party' from of the collection. 'i' is set as the index number of the listbox (with the command 'SelectedIndex'). This number is increased with 1 because a Visual Basic listbox counts from 0 upwards whereas a Visual Basic collection counts from 1 upwards.

The program determines which item in the listbox is selected (by index number). This number is increased with 1 to match the index of the collection. Let's take the example that the second item was selected in the listbox (thus 1 in the listbox index and 2 in the collection index). The code tests whether i = 1. If so, the item selected (index in the collection would be 1) is already on top and a warning shows. Else, if i is larger than 1, the party associated with the index number of the collection is retrieved and assigned to 'obj'. In the example, 2 is larger than 1 so indeed the party located at index no 2 in the collection is assigned to 'obj'. Next, this item is removed from the collection. As a consequence, the collection's index numbering is reset from 1 upwards. The third item in the collection (with index 3 in the collection) is renumbered to 2 and if there is more behind index 3 in the collection, all those numbers shift 1 down. As final step for the collection, the same item is added again (the 'obj' which is essentially a copy of the item with index 2 that was removed from the collection), but this item is now inserted at the index number one step above the original index number. Therefore, the item is inserted again in the collection at index no 1 instead of 2. The reason for this methode of moving an item in a collection is that the collection class does not have a native command to move items. The code shown is the way to do this. A bit clumsy, but it works. At the very end, the listbox is updated again to show the new line up of items in the collection (through the element 'Name' of each party class in the collection).

Now that you understand what is happening, add the following code for the Down button.

Dim i As Integer
        Dim obj As Object
        Dim count As Integer = MyPartiesCollection.Count

        i = lstParties.SelectedIndex + 1

        If i = count Then
            MsgBox("Item is already at the bottom!")
        ElseIf i < count And i > 0 Then
            obj = MyPartiesCollection.Item(i)
            MyPartiesCollection.Add(obj, , (i + 2))
            MyPartiesCollection.Remove(i)


            AddPartiesToListBox(MyPartiesCollection)

        End If

This code is quite similar to the code for the Up button, but with some differences. The code first checks whether the index selected (again, the index number 'i' is increased with 1 to account for the different manner of numbering of a VB collection) is the last index number in the collection. It does so by comparing the index number with the total count of the collection (counting all items in the collection). If the index number is indeed equal to the count, a message box shows with a warning that the item is already at the bottom. If the index number is not the last number, the program copies the 'party' class in the collection located at that index number, inserts the same party ('obj') in the index but two places further than the original index number and then removes that party from the collection at the index number chosen. This can be clarified with an example.

Let's take the example that there are 3 items in the listbox and that index number 2 of the collection was selected by the user. The party located at index no 2 in the collection is copied and then reinserted in the existing collection at index no 4. The next step is to remove the (same) party from the collection at index no 2. Visual Basic automatically refreshes the number of the collection and recounts the index from 1 to 3. Voila, the party at index no 3 is now at index no 2 and the newly inserted (same) party at index 4 is now at index no 3. Finally, the listbox is updated again to show the new line up of items in the collection (through the element 'Name' of each party class in the collection). For the user, it looks like the item at no 2 shifted to 3 and the item at index no 3 shifted to index no 2. In fact, that happened but with a particular method.

This is how VB collections work when moving items up and down.

When running the code, you will notice that - when an item is moved up or down - the selection of that item in the listbox is lost. This is behaviour that annoys your user. It Let's correct this by adding code to the procedures for up and down so that the code ends with selecting the moved item in the listbox. For the Up button, insert the following code right above the 'End If' statement.

lstParties.SelectedIndex = i - 2

and for the Down button, insert the following code right above the 'End If' statement

lstParties.SelectedIndex = i

By inserting this code, the user does not lose the selection chosen in the listbox when moving an item. The item cannot be unselected, but that is not a problem with this program.

Conclusion

You have built everything to work with multiple parties. In the next tutorial, you will write the code to insert all that data in a Word document.

Computing A-Z | Programming | Software


QR Code
QR Code programming_microsoft_word_-_10_-_working_with_a_collection_part_1 (generated for current page)
 

Advertise with Anonymous Ads