Menus

Monday, December 3, 2012

Loading images dynamically in Crystal Report using VB.Net

Visual Studio 2003/2005 does not readily allow you to load an image file on a Crystal Report dynamically unless you use "Dynamic Image Location" feature which is available in Crystal Reports Developer XI. But there is a cheaper work around for this. The solution is to dynamically add an binary column to the XSD dataset and in the dataset containing the data to be printed. Then load the image file as binary data into the dataset.
1. In a column in your database table store the path to the image that needs to be displayed in a crystal report document, in this example the image path column name is "ImagePath".
2. Create a new Dataset/XML schema(xsd) in VS.Net that maps the fields in the database table. This should be the normal procedure when creating a report. In this XSD DataSet add an additional field that is not in the table and which is of type base64Binary :
xs:element name="Image" type="xs:base64Binary" minOccurs="0"
Note that the opening and closing tags are missing above since it won't be printed on this site. Just add enclose the above in "< />"

3. When designing the report based on this DataSet, drag and drop the "Image" field in the region where you want it to appear.
4. Add the following procedures to your code:
Private Sub AddImageColumn(ByVal objDataTable As DataTable, ByVal strFieldName As String)
Try
'create the column to hold the binary image
Dim objDataColumn As DataColumn = New DataColumn(strFieldName, Type.GetType("System.Byte[]"))
objDataTable.Columns.Add(objDataColumn)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub

'*... and this one to load the image in the above added field:
Private Sub LoadImage(ByVal objDataRow As DataRow, ByVal strImageField As String, ByVal FilePath As String)
Try
Dim fs As System.IO.FileStream = New System.IO.FileStream(FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)
Dim Image() As Byte = New Byte(fs.Length-1) {}
fs.Read(Image, 0, CType(fs.Length, Integer))
fs.Close()
objDataRow(strImageField) = Image
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
5. Before assigning the dataset to the "SetDataSource" of your report, add the following code:
' Fill the dataset "DS" as required with data to be displayed on the report
'* Begin code to add
AddImageColumn(DS.Tables(0), "Image")
' Loop to load the image for each row
For index As Integer = 0 To DS.Tables(0).Rows.Count - 1
If Not String.IsNullOrEmpty(DS.Tables(0).Rows(index).Item("ImagePath").ToString) Then
LoadImage(DS.Tables(0).Rows(index), "Image", _
DS.Tables(0).Rows(index).Item("ImagePath").ToString)
Else
'* You could load a default image here, like "no image to display"
'* if you have a standard one then un-comment the code below and change the image path
'LoadImage(DS.Tables(0).Rows(index), "Image", "c:\MyDefaultImage.JPG")
End If
Next
'* End code to add
rptDoc.SetDataSource(DS.Tables(0))
' Display report in a report viewer control

No comments:

Post a Comment