Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1542 Part X Business Intelligence FIGURE 73-6 Example of multi-value nested parameters Adding calculated fields to a dataset Once the dataset is defined, it is possible to add fields to it and specify an expression for the field value. For example, you could add a field to the Products dataset named ‘‘Margin’’, and set the expression to calculate it as ListPrice – StandardCost . To add a field, follow these steps: 1. Right-click on the Products dataset and choose Add Calculated Field. The Dataset Properties dialog displays, showing a blank row on the Fields tag. 2. Enter ‘‘Margin’’ for the new Field Name. 3. Enter the following expression as the Field Source. Alternately, click the fx button to launch the expression editor and build the expression using the fields listed there. =Fields!ListPrice.Value - Fields!StandardCost.Value 4. Select OK and the new field is added to the dataset. Best Practice W hile it is possible to achieve the same result by including the calculation in the SQL statement, this approach is very convenient when calling a stored procedure that you don’t want to include the calculation in, or that you don’t have permission to update. However, the report expression language requires careful coding to handle any NULL values or data type conversions. It is also possible to include expressions in the report layout, but this may require writing and maintaining the expression multiple times within the report. Adding the calculated field to the dataset ensures that the expression is defined in one place and simplifies report construction and maintenance. Working with XML data sources XML can be a very useful data source for reports. Individual files can provide easy-to-deploy datasets that are not otherwise available. Web Service access allows reports to be enhanced by services available inside and outside the organization. The example in this section demonstrates both types of data 1542 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1543 Authoring Reports with Reporting Services 73 sources, using an XML file to populate a report parameter and a Web Service to provide the dataset for reporting. The ultimate goal is to choose a company from the parameter and view its stock quote in the report. The following XML file contains the stock symbols and their associated companies: <?xml version="1.0" encoding="utf-8" ?> <StockSymbols> <Symbol Value="AAPL" Name="Apple Computer, Inc. (AAPL)" /> <Symbol Value="CSCO" Name="Cisco Systems (CSCO)" /> <Symbol Value="MSFT" Name="Microsoft Corporation (MSFT)" /> <Symbol Value="ORCL" Name="Oracle Corporation (ORCL)" /> <Symbol Value="JAVA" Name="Sun Microsystems, Inc (JAVA)" /> </StockSymbols> Follow these steps to create a new dataset for the StockSymbols.xml file: 1. Create a file named StockSymbols.xml containing the stock symbols XML code above. 2. Place the file on a handy web server. 3. Create a new data source with the name ‘‘Stocks’’, the type XML, and a connection string that points to the newly created file — for example, http://localhost/StockSymbols.xml for a file saved on the root of the local web server. 4. Add a dataset under the Stocks data source, name it ‘‘StockSymbols’’, and use the following query: <Query> <ElementPath IgnoreNamespaces="true"> StockSymbols/Symbol{@Value, @Name} </ElementPath> </Query> 5. Use the Query Designer to execute the query to ensure successful connection and configuration. Now create a report parameter named Symbols and use the StockSymbols dataset to populate the values. Follow these steps: 1. Right-click the Parameters folder in the Report Data pane and choose Add Parameter. 2. Name the parameter Symbols, set the prompt to something user-friendly such as ‘‘Stock Symbol’’, and set the data type to Text. 3. Under the Available Values tag, select ‘‘Get values from query.’’ Set the dataset to Stock Symbols ,theValuetoValue, and the Label to Name. 4. Click OK to save the new parameter. When the report is executed, the user will be prompted to select a stock symbol from the parameter to obtain a quote. Now create a dataset to retrieve stock quote information from a Web Service. CDYNE Corporation provides a Web Service to return delayed stock quotes. The GetQuote method of the Web Service retrieves a current stock quote and requires two parameters: StockSymbol and LicenseKey. 1543 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1544 Part X Business Intelligence You will associate the StockSymbol query parameter to the Symbols Report parameter just created and hard-code the LicenseKey query parameter with a value of 0; the key is provided for testing purposes. Follow these steps to create the Stock Quote dataset: 1. Create a new data source named StockQuote as an XML data source and use the following URL for the connection string: http://ws.cdyne.com/delayedstockquote/delayedstockquote.asmx 2. Create a dataset named Quote under the new data source, using the following code: <Query> <Method Namespace="http://ws.cdyne.com/" Name="GetQuote"> <Parameters> <Parameter Name="StockSymbol"> <DefaultValue>MSFT</DefaultValue> </Parameter> <Parameter Name="LicenseKey"> <DefaultValue>0</DefaultValue> </Parameter> </Parameters> </Method> <SoapAction>http://ws.cdyne.com/GetQuote</SoapAction> <ElementPath IgnoreNamespaces="true">*</ElementPath> </Query> 3. On the Parameters tab, add a new Parameter named StockSymbol mapped to the [@Symbols] report parameter (available in the drop-down). Add a second parameter named LicenseKey and set the value to 0. Be aware that the parameter names are case sensitive. These parameters correspond to the parameter placeholders in the XML and override the default values specified there. 4. Use the Query Designer to execute the query to ensure successful connection and configuration. Now place fields from the Quote dataset in the report — a List item works well here because it is dif- ficult to fit all the fields across the page. Then run the report, choose a company, and view the Web Service results in the output. For a detailed description of query syntax, see the ‘‘XML Query Syntax for Specifying XML Report Data’’ topic in Books Online. Working with expressions Expressions are a powerful resource for report authors. They can be used as data for any item that appears on the report design surface, which enables calculations on source data and a vari- ety of summarizations. Expressions can also be included in most object properties, enabling items to be selectively hidden, formatted, and change most any other behavior controlled by properties. Figure 73-7 shows the Expression Editor used to build expressions. 1544 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1545 Authoring Reports with Reporting Services 73 To open the Expression Editor, select <Expression > from a property value list, right-click on an object, and select Expression from the context menu, or select the function button labeled ‘‘fx’’ next to a property in a property page. The Expression Editor contains the expression code window, a category tree, category items, and a description pane. Double-clicking a value in the Item pane or Description pane inserts code into the code window. FIGURE 73-7 The Expression Editor now contains advanced features such as IntelliSense and a list of available functions. Table 73-2 describes the categories available in the Expression Editor. Expression scope Aggregate functions enable you to specify the scope for performing a calculation. Scope refers to either the name of a dataset or the name of a grouping or data region that contains the report item in which the aggregate function is used. For example, consider a Sales by Product report containing a table with a group named grpProduct. To add a Running Total column to the report that resets the running total on each product, use the fol- lowing expression: =RunningValue(Fields!LineTotal.Value, Sum, "grpProduct") 1545 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1546 Part X Business Intelligence TABLE 73-2 Expression Editor Categories Category Description Constants Constants are not available for all report items and properties. This category will contain the constant values available for the property for which the expression is being written. For example, when editing an expression to set the background color for a row in a table, the Constants category contains the list of colors available and exposes controls enabling the addition of a custom color. Built-in Fields This category contains built-in tags to access information about the report and the execution of the report, such as ExecutionTime, PageNumber, TotalPages, and UserID. Parameters This category contains the list of report parameters. Note that special handling is required for multi-value parameters because they represent a list of values instead of a single value. For example, the Join function can be used to produce a single string from the multiple values; an expression like Join(Parameters!ProductCategoryID.Value,",") will produce a comma-separated list of category IDs. Fields This category contains the list of fields for the dataset within the scope of the selected report item or property. For example, when editing the expression for a cell in a table bound to the Products dataset, the Fields expression category will list all of the fields available in the Products dataset. Datasets This expression category contains each dataset defined in the report. Selecting a dataset displays the default aggregation function for each field in the dataset. The default aggregation function varies according to the data type for the field. For example, the default aggregation function of the ListPrice field in the Products dataset is Sum(ListPrice). Double-clicking this field adds the following code to the code window: Sum(Fields!ListPrice.Value, "Products") Operators This expression category contains Arithmetic, Comparison, Concatenation, Logical/Bitwise, and Bit Shift operators to assist with expression syntax and construction. Common Functions This expression category contains functions for working with Text, Date and Time, Math, Inspection, Program Flow, Aggregate, Financial, Conversion, and Miscellaneous. 1546 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1547 Authoring Reports with Reporting Services 73 To add a Running Total column to the report that does not reset by product, use this expression: =RunningValue(Fields!LineTotal.Value, Sum) Expression scope can also be important when adding an expression to a textbox. Because the textbox report item cannot b e bound directly to a dataset, the expression must include the dataset’s scope. The following expression calculates the sum of the LineTotal field in the Sales dataset: =Sum(Fields!LineTotal.Value, "Sales") Expressing yourself with common expressions The following examples demonstrate several common expressions used in reports. Using the following expression as the BackgroundColor property for the detail row in a table will set the background color for the even rows to AliceBlue: =IIf(RowNumber(nothing) mod 2 = 1, "AliceBlue", "White") It’s a good idea to include the date and time a report was executed. The f ollowing expression produces output like ‘‘Report Executed on Monday, August 15, 2005 at 2:24:33 P.M.’’: ="Report Executed On"&Globals!ExecutionTime.ToLongDateString & " at " & Globals!ExecutionTime.ToLongTimeString Expressions can be used to format text. The following expression calculates the sum of the LineTotal field in the Sales dataset and formats the result as a currency string such as $4,231,205.23: =FormatCurrency(Sum(Fields!LineTotal.Value, "Sales"), 2, true, true, true) Sometimes it doesn’t make sense to show certain report items based on the parameters selected. To tog- gle the visibility of a report item or even just a cell in a table, use an expression similar to the following in the Visibility.Hidden property: =IIf(Parameters!CategoryID.Value = 10, true, false) Designing the Report Layout The Report Designer contains a rich feature set for designing reports. This section discusses the basics of report design and demonstrates creating a report design, grouping and sorting data, and adding charts to areport. Design basics The Design tab in the Report Designer contains rich features to make formatting even the most com- plicated reports possible. The page layout contains three sections: header, body, and footer. Table 73-3 summarizes the behavior and purpose of each section. Designing the report layout is similar to working with Windows Forms. Report items are added by dragging them from the Toolbox onto the report. 1547 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1548 Part X Business Intelligence Best Practice B ecause a report represents the state of a dataset at a particular moment in time, it is important to include enough information in the report to answer the ‘‘5 Ws’’ of the report: who, what, when, where, and why? Who ran the report? Where did they run it? What criteria were provided to execute the report? When was the report generated? Why does the report exist? Communicating these facts on the report in a consistent manner avoids confusion and debate over the report’s content. TABLE 73-3 Report Sections Section Description Header By default, content in the header will appear on every page. This is a good place to include the report title to indicate why the report exists. The PrintOnFirstPage and PrintOnLastPage properties can be used to prevent the header from appearing on the first and last pages. Body If the report contains parameters, it’s a good idea to add a section to the top or bottom of the body to show the value of the parameters used to execute the report, and perhaps a short description of what the report represents. Adding this detail at the top or bottom of the body ensures that the information is printed only once, rather than on every page. Footer Like the header, the footer also appears on every page by default and can be turned off for the first and last pages. This is a good place to include information specifying who ran the report, when they ran it, the report version, and page numbering. Designing the report header To add a report title, follow these steps: 1. Right-click the left margin of the report and select Page Header to show the page header section. Be aware that once you have added content to a report section, the content is lost if you toggle that section off. 2. Add a textbox to the header from the Toolbox. 3. Type the report title and format the textbox. You may want the title to be dynamic based on the report content or parameters selected. This can be achieved by using an expression. Nearly all visual aspects of the textbox permit expressions too. 1548 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1549 Authoring Reports with Reporting Services 73 Designing the report footer The footer should include information such as who ran the report, when the report was executed, and page numbering. This type of information can be added using expressions. Follow these steps to build the footer: 1. Right-click the left margin of the report and select Page Footer to show the page footer section. 2. Add three textboxes using these expressions: =User!UserID =Globals!PageNumber & " of " & Globals!TotalPages =Globals!ExecutionTime 3. Add a line above the textboxes to provide visual separation. Adding and formatting a Table report item Use the Table report item to render the data from a row-oriented dataset — the type of data that might present well in a simple Excel spreadsheet. Follow these steps to add a table showing the data from a dataset named Products: 1. Add a table to the body of the report from the Toolbox. 2. Drag fields from the dataset to the detail section of the table. Notice how the indicator high- lights where the field will be placed — either in an empty column or between columns. If necessary, highlight and right-click column headers and delete columns as necessary. Column headers are automatically set based on the field name. Note that dropping fields into the header and footer sections of the table will create an expression to either return the value for that field from the first row in the dataset or to calculate the sum of a numeric dataset field. 3. Format the report by using the numerous formatting options available in the toolbar and prop- erties pane to control data presentation. Table formatting can be set at the table, row, column, and cell level — each parent’s formatting can be overridden at the child level. Property values can be specified as expressions to dynamically change the formatting based on data values (e.g., exceptions could be highlighted by changing the font color or weight). Figure 73-8 shows the layout of the report, including the header, table, and footer. Figure 73-9 shows the rendered report. Adding and formatting a List report item Adding a List item to a report places both a Tablix and a Rectangle item on the design surface. Because it includes a Tablix, it can present anything that a Table or Matrix can present, but the List item is in a convenient form to contain other items, suggesting a number of uses: ■ Place other items within the List item, such as textboxes, images, charts, etc. All these nested items will be repeated for each row of the dataset associated with the list. This is an excellent approach for data that does not fit cleanly into a grid because the arrangement of items within the List is free-form. 1549 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1550 Part X Business Intelligence FIGURE 73-8 Report layout with formatted header, body, and footer FIGURE 73-9 Rendered report with formatted header, body, and footer 1550 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1551 Authoring Reports with Reporting Services 73 ■ By adding group(s) to the List (see ‘‘Grouping and Sorting Data in a Tablix’’ later in this chapter), it is simple to show both master and detail data in flexible layouts. For example, textboxes in a group header can show customer information, while a table in the group footer can list all of the customer’s associated order detail. ■ Adding a group to a List item (and eliminating the detail section) can summarize a dataset that is reported in detail elsewhere. Using the Tablix property pages Use the Tablix property pages to define key behaviors as described in Table 73-4. Invoke the property pages by clicking somewhere within the Tablix to expose the row and column handles, then right-click one of the handles and choose Tablix Properties. While the options vary slightly among the Table, Matrix, and List report items, the process to work with them is very similar. TABLE 73-4 Table and Matrix Property Pages Property Page Description General Name the table/matrix/list, bind a dataset, set the tooltip text, control page breaks, and control where row/column headers appear. Note that row/column headers are not simply the first row or column displayed, but group or other headers as designated by dotted lines around the cells in design mode. Visibility Control the initial visibility of the item upon report execution. Allow the item visibility to be toggled by another report item. Filters Supply filter criteria. Use expressions to apply values from report parameters or other data for filtering. Sorting Set the sort order of the details section of the Tablix. Many of the same properties are available in the Properties pane of the design environment. For example, the dataset can be set directly in the Properties pane. The property pages can also be launched from the icon in the Properties pane, or by choosing the ellipses of some property values (e.g., SortExpressions). Grouping and sorting data in a Tablix Grouping within a Tablix provides the power to organize data in many ways. Figure 73-10 shows a matrix item with groups. The row and column groups displayed at the bottom show the name and order of the groups of the currently selected report item. This grouping display is enabled by checking the Grouping option of the Report menu of the design environment. The scope of the grouping in the Tablix is indicated by the brace markings within the row and column handles, indicating which portions will be repeated for each group. Groups can be created by dragging fields into the Row Groups or Column Groups areas, or by clicking the drop-down on each group. The drop-down also allows a group to be removed, or totals, such as the Sub Total and Grand Total rows in Figure 73-10, to be added. 1551 www.getcoolebook.com . report. 1547 www.getcoolebook.com Nielsen c73.tex V4 - 07/21/2009 3:59pm Page 1548 Part X Business Intelligence Best Practice B ecause a report represents the state of a dataset at a particular moment in time, it is important to. dataset. Best Practice W hile it is possible to achieve the same result by including the calculation in the SQL statement, this approach is very convenient when calling a stored procedure that you don’t want. Value="CSCO" Name="Cisco Systems (CSCO)" /> <Symbol Value="MSFT" Name=" ;Microsoft Corporation (MSFT)" /> <Symbol Value="ORCL" Name="Oracle Corporation