Introduction to Fixed Page Layout–Part 2
Welcome to the next post in the "What's New in ActiveReports Developer 7?" series! This time we'll go from taking a 50,000 foot view of Fixed Page Layout (FPL) reports and get into the nitty gritty and create a couple of reports.
We'll start off by creating a simple report. We have the items that a customer has purchased and want to print an invoice for it. We'll be concerned with printing just a single invoice to start with, and later we'll modify this report to be able to work with multiple invoices at once.
I'm using the standalone designer that is installed alongside ActiveReports 7, however you can also use Visual Studio to create the reports.
To create a new Page report, from the File menu, select New and choose Page Report (in Visual Studio this is called ActiveReports 7 Page Report).
In the Report Explorer, right-click on the Data Sources node and choose Add Data Source.
In the dialog that comes up select Shared Reference and browse to the samples directory included with ActiveReports. Inside of the samples directory, select the Data**ReelsDataSource.rdsx** file. This file contains all of the connection information to use the Reels sample database.
Click OK to accept our changes and close the dialog.
Now in the Report Explorer, right-click on our newly added DataSource1 and choose Add Data Set. On the left navigate to the Query page, and use the following SQL query.
SELECT * FROM CustomerOrders WHERE CustomerID = 1000
This will give us just the records associated with a single customer in the database. Click the OK button to accept our changes and return to the design surface.
Now that we're here we can design our invoice. We'll just do something basic here, however you can pretty up the report as much as you want. While our data contains the customer contact info, for reasons that will become clear later, we'll not put that information on the invoice for now.
We'll start off by setting our paper size. We don't have a ton of data in our invoices so we'll make our paper smaller to work around that. Click on the page grid and set the page size to 6in x 6in and the margins to 0.5in on all sides.
Now that we have our page size set, drag out a Table from the toolbox. Click one of the textboxes inside of it to trigger the display of the row and column headers. Right-click on a column header and choose Add Columns... Specify 2 and click OK. Now we have a table with 5 columns in it.
Let's start by adding our data to the cells and then we'll adjust the size of our columns to fit the data.
As you may have noticed earlier, when your mouse cursor hovers over a textbox an icon appears on the right side of it. When you click this icon, it will bring up the Field Selection menu. This menu allows you to quickly select the field you want to use in the textbox without having to resort to typing or drag-and-drop from the Report Explorer.
Besides being quick to use, it also does a couple of other things for you. It will automatically add a title to the table or matrix column, and if you are in a data scope it will automatically apply an aggregate to it.
In the middle row, select the following fields from left-to-right: Title, Quantity, Price, and Discount. In the last column we'll calculate the total, so in the last cell type:
=[Quantity][Price](1-[Discount])
Finally, type Total in the last column's header cell.
We're almost done! Now for our total and some formatting. In the bottom left cell, in the table footer, type the following expression:
=Sum([Quantity][Price](1-[Discount]))
For the formatting, select the Price cell and the two Total cells, go to the property grid and set the Format property to C (you can also use the drop-down and select Currency). Select the Discount cell and set the Format to P0 (or select Percent with 0 decimal places).
Two more things to do and we're done, I swear! First, make the title column as large as you can; don't worry the page won't resize on you. Finally, select the table, and in the property grid, find the FixedSize property, expand it and set the Height to 3in.
This last step is important. Remember when we talked about Fixed Page Layout reports in the previous post? We define a page layout and then define spaces in the report in which the data will appear. The FixedSize property is how you define how large you want the space for the table to appear for your report.
Now for that picky issue with the customer's contact information I mentioned earlier. Unlike other reporting types, in FPL the layout is king. We cannot change the way things are laid out at run time like we can with the other report types by pushing things around as report items grow. This report may wind up printed on a form, after all, and moving things is not good when you've taken the time to place items *just* right.
For this reason, the behavior of CanGrow and CanShrink isn't allowed (and are, in fact, hidden on FPL reports). But this also means that where you might have expected CanGrow or CanShrink to work, you need to anticipate that and include it in your design. The customer's contact information is one place where we need to account for this because some customers have 2 address lines, and some only have 1. This leaves us with two choices, we can put up with the blank that appears there (boo) or use an expression to conditionally output it.
We can tackle the expression in one of two ways, we can output it inline, or we can pass our data into a custom code function. If it's straightforward, I prefer to use an inline expression. However, in this case we're dealing with multiple conditionals so we'll go the route of creating a custom code function that we can call.
On the Script tab, copy and paste the following code:
Public Function GetCustomerInfo(FirstName As Object, MiddleInit As Object, _ LastName As Object, Add1 As Object, Add2 As Object, City As Object, _ St As Object, PostCode As Object, Country As Object) As String
Dim ret As String = FirstName
If Not MiddleInit Is Nothing Then
ret = ret & " " & MiddleInit
End If
ret = ret & " " & LastName
ret = ret & vbCrLf & Add1
If Not Add2 Is Nothing And Add2 <> "" Then
ret = ret & vbCrLf & Add2
End If
ret = ret & vbCrLf & City & ", " & _
St & " " & PostCode & " " & Country
Return ret
End Function
Finally, we need to call this function from our report. Add a textbox to the upper part of the report and use the following expression:
=Code.GetCustomerInfo([FirstName], [MiddleInitial], [LastName], [Address1], [Address2], [City], [Region], [PostalCode], [Country])
If you run this report now, you should see we have everything needed to output a single receipt or invoice.
This is useful if you want to print this now, for this one sale, but what if you batch your invoices together?
Thankfully, this is incredibly easy to handle. You see, FPL reports have a property in them that lets you group data together at the page level. Once one instance of the group is finished you get an entirely new set of pages for the next group. We can use this to batch together multiple invoices or receipts at once. And all it takes are two changes, one to pull in more data and one to set the grouping.
First, lets get that data! In the Report Explorer, right click on our DataSet, DataSet1, and choose Edit. On the Query page, update our query to:
SELECT * FROM CustomerOrders WHERE CustomerID IN (1000, 1008, 1029)
With this change we'd have all of our data in a single report--not quite what we want. Let's add the page-level grouping now. Click on the gray surface surrounding the report. In the property grid, click Fixed Layout Settings. For Dataset name, click the dropdown and select DataSet1. Now go to the Grouping page, and under Group Expressions, click in the area and in the dropdown that appears, select, =Fields!CustomerID.Value.
That's it! We're done. We've now successfully created a report which uses FPL to display a single receipt or invoice, then updated that report to be able to handle batches of receipts or invoices.
Next time, we'll look at a more complicated layout dealing with overflow, for example, what happens when there is more data than the space defined on the page will allow? Subscribe to our feed or check back often for new posts.