为什么这个VBA生成的QR码口吃? (条形码VBA的宏只)

时间:2016-12-31 00:02:25

标签: excel vba excel-vba qr-code

上下文

我在MS Excel 2010中使用barcode-vba-macro-only(在this SO post中提到)来生成QR码。

(条形码将用于方便使用Girocode支付账单,但这在此并不重要,只是说我需要完全按照下面所示的方式构建输入。)

问题

VBA宏创建了很好的QR码,但不知何故,当给定某些输入时,输出(在QR码中编码)“断断续续”,即重复部分文本。

,例如,当给出此输入时:

BCD
001
1
SCT
SOLADES1HDB
Recipient First and Last Name
DE86672500200000123456
EUR123.45

它产生这个输出:

QR-code generated by the VBA macro

奇怪地重复部分内容:

BCD
001
1
SCT
SOLADES1HDB
Recipient First and Last Name
DE
Recipient First and Last Name
DE86672500200000123456
EUR123.45

(请注意 DE 收件人名字和姓氏这两行会出现。)

我想要什么

Excel中的工作,免费/ GPL解决方案,用于生成此类代码;-) ...例如,通过了解发生这种情况的原因,以及修复VBA代码。

我尝试过的(更新1)

  1. 我玩过不同的输入,发现只需在长号末尾添加一些额外的“AAA”即可解决口吃......所以我很感兴趣是什么导致了这种情况。

  2. 我在GitHub上分叉代码,添加了一些代码注释并翻译了一些现有的(捷克语)评论

  3. 通过一些调试,我发现实现会混淆不同编码的起始位置(它存储在数组eb中):编码“收件人优先”后姓氏“包括换行符和”DE“作为”字节“,它可能会尝试切换到”十进制“或”字母“编码(每个字符只有3.33或5.5位而不是8)...但后来又回到编码中“字节”格式从而使起始位置错误。

  4. 代码

    您可以下载我的测试XLSM文件here,然后访问我的improved code file on GitHub

    我认为问题可能出在下面显示的核心功能中,在数组eb()被填充的部分。

    Function qr_gen(ptext As String, poptions As String) As String
      Dim encoded1() As Byte ' byte mode (ASCII) all max 3200 bytes
      Dim encix1%
      Dim ecx_cnt(3) As Integer
      Dim ecx_pos(3) As Integer
      Dim ecx_poc(3) As Integer
      Dim eb(1 To 20, 1 To 4) As Integer 'store how many characters should be in which ECI mode. This is a list of rows, each row corresponding a the next batch of characters with a different ECI mode.
      ' eb(i, 1) - ECI mode (1 = numeric, 2 = alphanumeric, 3 = byte)
      ' eb(i, 2) - last character in previous row
      ' eb(i, 3) - number of characters in THIS row
      ' eb(i, 4) - number of bits for THIS row
      Dim ascimatrix$, mode$, err$
      Dim ecl%, r%, c%, mask%, utf8%, ebcnt%
      Dim i&, j&, k&, m&
      Dim ch%, s%, siz%
      Dim x As Boolean
      Dim qrarr() As Byte ' final matrix
      Dim qrpos As Integer
      Dim qrp(15) As Integer     ' 1:version,2:size,3:ccs,4:ccb,5:totby,6-12:syncs(7),13-15:versinfo(3)
      Dim qrsync1(1 To 8) As Byte
      Dim qrsync2(1 To 5) As Byte
    
      ascimatrix = ""
      err = ""
      mode = "M"
      i = InStr(poptions, "mode=")
      If i > 0 Then mode = Mid(poptions, i + 5, 1)
    ' M=0,L=1,H=2,Q=3
      ecl = InStr("MLHQ", mode) - 1
      If ecl < 0 Then mode = "M": ecl = 0
      If ptext = "" Then
        err = "Not data"
        Exit Function
      End If
      For i = 1 To 3
        ecx_pos(i) = 0
        ecx_cnt(i) = 0
        ecx_poc(i) = 0
      Next i
      ebcnt = 1
      utf8 = 0
      For i = 1 To Len(ptext) + 1
        ' Decide how many bytes this character has
        If i > Len(ptext) Then
          k = -5 ' End of text --> skip several code sections
        Else ' need to parse character i of ptext and decide how many bytes it has
          k = AscL(Mid(ptext, i, 1))
          If k >= &H1FFFFF Then ' FFFF - 1FFFFFFF
            m = 4
            k = -1
          ElseIf k >= &H7FF Then ' 7FF-FFFF 3 bytes
            m = 3
            k = -1
          ElseIf k >= 128 Then
            m = 2
            k = -1
          Else ' normal 7bit ASCII character, so it is worth it to check if it belong to the Numeric or Alphanumeric subsets defined in ECI (array qralnum)
            m = 1
            k = InStr(qralnum, Mid(ptext, i, 1)) - 1
          End If
        End If
        ' Depending on k and a lot of other things, increase ebcnt
        If (k < 0) Then ' Treat mult-byte case or exit? (bude byte nebo konec)
          If ecx_cnt(1) >= 9 Or (k = -5 And ecx_cnt(1) = ecx_cnt(3)) Then ' Until now it was possible numeric??? (Az dosud bylo mozno pouzitelne numeric)
            If (ecx_cnt(2) - ecx_cnt(1)) >= 8 Or (ecx_cnt(3) = ecx_cnt(2)) Then ' pred num je i pouzitelny alnum
              If (ecx_cnt(3) > ecx_cnt(2)) Then ' Jeste pred alnum bylo byte
                eb(ebcnt, 1) = 3         ' Typ byte
                eb(ebcnt, 2) = ecx_pos(3) ' Position pozice
                eb(ebcnt, 3) = ecx_cnt(3) - ecx_cnt(2) ' delka
                ebcnt = ebcnt + 1
                ecx_poc(3) = ecx_poc(3) + 1
              End If
              eb(ebcnt, 1) = 2         ' Typ alnum
              eb(ebcnt, 2) = ecx_pos(2)
              eb(ebcnt, 3) = ecx_cnt(2) - ecx_cnt(1) ' delka
              ebcnt = ebcnt + 1
              ecx_poc(2) = ecx_poc(2) + 1
              ecx_cnt(2) = 0
            ElseIf ecx_cnt(3) > ecx_cnt(1) Then ' byly bytes pred numeric
              eb(ebcnt, 1) = 3         ' Typ byte
              eb(ebcnt, 2) = ecx_pos(3) ' Position pozice
              eb(ebcnt, 3) = ecx_cnt(3) - ecx_cnt(1) ' delka
              ebcnt = ebcnt + 1
              ecx_poc(3) = ecx_poc(3) + 1
            End If
          ElseIf (ecx_cnt(2) >= 8) Or (k = -5 And ecx_cnt(2) = ecx_cnt(3)) Then ' Az dosud bylo mozno pouzitelne alnum
            If (ecx_cnt(3) > ecx_cnt(2)) Then ' Jeste pred alnum bylo byte
              eb(ebcnt, 1) = 3         ' Typ byte
              eb(ebcnt, 2) = ecx_pos(3) ' Position pozice
              eb(ebcnt, 3) = ecx_cnt(3) - ecx_cnt(2) ' delka
              ebcnt = ebcnt + 1
              ecx_poc(3) = ecx_poc(3) + 1
            End If
            eb(ebcnt, 1) = 2         ' Typ alnum
            eb(ebcnt, 2) = ecx_pos(2)
            eb(ebcnt, 3) = ecx_cnt(2) ' delka
            ebcnt = ebcnt + 1
            ecx_poc(2) = ecx_poc(2) + 1
            ecx_cnt(3) = 0
            ecx_cnt(2) = 0 ' vse zpracovano
          ElseIf (k = -5 And ecx_cnt(3) > 0) Then ' konec ale mam co ulozit
            eb(ebcnt, 1) = 3         ' Typ byte
            eb(ebcnt, 2) = ecx_pos(3) ' Position pozice
            eb(ebcnt, 3) = ecx_cnt(3) ' delka
            ebcnt = ebcnt + 1
            ecx_poc(3) = ecx_poc(3) + 1
          End If
        End If
        If k = -5 Then Exit For
        If (k >= 0) Then ' We can alphanumeric? (Muzeme alnum)
          If (k >= 10 And ecx_cnt(1) >= 12) Then ' Until now it was perhaps numeric (Az dosud bylo mozno num)
            If (ecx_cnt(2) - ecx_cnt(1)) >= 8 Or (ecx_cnt(3) = ecx_cnt(2)) Then ' There is also an alphanumeric which is worth it(Je tam i alnum ktery stoji za to)
              If (ecx_cnt(3) > ecx_cnt(2)) Then ' Even before it was alnum byte (Jeste pred alnum bylo byte)
                eb(ebcnt, 1) = 3         ' Typ byte
                eb(ebcnt, 2) = ecx_pos(3) ' Position (pozice)
                eb(ebcnt, 3) = ecx_cnt(3) - ecx_cnt(2) ' length (delka)
                ebcnt = ebcnt + 1
                ecx_poc(3) = ecx_poc(3) + 1
              End If
              eb(ebcnt, 1) = 2         ' Typ alnum
              eb(ebcnt, 2) = ecx_pos(2)
              eb(ebcnt, 3) = ecx_cnt(2) - ecx_cnt(1) ' length (delka)
              ebcnt = ebcnt + 1
              ecx_poc(2) = ecx_poc(2) + 1
              ecx_cnt(2) = 0 ' processed everything (vse zpracovano)
            ElseIf (ecx_cnt(3) > ecx_cnt(1)) Then ' Previous Num is byte (Pred Num je byte)
              eb(ebcnt, 1) = 3         ' Typ byte
              eb(ebcnt, 2) = ecx_pos(3) ' Position (pozice)
              eb(ebcnt, 3) = ecx_cnt(3) - ecx_cnt(1) ' length (delka)
              ebcnt = ebcnt + 1
              ecx_poc(3) = ecx_poc(3) + 1
            End If
            eb(ebcnt, 1) = 1         ' Typ numerix
            eb(ebcnt, 2) = ecx_pos(1)
            eb(ebcnt, 3) = ecx_cnt(1) ' length (delka)
            ebcnt = ebcnt + 1
            ecx_poc(1) = ecx_poc(1) + 1
            ecx_cnt(1) = 0
            ecx_cnt(2) = 0
            ecx_cnt(3) = 0 ' processed everything (vse zpracovano)
          End If
          If ecx_cnt(2) = 0 Then ecx_pos(2) = i
          ecx_cnt(2) = ecx_cnt(2) + 1
        Else ' possible alnum (mozno alnum)
          ecx_cnt(2) = 0
        End If
        If k >= 0 And k < 10 Then ' Can be numeric (muze byt numeric)
          If ecx_cnt(1) = 0 Then ecx_pos(1) = i
          ecx_cnt(1) = ecx_cnt(1) + 1
        Else
          ecx_cnt(1) = 0
        End If
        If ecx_cnt(3) = 0 Then ecx_pos(3) = i
        ecx_cnt(3) = ecx_cnt(3) + m
        utf8 = utf8 + m
        If ebcnt >= 16 Then ' We have already taken 3 other blocks of bits (Uz by se mi tri dalsi bloky stejne nevesli)
          ecx_cnt(1) = 0
          ecx_cnt(2) = 0
        End If
        Debug.Print "Character:'" & Mid(ptext, i, 1) & "'(" & k & _
            ") ebn=" & ecx_pos(1) & "." & ecx_cnt(1) & _
             " eba=" & ecx_pos(2) & "." & ecx_cnt(2) & _
             " ebb=" & ecx_pos(3) & "." & ecx_cnt(3)
      Next
      ebcnt = ebcnt - 1 ' ebcnt now has its final value
      Debug.Print ("ebcnt=" & ebcnt)
      c = 0
      For i = 1 To ebcnt
        Select Case eb(i, 1)
          Case 1: eb(i, 4) = Int(eb(i, 3) / 3) * 10 + (eb(i, 3) Mod 3) * 3 + IIf((eb(i, 3) Mod 3) > 0, 1, 0)
          Case 2: eb(i, 4) = Int(eb(i, 3) / 2) * 11 + (eb(i, 3) Mod 2) * 6
          Case 3: eb(i, 4) = eb(i, 3) * 8
        End Select
        c = c + eb(i, 4)
      Next i
      Debug.Print ("c=" & c)
    '  UTF-8 is default not need ECI value - zxing cannot recognize
    '  Call qr_params(i * 8 + utf8,mode,qrp)
      Call qr_params(c, ecl, qrp, ecx_poc)
      If qrp(1) <= 0 Then
        err = "Too long"
        Exit Function
      End If
      siz = qrp(2)
    Debug.Print "ver:" & qrp(1) & mode & " size " & siz & " ecc:" & qrp(3) & "x" & qrp(4) & " d:" & (qrp(5) - qrp(3) * qrp(4))
    'MsgBox "ver:" & qrp(1) & mode & " size " & siz & " ecc:" & qrp(3) & "x" & qrp(4) & " d:" & (qrp(5) - qrp(3) * qrp(4))
      ReDim encoded1(qrp(5) + 2)
      ' Table 3 — Number of bits in character count indicator for QR Code 2005:
      ' mode indicator (1=num,2=AlNum,4=Byte,8=kanji,ECI=7)
      '      mode: Byte Alphanum  Numeric  Kanji
      ' ver 1..9 :  8      9       10       8
      '   10..26 : 16     11       12      10
      '   27..40 : 16     13       14      12
    ' UTF-8 is default not need ECI value - zxing cannot recognize
    '  if utf8 > 0 Then
    '    k = &H700 + 26 ' UTF-8=26 ; Win1250 = 21; 8859-2 = 4 viz http://strokescribe.com/en/ECI.html
    '    bb_putbits(encoded1,encix1,k,12)
    '  End If
      encix1 = 0
      For i = 1 To ebcnt
        Select Case eb(i, 1)
          Case 1: c = IIf(qrp(1) < 10, 10, IIf(qrp(1) < 27, 12, 14)): k = 2 ^ c + eb(i, 3) ' encoding mode "Numeric"
          Case 2: c = IIf(qrp(1) < 10, 9, IIf(qrp(1) < 27, 11, 13)): k = 2 * (2 ^ c) + eb(i, 3) ' encoding mode "alphanum
          Case 3: c = IIf(qrp(1) < 10, 8, 16): k = 4 * (2 ^ c) + eb(i, 3) ' encoding mode "Byte"
        End Select
        Call bb_putbits(encoded1, encix1, k, c + 4)
        Debug.Print "ver:" & qrp(1) & mode & " size " & siz & " ecc:" & qrp(3) & "x" & qrp(4) & " d:" & (qrp(5) - qrp(3) * qrp(4))
        j = 0 ' count characters that have been output in THIS row eb(i,...)
        m = eb(i, 2) 'Start (after) last character of input from previous row
        r = 0
        While j < eb(i, 3)
          k = AscL(Mid(ptext, m, 1))
          m = m + 1
          If eb(i, 1) = 1 Then
            ' parse numeric input - output 3 decimal digits into 10 bit
            r = (r * 10) + ((k - &H30) Mod 10)
            If (j Mod 3) = 2 Then
              Call bb_putbits(encoded1, encix1, r, 10)
              r = 0
            End If
            j = j + 1
          ElseIf eb(i, 1) = 2 Then
            ' parse alphanumeric input - output 2 alphanumeric characters into 11 bit
            r = (r * 45) + ((InStr(qralnum, Chr(k)) - 1) Mod 45)
            If (j Mod 2) = 1 Then
              Call bb_putbits(encoded1, encix1, r, 11)
              r = 0
            End If
            j = j + 1
          Else
            ' Okay, byte mode: coding according to Chapter "6.4.2 Extended Channel Interpretation (ECI) mode" of ISOIEC 18004_2006Cor 1_2009.pdf
            If k > &H1FFFFF Then ' FFFF - 1FFFFFFF
              ch = &HF0 + Int(k / &H40000) Mod 8
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + Int(k / &H1000) Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + Int(k / 64) Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + k Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              j = j + 4
            ElseIf k > &H7FF Then ' 7FF-FFFF 3 bytes
              ch = &HE0 + Int(k / &H1000) Mod 16
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + Int(k / 64) Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + k Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              j = j + 3
            ElseIf k > &H7F Then ' 2 bytes
              ch = &HC0 + Int(k / 64) Mod 32
              Call bb_putbits(encoded1, encix1, ch, 8)
              ch = 128 + k Mod 64
              Call bb_putbits(encoded1, encix1, ch, 8)
              j = j + 2
            Else
              ch = k Mod 256
              Call bb_putbits(encoded1, encix1, ch, 8)
              j = j + 1
            End If
          End If
        Wend
        Select Case eb(i, 1)
          Case 1:
            If (j Mod 3) = 1 Then
              Call bb_putbits(encoded1, encix1, r, 4)
            ElseIf (j Mod 3) = 2 Then
              Call bb_putbits(encoded1, encix1, r, 7)
            End If
          Case 2:
            If (j Mod 2) = 1 Then Call bb_putbits(encoded1, encix1, r, 6)
        End Select
    'MsgBox "blk[" & i & "] t:" & eb(i,1) & "from " & eb(i,2) & " to " & eb(i,3) + eb(i,2) & " bits=" & encix1
      Next i
      Call bb_putbits(encoded1, encix1, 0, 4) ' end of chain
      If (encix1 Mod 8) <> 0 Then  ' round to byte
        Call bb_putbits(encoded1, encix1, 0, 8 - (encix1 Mod 8))
      End If
      ' padding
      i = (qrp(5) - qrp(3) * qrp(4)) * 8
      If encix1 > i Then
        err = "Encode length error"
        Exit Function
      End If
      ' padding 0xEC,0x11,0xEC,0x11...
      Do While encix1 < i
        Call bb_putbits(encoded1, encix1, &HEC11, 16)
      Loop
      ' doplnime ECC
      i = qrp(3) * qrp(4) 'ppoly, pmemptr , psize , plen , pblocks
      Call qr_rs(&H11D, encoded1, qrp(5) - i, i, qrp(4))
    'Call arr2hexstr(encoded1)
      encix1 = qrp(5)
      ' Pole pro vystup
      ReDim qrarr(0)
      ReDim qrarr(1, qrp(2) * 24& + 24&) ' 24 bytes per row
      qrarr(0, 0) = 0
      ch = 0
      Call bb_putbits(qrsync1, ch, Array(&HFE, &H82, &HBA, &HBA, &HBA, &H82, &HFE, 0), 64)
      Call qr_mask(qrarr, qrsync1, 8, 0, 0) ' sync UL
      Call qr_mask(qrarr, 0, 8, 8, 0)   ' fmtinfo UL under - bity 14..9 SYNC 8
      Call qr_mask(qrarr, qrsync1, 8, 0, siz - 7) ' sync UR ( o bit vlevo )
      Call qr_mask(qrarr, 0, 8, 8, siz - 8)   ' fmtinfo UR - bity 7..0
      Call qr_mask(qrarr, qrsync1, 8, siz - 7, 0) ' sync DL (zasahuje i do quiet zony)
      Call qr_mask(qrarr, 0, 8, siz - 8, 0)   ' blank nad DL
      For i = 0 To 6
        x = qr_bit(qrarr, -1, i, 8, 0) ' svisle fmtinfo UL - bity 0..5 SYNC 6,7
        x = qr_bit(qrarr, -1, i, siz - 8, 0) ' svisly blank pred UR
        x = qr_bit(qrarr, -1, siz - 1 - i, 8, 0) ' svisle fmtinfo DL - bity 14..8
      Next
      x = qr_bit(qrarr, -1, 7, 8, 0) ' svisle fmtinfo UL - bity 0..5 SYNC 6,7
      x = qr_bit(qrarr, -1, 7, siz - 8, 0) ' svisly blank pred UR
      x = qr_bit(qrarr, -1, 8, 8, 0) ' svisle fmtinfo UL - bity 0..5 SYNC 6,7
      x = qr_bit(qrarr, -1, siz - 8, 8, 1) ' black dot DL
      If qrp(13) <> 0 Or qrp(14) <> 0 Then ' versioninfo
      ' UR ver 0 1 2;3 4 5;...;15 16 17
      ' LL ver 0 3 6 9 12 15;1 4 7 10 13 16; 2 5 8 11 14 17
        k = 65536 * qrp(13) + 256& * qrp(14) + 1& * qrp(15)
        c = 0: r = 0
        For i = 0 To 17
          ch = k Mod 2
          x = qr_bit(qrarr, -1, r, siz - 11 + c, ch) ' UR ver
          x = qr_bit(qrarr, -1, siz - 11 + c, r, ch) ' DL ver
          c = c + 1
          If c > 2 Then c = 0: r = r + 1
          k = Int(k / 2&)
        Next
      End If
      c = 1
      For i = 8 To siz - 9 ' sync lines
        x = qr_bit(qrarr, -1, i, 6, c) ' vertical on column 6
        x = qr_bit(qrarr, -1, 6, i, c) ' horizontal on row 6
        c = (c + 1) Mod 2
      Next
      ' other syncs
      ch = 0
      Call bb_putbits(qrsync2, ch, Array(&H1F, &H11, &H15, &H11, &H1F), 40)
      ch = 6
      Do While ch > 0 And qrp(6 + ch) = 0
        ch = ch - 1
      Loop
      If ch > 0 Then
        For c = 0 To ch
          For r = 0 To ch
            ' corners
            If (c <> 0 Or r <> 0) And _
               (c <> ch Or r <> 0) And _
               (c <> 0 Or r <> ch) Then
              Call qr_mask(qrarr, qrsync2, 5, qrp(r + 6) - 2, qrp(c + 6) - 2)
            End If
          Next r
        Next c
      End If
     ' qr_fill(parr as Variant, psiz%, pb as Variant, pblocks%, pdlen%, ptlen%)
     ' vyplni pole parr (psiz x 24 bytes) z pole pb pdlen = pocet dbytes, pblocks = bloku, ptlen celkem
      Call qr_fill(qrarr, siz, encoded1, qrp(4), qrp(5) - qrp(3) * qrp(4), qrp(5))
      mask = 8 ' auto
      i = InStr(poptions, "mask=")
      If i > 0 Then mask = val(Mid(poptions, i + 5, 1))
      If mask < 0 Or mask > 7 Then
        j = -1
        For mask = 0 To 7
          GoSub addmm
          i = qr_xormask(qrarr, siz, mask, False)
    '      MsgBox "score mask " & mask & " is " & i
          If i < j Or j = -1 Then j = i: s = mask
        Next mask
        mask = s
    '    MsgBox "best is " & mask & " with score " & j
      End If
      GoSub addmm
      i = qr_xormask(qrarr, siz, mask, True)
      ascimatrix = ""
      For r = 0 To siz Step 2
        s = 0
        For c = 0 To siz Step 2
          If (c Mod 8) = 0 Then
            ch = qrarr(1, s + 24 * r)
            If r < siz Then i = qrarr(1, s + 24 * (r + 1)) Else i = 0
            s = s + 1
          End If
          ascimatrix = ascimatrix _
             & Chr(97 + (ch Mod 4) + 4 * (i Mod 4))
          ch = Int(ch / 4)
          i = Int(i / 4)
        Next
        ascimatrix = ascimatrix & vbNewLine
      Next r
      ReDim qrarr(0)
      qr_gen = ascimatrix
      Exit Function
    addmm:
      k = ecl * 8 + mask
      ' poly: 101 0011 0111
      Call qr_bch_calc(k, &H537)
    'MsgBox "mask :" & hex(k,3) & " " & hex(k xor &H5412,3)
      k = k Xor &H5412 ' micro xor &H4445
      r = 0
      c = siz - 1
      For i = 0 To 14
        ch = k Mod 2
        k = Int(k / 2)
        x = qr_bit(qrarr, -1, r, 8, ch) ' svisle fmtinfo UL - bity 0..5 SYNC 6,7 .... 8..14 dole
        x = qr_bit(qrarr, -1, 8, c, ch) ' vodorovne odzadu 0..7 ............ 8,SYNC,9..14
        c = c - 1
        r = r + 1
        If i = 7 Then c = 7: r = siz - 7
        If i = 5 Then r = r + 1 ' preskoc sync vodorvny
        If i = 8 Then c = c - 1 ' preskoc sync svisly
      Next
      Return
    End Function  ' qr_gen
    

2 个答案:

答案 0 :(得分:4)

为什么会发生这种情况

通过一些调试,我发现原始实现混淆了不同编码的起始位置(它存储在数组eb中):编码&#34;收件人名字和姓氏&#34;包括换行和&#34; DE&#34; as&#34; Byte&#34;,它可能会尝试切换到&#34; Decimal&#34;或&#34; Alphanum&#34;编码(每个字符只有3.33或5.5位而不是8位)...但是后来又回到了#34; Byte&#34;格式,从而使起始位置错误。

解决方案

我现在在代码中添加了一些错误检查,手动删除了口吃。

您可以在Github找到我改进的代码,特别参见barcody.bas

关键的补充是这部分:

  i = 1
  While i < (ebcnt - 1)
    If eb(i, 2) + eb(i, 3) <> eb(i + 1, 2) Then
        ' oops, this should not happen. First document it:
        Debug.Print ("eb() rows " & i & " and " & i + 1 & " are overlapping!")
        ' Now Lets see if we can fix it:
        wasfixed = False
        For k = i To 1 Step -1
            If eb(k, 2) = eb(i + 1, 2) Then
                ' okay, the row k to i seem to be contained in i+1 and following. Delete k to i ...
                For j = k To ebcnt - (i - k + 1) ' ... by copying upwards all later rows...
                    eb(j, 1) = eb(j + (i - k + 1), 1)
                    eb(j, 2) = eb(j + (i - k + 1), 2)
                    eb(j, 3) = eb(j + (i - k + 1), 3)
                    eb(j, 4) = eb(j + (i - k + 1), 4)
                Next j
                ebcnt = ebcnt - (i - k + 1) ' and correcting the total rowcount
                wasfixed = True
                Exit For
            End If
        Next k
        If Not (wasfixed) Then
            MsgBox ("The input text analysis failed - entering debug mode...")
            Debug.Assert False
        End If
    End If
    i = i + 1
  Wend

答案 1 :(得分:1)

我注意到同样的问题,某些角色在遇到问题后会触发此问题。在你的情况下,它看起来像&#34; DE&#34;由于我没有编写代码,我没有彻底搜索代码,为什么会触发重复,但我猜测函数中的某些十六进制转换会导致这个问题。在我的情况下,我通过在整个字符串前面的空格输入到生成器来避免这个问题。由于某些原因,在开头有空间以某种方式阻止重复的触发。在我的情况下读取条形码的读取器程序无论如何都会从字符串中删除空格,所以它并不重要。

我不知道这对您的应用程序是否有问题,但请尝试在有问题的字符串(DE86672500200000123456)前放置一个空格(&#34;&#34;)并查看是否存在问题的工作原理。

BCD
001
1
SCT
SOLADES1HDB
Recipient First and Last Name
 DE86672500200000123456 
EUR123.45