Extending Reporting Services with Custom Code
Written By: Devin Knight
@Knight_Devin
Bidn.com/Blogs/DevinKnight
PAGE 3 INTRODUCTION
PAGE 4 WHY USE CUSTOM CODE?
PAGE 4 DIRECT EMBEDDING
PAGE 5 Direct Inputting CodePAGE 6 Writing a Function
PAGE 8 EXTERNAL ASSEMBLIES
PAGE 9 Building a .Net AssemblyPAGE 1 1 Deploying an AssemblyPAGE 1 2 Using an Assembly in a Report
PAGE 13 SUMMARY
CONTENTS
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 3
INTRODUCTION
SQL Server Reporting Services is capable of creating eye-popping
visualizations that can be consumed by a variety of business
users. The tool has built-in functionality for developers to
produce reports that users will find not only functional, but also
visually appealing. A report developer is tasked with designing
these reports using many of the native components like charts,
gauges, and matrix to name a few.
Along with these report tools your developers must learn
Reporting Services expressions. Expressions are used frequently
in reports to control content and report appearance. While the
expression language is powerful, it does have some gaps in
functionality that can leave a developer searching for ways to
solve complex problems.
This whitepaper will focus on how to overcome the gaps that
expressions leaves by using custom code. You will also learn
many other advantages of using custom code like creating
consistency across all reports developed. As you read this paper,
you will walk through many examples of using custom code.
These examples will emphasize the use of custom code, and
will therefore skip topics like creating data sources, datasets and
basic report toolbox items. It will significantly benefit the reader
to have a basic understanding of Visual Basic which all examples
will be shown using. The intent of this paper is not to teach
you Visual Basic, but to know show it can be used in Reporting
Services and take away some real-world examples you could use
at your work. All the reports developed in this whitepaper can
be downloaded at PragmaticWorks.com.
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 4
WHY USE CUSTOM CODE?
Reporting Services can often produce several challenges that are
difficult to overcome with the native tools provided to you. A report
developer could easily spend weeks racking their brain trying to
figure out how to manipulate the native tools in Reporting Services
to fit an end user requirement. Using custom code can make
complex user requirements a lot quicker to solve and require a lot
less code. Rather than forcing your needs into the native Reporting
Services expression language, you could use custom code to make
developing these complex requests simpler. The reason custom
code makes this so much easier, is because it gives you the ability to
couple .Net languages with Reporting Services.
DIRECT EMBEDDING
Embedding custom code is a quick and easy way to add in new
functionality into Reporting Services that does not exist in the
natively provided tools. This is a quick process as you simply
input your code and preview the report to see how it changed
the design. You also have the ability to add multiple functions
at once, so if there are several custom functions you would like
to use in a report you can add them simultaneously. Another
benefit often overlooked is that it gives you one consolidated
place to edit code. Many times when you use Reporting Services
expressions you apply the same expressions value to multiple cells.
If you needed to make a change to those expression values you
would have to open each textbox property individually, but with a
custom code you could have a just altered the embedded code in
one spot and it would have been applied to all the necessary cells.
While it may sound like embedding custom code in a report has no
shortcomings, that is far from the truth. The code must be written
in Visual Basic (no C#), so having some previous knowledge of the
language will greatly benefit you. Even without that knowledge,
it is fairly easy to find what you’re looking for with a few simple
web searches. Another disadvantage is that the embedded code
window is lacking a lot of the functionality of Visual Studio. For
example you do not have intellisense available or even basic code
errors until the report is in preview mode.
A summary of many of the pros and cons of using embedded
code can be found in Figure 1.
Pros Cons
More than one function can be embedded
Must use Visual Basic
Immediately see the results of code without creating a Visual Studio project
No intellisense in the code window
One place to make changes to code Code Errors are not visible until report preview
Figure 1
If you are looking for consistency with how your developers write
reports custom code is a great way of accomplishing it. The
best way this can be done is with external assemblies (which
will be discussed in detail later in this paper) that can be shared
with multiple report developers to standardize how reports are
developed. After creating and deploying an assembly, Reporting
Services will reference the code externally, giving the developer
the ability to manage the code completely separate from the
reporting tool.
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 5
DIRECT INPUTTING CODE
Once you have come to the conclusion that the best
way to solve your business problem is with custom
code you can begin inputting your VB. The embedded
custom code must be inputted on each report you
wish to use the code. So if you have written code
that will help make your report formatting consistent
across your entire report then you must add the code
to every report that will use the code.
When you are ready to input your code you must go
to the Report Properties window. You can find the
Report Properties window two different ways. The first
method is to right-click outside the design surface of
a report and select Report Properties. In Figure 2 you
will see the first method of getting to the properties.
The second method for navigating to the Report
Properties window can be found in the toolbar. From
the toolbar select Report -> Report Properties. If you
do not see the Report menu in the toolbar then first
select somewhere in the background of your report
and it should appear. Sometimes the Report menu is
hidden when other windows are active. For example
if you are looking at the properties of a textbox in your
report, then the Report menu in the toolbar is hidden.
Figure 3 shows the second method for getting to the
properties.
Either way you choose to get to the Report Properties
window you will get the same result. After the Report
Properties window opens, select the Code page where
you can enter your custom code (Figure 4).
You will instantly see some of the disadvantages of
using embedded code that were discussed earlier. It
lacks major Visual Studio functionality like intellisense
and code error windows. Next, we will walk through
creating an example of embedded custom code.
Figure 2
Figure 3
Figure 4
WRITING A FUNCTION
Writing custom code in Reporting Services assumes you have a
little knowledge of Visual Basic. Unfortunately, VB is currently
the only acceptable coding language when embedding code in
a report. This would likely not change in future versions of SQL
Server either, so get comfortable with VB if you choose to embed
you custom code. If you do not know VB this whitepaper does
not intend to teach you the .Net language, but rather show you
how it can be integrated with Reporting Services. So if VB is new
to you use this paper as a reference while you learn how powerful
having the knowledge of Visual Basic can be.
In our first example we will walk through a basic report and show
how to use embed custom code to do something that is possible
with native SSRS expressions, but would require nested logic that
can be much more confusing. I’m starting off with a very simple
report that lists all products and the sales for each, as shown in
Figure 5. This base report and the completed report can be found
on PragmaticWorks.com.
The requirement for this example is to change the background
color of the Order Quantity column based on the data values. The
users would like:
Order Quantity less than 500 to show Maroon
Order Quantity less than 1000 to show Yellow
Order Quantity less than 2000 to show Orange
Order Quantity greater than or equal to 2000 to show Green
We could accomplish this using the Reporting Services Expression
language with several nested IIF statements, but to make any
changes to the thresholds you would have to alter every cell
that applied the formatting. Using a function you can simply go
back to the code window to adjust the custom code and see the
immediate results next time you preview the report. To input the
function, navigate to the Report Properties window and open the
Code page. Use the following code to satisfy the requirement:
Public Shared Function SetColor(ByVal Value As Integer) As String
SetColor = “Green”
If Value < 500 Then
SetColor = “Maroon”
ElseIf Value < 1000 Then
SetColor = “Yellow”
ElseIf Value < 2000 Then
SetColor = “Orange”
End If
End Function
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 6
Figure 5
This code will accept a parameter value and compare that value
against each of each condition to determine what color should be
appropriately returned. Your Code page should appear the same
as Figure 6 before you click OK and return back to the report.
With the custom code set, it is now time to actually call the code in
the background property of the cell that we would like to format.
First select the cell that you wish to apply the formatting to and
then open the properties menu (F4). Find the BackgroundColor
property then select expression to make the property value
dynamic. In the Expression window use the following code to call
the custom code and pass in the value from the OrderQuantity
field (shown in Figure 7):
=Code.SetColor(SUM(Fields!OrderQuantity.Value))
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 7
Figure 6
Figure 7
Figure 8
Once these changes are complete click OK and preview the
report. Your completed report should look similar to Figure 8.
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 8
EXTERNAL ASSEMBLIES
Creating external assemblies for custom code is really the best
long term solution to creating consistency and standards in the
way report development is done. Any custom code is compiled
in Visual Studio without the possibility of someone that is less
familiar with .Net making changes with embedded code.
You will notice that statement was less specific in the coding
language that can be used this time. Previously, as this paper
mentioned in the embedded code section, you could only use VB.
With external assemblies you are no longer limited to VB, you are
free to develop your custom code using either VB or C# because
the code you develop with external assemblies is done in Visual
Studio and not Reporting Services.
External assemblies are also a great way to manage custom code.
You aren’t forced to open the report to make changes to the
code because the report simply stores a reference to where the
assembly is stored. This is great because you can make change to
the assembly and after redeploying it can affect dozens of reports
that use the code reference.
Pros Cons
Can be any .Net language Deployment is a bit tedious
Updates to code can be managed from outside of SSRS
Assemblies will have restricted access to system resources
Best way to standardize custom code
Figure 9
Of course there are disadvantages to using external assemblies
also. For example, it can be very tedious to deploy an assembly.
The steps for deploying will be described later on in this
whitepaper, but for now understand that it is much more time
consuming then using the embedded custom code method
described earlier. External Assemblies will also have restricted
access to the system resources. This means if you anticipate the
assembly using the file system or accessing outside data that
there are some configuration settings that must be changed.
A summary of many of the pros and cons of using embedded
code can be found in Figure 9.
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 9
BUILDING A .NET ASSEMBLY
So you have weighed the pros and cons of using embedded
custom code and building an external assembly and have decided
to go with building an assembly. This section will walk you through
creating an assembly, using the same example scenario we used
for embedded code of wanting to format the background color
based on the value of our Order Quantity field.
Open Visual Studio and create a new Class Library project as
shown in Figure 10. Before you hit OK ensure that the project is
created using .Net Framework 2.0 otherwise Reporting Services
will not accept the assembly
Figure 10
Figure 11
Once the project is created rename the Class1.vb file in the
Solution Explorer to ValueFormat.vb. Open the ValueFormat.vb
file if it is not already open. Use the same code from the previous
example and place it between the existing code, as shown in
Figure 11.
Public Class ValueFormat
Public Shared Function SetColor(ByVal Value As
Integer) As String
SetColor = “Green”
If Value < 500 Then
SetColor = “Maroon”
ElseIf Value < 1000 Then
SetColor = “Yellow”
ElseIf Value < 2000 Then
SetColor = “Orange”
End If
End Function
End Class
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 10
There are a few more things we must do to handle security for
this assembly once we are ready to register the dll to the Global
Assembly Cache (GAC). The first step is to set the <Assembly:
AllowPartiallyTrustedCallers()> property. Without this declaration
applications like Reporting Services are unable to use the assembly.
To make this change you must navigate to the Solution Explorer
and with the project select click the button to Show All Files as
shown in Figure 12. Once all the project files are visible expand
My Project and open the AssemblyInfo.vb file.
With the AssemblyInfo.vb file open add the Imports System.Security
namespace and the <Assembly: AllowPartiallyTrustedCallers()>
declaration as shown in Figure 13.
Once these changes are complete save and close the AssemblyInfo.
vb file. The last change we need to do before this assembly is
complete and ready for deployment is to sign it with a strong
name. A strong name is basically a way of naming or versioning
the dll. Without giving the dll a strong name it cannot be
registered in the GAC.
To give the dll a strong name right-click on the project name in the
Solution Explorer and select Properties. Go to the Signing page
and check Sign the assembly. You must then create a new strong
name key file by selecting <New…> from the dropdown box as
shown in Figure 14.
Figure 12
Figure 13
Figure 14
Name the file StrongName and uncheck protect my file with a
password, then click OK. Once this is complete, Save All and
preform a build of the project. You can build the project by select
the Build menu from the toolbar and then Build ColorFormat.
With the assembly now created you will learn how to properly
deploy it. From here on you are done with Visual Studio.
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 11
DEPLOYING AN ASSEMBLY
To deploy an assembly for Reporting Services use, you must copy the dll you created to the
two different locations listed below:
C:\Windows\assembly
C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\
ReportServer\bin
Navigate to the bin\Debug folder in the path of the where the Class Library project was
created. In the Debug folder you should see the ColorFormat.dll file. Copy and paste
this file to the C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting
Services\ReportServer\bin folder.
Next you will place the dll in the GAC. This cannot be done by copying and pasting the file
though. It must actually be dragged and dropped into the C:\Windows\assembly folder.
Once this is complete you will see the dll appear in the GAC as shown in Figure 15.
Figure 15
Figure 16 Figure 17
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 12
USING AN ASSEMBLY IN A REPORT
With the dll creation and deployment completed the assembly
should now be ready to use. Open the designer for Reporting
Services with the base report that we started with in the
first example. Again all these examples can be found on
PragmaticWorks.com with the beginning and completed
examples.
Find the Report Properties menu that you learned about in the
first section of this white paper. With the Report Properties
menu open select the References page. This is different from the
embedded code example where we just started typing our code
on the Code page. The Reference page is where we will point the
report to any assemblies that we have previously created. Click
Add under Add or Remove assemblies and then select the ellipsis
next to the new entry as shown in Figure 16.
On the Browse tab of the Add Reference window, select the
ColorFormat.dll then click OK. Although we have selected the
dll from the C:\Program Files\Microsoft SQL Server\MSRS10_50.
MSSQLSERVER\Reporting Services\ReportServer\bin folder, it
will actually load the GAC version when the report runs. Also,
notice now that the reference appears on the Reference page
of the Report Properties. Click OK again to return to the report
designer.
Once the expression is entered click OK and preview the report.
The report should look exactly the same as the embedded code
example but now this is using an external assembly to control
the background color. If you ever needed to modify the color
thresholds you would modify the Class Library project and
redeploy the dll. This is helpful because if the same dll is used
in several reports then you can change the report appearance
without having to open a single rdl report file.
Like we did in the embedded code example, you will select the
cell that you wish to apply the formatting to and then open the
properties menu (F4). Find the BackgroundColor property then
select expression to make the property value dynamic. In the
Expression window use the following code to call the assembly
and pass in the value from the OrderQuantity field (shown in
Figure 17):
Template
=AssemblyName.ClassName.FunctionName(Parameter)
Code for this example
=ColorFormat.ValueFormat.SetColor(SUM(Fields!OrderQuantity.
Value))
PRAGMATIC WORKS White Paper Extending Reporting Services with Custom Code
www.pragmaticworks.com PAGE 13
SUMMARY
This white paper has covered how to use custom code to extend the functionality of Reporting Services. Using custom code also allows
you to standardize coding practices among developers that may try and accomplish the same goal using multiple methods. While the
direct embedding of custom code is quick and simple to do, it does not scale nearly as well as an external assembly when multiple
reports use the same functions. External assemblies are a little more cumbersome to create and maintain, but it truly is the ideal solution
because you are not limited by .Net language and it can be managed from outside of Reporting Services.