Search code examples
reporting-servicesbarcodereportbuilder3.0

Adding Barcode to Report Builder 3.0


I am trying to embed a barcode in my RDL report which is developed by Microsoft SQL Server Report Builder 3.0.

I found couple of suggested solutions in the internet, one of them is to add a DLL reference and add some code, but it didn't work and it always fails to load the DLL, I found another solution by using an API as source of an image, but that would not be a feasible solution for me since I do not always have internet connection in my server.

Is there a way to use Code 128 font in my report? Or any other solution that does not require internet connection?


Solution

  • After a lot of research, I managed to embed barcode in my report and have it running using Code 128 font.

    However, the font by itself is not enough since you need to prepare the text first in order for the barcode to be scannable, following solution does not require installing the font on the clients machines, you only need to install it on the server:

    1. First you need to install Code 128 font if you did not already! You can download it from here.

    2. Open your report or create a new one.

    3. We need to add System.Drawing DLL file as reference:

      This can be done by going to the Report Properties (Right Click outside the body -> Report Properties), click on References tab, click on Add button in Add or remove assemblies section, click on the Open button ... Browse for C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll file, and click Open.

      You should have something like this:

      enter image description here


    1. Now we need to add some custom code to the report:

    Go to Code tab in the Report Properties, copy and past the following code and click Ok:

    Function StringToBarcode(value As String) As String
      Dim charPos, minCharPos As Integer
      Dim currentChar, checksum As Integer
      Dim isTableB As Boolean = True, isValid As Boolean = True
      Dim returnValue As String = String.Empty
    
      If (value Is Nothing OrElse value.Length = 0) Then
        Return String.Empty
      End If
    
      'Check for valid characters
      For charCount As Integer = 0 To value.Length - 1
        currentChar = Asc(value.Substring(charCount, 1))
        If (Not (currentChar >= 32 AndAlso currentChar <= 126)) Then
          isValid = False
          Exit For
        End If
      Next
    
      If Not (isValid) Then Return returnValue
      charPos = 0
      While (charPos < value.Length)
        If (isTableB) Then
          'See if interesting to switch to table C
          'yes for 4 digits at start or end, else if 6 digits
          If (charPos = 0 OrElse charPos + 4 = value.Length) Then
            minCharPos = 4
          Else
            minCharPos = 6
          End If
          minCharPos = IsNumber(value, charPos, minCharPos)
    
          If (minCharPos < 0) Then
            'Choice table C
            If (charPos = 0) Then
            'Starting with table C
            'char.ConvertFromUtf32(205)
              returnValue = Chr(205).ToString()
            Else
              'Switch to table C
              returnValue = returnValue + Chr(199).ToString()
            End If
            isTableB = False
          Else
            If (charPos = 0) Then
              'Starting with table B
              returnValue = Chr(204).ToString()
              'char.ConvertFromUtf32(204);
            End If
          End If
        End If
    
        If (Not isTableB) Then
          'We are on table C, try to process 2 digits
          minCharPos = 2
          minCharPos = IsNumber(value, charPos, minCharPos)
    
          If (minCharPos < 0) Then
            'OK for 2 digits, process it
            currentChar = Integer.Parse(value.Substring(charPos, 2))
            If (currentChar < 95) Then
              currentChar = currentChar + 32
            Else
              currentChar = currentChar + 100
            End If
            returnValue = returnValue + Chr(currentChar).ToString()
            charPos += 2
          Else
            'We haven't 2 digits, switch to table B
            returnValue = returnValue + Chr(200).ToString()
            isTableB = True
          End If
        End If
    
        If (isTableB) Then
          'Process 1 digit with table B
          returnValue = returnValue + value.Substring(charPos, 1)
          charPos += 1
        End If
    
       End While
    
      'Calculation of the checksum
      checksum = 0
      Dim loo As Integer
      For loo = 0 To returnValue.Length - 1
        currentChar = Asc(returnValue.Substring(loo, 1))
        If (currentChar < 127) Then
          currentChar = currentChar - 32
        Else
          currentChar = currentChar - 100
        End If
        If (loo = 0) Then
          checksum = currentChar
        Else
          checksum = (checksum + (loo * currentChar)) Mod 103
        End If
      Next
    
      'Calculation of the checksum ASCII code
      If (checksum < 95) Then
        checksum = checksum + 32
      Else
        checksum = checksum + 100
      End If
    
      ' Add the checksum and the STOP
      returnValue = returnValue + _
      Chr(checksum).ToString() + _
      Chr(206).ToString()
    
      Return returnValue
    End Function
    
    Function IsNumber(InputValue As String, CharPos As Integer, MinCharPos As Integer) As Integer
      MinCharPos -= 1
      If (CharPos + MinCharPos < InputValue.Length) Then
        While (MinCharPos >= 0)
          If (Asc(InputValue.Substring(CharPos + MinCharPos, 1)) < 48 _
          OrElse Asc(InputValue.Substring(CharPos + MinCharPos, 1)) > 57) Then
          Exit While
        End If
        MinCharPos -= 1
        End While
      End If
      Return MinCharPos  
    End Function
    
    Public Function Code128(ByVal stringText As String) As Byte()
      Dim result As Byte() = Nothing
    
      Try
      result = GenerateImage("Code 128", StringToBarcode(stringText))
      Catch ex As Exception
      End Try
    
      Return result
    End Function
    
    Public Function GenerateImage(ByVal fontName As String, ByVal stringText As String) As Byte()
      Dim oGraphics As System.Drawing.Graphics
      Dim barcodeSize As System.Drawing.SizeF
      Dim ms As System.IO.MemoryStream
    
      Using font As New System.Drawing.Font(New System.Drawing.FontFamily(fontName), 30)
      Using tmpBitmap As New System.Drawing.Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
      oGraphics = System.Drawing.Graphics.FromImage(tmpBitmap)
      oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel
      barcodeSize = oGraphics.MeasureString(stringText, font)
      oGraphics.Dispose()
      End Using
    
      Using newBitmap As New System.Drawing.Bitmap(barcodeSize.Width, barcodeSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
      oGraphics = System.Drawing.Graphics.FromImage(newBitmap)
      oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel
    
      Using oSolidBrushWhite As New System.Drawing.SolidBrush(System.Drawing.Color.White)
      Using oSolidBrushBlack As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
      oGraphics.FillRectangle(oSolidBrushWhite, New System.Drawing.Rectangle(0, 0, barcodeSize.Width, barcodeSize.Height))
      oGraphics.DrawString(stringText, font, oSolidBrushBlack, 0, 0)
      End Using
    
      End Using
    
      ms = New System.IO.MemoryStream()
      newBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
      End Using
      End Using
    
      Return ms.ToArray()
    End Function
    

    1. Insert an image in your report, and select Database as the image source, and use image/png as MIMI type:

      enter image description here


    1. Click on fx button in Use this field button, and use this function =Code.Code128(Fields!your_field_name.Value), press Ok and Ok.

      enter image description here


    1. Run the report, now you have a barcode :)

      enter image description here