Adding Barcode to Report Builder 3.0

Mohammad Anini picture Mohammad Anini · May 24, 2016 · Viewed 7.8k times · Source

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?

Answer

Mohammad Anini picture Mohammad Anini · May 27, 2016

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