One of the really neat features with the new Reporting Services authoring tool code named ‘Crescent’ is that you can reference images directly from your model. This can look really cool when you use the images in a card visualizations, part of a table, as tiles, and as slicers to use as filters within the report. Here is a nice report that is part of the Hello World Picnic Sample that came out with the CTP3 release of SQL Server ‘Denali’ (download from Project Crescent Samples and download images from Sample Images and you can find information on the Crescent Samples for CTP3 in the readme here).
So this is really cool and provides a really nice visualization perspective to the report both from what you are looking at and to add a little color and life to the report. When you are looking at a sales report for products, wouldn’t it be nice to see the image of the product or category that you are looking at. So what better place to store this information than in your BI Semantic Model that you can then leverage with your reporting tool like Crescent. So how do you do this?
Well in the current CTP3 there are a couple of different ways that you can go about this. The first option is to store your images in say a SharePoint library and the provide the Image URL references in the model. That is how the example above is being done. That report is actually leveraging a PowerPivot Tabular model that was built in Excel 2010 leveraging the CTP3 release of the PowerPivot add-in which you can download here. The second option that you have right now is to store the images in a database table and reference that way use base64-encoded strings. Getting this option to work in CTP3 is by no means straightforward either and took me quite a while to figure out. Just using a base64-encoded string was a puzzle and luckily Robert Bruckner provided that solution as to how to format the binary data in the database to this format. There is a third option which is simply referencing the binary data from the database, but currently the CTP3 release of Crescent will not recognize this field type in the model at all.
So lets take a look at the two working options we have that we can use with the CTP3 release of Crescent along with the Tabular BI Semantic Models using both a PowerPivot and a Tabular Analysis Services solution as examples.
As I mentioned, the Hello World Picnic PowerPivot model uses this setup. So I will highlight how this is done.
- First you need to have images available for what ever you want to display. The download link is available above for the samples and then the instructions are provided in the information readme.
- Next you need to place the images in a location that can be referenced as a URL in the model. In this example they are placed in a document library within a folder.
images are stored in a SharePoint document library called Shared Documents buried down a couple of levels –> /Images/HelloWorldPicnic/
- Then within your table in the PowerPivot Tabular model you can provide your URL to the image. In this example they store the name of the image in the table and then use a calculated column to generate the Image URL. In order to activate the option to set this as an Image URL in the Reporting Properties (which is in the Advanced tab – might need to turn on the Advanced Mode in the file setting first) you need to define the Table Identifier column in the table. This means that you need to specify which column makes the table unique to identify each record (in this example it is the ItemId column).
need to specify a table identifier – a column that defines the table and makes each record unique
a calculated column is used here that includes the image name column from the table along with the rest of the string to the SharePoint location and concatenates everything together
- Then once you have deployed your file to SharePoint you can create a Crescent report from the PowerPivot file and you will now see the field in the field list to select from along you can start leveraging this in your report design.
the Items Name and Drawing fields are selected from the Field List which get added to a Table
So that one wasn’t too bad. And this is a nice option because having the images in a document library location is a nice spot where end-users can maintain these as needed and swap them out.
Okay, let’s take a look at the other option that is currently available and that is storing the images in the database and using a base64-encoded string.
So what if the images are already stored and available in a database table? Well there is a solution that can allow you to do this, at least if you are doing the Tabular Analysis Services project type.
- Here we already have the images stored in a database table in as a varbinary(max) data type – just a warning, I believe that the max size for the images is 25K, I don’t believe that has changed yet, so just be aware of that in case your images do not show up. In this example we will be using the AdventureWorksDWDenali CTP3 sample database leveraging the product dimension data – you can download the sample databases and projects for Denali CTP3 here.
table contains a varbinary(max) column called LargePhoto that contains some images of our products
- Once the table is imported into a Tabular Analysis Services project we need to modify the Table Properties for the product dimension and change the reference from Table Preview to Query Editor to generate our base64-encoded string that we will use in our model instead of the binary data that is already available from the LargePhoto data (this is currently not supported by Crescent right now, but will be in next release).
now the key here is to add the logic to generate the base64-encoded string which is the following – thanks to Robert Bruckner for providing the logic:
cast(N” as xml).value(‘xs:base64Binary(xs:hexBinary(sql:column(“[dbo].[DimProduct].LargePhoto”)))’, ‘varchar(MAX)’) as LargePhoto64
- Next we need to once again set the Table Identifier (Product Id column – in this example the ProductKey column has been renamed to Product Id) and then set the properties on the new LargePhoto64 column for Image URL to True along with Representative Image to True
set the Product Id as the Table Identifier (which is actually the ProductKey column)
set the Image URL and Representative Image properties to True for the LargePhoto64 column
- The next step is the hack that we have to perform to the Code portion because if you try to change the Image URL property back to False it will also set the Representative Image to False and that is not what we want. You can right-click on the bim file in the Solution Explorer and select ‘View Code’ or pick the option from the ‘View’ file menu. Once you are in the Code behind do a search for LargePhoto64 and it will take about three times to find the right spot we are looking for which contains the Type property setting that displays ImageURL. We need to change this to just Image.
find the LargePhoto64 column where the Type property is located with ImageURL
now change the Type so that it does not include the valuens=”ddl300” and remove URL from the value so that it is just <Type>Image</Type>
- Now you want to Save this change and then double click on the bim file in the Solution Explorer to go back into the Design view and deploy the database to your Tabular instance of Analysis Service.
- Setup the BISM Connection File to you model (see my previous posting on this if you are not familiar with how to setup data connections to a Tabular BI Semantic Model – Configuring SQL Server Denali Reporting Services SharePoint 2010 Integration) and then click on the connection file in your SharePoint library and you will now be able to utilize the LargePhoto64 column as an image in your reports.
the Product Name and LargePhoto64 columns were selected from the Field List and added to a Table
So there you go, not too bad, huh? You have two different options right now for using Images in your models. In the next release we should see direct support with Crescent in being able to utilize binary data directly instead of having to use the base64-encoded string method. But for the time being this is what you can use. My preference would be the Image URL. This just seems not only more straightforward, but also easier to maintain and update, especially from an end-user standpoint.