💻💡 Code to check if IBAN is valid

Started by Theo Gottwald, February 17, 2024, 09:52:27 PM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.

Theo Gottwald

This code is a Side-Product of the SPR-Development.

🔍 This is a special Tipp. If you have an IBAN and want to check if it is valid, you have to go through several steps. Here is the PowerBasic code for it. 💻💡

🔍 Dies ist ein besonderer Tipp. Wenn du eine IBAN hast und überprüfen möchtest, ob sie gültig ist, musst du mehrere Schritte durchführen. Hier ist der PowerBasic-Code dafür. 💻💡


'--------------------------------------------------------------------------------
Function IBAN_ValidateByLength(ByVal U01 As String) As Long
    Local isValid As Long
    Local ibanLength As Long
    Local countryCode As String
    Local S01 As String

    ' Initialize as not valid
    isValid = 0
    S01 = IBAN_Filter(U01) ' Assuming IBAN_Filter removes spaces and invalid characters
   
    ibanLength = Len(S01)
    ' Ensure IBAN length is within the valid range globally
    If ibanLength < 15 Or ibanLength > 34 Then
      ' IBAN is automatically invalid if it doesn't meet the global length criteria
      GoTo enx   
    End If
   
    ' Extract country code to determine the specific length requirement
    countryCode = Left$(S01, 2)   

    ' Validation based on country code and respective IBAN length
    Select Case countryCode
        ' Adding Germany (DE) with correct IBAN length of 22
        Case "DE": If ibanLength = 22 Then isValid = 1 ' Germany
        Case "NO": If ibanLength = 15 Then isValid = 1 ' Norway
        Case "BE", "DK", "FI", "NL": If ibanLength = 18 Then isValid = 1 ' Belgium, Denmark, Finland, Netherlands
        Case "SI": If ibanLength = 19 Then isValid = 1 ' Slovenia
        Case "AT", "EE", "LT", "LU": If ibanLength = 20 Then isValid = 1 ' Austria, Estonia, Lithuania, Luxembourg
        ' Groups of countries sharing the same IBAN length are combined for efficiency
        Case "CH", "CR", "CV", "CY", "LI", "LV", "MC", "ME", "SM", "ST", "VA": If ibanLength = 21 Then isValid = 1
        Case "AD", "AE", "AL", "AZ", "BA", "BH", "DO", "GB", "GE", "GI", "IL", "IQ", "IS", "IT", "JO", "KW", "KZ", "LB", "MD", "MK", "MR", "MT", "MU", "PK", "PS", "QA", "RS", "SA", "SC", "SE", "TR", "VG"
              If ibanLength = 22 Then isValid = 1     
        Case Else
            isValid = 0 ' Country code not recognized or handled explicitly                         
    End Select
    enx:
    Function = isValid
End Function

'--------------------------------------------------------------------------------------------------------
$IBAN_Valid="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Function IBAN_Filter(ByRef U01  As String) As String
  G_S02
  S01=Trim$(UCase$(U01))
  S02=Retain$(S01,Any $IBAN_Valid)
  Function=S02
End Function 
'--------------------------------------------------------------------------------------------------------
Function IBAN_Validate_Numeric(ByVal iban As String) As Long
    Register i As Long
    Local ibanNumeric As String
    Local countryCode As String
    Local ibanCheckDigits As String
    Register remainder As Long   
    Local T01, isValid As Long
    Local S01 As String
   
    ibanNumeric = IBAN_Filter(iban)
   
    ' Extract the country code and check digits
    countryCode = Left$(ibanNumeric, 2)
    ibanCheckDigits = Mid$(ibanNumeric, 3, 2)
   
    ' Move the country code and check digits to the end of the IBAN
    ibanNumeric = Mid$(ibanNumeric, 5) & countryCode & ibanCheckDigits
   
    ' Replace each letter in the IBAN with its corresponding numeric value (A=10, B=11, ..., Z=35)
    T01 = Len(ibanNumeric)
    S01 = ""
    For i = 1 To T01
        Dim ch As String
        ch = Mid$(ibanNumeric, i, 1)
        If ch >= "A" And ch <= "Z" Then
            S01 = S01 & Format$(Asc(ch) - 55)
        Else
            S01 = S01 & ch
        End If
    Next i
   
    ' The modulo 97 operation for a very long number is complex and cannot be done directly.
    ' A correct implementation would need to process the number in chunks.
    ' Here, we'll pretend there's a function called Mod97ForLargeNumber that correctly handles this.
    ' This is a placeholder for an actual implementation.
    remainder = Mod97ForLargeNumber(S01)
   
    ' If the remainder is 1, the IBAN is valid
    isValid = IIF(remainder = 1, 1, 0)
   
    ' Return the validity flag
    Function = isValid
End Function
'--------------------------------------------------------------------------------------------------------
Function Mod97ForLargeNumber(ByVal ibanNumeric As String) As Long
    Local tempNum As String
    Local remainder As Long
    Local i As Long

    ' Initial remainder is 0
    remainder = 0

    ' Process the string in chunks
    For i = 1 To Len(ibanNumeric) Step 9 ' Process in chunks of 9 digits to avoid overflow
        ' Extract up to 9 digits, taking into account the current remainder
        tempNum = Str$(remainder) & Mid$(ibanNumeric, i, 9)
       
        ' Convert the chunk into a number and find its remainder when divided by 97
        remainder = Val(tempNum) Mod 97
    Next i

    ' The final remainder is the result of the modulo 97 operation for the entire number
    Function = remainder
End Function

'--------------------------------------------------------------------------------------------------------

Function Check_IBAN(ByRef U01 As String) As Long
   G_REG
   G_S01   
   S01=IBAN_Filter(U01)
   R01=IBAN_Validate_Numeric(S01)
   If  R01=0 Then GoTo enx
   R01=IBAN_ValidateByLength(S01)
   If R01 Then R01=1
enx:
    Function = R01
End Function
'--------------------------------------------------------------------------------------------------------