Multicolumn Pictures in Crystal Reports

Hello guys, its been a while since a posted something on this blog. I was working on this project where an item can have as many pictures as possible, as part of the requirement , a report was to be generated to show the item information and its pictures ( in a multicolumn way).

Below are the steps to show pictures in crystal reports (Note that the the data type used is image and hence using datasets as the data source for the reports, the picture can easily be dragged onto the report)

1. To start, the picture is dragged to the detail section of the report as shown in the picture below


2. Then right click on the “detail section” tab and choose the “section expert” as shown in the picture below


3. In the dialog box that appear, make sure the “details” section is selected and on the right hand side, on the “common” tab make sure “Format with Multiple columns “ is checked. The move to the “Layout” tab, make the required changes and make sure in the “printing direction” section you select “across” and down.


4. You are now done, with the reports, run you program and something as shown in the picture below should be shown.



Crystal reports can be created in .Net applications with different data sources including using database tables, stored procedures, typed datasets and also without a data source.

In this article we are going through how to create a crystal report for the first time using database tables as the datasource.

1. You have to create your windows project in using VS 2005. After creating the project, right on then project name in the solution explorer, select “add” and then “add new” as shown below.


2. In the add new dialog box, select “crystal Report” and name it, and then click on the add button.


3. You will be presented with the “crystal report gallery” dialog, choose “using the report wizard” and click on ok


4.In the choose data source dialog, go to the “ Create New Connection” node and then select the “OLE DB(ADO)” sub node.


4. You will then be required to provide the database connection information. Slect the “Microsoft OLE DB provider for SQL server” and click on the next button


5. Here you provide the database logon parameters


6. After successfully connecting to the database, you then select the table (s) you want to display its content on your report


6. After selecting the table(s) you select the actual columns you want to displayimage

7. After choosing the columns you will display, you can click on next to choose the columns for grouping and then for filtering, and then finally you choose the format to display your report.


8. After you have finished designing your report, you then drag a “crystal reports viewer” onto your form.


Then create a code under the form load event to show your report on for load

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ‘create a new report document 
        ‘and load the report from its source
        ‘use Application.StartupPath to get the address of your report fro deployment issues
        Dim rpd As New ReportDocument
        Me.CrystalReportViewer1.ReportSource = rpd

    End Sub

    ‘for deployment issues make sure the database paramaters are encrypted
    ‘and saved in the mysettings class

Private Sub SetDBLogonForReport(ByVal myReportDocument As ReportDocument)
       Dim myConnectionInfo As ConnectionInfo = New   ConnectionInfo()
       myConnectionInfo.DatabaseName = "datalinkDB"
       myConnectionInfo.UserID = "sa"
       myConnectionInfo.Password = "qwerty"
       myConnectionInfo.ServerName = "localhost"
       myConnectionInfo.IntegratedSecurity = "false"
       Dim myTables As Tables = myReportDocument.Database.Tables
       For Each myTable As  CrystalDecisions.CrystalReports.Engine.Table In myTables
           Dim myTableLogonInfo As TableLogOnInfo = myTable.LogOnInfo
           myTableLogonInfo.ConnectionInfo = myConnectionInfo
   End Sub

Below is a picture when the application is run



Sometimes in web applications (ASP.NET) we prefer printing a window without some controls that appear on the interface. For example, printing a window by clicking on a print button without showing the print button on the printed document. In this example we are printing a student’s results without showing the Print and the close buttons.

To start, we place the two control in a DIV control.Drag the “DIV” control from the HTML controls section. Name the DIV control by giving a value to ID property as shown below. Place the print and close button in the DIV control.


Note that in creating ASP.NET applications, there are two types of source codes, the VB/C# source code and the HTML code. First we create a script to hide the DIV control as shown below. In the script below the “dv1” is the ID value of the DIV control

Add this script to the HTML source

   1: <script language="javascript" type="text/javascript">

   2:    function hidePrint(){

   3:     document.getElementById("dv1").style.display='none';

   4:     window.print();

   5:     window.close();

   6:             }

   7: </script>

Note that the script should be in between the <head></head> tag of the html source code

Select the print button and go to the html source code and add the onclick property . The value of the onclick property should be the created javascript function (named hidePrint()). The button’s html code should look like the one below after the addition of the onclick property

   1: <input type="button" id="Button1" runat="server" 

   2: value="Print" class="fltbutton"  style="width:60px" 

   3: onclick="javascript:hidePrint();" />

This is all you have to do and you are good to go.

Below is a window showing the student’s results and the Print and the Close Button


What is printed after clicking on the “print” button




Due to flexibility in creating reports with some tools in the .NET framework , using PrintDocument() class in creating reports is fading out. But sometimes you don’t have a choice but to use it. For instance creating reports without any predefined data source or generating reports where needed columns are determined at runtime.

In this post we will go through creating a report using the PrintDocument. Our datasoure will also come from a listview which contains a list of file types and their sizes from an indexed drive. When using the report document everything is drawn to the report interface, thus you draw a string, an image,a line. the difficulty in here also is, you yourself determine at runtime where your text, lines and images should be positioned

To start with, first drag a PrintPreviewDialog control on your form. The control is named “PrintPreview1”.


Then go to the code view and create  your procedure below.

Private Sub detaildisksreport_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
        Dim linesPerPage As Single = 0
        Dim yPos As Single = 0
        Static count As Integer = 0
        Dim x, y, c, i As Integer
        Dim leftMargin As Single = e.MarginBounds.Left
        Dim topMargin As Single = e.MarginBounds.Top

        ‘declaring fonts to use in your reports
        Dim backFont As New Font("Arial", 10, FontStyle.Italic)
        Dim HeaderFont As New Font("Arial", 20, FontStyle.Bold)
        Dim normfont As New Font("Times New Roman", 18, FontStyle.Regular)

        ‘ Calculate the number of lines per page.
        linesPerPage = e.MarginBounds.Height / normfont.GetHeight(e.Graphics)

        ‘x determines the horizontal positions whiles y determines the vertical position

        ‘ Drawing an image on top of the report
        Dim b As Rectangle
        Dim pic As New Rectangle(40, 5, pic1.Width + 40, pic1.Height + 40)
        e.Graphics.DrawImage(pic1.Image, pic)

        ‘drawing a line around the image
        b = New Rectangle(40, 5, pic1.Width + 40, pic1.Height + 40)
        e.Graphics.DrawRectangle(Pens.Black, b)

        linesPerPage = e.MarginBounds.Height / normfont.GetHeight(e.Graphics)
        linesPerPage = linesPerPage – 5

        ‘ Drawing our report titles
        x = 190
        y = pic1.Height + 70

        e.Graphics.DrawString("DETAIL DRIVE REPORT", HeaderFont, Brushes.Black, x, y)

        y += 40
        x = 25
        e.Graphics.DrawString(" FOLDERS ON DRIVE :  " & Me.cmbCat.SelectedItem.ToString.ToUpper, HeaderFont, Brushes.Black, x, y)
        y += 40
        x = 10
        e.Graphics.DrawString("REPORT GENERATED ON " & Now.ToLongDateString.ToUpper, HeaderFont, Brushes.Black, x, y)
        y += 10
        x = 5

        e.Graphics.DrawLine(Pens.Black, 5, y + 30, 820, y + 30)
        x = 10
        y += 60
        c = y

        e.Graphics.DrawString("FOLDER NAME", HeaderFont, Brushes.Blue, x, y)
        x += 260

        e.Graphics.DrawString("NUMBER OF FILES", HeaderFont, Brushes.Blue, x, y)
        x += 330

        e.Graphics.DrawString("FOLDER SIZE", HeaderFont, Brushes.Blue, x, y)

        e.Graphics.DrawLine(Pens.Black, 5, y + 30, 820, y + 30)

        x = 33
        y = c + 40

        i = 0
        ‘adding the content to the report
        For i = count To Me.LsvCDs.Items.Count – 1

            Dim len As Integer
            If LsvCDs.Items.Item(i).SubItems(0).Text.Length > 25 Then
                len = 25
                len = LsvCDs.Items.Item(i).SubItems(0).Text.Length
            End If

            e.Graphics.DrawImage(Me.SmallImages.Images(0), 15, y + 2)

            e.Graphics.DrawString(Me.LsvCDs.Items.Item(i).SubItems(0).Text.Substring(0, len), normfont, Brushes.Blue, x, y)
            x += 400
            e.Graphics.DrawString(Me.LsvCDs.Items.Item(i).SubItems(1).Text, normfont, Brushes.Blue, x, y)
            x += 220
            e.Graphics.DrawString(Me.LsvCDs.Items.Item(i).SubItems(2).Text, normfont, Brushes.Blue, x, y)

            ‘setting the y value to point to the next line
            ‘reseting the x value to the margin
            y += 30
            x = 33

            ‘checking to see if the current page is full
            If y + normfont.Height > e.PageSettings.PaperSize.Height Then
                count = i + 1
                e.HasMorePages = True

            End If

        count = 0
        e.HasMorePages = False
    End Sub

Also add the code below to a button click event and you are good to go.

   1: Dim pd As New PrintDocument()

   2: 'adding the print method created to the printdocument printpage event

   3: AddHandler pd.PrintPage, AddressOf disksreport_PrintPage


   5: 'passing the print doucument to the PrintPreviewDialog

   6: PrintPreview1.Document = pd

   7: PrintPreview1.ShowDialog()

Below are sample interfaces, using printDocument to generate reports




Generating random numbers can be sometimes frustrating, especially when you want them to be unique.

Example in this instance is when you give users unique usernames when they register with you websites.

Below is a simple function to generate random numbers. To make these generated random strings unique (for the purpose of your application you can add the row index, when inserting it into a database, to make it unique. In this case you will be generating always unique random variables)

Function Generate() As String
‘key_chars, is the length of random numbers u want to generate

Dim i_key As Integer

Dim RandomNo As Single
Dim arrIndex As Int16

Dim sb As New StringBuilder

Dim RandomLetter As String

lstLetters = "abcdefghijklmnopqrstuvwxyz"

lstNumber = "0123456789"

LettersArray = Me.Key_Letters.ToCharArray

NumbersArray = Me.lstNumber.ToCharArray

For i_key = 1 To Key_Chars


RandomNo = Rnd()

arrIndex = -1 ‘the number 101 was randomly chosen

If (CType(Random1 * 101, Integer)) Mod 2 = 0 Then

‘if the number generated from the if condition is even get a letter else get a number

‘ generate a random number from the letters array

Do While arrIndex < 0

arrIndex = Convert.ToInt16(LettersArray.GetUpperBound(0) * RandomNo)


RandomLetter = LettersArray(arrIndex)



While arrIndex < 0

arrIndex = Convert.ToInt16(NumbersArray.GetUpperBound(0) * RandomNo)


RandomLetter = NumbersArray(arrIndex)




Return sb.ToString

End Function


Hi fellows, this is a simple way of retrieving system properties through your application. For example how to know the system owner, the operating system version, the processor information, etc

Below is the code which is handled by a form_load event

Don’t forget this import; Imports Microsoft.Win32


            Dim info As String = “”

            Dim oReg As RegistryKey

            oReg = Registry.LocalMachine.OpenSubKey(“SOFTWARE\Microsoft\Windows NT\CurrentVersion”)

            info = info & ” OS Version:  ” & oReg.GetValue(“CSDVersion”, “DEFAULT-VALUE”).ToString & vbCrLf

            info = info & ” System User:  ” & oReg.GetValue(“RegisteredOwner”, “DEFAULT-VALUE”).ToString & vbCrLf


            Dim Str As String = “Hardware\DESCRIPTION\System\CentralProcessor”

            Dim Stride As String = “Identifier”

            Dim strspeed As String = “~MHz”

            Dim strvendor As String = “VendorIdentifier”

            info = info & ” Processor Speed:  ” & Registry.LocalMachine.OpenSubKey(Str.ToString).GetValue(strspeed.ToString) & ” MHz” & vbCrLf


            info = info & ” Processor Vendor:  ” & Registry.LocalMachine.OpenSubKey(Str.ToString).GetValue(strvendor.ToString) & vbCrLf

            info = info & ” Processor Identifier:  ” & Registry.LocalMachine.OpenSubKey(Str.ToString).GetValue(Stride.ToString) & vbCrLf


            Me.Label1.Text = info

        Catch ex As Exception

        End Try


Below is a picture after runing the application

sys info


If you want to insert images from the file system (eg, C:\images folder) into crystal reports here is a simple process of doing that.

Add a dataset  to your project. Add a datatable to the dataset. Then add a row of data type system.byte().


Add a new crystal report using the dataset created as its datasource. You are done now.

Add a new form to your project with a crystal report viewer and a button

The method below handles the button click event

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim ofd As New OpenFileDialog()

        ofd.Multiselect = False

        ofd.Filter = “Images|*.jpg;*gif;*.bmp”

        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then



            MessageBox.Show(“Please select a Picture”)

        End If

    End Sub


Public Function savepic(ByVal fsource As String) As Byte()

        Dim arrImage() As Byte = Nothing

        If File.Exists(fsource) = False Then

            Return arrImage

        End If

        Dim img As Image = Image.FromFile(fsource)

        Dim ms As New IO.MemoryStream

        img.Save(ms, img.RawFormat)

        arrImage = ms.GetBuffer


        Return arrImage

    End Function


    Private Sub createReports(ByVal image() As Byte)


        Dim nrow As DataRow = DataSet1.reports.NewreportsRow

        nrow(0) = image


        Dim rpt1 As New rptImages     ‘ crystal report object

        rpt1.SetDataSource(DataSet1)            ‘ set the datasource of crystalreport object, dataset 1 was the one created

        CrystalReportViewer1.ReportSource = rpt1

    End Sub


Sample picture when the application is run

Sample Picture of the Application
Sample Picture of the Application


To change the connection string of a typed dataset in 2005 and also Building a dynamic connection strings in Below are easy ways these can be done.

1. To change the connection string of a typed dataset, add the method below to the setting file. To see the setting.vb file, go the your project properties, on the settings tab, click on the the view code button and there you go.

Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded

Dim db As New DBConnect

Me.Item("HospitalConnectionString")  =db.returnConnectionString

End Sub

Note: HospitalConnectionString is the name of the connections string as saved in your project settings

Below is the detail of the “returnConnectionString” procedure

Also note that servername, username, database, password are all saved in the settings

Public function returnConnectionString ()as string


client = getClientName()

With My.Settings

If .servername = client Then

If Me.integratedSecurity = False Then

connectionString = "Data source= " & .servername & "; initial catalog= " & .database & ";user id= " & .username & " ;password = " & .password


connectionString = "Data source= " & servername & "; initial catalog= " & database & "; Integrated Security= " & integratedSecurity

End If


connectionString = "workstation id= " & client & " ;Data source= " & servername & " ;initial catalog= " & database & " ;user id= " & username & " ;password = " & password & " ;Integrated Security=" & integratedSecurity & " ; Connect TimeOut=30"

End If

End With

Catch ex As Exception


End Try

Return connectonString

End function


A function to return the name of the current machine(the machine the program is running on)

Public Function getClientName() As String

Dim client As String = ""

client = Dns.GetHostName

Return client

End Function

Saving items in the Settings

Below is code under the save setting buttons

With My.Settings

.Server = Me.txtServer.Text

.Dbase = Me.txtDbase.Text

.UserName = Me.txtUserName.Text

.Password = Me.txtPassWord.Text

.integrated = Me.ChkSecurity.Checked


End With

Tags: , , , ,