【问题标题】:Generating 2D (PDF417 or QR) barcodes using Excel VBA使用 Excel VBA 生成二维(PDF417 或 QR)条码
【发布时间】:2013-04-15 03:09:56
【问题描述】:

我想使用宏在 Excel 单元格中生成二维条码(PDF417 或 QR 码)。只是想知道是否有任何免费的替代付费图书馆可以做到这一点?

我知道certain tools 可以完成这项工作,但它对我们来说相对昂贵。

【问题讨论】:

标签: excel vba fonts barcode


【解决方案1】:

VBA 模块barcode-vba-macro-only(Sébastien Ferry 在 cmets 中提到)是 Jiri Gabriel 在 2013 年在 MIT 许可下创建的纯 VBA 1D/2D 代码生成器。

代码不是很容易理解,但在上面链接的版本中,许多 cmets 已经从捷克语翻译成英语。

要在工作表中使用它,只需将barcody.bas 复制或导入到模块中的 VBA 中。在工作表中,输入如下函数:

=EncodeBarcode(CELL("SHEET"),CELL("ADDRESS"),A2,51,1,0,2)

用法如下:

  1. 保留 CELL("SHEET)CELL("ADDRESS") 原样,因为它是 只需参考您拥有的工作表和单元格地址 公式
    • A2 是您要对字符串进行编码的单元格。在我的情况下,它是单元格 A2 你可以传递带有引号的“文本”来做同样的事情。 拥有单元格使其更具活力
    • 51 是二维码的选项。其他选项为 1=EAN8/13/UPCA/UPCE,2=五个交错的两个,3=Code39,50=Data 矩阵,51=二维码
      • 1 用于图形模式。条形码绘制在 Shape 对象上。 0 表示字体模式。我假设您需要安装字体类型。 没那么有用。
      • 0 是特定条形码类型的参数。对于 QR_Code,0=低纠错,1=中纠错,2=四分位数错误 纠错,3=高纠错。
      • 2 仅适用于一维代码。是缓冲区。我不确定它到底做了什么,但可能与 一维酒吧空间?

我添加了包装函数以使其成为纯 VBA 函数调用,而不是将其用作工作表中的公式:

Public Sub RenderQRCode(workSheetName As String, cellLocation As String, textValue As String)
   Dim s_param As String
   Dim s_encoded As String
   Dim xSheet As Worksheet
   Dim QRShapeName As String
   Dim QRLabelName As String

   s_param = "mode=Q"
   s_encoded = qr_gen(textValue, s_param)
   Call DrawQRCode(s_encoded, workSheetName, cellLocation)

   Set xSheet = Worksheets(workSheetName)
   QRShapeName = "BC" & "$" & Left(cellLocation, 1) _
       & "$" & Right(cellLocation, Len(cellLocation) - 1) & "#GR"

   QRLabelName = QRShapeName & "_Label"

   With xSheet.Shapes(QRShapeName)
       .Width = 30
       .Height = 30
   End With

   On Error Resume Next
   If Not (xSheet.Shapes(QRLabelName) Is Nothing) Then
       xSheet.Shapes(QRLabelName).Delete
   End If

   xSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, _
       xSheet.Shapes(QRShapeName).Left+35, _
       xSheet.Shapes(QRShapeName).Top, _                          
       Len(textValue) * 6, 30) _
       .Name = QRLabelName


   With xSheet.Shapes(QRLabelName)
       .Line.Visible = msoFalse
       .TextFrame2.TextRange.Font.Name = "Arial"
       .TextFrame2.TextRange.Font.Size = 9
       .TextFrame.Characters.Text = textValue
       .TextFrame2.VerticalAnchor = msoAnchorMiddle
   End With
End Sub

Sub DrawQRCode(xBC As String, workSheetName As String, rangeName As String, Optional xNam As String)
 Dim xShape As Shape, xBkgr As Shape
 Dim xSheet As Worksheet
 Dim xRange As Range, xCell As Range
 Dim xAddr As String
 Dim xPosOldX As Double, xPosOldY As Double
 Dim xSizeOldW As Double, xSizeOldH As Double
 Dim x, y, m, dm, a As Double
 Dim b%, n%, w%, p$, s$, h%, g%

Set xSheet = Worksheets(workSheetName)
Set xRange = Worksheets(workSheetName).Range(rangeName)
xAddr = xRange.Address
xPosOldX = xRange.Left
xPosOldY = xRange.Top

 xSizeOldW = 0
 xSizeOldH = 0
 s = "BC" & xAddr & "#GR"
 x = 0#
 y = 0#
 m = 2.5
 dm = m * 2#
 a = 0#
 p = Trim(xBC)
 b = Len(p)
 For n = 1 To b
   w = AscL(Mid(p, n, 1)) Mod 256
   If (w >= 97 And w <= 112) Then
     a = a + dm
   ElseIf w = 10 Or n = b Then
     If x < a Then x = a
     y = y + dm
     a = 0#
   End If
 Next n
 If x <= 0# Then Exit Sub
 On Error Resume Next
 Set xShape = xSheet.Shapes(s)
 On Error GoTo 0
 If Not (xShape Is Nothing) Then
   xPosOldX = xShape.Left
   xPosOldY = xShape.Top
   xSizeOldW = xShape.Width
   xSizeOldH = xShape.Height
   xShape.Delete
 End If
 On Error Resume Next
 xSheet.Shapes("BC" & xAddr & "#BK").Delete
 On Error GoTo 0
 Set xBkgr = xSheet.Shapes.AddShape(msoShapeRectangle, 0, 0, x, y)
 xBkgr.Line.Visible = msoFalse
 xBkgr.Line.Weight = 0#
 xBkgr.Line.ForeColor.RGB = RGB(255, 255, 255)
 xBkgr.Fill.Solid
 xBkgr.Fill.ForeColor.RGB = RGB(255, 255, 255)
 xBkgr.Name = "BC" & xAddr & "#BK"
 Set xShape = Nothing
 x = 0#
 y = 0#
 g = 0
 For n = 1 To b
   w = AscL(Mid(p, n, 1)) Mod 256
   If w = 10 Then
     y = y + dm
     x = 0#
   ElseIf (w >= 97 And w <= 112) Then
     w = w - 97
     With xSheet.Shapes
     Select Case w
       Case 1: Set xShape = .AddShape(msoShapeRectangle, x, y, m, m): GoSub fmtxshape
       Case 2: Set xShape = .AddShape(msoShapeRectangle, x + m, y, m, m): GoSub fmtxshape
       Case 3: Set xShape = .AddShape(msoShapeRectangle, x, y, dm, m): GoSub fmtxshape
       Case 4: Set xShape = .AddShape(msoShapeRectangle, x, y + m, m, m): GoSub fmtxshape
       Case 5: Set xShape = .AddShape(msoShapeRectangle, x, y, m, dm): GoSub fmtxshape
       Case 6: Set xShape = .AddShape(msoShapeRectangle, x + m, y, m, m): GoSub fmtxshape
               Set xShape = .AddShape(msoShapeRectangle, x, y + m, m, m): GoSub fmtxshape
       Case 7: Set xShape = .AddShape(msoShapeRectangle, x, y, dm, m): GoSub fmtxshape
               Set xShape = .AddShape(msoShapeRectangle, x, y + m, m, m): GoSub fmtxshape
       Case 8: Set xShape = .AddShape(msoShapeRectangle, x + m, y + m, m, m): GoSub fmtxshape
       Case 9: Set xShape = .AddShape(msoShapeRectangle, x, y, m, m): GoSub fmtxshape
               Set xShape = .AddShape(msoShapeRectangle, x + m, y + m, m, m): GoSub fmtxshape
       Case 10: Set xShape = .AddShape(msoShapeRectangle, x + m, y, m, dm): GoSub fmtxshape
       Case 11: Set xShape = .AddShape(msoShapeRectangle, x, y, dm, m): GoSub fmtxshape
                Set xShape = .AddShape(msoShapeRectangle, x + m, y + m, m, m): GoSub fmtxshape
       Case 12: Set xShape = .AddShape(msoShapeRectangle, x, y + m, dm, m): GoSub fmtxshape
       Case 13: Set xShape = .AddShape(msoShapeRectangle, x, y, m, m): GoSub fmtxshape
                Set xShape = .AddShape(msoShapeRectangle, x, y + m, dm, m): GoSub fmtxshape
       Case 14: Set xShape = .AddShape(msoShapeRectangle, x + m, y, m, m): GoSub fmtxshape
                Set xShape = .AddShape(msoShapeRectangle, x, y + m, dm, m): GoSub fmtxshape
       Case 15: Set xShape = .AddShape(msoShapeRectangle, x, y, dm, dm): GoSub fmtxshape
     End Select
     End With
     x = x + dm
   End If
 Next n
 On Error Resume Next
 Set xShape = xSheet.Shapes(s)
 On Error GoTo 0
 If Not (xShape Is Nothing) Then
   xShape.Left = xPosOldX
   xShape.Top = xPosOldY
   If xSizeOldW > 0 Then
     xShape.Width = xSizeOldW
     xShape.Height = xSizeOldH
   End If
 Else
   If Not (xBkgr Is Nothing) Then xBkgr.Delete
 End If
 Exit Sub
fmtxshape:
  xShape.Line.Visible = msoFalse
  xShape.Line.Weight = 0#
  xShape.Fill.Solid
  xShape.Fill.ForeColor.RGB = RGB(0, 0, 0)
  g = g + 1
  xShape.Name = "BC" & xAddr & "#BR" & g
  If g = 1 Then
    xSheet.Shapes.Range(Array(xBkgr.Name, xShape.Name)).Group.Name = s
  Else
    xSheet.Shapes.Range(Array(s, xShape.Name)).Group.Name = s
  End If
  Return

End Sub

使用这个包装器,您现在可以通过在 VBA 中调用它来简单地调用以呈现 QRCode:

Call RenderQRCode("Sheet1", "A13", "QR Value")

只需输入工作表名称、单元格位置和 QR_value。 QR 形状将在您指定的位置绘制。

您可以使用这部分代码来更改 QR 的大小

With xSheet.Shapes(QRShapeName)
       .Width = 30  'change your size
       .Height = 30  'change your size
   End With

【讨论】:

  • 不知何故 QR 码内容结结巴巴,好像通过我的输入生成代码的“for循环”计数器在消息中途的某个地方被重置,从我的消息中间复制了几个单词:-/。有没有其他人看到上面链接的 Google 代码存在这样的问题?
  • 我仍然有这个问题 - 我将它添加为一个新问题:stackoverflow.com/questions/41404226/…
  • 我现在修复了口吃问题(至少对于我遇到的所有边缘情况),并将改进后的代码放在 GitHub 上。请参阅答案中的更新链接。
  • 干得好!感谢您将代码分享给社区!
  • 非常适合文本,但如果您只想使用数字,则不起作用。知道如何或改变什么以仅对数字起作用吗?
【解决方案2】:

我知道这是一个相当古老且成熟的帖子(尽管尚未接受非常好的现有答案),但我想分享一个替代方案,我为StackOverflow in Portuguese 中的类似帖子准备了一个使用免费online API from QR Code Generator

代码如下:

Sub GenQRCode(ByVal data As String, ByVal color As String, ByVal bgcolor As String, ByVal size As Integer)
On Error Resume Next

    For i = 1 To ActiveSheet.Pictures.Count
        If ActiveSheet.Pictures(i).Name = "QRCode" Then
            ActiveSheet.Pictures(i).Delete
            Exit For
        End If
    Next i

    sURL = "https://api.qrserver.com/v1/create-qr-code/?" + "size=" + Trim(Str(size)) + "x" + Trim(Str(size)) + "&color=" + color + "&bgcolor=" + bgcolor + "&data=" + data
    Debug.Print sURL

    Set pic = ActiveSheet.Pictures.Insert(sURL + sParameters)
    Set cell = Range("D9")

    With pic
        .Name = "QRCode"
        .Left = cell.Left
        .Top = cell.Top
    End With

End Sub

它通过简单地(重新)从根据单元格中的参数构建的 URL 创建图像来完成工作。自然,用户必须连接到互联网。

例如(工作表,内容为巴西葡萄牙语,可下载from 4Shared):

【讨论】:

  • 感谢您的帖子!非常感谢!我设法让你的代码使用 API 工作。我正在开发一个在一张纸上使用 200 多个二维码的系统,因此 Patratacus 解决方案大大减慢了系统速度,所以我尝试了你的系统,它似乎工作得更好。唯一的挑战是 - 它适用于我的 PC,但不适用于我的客户端 Mac。调用 sURL 的问题。似乎需要使用 Mac Shell,但我很难实现它。有任何想法吗?我应该将其重新发布为新问题还是答案而不是评论?提前致谢。
  • 你好@特里斯坦。不客气。 :) 我不是 Mac 用户,所以恐怕我无法帮助你。尽管如此,我怀疑操作系统可能会阻止 Excel 发出 HTTP 请求。您是否尝试过使用不同的 URL(仅以固定图像响应的 URL)?你应该检查那个方向的东西。发布一个新问题可能很有用,但您需要有关您的问题的更多详细信息,特别是为了避免将其暂停为超出范围或不可重现。祝你好运! :)
  • 嗨@Luiz,在 Mac 上,我们有 api 返回与 Pictures.Insert 代码中的“sURL + sParameters”命令返回的字符串相同的字符串。我们通过使用 Mac 的 shell 脚本“curl --get -d”得到了这个。这似乎返回图像原始数据?现在看来,Macs Picture.Insert 无法读取原始数据,只能读取图像路径。所以我们正试图找到解决这个问题的方法。要么为 Macs Picture.Insert 找到一种读取原始数据的方法,要么获取 api 返回的数据以保存为文件,然后使用 pictures.insert 打开它。也许我会开始一个新问题。再次感谢!
  • 嗨@特里斯坦。我认为你错过了代码的重点。在 MS Excel 中,您不需要事先下载文件,然后将原始数据传递给 Picture.Insert。它直接在 URL 上工作(MS Excel 会自动下载它)。好吧,至少在 Windows 版本中...... :)
  • 嗨@Luiz,是的,在 PC 上使用 MS Excel pictue.Insert 可以直接在 URL 上正常工作,就像在您的代码中一样,但不幸的是它在 Mac 上不能这样做。使用 Mac Picture.Insert 只能购买给它文件的完整路径。因此,对于使用 Mac,必须先保存文件,然后使用 Picture.Insert 打开该文件。我想我们已经找到了解决办法。我已经发布了一个新问题,并将在对该解决方案进行更多测试后不久发布答案。 stackoverflow.com/questions/43054725/…再次感谢您的帮助!一切顺利。
猜你喜欢
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
  • 2014-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多