Como gerar códigos de barras Code39 em vb.net
Pergunta
Eu quero criar Code39 codificado códigos de barras do meu aplicativo.
Eu sei que posso usar uma fonte para isso, mas eu prefiro não como eu teria que registrar a fonte no servidor e eu tive algumas experiências muito ruins com isso.
Um exemplo de que tenho produzido após essa pergunta está nas respostas
Solução
Este é o meu codebehind atual, com muitos comentários:
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("$", "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
Outras dicas
Se você escolher Code39, você poderia provavelmente código a partir deste código que eu escrevi
http: //www.atalasoft.com/cs/blogs/loufranco/archive/2008/03/24/code-39-barcode-generation.aspx
Eu o escrevi para usar nosso kit de ferramentas para geração de imagem, mas você poderia reescrevê-lo para usar .NET imagem / gráficos com bastante facilidade.
Eu não sei sobre bibliotecas - todo o trabalho de código de barras que eu fiz foi com fontes de código de barras. Confira livre 3-of-9 se você estiver usando o "3 de 9" formato.
Advertências de 3-of-9:
Certifique-se todo o texto é em letras maiúsculas começar e terminar cada código de barras com um asterisco
Aqui está uma biblioteca de renderização de código de barras de código aberto para linguagens .NET: http://www.codeplex.com/BarcodeRender
Ele pode render algumas codificações habituais.
A licença parece benigno, e parece ser utilizável em ambos os aplicativos open source e comerciais (no entanto, IANAL, você pode querer verificar a sua licença si mesmo.)
Aqui está mais um, também de código aberto, usando a licença Apache 2.0: http://sourceforge.net/ projectos / OneCode /
Geralmente, quando você sabe desde o início que você está procurando componentes de código aberto, é melhor ignorar Google e iniciar diretamente pesquisando na SourceForge (ele tem um sistema de filtragem maravilhoso para os resultados de pesquisa, você pode filtrar por idioma, o que provavelmente é do seu interesse) ou do Microsoft CodePlex (onde a escolha é geralmente mais limitado, mas lá vai.)
Está a imprimir em uma impressora padrão ou uma impressora de código de barras real (zebra ou datamax)? tanto zebra e datamax têm suas próprias linguagens de script - na verdade mais como linguagens de marcação. ZPL e DPL respectivamente. I como a zebra de mais e sua documentação é muito mais limpo.
Se você não tiver uma impressora de código de barras legítimo, eu sugiro comprar um e faça o seguinte .... (que vai ser muito mais limpo do que tentando descobrir a construção de pequenos blocos de imagem e pintá-los para simular uma fonte de código de barras )
ambos permitem grande flexibilidade e você pode deixar o identificador de impressora criar a imagem de código de barras real.
tem o seu envio um programa personalizado ZPL / DPL roteiro que inclui os valores que você deseja imprimir como códigos de barras para a impressora via ftp. Basicamente, você só "colocar" um arquivo de texto que contém o script para o IP da impressora e a impressora cuida da fonte.
A biblioteca iTextSharp , enquanto ostensivamente para a criação de PDFs criando, também tem uma biblioteca de geração de código de barras que inclui Code39 .
Uma vez que você adicionar uma referência para a DLL, é tão simples como:
Barcode39 code39 = new Barcode39();
code39.Code = "Whatever You're Encoding";
Opa, isso é C #, mas você começa a idéia. Uma vez criado, você pode renderizar uma imagem em praticamente qualquer formato de imagem e usá-lo como quiser.
Se você processar lado do cliente, em seguida, a fonte pode residir em uma estação de trabalho. Desta forma, você pode usar 3-of-9. Eu usei 3-of-9 em vários projetos e a solução mais simples para você.
Aqui está um exemplo de como gerar códigos de barras Code39 em vb.net . Eu testei-o agora e ele 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
Em vez de usar fonte de código de barras, eu preferiria um .net código de barras gerador componente . Abaixo está uma amostra vb.net para criar o código 39 código de barras .
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
No meu último emprego eu trabalhei com um casal diferentes bibliotecas em vb.net para isso. Tivemos um, e se mudou para um diferente. Não me lembro de seus nomes (eu reconhecê-los novamente se eu os vi), mas eu sei que ambos foram para-pay, avaliamos vários componentes diferentes no momento do switch, e eu acho que incluiu um livre. Estávamos um muito pequena loja e muito custo sensível, por isso, se o componente livre fosse qualquer bom em tudo o que você pode apostar que teria usado (eu acho que precisávamos 128b apoio , e só code39 tratado).
Lembro-me também que a razão que nós mudamos é que era, ao mesmo tempo que se mudou de .Net 1.1 a Net 2.0, e o primeiro componente foi muito lento fazer a transição.
Assim, em resumo, há algo lá fora, mas não era bom há 3 anos. Esperemos que alguém pode vir e preencher alguns nomes reais.