0% found this document useful (0 votes)
0 views5 pages

Modul Data Matrix

The document contains a VBA function named DataMatrix that generates a Data Matrix barcode symbol in an Excel cell based on a given text input. It includes parameters for encoding the text and options for rectangle dimensions, following the ISO/IEC 16022:2006 standard. The function handles various encoding modes, calculates symbol size, and lays out the barcode visually in the specified cell.

Uploaded by

José Sánchez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views5 pages

Modul Data Matrix

The document contains a VBA function named DataMatrix that generates a Data Matrix barcode symbol in an Excel cell based on a given text input. It includes parameters for encoding the text and options for rectangle dimensions, following the ISO/IEC 16022:2006 standard. The function handles various encoding modes, calculates symbol size, and lays out the barcode visually in the specified cell.

Uploaded by

José Sánchez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

Attribute VB_Name = "ModulDataMatrix"

Option Explicit

' creates Data Matrix barcode symbol as shape in Excel cell.


' param text to encode
' param rectangle boolean, default autodetect on cell dimension
' Data Matrix symbol creation according ISO/IEC 16022:2006
Public Function DataMatrix(text As String, Optional rectangle As Integer = -2) As
String
Attribute DataMatrix.VB_Description = "Draw DataMatrix barcode"
Attribute DataMatrix.VB_ProcData.VB_Invoke_Func = " \n18"
On Error GoTo failed
If Not TypeOf Application.Caller Is Range Then Err.Raise 513, "DataMatrix", "Call
only from sheet"
Dim enc As String, en As String, el As Long, k As Variant, l As Long
Dim h As Long, w As Long, nc As Byte, nr As Byte, shp As Shape
Dim fw As Integer, fh As Integer, i As Long, j As Long, b As Double
Dim c As Long, r As Double, s As Long, x As Long, y As Long, txt As String
Dim fColor As Long, bColor As Long, line As Long
fColor = vbBlack: bColor = vbBlack: line = xlHairline ' redraw graphic ?
For Each shp In Application.Caller.Parent.Shapes
If shp.Name = Application.Caller.Address Then
If shp.Title = text Then Exit Function ' same as prev ?
fColor = shp.Fill.ForeColor.RGB ' remember format
bColor = shp.line.ForeColor.RGB
line = shp.line.Weight
shp.Delete
End If
Next shp
txt = IIf(text = "", " ", (text)): l = Len(txt)
For i = 1 To l ' ASCII mode encoding
c = Asc(Mid(txt, i, 1)): r = 0
If i < l Then r = Asc(Mid(txt, i + 1, 1))
If c > 47 And c < 58 And r > 47 And r < 58 Then
enc = enc + Chr((c - 48) * 10 + r - 48 + 130) ' 2 digits
i = i + 1
ElseIf (c > 127) Then ' extended char
enc = enc + Chr(235) + Chr(c - 127)
Else
enc = enc + Chr(c + 1)
End If
Next i
For x = 0 To 2 ' C40, TEXT and X12 modes encoding
k = Array(Array(230, 31, 0, 0, 32, 9, 32 - 3, 47, 1, 33, 57, 9, 48 - 4, 64, 1,
58 - 15, 90, 9, 65 - 14, 95, 1, 91 - 22, 127, 2, 96, 255, 1, 0), _
Array(239, 31, 0, 0, 32, 9, 32 - 3, 47, 1, 33, 57, 9, 48 - 4, 64, 1,
58 - 15, 90, 2, 64, 95, 1, 91 - 22, 122, 9, 97 - 14, 127, 2, 123 - 27, 255, 1, 0),
_
Array(238, 12, 8, 0, 13, 9, 13, 31, 8, 0, 32, 9, 32 - 3, 41, 8, 0,
42, 9, 42 - 1, 47, 8, 0, 57, 9, 48 - 4, 64, 8, 0, 90, 9, 65 - 14, 255, 8, 0))(x)
b = 0: h = 0
en = Chr(k(0)) ' start switch
For i = 1 To l
If h = 0 And i = l Then Exit For
c = Asc(Mid(txt, i, 1))
If c > 127 And k(0) <> 238 Then
b = b * 40 + 1: b = b * 40 + 30
h = h + 2: c = c - 128 ' hi bit in C40 & TEXT
End If
For j = 1 To 90 Step 3 ' select char set
If c <= k(j) Then Exit For
Next j
s = k(j + 1) ' set
If s = 8 Or (s = 9 And h = 0 And i = l) Then
en = txt + txt
Exit For ' char not in set, next mode
End If
If s < 5 And h = 2 And i = l Then 'Exit For ' last char in ASCII
b = b * 40: h = 3 ' add padding
i = i - 1
Else
If s < 5 Then b = b * 40 + s: h = h + 1 ' set
b = b * 40 + c - k(j + 2): h = h + 1 ' char offset
If h Mod 3 = 2 And k(0) <> 238 And i = l Then b = b * 40: h = h + 1 '
add padding
End If
Do While h > 2 ' pack 3 chars in 2 bytes
h = h - 3: r = 40& ^ h
c = Int(b / r) + 1
en = en + Chr((c \ 256) And 255) + Chr(c And 255)
b = b - c * r + r
Loop
Next i
en = en + Chr(254) ' return to ASCII
For i = i - h To l ' add last chars
c = Asc(Mid(txt, i, 1))
If (c > 127) Then en = en + Chr(235)
en = en + Chr((c And 127) + 1)
Next i
If Len(en) < Len(enc) Then enc = en ' take shorter
Next x

j = (l + 1) And -4: b = 0: en = Chr(240) ' switch to Edifact


For i = 1 To j
If i < j Then ' encode char
c = Asc(Mid(txt, i, 1))
If c < 32 Or c > 94 Then Exit For ' not in set
Else
c = 31 ' return to ASCII
End If
b = b * 64 + (c And 63)
If (i And 3) = 0 Then ' 4 data in 3 bytes
en = en + Chr(b \ 65536) + Chr((b \ 256) And 255) + Chr(b And 255)
b = 0
End If
Next i
If j > 0 And i > j Then
For i = i - 1 To l ' add last chars
c = Asc(Mid(txt, i, 1))
If (c > 127) Then en = en + Chr(235)
en = en + Chr((c And 127) + 1)
Next i
If Len(en) < Len(enc) Then enc = en ' take shorter
End If

en = Chr(231) ' Base256 encoding


If l > 250 Then en = en + Chr((l \ 250 + 37) And 255) ' len high byte
en = en + Chr((l Mod 250 + (149 * (Len(en) + 1)) Mod 255 + 1) And 255) ' low
For i = 1 To l ' data in 255 state algo
en = en + Chr((Asc(Mid(txt, i, 1)) + (149 * (Len(en) + 1)) Mod 255 + 1) And
255)
Next i
If Len(en) < Len(enc) Then enc = en ' take shorter

' compute symbol size


nc = 1: nr = 1: j = -1: b = 1: el = Len(enc) ' symbol size, regions, region size
If (rectangle = -1 Or (rectangle = -2 And (Application.Caller.MergeArea.Width * 3 >
Application.Caller.MergeArea.Height * 4))) And el < 50 Then ' rectangular pattern ?
k = Array(16, 7, 28, 11, 24, 14, 32, 18, 32, 24, 44, 28) ' symbol width,
checkwords
Do
j = j + 1: w = k(j) ' width w/o finder pattern
h = 6 + (j And 12) ' height
l = w * h / 8: j = j + 1 ' # of bytes in symbol
Loop While l - k(j) < el ' data fit in symbol ?
If w > 25 Then nc = 2 ' column regions
Else ' square symbol
w = 6: h = w
i = 2 ' size increment
k = Array(5, 7, 10, 12, 14, 18, 20, 24, 28, 36, 42, 48, 56, 68, 84, _
112, 144, 192, 224, 272, 336, 408, 496, 620) ' checkwords
Do
If j = UBound(k) Then Err.Raise 514, "DataMatrix", "Message too long"
j = j + 1
If w > 11 * i Then i = 4 + i And 12 ' advance increment
w = w + i: h = w
l = (w * h) \ 8
Loop While l - k(j) < el
If w > 27 Then nr = 2 * (w \ 54) + 2: nc = nr ' regions
If l > 255 Then b = 2 * (l \ 512) + 2 ' blocks
End If
s = k(j) ' checkwords
fw = w / nc: fh = h / nr ' region size

If el < l - s Then enc = enc + Chr(129): el = el + 1 ' first padding


Do While el < l - s ' add more padding
el = el + 1
enc = enc + Chr((((149 * el) Mod 253) + 130) Mod 254)
Loop

enc = enc + Space(s) ' compute Reed Solomon error detection and correction
Dim rs(70) As Integer, rc(70) As Integer ' RS code
Dim lg(256) As Integer, ex(255) As Integer ' log/exp table
s = s / b: j = 1
For i = 0 To 254
ex(i) = j: lg(j) = i ' compute log/exp table of Galois field
j = j + j: If j > 255 Then j = j Xor 301 ' GF polynomial a^8+a^5+a^3+a^2+1 =
100101101b = 301
Next i
rs(s + 1) = 0 ' compute RS generator polynomial
For i = 0 To s
rs(s - i) = 1
For j = s - i + 1 To s
rs(j) = rs(j + 1) Xor ex((lg(rs(j)) + i) Mod 255)
Next j
Next i
For c = 1 To b ' compute RS correction data for each block
For i = 0 To s: rc(i) = 0: Next i
For i = c To el Step b
x = rc(0) Xor Asc(Mid(enc, i, 1))
For j = 1 To s
rc(j - 1) = rc(j) Xor IIf(x, ex((lg(rs(j)) + lg(x)) Mod 255), 0)
Next j
Next i
For i = 0 To s - 1 ' add interleaved correction data
Mid(enc, el + c + i * b, 1) = Chr(rc(i))
Next i
Next c

With Application.Caller.Parent.Shapes
b = .Count + 1 ' layout DataMatrix barcode
For i = 0 To h + 2 * nr - 1 Step fh + 2 ' finder horizontal
For j = 0 To w + 2 * nc - 1
.AddShape(msoShapeRectangle, j, i + fh + 1, 1, 1).Name =
Application.Caller.Address
If (j And 1) = 0 Then .AddShape(msoShapeRectangle, j, i, 1, 1).Name =
Application.Caller.Address
Next j
Next i
For i = 0 To w + 2 * nc - 1 Step fw + 2 ' finder vertical
For j = 0 To h - 1
.AddShape(msoShapeRectangle, i, j + (j \ fh) * 2 + 1, 1, 1).Name =
Application.Caller.Address
If (j And 1) = 1 Then .AddShape(msoShapeRectangle, i + fw + 1, j + (j \
fh) * 2, 1, 1).Name = Application.Caller.Address
Next j
Next i
'layout data
s = 2: c = 0: r = 4 ' step,column,row of data position
For i = 1 To l
If (r = h - 3 And c = -1) Then ' corner A
k = Array(w, 6 - h, w, 5 - h, w, 4 - h, w, 3 - h, w - 1, 3 - h, 3, 2,
2, 2, 1, 2)
ElseIf r = h + 1 And c = 1 And (w And 7) = 0 And (h And 7) = 6 Then '
corner D
k = Array(w - 2, -h, w - 3, -h, w - 4, -h, w - 2, -1 - h, w - 3, -1 -
h, w - 4, -1 - h, w - 2, -2, -1, -2)
Else
If r = 0 And c = w - 2 And (w And 3) Then i = i - 1: GoTo continue '
corner B
If r < 0 Or c >= w Or r >= h Or c < 0 Then ' outside
s = -s: r = r + 2 + s / 2: c = c + 2 - s / 2 ' turn around
Do While r < 0 Or c >= w Or r >= h Or c < 0
r = r - s: c = c + s
Loop
End If
If r = h - 2 And c = 0 And (w And 3) Then ' corner B
k = Array(w - 1, 3 - h, w - 1, 2 - h, w - 2, 2 - h, w - 3, 2 - h, w
- 4, 2 - h, 0, 1, 0, 0, 0, -1)
ElseIf r = h - 2 And c = 0 And (w And 7) = 4 Then ' corner C
k = Array(w - 1, 5 - h, w - 1, 4 - h, w - 1, 3 - h, w - 1, 2 - h, w
- 2, 2 - h, 0, 1, 0, 0, 0, -1)
ElseIf r = 1 And c = w - 1 And (w And 7) = 0 And (h And 7) = 6 Then '
omit corner D
i = i - 1: GoTo continue
Else
k = Array(0, 0, -1, 0, -2, 0, 0, -1, -1, -1, -2, -1, -1, -2, -2, -
2) ' nominal layout
End If
End If
el = Asc(Mid(enc, i, 1))
For j = 0 To 15 Step 2 ' layout each bit
If el And 1 Then
x = c + k(j): y = r + k(j + 1)
If x < 0 Then x = x + w: y = y + 4 - ((w + 4) And 7) ' wrap around
If y < 0 Then y = y + h: x = x + 4 - ((h + 4) And 7)
.AddShape(msoShapeRectangle, x + 2 * (x \ fw) + 1, y + 2 * (y \ fh)
+ 1, 1, 1).Name = Application.Caller.Address
End If
el = el \ 2
Next j
continue:
r = r - s: c = c + s ' diagonal step
Next i
For i = (w And -4) + 1 To w ' unfilled corner
.AddShape(msoShapeRectangle, i, i, 1, 1).Name = Application.Caller.Address
Next i
b = .Count - b
ReDim shps(b) As Integer ' group all shapes
For i = .Count To 1 Step -1
If .Range(i).Name = Application.Caller.Address Then
shps(b) = i: b = b - 1
If b < 0 Then Exit For
End If
Next i
s = 2 ' padding around symbol
x = Application.Caller.MergeArea.Width * w / (w + s)
y = Application.Caller.MergeArea.Height * h / (h + s) * (w + s) / (h + s)
If x > y Then x = y
With .Range(shps).Group
.Fill.ForeColor.RGB = fColor ' format barcode shape
.line.ForeColor.RGB = bColor
.line.Weight = line
.Width = x ' fit symbol in excel cell
.Height = .Width * (h + s) / (w + s)
.Left = Application.Caller.Left + (Application.Caller.MergeArea.Width
- .Width) / 2
.Top = Application.Caller.Top + (Application.Caller.MergeArea.Height
- .Height) / 2
.Name = Application.Caller.Address ' link shape to data
.Title = text
.AlternativeText = "DataMatrix barcode, " & (w + 2 * nc) & "x" & (h + 2 *
nr) & " cells"
.LockAspectRatio = True
.Placement = xlMove
End With
End With
failed:
If Err.Number Then DataMatrix = "ERROR DataMatrix: " & Err.Description
End Function

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy