如何在vb.net中生成Code39条形码

10

我想从我的应用程序中创建Code39编码的条形码。

我知道可以使用字体来实现,但我不想这样做,因为我必须在服务器上注册字体,而我曾经有过一些非常糟糕的经历。

在询问此问题之后,我制作了一个示例,可在答案中找到。

10个回答

11

这是我的当前代码(带有很多注释):

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

6

谢谢,我已经联系了扫描人员,Code39 很好。我使用了您的 Javascript 示例来构建一个 .Net 版本,因为您的链接使用了我没有的 dll。http://www.atalasoft.com/cs/blogs/loufranco/archive/2008/04/25/writing-code-39-barcodes-with-javascript.aspx - sebastiaan
很酷——是的,我用我们的产品制作了这张图片,但也可以使用.NET Image/Bitmap完成——我猜你也是这样做的。 - Lou Franco

6

我不了解图书馆——我所做的所有条形码工作都是使用条形码字体完成的。如果您正在使用“3 of 9”格式,请查看免费的3-of-9

3-of-9的注意事项:

确保所有文本都是大写的 在每个条形码的开头和结尾加上星号


额外的注意事项:它没有压缩,因此条形码的宽度可能会非常快地变长!但是,+1 因为它非常容易使用! - Doug L.

3
这里有一个针对.NET语言的开源条形码渲染库:http://www.codeplex.com/BarcodeRender。它可以渲染一些常见的编码方式。
该许可证看起来很良心,并且似乎可用于开源和商业应用程序(然而,我不是法律专家,您可能需要自行查看其许可证)。另外还有另一个开源项目,使用Apache 2.0许可证:http://sourceforge.net/projects/onecode/
通常情况下,如果您从一开始就知道要寻找开源组件,最好绕过Google,直接在SourceForge(它拥有一个精美的搜索结果过滤系统,您可以按语言进行过滤,这可能是您感兴趣的)或Microsoft的CodePlex(那里的选择通常更有限,但是您可以去试试)。

谢谢,BarcodeRender似乎是一个被遗弃的产品,存在严重的错误。Onecode仅支持美国邮政编码条形码。到目前为止,在CodePlex或SourceForge上我还没有找到其他的东西。 - sebastiaan

1

虽然iTextSharp库主要用于创建PDF,但它还包含一个条形码生成库,其中包括Code39。

一旦你添加了对DLL的引用,使用起来非常简单:

Barcode39 code39 = new Barcode39();
code39.Code = "Whatever You're Encoding";

糟糕,那是C#,但你明白了。一旦创建,您可以以几乎任何图像格式呈现图像并按照您的意愿使用它。


1

你是在打印到一台标准打印机还是一台实际的条码打印机(zebra或datamax)? zebra和datamax都有自己的脚本语言 - 实际上更像是标记语言。分别是ZPL和DPL。我更喜欢zebra的,他们的文档更清晰。

如果你没有合法的条码打印机,我建议购买一台,并按照以下步骤操作...(相比尝试构建小图像块并绘制它们以模拟条码字体,这样做会更简洁)

两者都允许您具有很大的灵活性,并且可以让打印机处理创建实际的条码图像。

让你的程序通过FTP向打印机发送一个定制的包含要打印为条码的值的ZPL/DPL脚本。基本上,你只需要向打印机的IP地址“put”一个包含脚本的文本文件,然后打印机就会处理字体。


0

这里有一个关于如何在vb.net中生成Code39条形码的示例how to generate Code39 barcodes in vb.net。我现在已经测试过了,它可以正常工作。

 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

这是EAN 13码,仅适用于12位数字条形码,而不是如其所述的Code 39。 - charles

0

我更喜欢使用.net条形码生成器组件,而不是使用条形码字体。以下是一个用于创建Code 39条形码的VB.net示例

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

0
如果您在客户端渲染,则字体可以驻留在工作站上。这样,您就可以使用3-of-9。我已经在几个项目中使用了3-of-9,并为您提供了最简单的解决方案。

-1

在我上一份工作中,我使用了几个不同的vb.net库。我们有一个库,后来换成了另一个库。我记不得它们的名字了(如果我再看到它们,我会认出来),但我知道两个都是付费的。在切换时,我们评估了几个不同的组件,我想其中包括一个免费的组件。我们是一个非常小的公司,非常注重成本,所以如果免费组件真的很好,你可以肯定我们会使用它(我想我们需要128b支持,而它只处理code39)。

我还记得我们换掉的原因是同时从.Net 1.1转移到了.Net 2.0,而第一个组件太慢了,使得过渡变得困难。

因此,总之,市面上有一些组件,但三年前它们都不怎么好用。希望其他人能提供一些实际的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接