Cómo generar códigos de barras Code39 en vb.net
Pregunta
Quiero crear códigos de barras codificados en Code39 desde mi aplicación.
Sé que puedo usar una fuente para esto, pero preferiría no hacerlo porque tendría que registrar la fuente en el servidor y he tenido algunas experiencias bastante malas con eso.
Un ejemplo de lo que he producido después de hacer esta pregunta está en las respuestas
Solución
Este es mi código actual, con muchos comentarios:
Option Explicit On
Option Strict On
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Drawing.Bitmap
Imports System.Drawing.Graphics
Imports System.IO
Partial Public Class Barcode
Inherits System.Web.UI.Page
'Sebastiaan Janssen - 20081001 - TINT-30584
'Most of the code is based on this example:
'http://www.atalasoft.com/cs/blogs/loufranco/archive/2008/04/25/writing-code-39-barcodes-with-javascript.aspx-generation.aspx
'With a bit of this thrown in:
'http://www.atalasoft.com/cs/blogs/loufranco/archive/2008/03/24/code-39-barcode
Private _encoding As Hashtable = New Hashtable
Private Const _wideBarWidth As Short = 8
Private Const _narrowBarWidth As Short = 2
Private Const _barHeight As Short = 100
Sub BarcodeCode39()
_encoding.Add("*", "bWbwBwBwb")
_encoding.Add("-", "bWbwbwBwB")
_encoding.Add("<*>quot;, "bWbWbWbwb")
_encoding.Add("%", "bwbWbWbWb")
_encoding.Add(" ", "bWBwbwBwb")
_encoding.Add(".", "BWbwbwBwb")
_encoding.Add("/", "bWbWbwbWb")
_encoding.Add("+", "bWbwbWbWb")
_encoding.Add("0", "bwbWBwBwb")
_encoding.Add("1", "BwbWbwbwB")
_encoding.Add("2", "bwBWbwbwB")
_encoding.Add("3", "BwBWbwbwb")
_encoding.Add("4", "bwbWBwbwB")
_encoding.Add("5", "BwbWBwbwb")
_encoding.Add("6", "bwBWBwbwb")
_encoding.Add("7", "bwbWbwBwB")
_encoding.Add("8", "BwbWbwBwb")
_encoding.Add("9", "bwBWbwBwb")
_encoding.Add("A", "BwbwbWbwB")
_encoding.Add("B", "bwBwbWbwB")
_encoding.Add("C", "BwBwbWbwb")
_encoding.Add("D", "bwbwBWbwB")
_encoding.Add("E", "BwbwBWbwb")
_encoding.Add("F", "bwBwBWbwb")
_encoding.Add("G", "bwbwbWBwB")
_encoding.Add("H", "BwbwbWBwb")
_encoding.Add("I", "bwBwbWBwb")
_encoding.Add("J", "bwbwBWBwb")
_encoding.Add("K", "BwbwbwbWB")
_encoding.Add("L", "bwBwbwbWB")
_encoding.Add("M", "BwBwbwbWb")
_encoding.Add("N", "bwbwBwbWB")
_encoding.Add("O", "BwbwBwbWb")
_encoding.Add("P", "bwBwBwbWb")
_encoding.Add("Q", "bwbwbwBWB")
_encoding.Add("R", "BwbwbwBWb")
_encoding.Add("S", "bwBwbwBWb")
_encoding.Add("T", "bwbwBwBWb")
_encoding.Add("U", "BWbwbwbwB")
_encoding.Add("V", "bWBwbwbwB")
_encoding.Add("W", "BWBwbwbwb")
_encoding.Add("X", "bWbwBwbwB")
_encoding.Add("Y", "BWbwBwbwb")
_encoding.Add("Z", "bWBwBwbwb")
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
BarcodeCode39()
Dim barcode As String = String.Empty
If Not IsNothing(Request("barcode")) AndAlso Not (Request("barcode").Length = 0) Then
barcode = Request("barcode")
Response.ContentType = "image/png"
Response.AddHeader("Content-Disposition", String.Format("attachment; filename=barcode_{0}.png", barcode))
'TODO: Depending on the length of the string, determine how wide the image will be
GenerateBarcodeImage(250, 140, barcode).WriteTo(Response.OutputStream)
End If
End Sub
Protected Function getBCSymbolColor(ByVal symbol As String) As System.Drawing.Brush
getBCSymbolColor = Brushes.Black
If symbol = "W" Or symbol = "w" Then
getBCSymbolColor = Brushes.White
End If
End Function
Protected Function getBCSymbolWidth(ByVal symbol As String) As Short
getBCSymbolWidth = _narrowBarWidth
If symbol = "B" Or symbol = "W" Then
getBCSymbolWidth = _wideBarWidth
End If
End Function
Protected Overridable Function GenerateBarcodeImage(ByVal imageWidth As Short, ByVal imageHeight As Short, ByVal Code As String) As MemoryStream
'create a new bitmap
Dim b As New Bitmap(imageWidth, imageHeight, Imaging.PixelFormat.Format32bppArgb)
'create a canvas to paint on
Dim canvas As New Rectangle(0, 0, imageWidth, imageHeight)
'draw a white background
Dim g As Graphics = Graphics.FromImage(b)
g.FillRectangle(Brushes.White, 0, 0, imageWidth, imageHeight)
'write the unaltered code at the bottom
'TODO: truely center this text
Dim textBrush As New SolidBrush(Color.Black)
g.DrawString(Code, New Font("Courier New", 12), textBrush, 100, 110)
'Code has to be surrounded by asterisks to make it a valid Code39 barcode
Dim UseCode As String = String.Format("{0}{1}{0}", "*", Code)
'Start drawing at 10, 10
Dim XPosition As Short = 10
Dim YPosition As Short = 10
Dim invalidCharacter As Boolean = False
Dim CurrentSymbol As String = String.Empty
For j As Short = 0 To CShort(UseCode.Length - 1)
CurrentSymbol = UseCode.Substring(j, 1)
'check if symbol can be used
If Not IsNothing(_encoding(CurrentSymbol)) Then
Dim EncodedSymbol As String = _encoding(CurrentSymbol).ToString
For i As Short = 0 To CShort(EncodedSymbol.Length - 1)
Dim CurrentCode As String = EncodedSymbol.Substring(i, 1)
g.FillRectangle(getBCSymbolColor(CurrentCode), XPosition, YPosition, getBCSymbolWidth(CurrentCode), _barHeight)
XPosition = XPosition + getBCSymbolWidth(CurrentCode)
Next
'After each written full symbol we need a whitespace (narrow width)
g.FillRectangle(getBCSymbolColor("w"), XPosition, YPosition, getBCSymbolWidth("w"), _barHeight)
XPosition = XPosition + getBCSymbolWidth("w")
Else
invalidCharacter = True
End If
Next
'errorhandling when an invalidcharacter is found
If invalidCharacter Then
g.FillRectangle(Brushes.White, 0, 0, imageWidth, imageHeight)
g.DrawString("Invalid characters found,", New Font("Courier New", 8), textBrush, 0, 0)
g.DrawString("no barcode generated", New Font("Courier New", 8), textBrush, 0, 10)
g.DrawString("Input was: ", New Font("Courier New", 8), textBrush, 0, 30)
g.DrawString(Code, New Font("Courier New", 8), textBrush, 0, 40)
End If
'write the image into a memorystream
Dim ms As New MemoryStream
Dim encodingParams As New EncoderParameters
encodingParams.Param(0) = New EncoderParameter(Encoder.Quality, 100)
Dim encodingInfo As ImageCodecInfo = FindCodecInfo("PNG")
b.Save(ms, encodingInfo, encodingParams)
'dispose of the object we won't need any more
g.Dispose()
b.Dispose()
Return ms
End Function
Protected Overridable Function FindCodecInfo(ByVal codec As String) As ImageCodecInfo
Dim encoders As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders
For Each e As ImageCodecInfo In encoders
If e.FormatDescription.Equals(codec) Then Return e
Next
Return Nothing
End Function
End Class
Otros consejos
Si elige Code39, probablemente podría codificar a partir de este código que escribí
http: //www.atalasoft.com/cs/blogs/loufranco/archive/2008/03/24/code-39-barcode-generation.aspx
Lo escribí para usar nuestro kit de herramientas para la generación de imágenes, pero puedes reescribirlo para usar .NET Image / Graphics con bastante facilidad.
No sé de bibliotecas, todo el trabajo de código de barras que he hecho ha sido con fuentes de código de barras. Echa un vistazo a libre 3-de-9 si estás usando el " 3 de 9 " ; formato.
Advertencias de 3-de-9:
asegúrese de que todo el texto esté en mayúsculas Comience y termine cada código de barras con un asterisco
Aquí hay una biblioteca de código de barras de código abierto para lenguajes .NET: http://www.codeplex.com/BarcodeRender
Puede representar algunas codificaciones habituales.
La licencia parece benigna, y parece que se puede usar tanto en aplicaciones de código abierto como comerciales (sin embargo, IANAL, es posible que desee consultar su licencia usted mismo.)
Aquí hay otro, también código abierto, que utiliza la licencia Apache 2.0: http://sourceforge.net/ proyectos / onecode /
En general, cuando sabe desde el principio que está buscando componentes de código abierto, es mejor omitir Google y comenzar a buscar directamente en SourceForge (tiene un maravilloso sistema de filtrado para los resultados de búsqueda, puede filtrar por idioma, lo que probablemente sea de su interés) o en CodePlex (donde la elección suele ser más limitada, pero ya está.)
¿está imprimiendo en una impresora estándar o en una impresora de códigos de barras real (cebra o datamax)? Tanto cebra como datamax tienen sus propios lenguajes de scripting, en realidad más como lenguajes de marcado. ZPL y DPL respectivamente. Me gustan más las de cebra y su documentación es mucho más limpia.
Si no tiene una impresora de códigos de barras legítima, le sugiero que compre una y haga lo siguiente ... (será mucho más limpio que intentar construir pequeños bloques de imágenes y pintarlos para simular una fuente de código de barras )
ambos le permiten una gran flexibilidad y puede dejar que la impresora se encargue de crear la imagen de código de barras real.
haga que su programa envíe un script ZPL / DPL personalizado que incluya los valores que desea que se impriman como códigos de barras en la impresora a través de ftp. básicamente, solo tienes que " poner " un archivo de texto que contiene el script para el IP de la impresora y la impresora se encarga de la fuente.
La biblioteca iTextSharp , aunque aparentemente para crear archivos PDF, también tiene una biblioteca de generación de códigos de barras que incluye Code39 .
Una vez que agregue una referencia a la DLL, es tan simple como:
Barcode39 code39 = new Barcode39();
code39.Code = "Whatever You're Encoding";
Vaya, eso es C #, pero entiendes la idea. Una vez creada, puede renderizar una imagen en casi cualquier formato de imagen y usarla como desee.
Si representa el lado del cliente, la fuente puede residir en una estación de trabajo. De esta manera puedes usar 3-de-9. He utilizado 3 de 9 en varios proyectos y la solución más sencilla para usted.
Aquí hay un ejemplo de cómo generar códigos de barras Code39 en vb.net . Lo probé ahora y funciona.
Public Class code39
Private bitsCode As ArrayList
Public Sub New()
bitsCode = New ArrayList
bitsCode.Add(New String(3) {"0001101", "0100111", "1110010", "000000"})
bitsCode.Add(New String(3) {"0011001", "0110011", "1100110", "001011"})
bitsCode.Add(New String(3) {"0010011", "0011011", "1101100", "001101"})
bitsCode.Add(New String(3) {"0111101", "0100001", "1000010", "001110"})
bitsCode.Add(New String(3) {"0100011", "0011101", "1011100", "010011"})
bitsCode.Add(New String(3) {"0110001", "0111001", "1001110", "011001"})
bitsCode.Add(New String(3) {"0101111", "0000101", "1010000", "011100"})
bitsCode.Add(New String(3) {"0111011", "0010001", "1000100", "010101"})
bitsCode.Add(New String(3) {"0110111", "0001001", "1001000", "010110"})
bitsCode.Add(New String(3) {"0001011", "0010111", "1110100", "011010"})
End Sub
Public Function Generate(ByVal Code As String) As Image
Dim a As Integer = 0
Dim b As Integer = 0
Dim imgCode As Image
Dim g As Graphics
Dim i As Integer
Dim bCode As Byte()
Dim bitCode As Byte()
Dim tmpFont As Font
If Code.Length <> 12 Or Not IsNumeric(Code.Replace(".", "_").Replace(",", "_")) Then Throw New Exception("Le code doit être composé de 12 chiffres")
ReDim bCode(12)
For i = 0 To 11
bCode(i) = CInt(Code.Substring(i, 1))
If (i Mod 2) = 1 Then
b += bCode(i)
Else
a += bCode(i)
End If
Next
i = (a + (b * 3)) Mod 10
If i = 0 Then
bCode(12) = 0
Else
bCode(12) = 10 - i
End If
bitCode = getBits(bCode)
tmpFont = New Font("times new roman", 14, FontStyle.Regular, GraphicsUnit.Pixel)
imgCode = New Bitmap(110, 50)
g = Graphics.FromImage(imgCode)
g.Clear(Color.White)
g.DrawString(Code.Substring(0, 1), tmpFont, Brushes.Black, 2, 30)
a = g.MeasureString(Code.Substring(0, 1), tmpFont).Width
For i = 0 To bitCode.Length - 1
If i = 2 Then
g.DrawString(Code.Substring(1, 6), tmpFont, Brushes.Black, a, 30)
ElseIf i = 48 Then
g.DrawString(Code.Substring(7, 5) & bCode(12).ToString, tmpFont, Brushes.Black, a, 30)
End If
If i = 0 Or i = 2 Or i = 46 Or i = 48 Or i = 92 Or i = 94 Then
If bitCode(i) = 1 Then 'noir
g.DrawLine(Pens.Black, a, 0, a, 40)
a += 1
End If
Else
If bitCode(i) = 1 Then 'noir
g.DrawLine(Pens.Black, a, 0, a, 30)
a += 1
Else 'blanc
a += 1
End If
End If
Next
g.Flush()
Return imgCode
End Function
Private Function getBits(ByVal bCode As Byte()) As Byte()
Dim i As Integer
Dim res As Byte()
Dim bits As String = "101"
Dim cle As String = bitsCode(bCode(0))(3)
For i = 1 To 6
bits &= bitsCode(bCode(i))(CInt(cle.Substring(i - 1, 1)))
Next
bits &= "01010"
For i = 7 To 12
bits &= bitsCode(bCode(i))(2)
Next
bits += "101"
ReDim res(bits.Length - 1)
For i = 0 To bits.Length - 1
res(i) = Asc(bits.Chars(i)) - 48
Next
Return res
End Function
End Class
En lugar de utilizar una fuente de código de barras, preferiría un .net componente de generador de código de barras . A continuación se muestra un vb.net ejemplo para crear el código de barras del Código 39 .
Imports System.IO
Imports PQScan.BarcodeCreator
Namespace BarcodeGeneratorVB
Class Program
Private Shared Sub Main(args As String())
Dim barcode As New Barcode()
barcode.Data = "www.pqscan.com"
barcode.BarType = BarCodeType.Code39
barcode.Width = 300
barcode.Height = 100
barcode.CreateBarcode("code39-vb.jpeg")
End Sub
End Class
End Namespace
En mi último trabajo, trabajé con un par de bibliotecas diferentes en vb.net para esto. Tuvimos uno, y nos mudamos a uno diferente. No puedo recordar sus nombres (los reconocería de nuevo si los viera), pero sé que ambos eran de pago, evaluamos varios componentes diferentes al momento del cambio, Y creo que eso incluía uno gratis. Éramos una muy pequeña tienda y muy sensibles al costo, por lo que si el componente gratuito fuera bueno, podemos apostar que lo habríamos utilizado (creo que necesitábamos 128b de asistencia). , y solo manejaba el código 39).
También recuerdo que la razón por la que cambiamos fue que fue al mismo tiempo que pasamos de .Net 1.1 a .Net 2.0, y el primer componente fue demasiado lento en la transición.
Entonces, en resumen, hay algo por ahí, pero no fue bueno hace 3 años. Con suerte, alguien más puede venir y completar algunos nombres reales.