Creating Reports

Part of the MyODBC Connector Databinding Tutorial

Matthew R. King
mking56@comcast.net

Purpose

This tutorial is in addition to my previous tutorial on using the MyODBC Connector, and uses the MyStore database. I will attempt to kill two birds with one tutorial: creating reports within Visual Basic.NET and modifying queries to the MySQL DataTables.

Why?

It took me awhile to figure out both, and – especially in the case of creating reports – I found other tutorials hard to follow. After fighting my way through it, I created this tutorial so i would not forget.

Initial Steps

This tutorial assumes you have completed the MyODBC Connector Databinding tutorial and have a working version of the MyStore database.

As in my previous tutorial, I do not spend a great deal of time on esthetics. Rather, I focus on functionality (getting it to work).

Creating a Report

I intend to create a very simple report that lists all employees by the store in which they work. First, I will create a report that shows employees for all stores, and then I will create a report that only shows the employees for the selected store.

Create a new DataTable in the DataSet

This first step is optional in most cases. When creating the report, one could simply drag and drop fields from existing DataTables. However, I have found this approach difficult in complex reports, and have found it easier to create a single DataTable that contains all information I need in the report.

  1. Open the MyStore Project in Visual Studio.NET
  2. Within the DataSet Designer, right-click an empty space and select Add –> TableAdapter
  3. rpt1.JPG

  4. Use the existing connection for this DataTable. Select Next >
  5. rpt2.JPG

  6. Select Use SQL Statements and select Next >
  7. rpt3.JPG

  8. Select to use the Query Builder…
  9. rpt4.JPG

  10. Add both tables by selecting them one at a time and pressing Add, then close the Add Table window.
  11. rpt5.JPG

  12. The Query Builder will show both tables, including the link between them.
  13. rpt6.JPG

  14. Select only the columns you want to show in the report. In this case, I want to list each store by city, state, and manager – then list each employee by first and last names.
  15. rpt6a.JPG

  16. Select OK to close the Query Builder
  17. rpt7.JPG

  18. Select Finish. The new DataTable and TableAdapter are added to the DataSet with the default name TableAdapter1.
  19. rpt8.JPG

I want to point out here that editing within the DataSet Designer rarely goes smoothly for me. Often, everything looks OK until I try to save it, then errors start popping up. Usually, exiting the program and restarting it takes me right back to where I left off without loss of data — but still a nuisance.

I do not know if this is due to my computer, me, or the unholy combination of Open Source and Microsoft, but I have gotten into the habit of attempting to save often when I make changes within the DataSet Designer.

Designing the Report

For the purpose of this tutorial, I will keep the report design to a minimum, but it is not difficult to see how very complex reports can be created with a little practice.

  1. Within the Solution Explorer, right-click on the solution and select Add –> New Item…
  2. rpt9.JPG

  3. Select the Report icon and select Add.
  4. rpt10.JPG

  5. The Report Designer appears, and the Report Items Toolbox becomes available.
  6. rpt11.JPG

  7. From the Report menu, select Data Sources…
  8. rpt12.JPG

  9. In the Report Data Sources dialog box, select the DataTable you created and select Add to Report. Select OK.
  10. rpt13.JPG

  11. Drag a List Item from the Toolbox. Once in the Report Designer, you can resize it.
  12. rpt14.JPG

  13. From the Data Sources window, drag the city, state, and manager textboxes from the DataTable into the List Item.
  14. rpt15.JPG

  15. Drag a textbox from the Toolbox into the List Item and enter a value of Employees:
  16. rpt16.JPG

  17. Drag another List Item from the Toolbox into the first List Item.
  18. rpt17.JPG

  19. With List2 selected, set the DataSetName property to your DataTable.
  20. rpt17a.JPG

  21. From the Data Sources window, drag the firstname and lastname textboxes from the DataTable into the second List Item.
  22. rpt18.JPG

  23. Set the Grouping property for list1 by right-clicking on the List Item and selecting Properties.
  24. rpt18a.JPG

  25. In the General tab of the List Properties dialog box, select the edit group details… button.
  26. rpt18b.JPG

  27. In the Group and Sorting Properties dialog box, select to use the city field as the Group On… expression.
  28. rpt18c1.JPG

  29. Select OK twice to close the List Properties windows.
  30. Obviously, this report could stand to have a little more formatting, but I am sticking to the fundamentals of data retrieval.

Create the Report Viewer

Setting up the Report Viewer – at least for this simple report – is quite easy.

  1. Within the Solution Explorer, right-click on the solution and select Add –> New Item…
  2. rpt9.JPG

  3. Select the Windows Form icon, and then select Add.
  4. rpt19.JPG

  5. From the Toolbox, drag a ReportViewer into the new form.
  6. rpt20.JPG

  7. From the Smart Tag, select the Report1 from the Choose Report list.
  8. rpt21.JPG

  9. Again from the Smart Tag, select Rebind Data Sources.
  10. rpt21a.JPG

  11. The Report Viewer is now located in Form2, and Report1 is the selected source. As before, many other settings affect the way the report shows up within this form, and how the Report Viewer acts. I am only focusing on the fundamentals.

Create a Button to Link the Forms

The final step is to create a button on Form1 that brings up Form2 with the Report Viewer.

  1. Open Form1 and add a button (btnPrintAll).
  2. rpt22.JPG

  3. Double-click the btnPrintAll button in the Form Designer to create a Click event in the code window.
  4. rpt23.JPG

  5. Within the btnPrintAll_Click event, enter the following code:

  6. Dim rpt As New Form2
    rpt.Show()

    rpt24.JPG

  7. Build the application and run it by pressing F5. You should be able to select the Print All button and see a very ugly report of employees listed by the store they work in. However, with more time and effort, the report can be drastically improved.

Filter the Report

There are several ways of filtering a report to view the records you want to see. I will use a method that creates a new query and passes parameters in order to only view information for the selected store. In order to do this, I need to select a parameter I can use to select a store.

The obvious choice of a filter is storeID, as it is the Primary Key of the store table. Therefore, we need a way of selecting the storeID.

  1. Open Form1 and select ComboBox1.
  2. rpt25.JPG

  3. In the Properties window, select storeID as the ValueMember. When the user selects the city, the ValueMember of the ComboBox1 will contain the storeID of the selection.
  4. rpt26.JPG

  5. Now that I have a way of selecting the storeID, I need to create a query that will use the storeID to filter the report. In the DataSet Designer, right-click the TableAdpater and select Add Query…
  6. rpt27.JPG

  7. Select to Use SQL Statements and select Next >
  8. rpt28.JPG

  9. Select to create a statement that is a Select which returns rows and select Next >
  10. rpt29.JPG

  11. At the end of the WHERE clause in the Query Configuration Wizard, add this code:
  12. AND (store.storeID = ?)

    rpt30.JPG

  13. Select Next >
  14. The Query Configuration Wizard provides the opportunity to rename the new methods. I entered FillByStoreID and GetDataByStoreID.
  15. rpt31.JPG

  16. Select Next >
  17. rpt32.JPG

  18. Select Finish. The Table Adapter shows the new method with which we can filter the results of the query by storeID.
  19. rpt33.JPG

Create a New Report Viewer

Although it is possible to write code to use the same Report Viewer (Form2), I will create a new Report Viewer (Form3). However, there is no need to create a new report, as Report1 contains all the data fields and bindings we need.

  1. Use the same procedure as above to create a new Windows Form (Form3)
  2. Add a ReportViewer to Form3
  3. Select the same report (MyStore.Report1.rdlc) for this ReportViewer as you did for Form2
  4. Rebind the Data Sources
  5. rpt34.JPG

  6. Press F7 to view From3’s code window.
  7. rpt35.JPG

  8. Notice the TableAdapter’s Fill method. We need to change this to use the new query we created. Modify the code to read:
  9. Me.DataTable1TableAdapter.FillByStoreID(Me.mystoreDataSet.DataTable1, storeID)

  10. Note that this method requires a variable (storeID), which is an integer I will pass to the query. I need to define this variable first, so above the From3_Load event, define the storeID variable as an integer. The next screenshot shows the code so far.
  11. rpt36.JPG

  12. Add the following function to Form3’s code:
  13. Sub New(ByVal s As Integer)

    Try
    initializeComponent()
    storeID = s
    Catch ex As Exception
    MsgBox("Error: " & ex.Message)
    End Try

    End Sub

    rpt37.JPG

Create a Button to Link the Forms

The final step is to create a button on Form1 that brings up Form3 with the Report Viewer, and passes the storeID to it.

  1. Open Form1 and add a button (btnPrintSelected).
  2. rpt38.JPG

  3. Double-click the btnPrintSelected button in the Form Designer to create a Click event in the code window.
  4. rpt39.JPG

  5. Within the btnPrintAll_Click event, enter following code:

  6. Dim rpt As New Form3(Me.ComboBox1.SelectedValue)
    rpt.Show()

    rpt40.JPG

  7. Notice in the code above that I am using the ComboBox’s SelectedValue - which we defined earlier as storeID - to the instance of Form3.
  8. Build the application and run it by pressing F5. You should be able to select a store in the Combo Box, select the Print Selected button, and view a report of the selected store only.

A Few ReportViewer Preferences

I have a few preferences in the layout of the ReportViewer that I did not add in the body of the tutorial. I will list them here.

  1. The first preference is an easy one. I like to dock the ReportViewer in the form.
  2. rpt41.JPG rpt42.JPG

  3. The next preference is to set the default layout to the Print Layout with the document zoomed to the Full Page Width. Add the following code above the RefreshReport command:
  4. Me.ReportViewer1.SetDisplayMode(Microsoft.Reporting.WinForms.DisplayMode.PrintLayout)
    Me.ReportViewer1.ZoomMode = Microsoft.Reporting.WinForms.ZoomMode.PageWidth

    rpt43.JPG

Summary

This tutorial demonstrated several Visual Basic.NET features:

  1. Creating Reports
  2. Creating DataTables
  3. Adding Queries to a DataTable
  4. Passing variables between forms
  5. Filtering Report Data

11 Responses to “Creating Reports”

  1. Niels Oltmanns Says:

    Great job. This is the best tutorial for the ReportViewer control I have seen. Thank you.

  2. Jack Says:

    This is a terriffic tutorial!

    2 questions though…

    1. can you update it so it uses the .net connector?
    2. How would you collate many reports into one report view this way, for say, batch printing, or invoicing?

  3. Matthew King Says:

    Thank you Jack and Niels.

    Jack — it is funny you should bring up your second question right now. I’m in the middle of a project where I am trying to send a batch print job straight to the printer. I was able to send them to the ReportViewer, where I could print them, but I ran into a problem with page numbering. The ReportViewer, using the global parameters, would number pages sequentially to the end — where I wanted the numbers to re-start with each new record.

    That paragraph may be confusing — but I have an example at http://www.emgeesoft.com/fprspr.htm. It is a VB and MySQL application. If you go through the problem of installing it, the Reports tab has a Batch Print area where you may be able to see the problem (after you add a few records). Maybe you can tell me if this is close to your question.

    In order to accomplish the Batch Print with ReportViewer, I basically followed this tutorial. I started by creating a TableAdapter that contained all of the information the report needed. The TableAdapter essentially becomes a flat-file — with many fields repeated in several rows. I was then able to use the List and Table features of the Report Designer (along with grouping) to place the data where I wanted it. A great link: http://www.codeproject.com/sqlrs/1tomanyreports_vsnet2005.asp?df=100&forumid=226607&exp=0&fr=26 shows how to use the List Feature and grouping.

    As for the .net connector — I do not have plans to work on that one for a while. I am spoiled — I like DataSet Designer and Drag and Drop tools too much. However, this site (VBMySQL.com) has a great tutorial for the .net connector. Once you master creating DataSets in code, I would think the expressions in the Report Designer might come pretty easy (maybe).

    I hope this has helped.

  4. Rufus Says:

    Dude , Super awesome !!! This was the most simplest way of creating report viewer ever seen. Thanks Alot, and keep up the great work!

  5. Tracy Says:

    i have a problem in Filter the Report step — 9
    after i click next then got error which error mention “The wizard detected the following problems when configuring TableAdapter query “FillByTransaction_ID”:

    Detail:
    Generated SELECT statement.
    No mapping exists from DbType Object to a known OdbcType.
    Tp apply these setting to your query, click finish.”

    Is that correct??????? i using MySQL as my database

  6. Tracy Says:

    when i type this —— Me.DataTable1TableAdapter.FillByStoreID(Me.mystoreDataSet.DataTable1, storeID)
    storeID come out error line, it mention no declare, but i already add in dataset…… pls help…

  7. Matthew King Says:

    Tracy,

    The “no mapping exists” error occurs because the query is looking for a parameter — storeID in this case — that is not defined. This has happened to me before, and I’m not always sure why — but I know how to fix it. The problem is that storeID is not properly defined as an integer type in the query.

    In the DataSet Designer, click on the query to select it. In the Properties Panel, select the Parameters -> (Collection…) to open the Parameters Collection Editor dialog box. From this dialog box, you can define the storeID parameter as a DbType -> Int32.

    That should do the trick.

    Good luck,
    Matt

  8. tracy Says:

    Matt,

    It’s work already…. thanks a lot…. But this is not get the result what i want. Is this method only can filter when using variable as integer only? But i need to filter few variable at the same time which are string variable, it cannot be work. Because it will come out a error message mention that “Convertion from string ” variable ” to type ‘integer’ is not valid. Any method suggestion?

  9. Andy Says:

    Thx a lot Matt,

    In the last couple of days I worked my brains out to figure a method to display an report in VB.NET filled with MySQL dates. My problem was I used MySQL Connector for the datagridview control in my forms (because I read it’s more faster then MySQL ODBC connector) and I was reluctant to add MySQL ODBC Connector too.
    I was close to your solution but your article put all together

    Thx again Matt.

  10. wayne Says:

    Hi

    Brillaint Tutorial.. just need a bit of guidance with the filtering step. For the web page im designing, i have adropdownbox control which points to my main dataset. I want users to be able to filter the report based on the dropdown selection. I have also created the appropriate getData select Statement agaisnt the table adapter/dataset. Now all i need is to be able to bind the getData select statement to the dropdownbox control. Could you please advise how to do this?

    Thanks in advance

    Wayne

  11. Matthew King Says:

    Wayne,

    Thanks for the comments. I will try to help based on my understanding of your post. It sounds as if your main problem is that you need to pass the SelectedValue from a combo box in one web page to another web page that contains the ReportViewer (with a query that uses the SelectedValue to filter the report). You could use JavaScript to set a cookie, PHP to set a Session Variable, or just pass the value as an url parameter.

    Or, perhaps your ReportViewer is on the same page as your combo box? In this case, I would post the SelectedValue from the combo box back to the same page and grab the variable.

    I am not overly familiar with using .NET controls in web pages (I am teaching that to myself now), and I am not even sure if I understood your question correctly, but I hope I was able to help.

    Matt

Leave a Reply