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

Posted

技术标签:

【中文标题】如何在 vb.net 中生成 Code39 条码【英文标题】:How to generate Code39 barcodes in vb.net 【发布时间】:2010-09-14 01:04:01 【问题描述】:

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

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

我提出这个问题后的一个例子在答案中

【问题讨论】:

【参考方案1】:

这是我当前的代码隐藏,有很多 cmets:

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("010", "*", 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

【讨论】:

【参考方案2】:

如果你选择 Code39,你可能可以从我写的这段代码开始编码

http://www.atalasoft.com/cs/blogs/loufranco/archive/2008/03/24/code-39-barcode-generation.aspx

我编写它是为了使用我们的工具包生成图像,但您可以很容易地重写它以使用 .NET Image/Graphics。

【讨论】:

谢谢,我已经联系了扫描人,Code39 没问题。我使用您的 Javascript 示例构建了一个 .Net 版本,因为您的链接使用了我没有的 dll。 atalasoft.com/cs/blogs/loufranco/archive/2008/04/25/… 酷 -- 是的,我使用我们的产品制作图像,但也可以使用 .NET Image/Bitmap 来完成 -- 我猜你正在这样做。【参考方案3】:

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

3-of-9 的注意事项:

确保所有文本都是大写的 用星号开始和结束每个条形码

【讨论】:

附加警告:它没有被压缩,所以条码宽度很快就会变得很长!但是,+1 因为它非常易于使用!【参考方案4】:

这是一个用于 .NET 语言的开源条形码渲染库:http://www.codeplex.com/BarcodeRender

它可以渲染一些常用的编码。

该许可证看起来不错,而且似乎可以在开源和商业应用程序中使用(不过,IANAL,您可能想自己查看它的license。)

这是另一个,也是开源的,使用 Apache 2.0 许可证:http://sourceforge.net/projects/onecode/

一般来说,当你从一开始就知道你在寻找开源组件时,最好绕过谷歌,直接在SourceForge上搜索(它有一个很棒的搜索结果过滤系统,你可以按语言过滤,这可能是您感兴趣的)或 Microsoft 的 CodePlex(选择通常比较有限,但您可以去。)

【讨论】:

谢谢,BarcodeRender 似乎是一个带有严重错误的废弃产品。 Onecode 仅支持美国邮政编码条形码。到目前为止,我还没有在 CodePlex 或 SourceForge 上找到任何其他内容。【参考方案5】:

您是打印到标准打印机还是实际的条码打印机(zebra 或 datamax)? zebra 和 datamax 都有自己的脚本语言——实际上更像是标记语言。分别是 ZPL 和 DPL。我更喜欢斑马,而且他们的文档更简洁。

如果您没有合法的条码打印机,我建议您购买一台并执行以下操作....(这比尝试构建小图像块并绘制它们以模拟条码字体要干净得多)

两者都为您提供了极大的灵活性,您可以让打印机处理创建实际的条形码图像。

让您的程序通过 ftp 向打印机发送一个自定义的 ZPL/DPL 脚本,其中包含您希望作为条形码打印的值。基本上,您只需将包含脚本的文本文件“放置”到打印机的 IP 中,打印机就会处理字体。

【讨论】:

【参考方案6】:

iTextSharp 库虽然表面上用于创建 PDF,但也有一个包含 Code39 的条形码生成库。

添加对 DLL 的引用后,它就像这样简单:

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

糟糕,那是 C#,但你明白了。创建后,您可以以几乎任何图像格式渲染图像并根据需要使用它。

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

这是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 位条形码,而不是其规定的代码 39【参考方案9】:

我更喜欢.net barcode generator component,而不是使用条形码字体。下面是vb.net sample for creating Code 39 barcode。

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

【讨论】:

【参考方案10】:

在我的上一份工作中,我为此在 vb.net 中使用了几个不同的库。我们有一个,然后搬到了另一个。我不记得他们的名字(如果我看到他们我会再次认出他们),但我知道两者都是付费的,我们在切换时评估了几个不同的组件,我认为这包括一个免费的。我们是一家非常小店并且非常成本敏感,所以如果免费组件有任何好处,你可以打赌我们会使用它(我认为我们需要 128b 支持,它只处理代码39)。

我还记得我们切换的原因是我们从 .Net 1.1 迁移到 .Net 2.0 的同时,第一个组件在转换时太慢了。

所以,总而言之,那里有一些东西,但在 3 年前并不是什么好东西。希望其他人可以过来填写一些实际姓名。

【讨论】:

以上是关于如何在 vb.net 中生成 Code39 条码的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 TD 6.3 中生成有效的 Code128 条码?

如何在 VB.NET 中生成用户定义的警告消息

VB.NET如何操作条码扫描枪,如何设置,如何进行条形码的设置及打印

在 windows 中生成声音频率 - VB.Net

VB.net:INSERT INTO 查询在 Access 数据库中生成所有“-1”

无法在VB.Net中生成多个单选按钮