MarkoD
MarkoD

Reputation: 37

Check unique number

I need to check JMBG (unique number of citizenship in my country). It has 13 numbers and is calculated by the following code. The function returns that my JMBG is wrong. Perhaps somewhere in code I did wrong calculations.

Here is an example. Real life JMBG is 0805988212987 and this function returns wrong month.

Function Check_JMBG(JMBG As String) As String

' Function returns message with notification of JMBG validation
' JMBG has 13 numbers and can be treated like this when checking it DD.MM.GGG.OO.BBB.K
' Details of JMBG (unique citizenship number in my country, is 13 by the way):

'DD - day of birth
'MM - manth of birth
'GGG - last 3 numbers of year of birth, starting from (1)899. year
'OO - municipality birth code
'BBB - serial number of birth person. Man from 001-499, woman from 501-999
'K - control number, modulo 11

Dim size As Integer, sum As Integer
Dim number(1 To 13) As Integer
Dim day As Integer, manth As Integer, year As String

size = Len(JMBG)
day = Int(Left(JMBG, 2))
manth = Int(Mid$(JMBG, 3, 2))
year = Mid$(JMBG, 5, 3)

' Size check
If (size <> 13) Then
  Check_JMBG = "ERR: size of JMBG is not 13!"
End If

'Date check
If day < 1 Then
  Check_JMBG = "ERR: date entered is wrong!"
  Exit Function
End If

'Manth check and date inside manth
Select Case manth
  Case 1, 3, 5, 7, 8, 10, 12
    If day > 31 Then
      Check_JMBG = "ERR: date number is wrong!"
      Exit Function
    End If
  Case 4, 6, 9, 11
    If day > 30 Then
      Check_JMBG = "ERR: data number is wrong!"
      Exit Function
    End If
  Case 2
    If ((year Mod 4 = 0) And day > 29) Or _
       ((year Mod 4 <> 0) And day > 28) Then
      Check_JMBG = "ERR: date number is wrong!"
      Exit Function
    End If
  Case Else
    Check_JMBG = "ERR: manth number is wrong!"
    Exit Function
End Select

'Check year: from 1899 till today
If (year > Right(str(Year(Now)), 3)) And (year < "899") Then
  Check_JMBG = "ERR: year number is wrong!"
  Exit Function
End If

'Control number check
For i = 1 To 13
  number(i) = Int(Mid$(JMBG, i, 1))
Next i

sum = number(13) + number(1) * 7 + number(2) * 6
sum = sum + number(3) * 5 + number(4) * 4
sum = sum + number(5) * 3 + number(6) * 2
sum = sum + number(7) * 7 + number(8) * 6
sum = sum + number(9) * 5 + number(10) * 4
sum = sum + number(11) * 3 + number(12) * 2

If (sum Mod 11) <> 0 Then
  Check_JMBG = "ERR: wrong control number!"
Else
  Check_JMBG = "JMBG is correct"
End If

End Function

Upvotes: 0

Views: 935

Answers (2)

Peter Albert
Peter Albert

Reputation: 17475

I ran your code and it works fine for the month. I got a compile error, as you use the same name for the variable year and the VBA function - once I replaced it with strYear this also works.

Take a look at the refactored code below and see if this fixes your problem:

Function Check_JMBG(JMBG As String) As String
    If (Len(JMBG) <> 13) Then
        Check_JMBG = "ERR: Length of JMBG is not 13!"
    ElseIf Not IsNumeric(JMBG) Then
        Check_JMBG = "ERR: JMBG contains non-numerical characters"
    ElseIf Not fctBlnCheckDate(JMBG) Then
        Check_JMBG = "ERR: Wrong date entered!"
    ElseIf fctBlnCheckSum(JMBG) Then
        Check_JMBG = "ERR: Wrong checksum!"
    Else
        Check_JMBG = "JMBG is correct"
    End If
End Function

Private Function fctBlnCheckDate(JMBG As String) As Boolean
    Dim intDay As Integer, intMonth As Integer, intYear As Integer
    Dim datCheck As Date

    intDay = Int(Left(JMBG, 2))
    intMonth = Int(Mid$(JMBG, 3, 2))
    intYear = Int(Mid$(JMBG, 5, 3)) + 1000

    datCheck = DateSerial(intYear, intMonth, intDay)

    fctBlnCheckDate = _
        (year(datCheck) = intYear) And _
        (Month(datCheck) = intMonth) And _
        (day(datCheck) = intDay)

End Function

Private Function fctBlnCheckSum(JMBG As String) As Boolean
    Dim intCheckSum As Integer, i As Integer

    For i = 1 To 13
        intCheckSum = intCheckSum + Int(Mid$(JMBG, i, 1)) * (IIf(i < 7, 8, 14) - i)
    Next 
    fctBlnCheckSum = (intCheckSum Mod 11) <> 0 
End Function

Upvotes: 1

SeanC
SeanC

Reputation: 15923

Your function is expecting a string, and you are passing a number. As you do not exit the function after the size check, you are not picking up the error.

=Check_JMBG(805988212987) gives the error manth is wrong

=Check_JMBG("0805988212987") gives message JMBG is correct

formatting makes a difference

note the green triangle in the upper left of cell A1... That means I have entered the number as text by including a ' (single quote) beefore the number.

You can alter your test slightly to cover the missing zeros. - right after you get the size, and before you extract the day,month and year, put this code:

If (size <> 13) Then
    'add leading zeros
    JMBG = String(13 - size, "0") & JMBG
End If

Full code:

Function Check_JMBG(JMBG As String) As String

' Function returns message with notification of JMBG validation
' JMBG has 13 numbers and can be treated like this when checking it DD.MM.GGG.OO.BBB.K
' Details of JMBG (unique citizenship number in my country, is 13 by the way):

'DD - day of birth
'MM - manth of birth
'GGG - last 3 numbers of strYear of brith, starting from (1)899. strYear
'OO - municipality birth code
'BBB - serial number of birth person. Man from 001-499, woman from 501-999
'K - control number, modulo 11

Dim size As Integer, sum As Integer
Dim number(1 To 13) As Integer
Dim day As Integer, manth As Integer, strYear As String

size = Len(JMBG)

' Size check
If (size <> 13) Then
  JMBG = String(13 - size, "0") & JMBG
End If

day = Int(Left(JMBG, 2))
manth = Int(Mid$(JMBG, 3, 2))
strYear = Mid$(JMBG, 5, 3)

'Date check
If day < 1 Then
  Check_JMBG = "ERR: date entered is wrong!"
  Exit Function
End If

'Manth check and date inside manth
Select Case manth
  Case 1, 3, 5, 7, 8, 10, 12
    If day > 31 Then
      Check_JMBG = "ERR: date number is wrong!"
      Exit Function
    End If
  Case 4, 6, 9, 11
    If day > 30 Then
      Check_JMBG = "ERR: data number is wrong!"
      Exit Function
    End If
  Case 2
    If ((strYear Mod 4 = 0) And day > 29) Or _
       ((strYear Mod 4 <> 0) And day > 28) Then
      Check_JMBG = "ERR: date number is wrong!"
      Exit Function
    End If
  Case Else
    Check_JMBG = "ERR: month number is wrong!"
    Exit Function
End Select

'Check strYear: from 1899 till today
If (strYear > Right(str(Year(Now)), 3)) And (strYear < "899") Then
  Check_JMBG = "ERR: strYear number is wrong!"
  Exit Function
End If

'Control number check
For i = 1 To 13
  number(i) = Int(Mid$(JMBG, i, 1))
Next i

sum = number(13) + number(1) * 7 + number(2) * 6
sum = sum + number(3) * 5 + number(4) * 4
sum = sum + number(5) * 3 + number(6) * 2
sum = sum + number(7) * 7 + number(8) * 6
sum = sum + number(9) * 5 + number(10) * 4
sum = sum + number(11) * 3 + number(12) * 2

If (sum Mod 11) <> 0 Then
  Check_JMBG = "ERR: wrong control number!"
Else
  Check_JMBG = "JMBG is correct"
End If

End Function

Upvotes: 1

Related Questions