'*****************************************************************
'  The following is a Visual Basic / VB / VBA module that 
'  calculates a check digit with the IEC/ISO 7064 MOD 37-2
'  algorithm, which is commonly used in ISBT-128 barcodes
'  as the K check character for keyboard manual entry.
'  https://www.barcodefaq.com/1d/isbt-128/
'  
'  © Copyright, IDAutomation.com, Inc. All rights reserved.
'  Redistribution and use of this code in source and/or binary
'  forms, with or without modification, are permitted provided
'  that: (1) all copies of the source code retain the above
'  unmodified copyright notice and this entire unmodified
'  section of text, (2) You or Your organization owns a valid
'  Developer License to the associated product from IDAutomation.com
'  and, (3) when any portion of this code is bundled in any
'  form with an application, a valid notice must be provided
'  within the user documentation, start-up screen or in the
'  help-about section of the application that specifies
'  IDAutomation.com as the provider of the Software bundled
'  with the application.
'*****************************************************************

Public Function ISO_MOD37_2(DataString As String, Optional ReturnType As Integer = 0) As String
    DataString = UCase(DataString)
    Dim CorrectData As String
    Dim WeightedSum As Long
    Dim StringLength As Long
    Dim AscValue As Long
    Dim CharValue As Long
    Dim CheckDigitAscVal As Long
    Dim CheckDigitAsc As Long
    Dim StringLen As Long
    Dim I As Long
    StringLen = Len(DataString)
    For I = 1 To StringLen
        AscValue = AscW(Mid(DataString, I, 1))
        If AscValue < 58 And AscValue > 47 Then CorrectData = CorrectData & Mid(DataString, I, 1) '0-9
        If AscValue < 91 And AscValue > 64 Then CorrectData = CorrectData & Mid(DataString, I, 1) 'A-Z
    Next I
    DataString = CorrectData
    CorrectData = ""
    WeightedSum = 0
    StringLength = Len(DataString)
    For I = 1 To StringLength
        AscValue = AscW(Mid(DataString, I, 1))
        If AscValue < 58 And AscValue > 47 Then CharValue = AscValue - 48 '0-9 = values 0-9
        If AscValue < 91 And AscValue > 64 Then CharValue = AscValue - 55 'A-Z = values 10-35
        WeightedSum = ((WeightedSum + CharValue) * 2) Mod 37
    Next I
    CheckDigitAscVal = (38 - WeightedSum) Mod 37
    If CheckDigitAscVal < 10 Then CheckDigitAsc = CheckDigitAscVal + 48 '0-9
    If CheckDigitAscVal < 36 And CheckDigitAscVal > 9 Then CheckDigitAsc = CheckDigitAscVal + 55 'A-Z
    If CheckDigitAscVal = 36 Then CheckDigitAsc = 42 '*
    If ReturnType = 1 Then ISO_MOD37_2 = " [" & ChrW(CheckDigitAsc) & "]"
    If ReturnType = 0 Then ISO_MOD37_2 = ChrW(CheckDigitAsc)
End Function