Creating a Monthly Summary Reports without Code by Creatively Using a Microsoft Access Crosstab Queryby Luke Chung, President of FMS, Inc.IntroductionA well designed database stores data in a normalized format with dates defined in a field so that new data is simply added as additional records. However, people want to see data with dates grouped by columns. How can we do this for any 12 month period, and do it without writing any code? This paper shows an easy way to display monthly summaries for any 12 month period in a report without any code. A sample database is included to show how this is done: Download (189K) Our ObjectiveHere's an example using the Orders data from the Northwind database showing monthly sales by country. Each country is a separate row, each month is a separate column, and column totals are shown at the bottom:
The user can specify the starting month of the report and automatically show 12 months of data. The column titles show the year and month. If there is no data for a particular month, the report still shows the column with no data under it. ChallengesData Storage is Different from the Way It Needs to be DisplayedDatabases store data optimally in normalized, tabular manner. One sign of a good database design is that as time passes, new fields never need to be added. New dates, clients, contacts, etc. are just new records in the tables without the need to modify any table structures. However, data often needs to be displayed in a "spreadsheet" or "matrix" format with different values in the columns such as a column for each month. Naturally, these columns change over time. Crosstab QueriesFortunately, Access crosstab queries make it easy to transform and summarize data from rows to columns. A crosstab lets you specify the field whose unique values are transformed to column fields and a value field to be summarized. However, the columns of a crosstab query change based on the data in the selected column field (and can change over time). Additionally, if there is data missing for a particular column (or month in our example), the crosstab would not show that column. This creates problems if a report expects the column names to remain the same each time, or writing a lot of code to accommodate this. Introduction to Crosstab QueriesHere's a quick introduction to crosstab queries, if you're not familiar. For more information, see the online Access help for crosstabs. This is an example of showing a crosstab grouped by Country with columns for each month (defined as the year-month format of the [OrderDate]), and displaying total sales:
Creating Crosstabs with Fixed ColumnsMicrosoft Access reports reference field names directly. If we want to use a crosstab query as the RecordSource of a report, its column names should not change (unless we want to write a lot of code to handle that). Fortunately, there's an easy way to make sure our crosstab query always generates 12 columns of monthly data even if the table doesn't have data for all 12 months. Take a look at the query qryCountryMonthlySalesDateXTAB with [StartDate] parameter in the criteria. This prompts the user for the date of the first month (e.g. 7/1/96) to define the the 12 months we want to retrieve:
Use Numbers Rather than Specific Month NamesIn the original crosstab query qryCountryMonthlySalesXTAB, each month column is shown in yyyy-mm format. That makes it difficult for a report (or subsequent query) to use as the date range changes. A better approach is to define each month as a number between 1 and 12, starting with the first month to display. This is defined in the ad hoc query qryCountryMonthlySalesDateXTAB. The trick is to think of each month as a unique number starting from Year 0:
The equation defines each month as a number (Years * 12 + Month) and subtracts the StartDate month from the OrderDate month plus one. The result is a month number from 1 to 12 defining the months we want. The result is this: Use the PIVOT IN Clause to Specify Required Column NamesDefining the month number is the first step and works great if you always have data for each month. However, if a month doesn't have any data, the crosstab won't create that field. We want to ensure every month from 1 to 12 exists. This is accomplished by using the IN clause in the crosstab syntax. To do this, we need to edit the SQL string of the query and insert the IN clause. Here's the query:
The important part is the last line highlighted in red. By adding the IN clause and listing the column names required, the crosstab always creates those columns. The IN clause also limits columns (e.g. month 13 and higher are not included). Report DesignWith the crosstab defining each month as a set number, we simply reference those columns in the report:
Column NamesTo label each column, we translate the month column based on the [StartDate] parameter with the Format property set to yyyy-mm. For instance:
The VBA DateAdd function when passed the "m" parameter adds the number of months to the [StartDate] to create the new date that the Format property is applied for display. Preview the Report
The sample data is from Northwind which has OrderDate between July 1996 and May 1998. Preview the report and enter the StartDate: You'll see the report shown at the beginning of this paper. Automatically Handles Missing MonthsIf you enter 1/1/96 as the StartDate, you'll see the report also works without any data for the first part of the year. This is because of the IN clause in the crosstab:
ConclusionThe need for monthly summary reports is quite common. Hopefully, the techniques shown here will help you create richer Access reports and use crosstabs more efficiently, while giving you more ideas on creating new reports. Good luck! Additional ResourcesTechnical PaperA variety of ways to create more powerful queries: Microsoft Access Query Tips and Techniques.
|
|
|
Contact Us
l Web questions: Webmaster
l Copyright
© 2009 FMS, Inc., Vienna, Virginia Celebrating 23 Years of Software Excellence |