Newsgroup: it.comp.lang.visual-basic
Titolo: Calcolo CIN

ciao a tutti,
sapete per caso dove reperire il codice per il calcolo del CIN, avengo già
Abi, Cab e C/C ?
Grazie.

Ciao, quella di seguito e la funzione che ti ricava il cin.
Saluti
Riccardo Cancani
Public Function RicavaCin(ByVal sAbi As String, ByVal sCab As String, ByVal
sCC As String) As String
'parametri in entrata:
'sAbi  =abi
'sCab = cab
'sCC=numero di conto corrente
'Parametro in uscita: numero cin
    If Trim(sCab) = "" Or Trim(sAbi) = "" Or Trim(sCC) = "" Then
        RicavaCin = ""
        Exit Function
    ElseIf ((Len(Trim(sAbi)) < 5) Or (Len(Trim(sCab)) < 5)) Then
        RicavaCin = ""
        Exit Function
    End If
    Dim c_pari(28) As String
    Dim c_dispari(28) As String
    Dim n_dispari(22) As String
    Dim conv(9)
    c_pari(0) = "A"
    c_pari(1) = "B"
    c_pari(2) = "C"
    c_pari(3) = "D"
    c_pari(4) = "E"
    c_pari(5) = "F"
    c_pari(6) = "G"
    c_pari(7) = "H"
    c_pari(8) = "I"
    c_pari(9) = "J"
    c_pari(10) = "K"
    c_pari(11) = "L"
    c_pari(12) = "M"
    c_pari(13) = "N"
    c_pari(14) = "O"
    c_pari(15) = "P"
    c_pari(16) = "Q"
    c_pari(17) = "R"
    c_pari(18) = "S"
    c_pari(19) = "T"
    c_pari(20) = "U"
    c_pari(21) = "V"
    c_pari(22) = "W"
    c_pari(23) = "X"
    c_pari(24) = "Y"
    c_pari(25) = "Z"
    c_pari(26) = "-"
    c_pari(27) = "."
    c_pari(28) = " "
    c_dispari(0) = "B"
    c_dispari(1) = "A"
    c_dispari(5) = "C"
    c_dispari(7) = "D"
    c_dispari(9) = "E"
    c_dispari(13) = "F"
    c_dispari(15) = "G"
    c_dispari(17) = "H"
    c_dispari(19) = "I"
    c_dispari(21) = "J"
    c_dispari(2) = "K"
    c_dispari(4) = "L"
    c_dispari(18) = "M"
    c_dispari(20) = "N"
    c_dispari(11) = "O"
    c_dispari(3) = "P"
    c_dispari(6) = "Q"
    c_dispari(8) = "R"
    c_dispari(12) = "S"
    c_dispari(14) = "T"
    c_dispari(16) = "U"
    c_dispari(10) = "V"
    c_dispari(22) = "W"
    c_dispari(25) = "X"
    c_dispari(24) = "Y"
    c_dispari(23) = "Z"
    c_dispari(27) = "-"
    c_dispari(28) = "."
    c_dispari(26) = " "
    n_dispari(1) = "0"
    n_dispari(0) = "1"
    n_dispari(5) = "2"
    n_dispari(7) = "3"
    n_dispari(9) = "4"
    n_dispari(13) = "5"
    n_dispari(15) = "6"
    n_dispari(17) = "7"
    n_dispari(19) = "8"
    n_dispari(21) = "9"
    conv(0) = "0"
    conv(1) = "1"
    conv(2) = "2"
    conv(3) = "3"
    conv(4) = "4"
    conv(5) = "5"
    conv(6) = "6"
    conv(7) = "7"
    conv(8) = "8"
    conv(9) = "9"
    Dim i As Integer
    Dim j As Integer
    Dim trovato
    Dim cont As Integer
    i = 1
    Dim totale As Integer
    Dim car As String
    totale = 0
    Dim tutto As String
    Dim zeri As Integer
    If (Len(cont) < 12) Then
        zeri = 12 - Len(cont)
        zeri = String(zeri, "0")
    End If
    tutto = sAbi + sCab + zeri + cont
    Do While (i <= Len(tutto))
        car = Mid(tutto, i, 1)
        car = UCase(car)
        If (i Mod 2 = 0) Then
            j = 0
            trovato = 0
            Do While (trovato = 0) And (j <= 9)
                If (car = conv(j)) Then
                            totale = totale + j
                            trovato = 1
                End If
                j = j + 1
            Loop
            If (trovato = 0) Then
                j = 0
                Do While (trovato <> 1) And (j <= 28)
                    If (car = c_pari(j)) Then
                            totale = totale + j
                            trovato = 1
                    End If
                    j = j + 1
                Loop
            End If
        Else
            j = 1
            trovato = 0
            Do While ((trovato <> 1) And (j < 21))
                If (car = n_dispari(j)) Then
                            totale = totale + j
                            trovato = 1
                End If
                j = j + 1
            Loop
            If (trovato = 0) Then
                j = 1
                Do While (trovato <> 1) And (j <= 28)
                    If (car = c_dispari(j)) Then
                            totale = totale + j
                            trovato = 1
                    End If
                    j = j + 1
                Loop
            End If
        End If
        i = i + 1
    Loop
    totale = totale Mod 26
    RicavaCin = c_pari(totale)
End Function

innanzitutto grazie del codice,
l'ho provato con alcuni C/C di banche diverse che avevo a disposizione ma
... mi risultano tutti diversi.
non è che per caso ogni banca utilizza un suo standard ?
grazie.

 Ciao, quella di seguito e la funzione che ti ricava il cin.
Interessava anche a me, ma non funziona (ho provato su un paio di banche).
Potresti, anche per verificare se la funzione è correttamente implementata,
citare un link dal quale si deduce la regola ufficiale? Grazie.

     tutto = sAbi + sCab + zeri + cont
Non entro nel merito della logica, ma questo passaggio può essere
migliorato:
     tutto = sAbi & sCab & zeri & cont
Ciao
Alberto

Ma io lo utilizzo da parecchio e va senza problemi.
Di certo puo essere migliorato ma e comunque una base da cui partire.
Per il link ecco la base da cui sono partito
http://it.geocities.com/arodichevski/comp-bban-it.html

 ha scritto:

Attenzione però.
Ho ricevuto notizie dalla sotware house che produce un gestionale a livello
nazionale (ESATTO2004 ndr)  che capita che alcune banche generino dei CIN
diversi rispetto all'algoritmo base. In questi casi fa fede comunque il CIN
generato dalla banca "proprietaria" del C/C
Ciao Gab

 Ciao Gab
č proprio quello che avevo sentito io.
ho provato il codice di Riccardo, ma non ho trovato riscontro con delle
pratiche compilate manualmente dai nostri dipendenti.
non so che fare quindi.
mi devo inesrire a mano il cin di circa 2500 dipendenti ?
boh !!!

 generino dei CIN diversi rispetto all'algoritmo base.
ehm... siamo sicuri di questo?
una affermazione del genere equivale a dire che il cin è cacca, anzi, meno.
--
Salutoni
Sergio
per rispondere... togli il group dall'indirizzo

 meno.
Giusto, specialmente se l'affermazione deriva da un algoritmo mal
implementato.
Non entro nel merito della validità dello stesso che (come può accadere per
il codice fiscale) può avere (può, non so se ha) qualche eccezione (come
ogni regola che si rispetti), ma, come da altri segnalato, la routine di
Riccardo non rispetta le regole di quanto riportato nel link da lui
riportato).
Ecco la mia versione che, per quelle poche prove fatte, funziona (posso
aggiungere anche un "porca pupattola"?):
abi, cab e conto sono dei textbox, btn_calcola un bottone:
Private Sub Form_Load()
    abi = ""
    cab = ""
    conto = ""
End Sub
Private Sub btn_calcola_Click()
    risultato = RICAVA_CIN(abi, cab, conto, errore_restituito)
    Select Case errore_restituito
        Case 0
            Call MsgBox("CIN = " & risultato & vbCrLf & "BBAN = " &
risultato & UCase(abi) & UCase(cab) & UCase(conto), vbOKOnly)
        Case 1
            Call MsgBox("Qualche campo non ha la lunghezza richiesta",
vbOKOnly + vbExclamation)
        Case 2
            Call MsgBox("Nelle posizioni 1>5 (ABI), 6>10 (CAB) sono ammesse
solo cifre", vbOKOnly + vbExclamation)
        Case 3
            Call MsgBox("Carattere diverso da 0-9, A-Z non ammesso",
vbOKOnly + vbExclamation)
    End Select
    abi.SetFocus
End Sub
Function RICAVA_CIN(abi, cab, conto, Optional errore_restituito = 0)
'errore_restituito  Se <>0  Indica il codice d'errore e RICAVA_CIN sara' =""
'                               1   Qualche campo non ha la lunghezza
richiesta
'                               2   Nelle posizioni 1>5 (ABI), 6>10 (CAB)
sono ammesse solo cifre
'                               3   Carattere diverso da 0-9, A-Z non
ammesso
    RICAVA_CIN = ""
    errore_restituito = 0
    If Len(abi) <> 5 Or Len(cab) <> 5 Or Len(conto) <> 12 Then
        errore_restituito = 1
        Exit Function
    End If
    stringa = UCase(abi) & UCase(cab) & UCase(conto)    '(5+5+12)=22
caratteri
    ReDim vn(1 To Len(stringa))
    vndispari = Array(1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11,
3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23)
    totale = 0
    For n = 1 To Len(stringa)
        crt = Mid(stringa, n, 1)
        Select Case crt
            Case "0" To "9"
                vn(n) = Val(crt)
            Case "A" To "Z"
                If n < 11 Then
                    errore_restituito = 2
                    Exit Function
                End If
                vn(n) = Asc(crt) - Asc("A")
            Case Else
                errore_restituito = 3
                Exit Function
        End Select
        If (n Mod 2) Then
'               Dispari
            totale = totale + vndispari(vn(n))
        Else
'               Pari
            totale = totale + vn(n)
        End If
    Next n
    RICAVA_CIN = Chr((totale Mod 26) + Asc("A"))
End Function

 meno.
Anche a me sembra follia, ma sembra sia proprio così. PS se hai avuto a che
fare con le banche (a livello informatico) non è una sorpresa
Ciao Gab

 il codice fiscale) può avere (può, non so se ha) qualche eccezione
credo che le uniche eccezioni del codice fiscale riguardino la costruzione
dello stesso, non il calcolo del carattere di controllo, se no il carattere
stesso perderebbe di significato.
un po' quello che pare capitare al cin, direi.
anzi, la sigla non ti suggerisce nulla? ;-)


 anzi, la sigla non ti suggerisce nulla? ;-)
Infatti..., anche se, perdonate la ripetizione, la routine di Riccardo è
errata.
Aggiungo, per chiarezza e completezza (un po' ribadendo quanto detto da te)
che il link citato da Riccardo indica come stabilire se un CIN è corretto,
non di come lo si determina. Le cose, anche informaticamente parlando, sono
(o possono essere) molto diverse. La prima dovrebbe essere sempre vera, la
seconda può andare di culo, nel senso che un CIN può (di nuovo, non ho
testato tutti i casi possibili) risultare valido anche se diverso da quello
che verrebbe ottenuto interpretando il metodo di validazione per ricavarne
quello di ottenimento.
In altre parole, se una regola di controllo dice (sto inventando) che un
numero deve essere dispari, 1,3,5,7,9, etc. sono dispari e quindi validi,
non per questo quello ricavabile è univocamente 1 oppure 9, oppure...

 a che fare con le banche (a livello informatico) non è una sorpresa
no, ne ho a che fare solo dal punto di vista finanziario, e tanto mi basta e
superchia.
comunque, se questi sono i loro standard, mi stupisco del fatto che non mi
siano ancora spariti dei soldi sul cc. (spariti inspiegabilmente, intendo.
tutte le sottrazioni effettuate dalla banca sono ampiamente spiegate, anche
se talvolta la loro logica mi sfugge: di fatto siamo arrivati a dover pagare
per tenere i soldi in banca. non pagare le singole operazioni, cosa che
sarebbe anche comprensibile, ma proprio un canone mensile)


 ha scritto nel messaggio
news:c0d9b1$15oj2t$1...@ID-174464.news.uni-berlin.de...


 ha scritto nel messaggio
news:Z96Wb.32939$VS6....@tornado.fastwebnet.it...


 >
ciao,
io non so cosa sia il codice IBAN, ma se può essere utile in un futuro .....
posta pure.
e grazie ancora a tutti.

 futuro ..... posta pure.
abi, cab, conto e stato sono dei textbox, btn_calcola un bottone:
Private Sub Form_Load()
    abi = ""
    cab = ""
    conto = ""
    stato = "IT"
    stato.Enabled = 0
End Sub
Private Sub btn_calcola_Click()
    risultato = RICAVA_CIN(abi, cab, conto, errore_restituito, stato, iban)
    Select Case errore_restituito
        Case 0, 4
            comodo = ""
            If risultato <> "" Then
                comodo = "CIN" & vbTab & risultato & vbCrLf & "BBAN" & vbTab
& risultato & UCase(abi) & UCase(cab) & UCase(conto)
            End If
            If stato <> "" Then
                comodo = comodo & IIf(comodo = "", "", vbCrLf) & "IBAN" &
vbTab
                If errore_restituito = 4 Then
                    comodo = comodo & "Stato diverso da 2 caratteri e/o
carattere non ammesso"
                Else
                    If iban <> "" Then comodo = comodo & Left(iban, 4) &
Space(1) & Mid(iban, 5)
                End If
            End If
            Call MsgBox(comodo, vbOKOnly)
        Case 1
            Call MsgBox("Qualche campo non ha la lunghezza richiesta",
vbOKOnly + vbExclamation)
        Case 2
            Call MsgBox("Nelle posizioni 1>5 (ABI), 6>10 (CAB) sono ammesse
solo cifre", vbOKOnly + vbExclamation)
        Case 3
            Call MsgBox("Carattere diverso da 0-9, A-Z non ammesso",
vbOKOnly + vbExclamation)
    End Select
    abi.SetFocus
End Sub
Function RICAVA_CIN(abi, cab, conto, Optional errore_restituito = 0,
Optional stato = "", Optional iban = "")
'errore_restituito  Se <>0  Indica il codice d'errore e RICAVA_CIN sara' =""
'                               1   Qualche campo non ha la lunghezza
richiesta
'                               2   Nelle posizioni 1>5 (ABI), 6>10 (CAB)
sono ammesse solo cifre
'                               3   Carattere diverso da 0-9, A-Z non
ammesso
'                               4   Stato diverso da "" e diverso da 2
caratteri e/o crt non ammessi
'                                       RICAVA_CIN viene comunque
restituito,
'                                       se non vi sono altri errori che lo
impediscono.
'stato              Se passato e ="IT", verra' calcolato anche l'IBAN per
l'Italia (restituito in iban)
'Informazioni da:   
http://it.geocities.com/arodichevski/comp-bban-it.html
'
http://it.geocities.com/arodichevski/comp-iban-it.html
    RICAVA_CIN = ""
    errore_restituito = 0
    iban = ""
    If Len(abi) <> 5 Or Len(cab) <> 5 Or Len(conto) <> 12 Then
        errore_restituito = 1
        Exit Function
    End If
    bban_senza_cin = UCase(abi) & UCase(cab) & UCase(conto)     '(5+5+12)=22
caratteri
    ReDim vn(1 To Len(bban_senza_cin))
    vndispari = Array(1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11,
3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23)
    totale = 0
    For n = 1 To Len(bban_senza_cin)
        crt = Mid(bban_senza_cin, n, 1)
        Select Case crt
            Case "0" To "9"
                vn(n) = Val(crt)
            Case "A" To "Z"
                If n < 11 Then
                    errore_restituito = 2
                    Exit Function
                End If
                vn(n) = Asc(crt) - Asc("A")
            Case Else
                errore_restituito = 3
                Exit Function
        End Select
        If (n Mod 2) Then
'               Dispari
            totale = totale + vndispari(vn(n))
        Else
'               Pari
            totale = totale + vn(n)
        End If
    Next n
    cin = Chr((totale Mod 26) + Asc("A"))
    RICAVA_CIN = cin
    If stato <> "" Then
'           Calcola anche IBAN (Italia)
'--------------------------------------
        If Len(stato) <> 2 Then
            errore_restituito = 4
            Exit Function
        End If
        If UCase(stato) = "IT" Then
'               Applica l'algoritmo per l'Italia (non conosco quello per
altri stati)
            iban = UCase(stato) & "00" & cin & bban_senza_cin
'(2+2+1+22)=27 caratteri
'               Sposta in coda stato e codice controllo
            iban_inv = Mid(iban, 5) & Left(iban, 4)
            stringa_numerica = ""
            For n = 1 To Len(iban_inv)
                crt = Mid(iban_inv, n, 1)
                Select Case crt
                    Case "0" To "9"
                        stringa_numerica = stringa_numerica & crt
                    Case "A" To "Z"
                        stringa_numerica = stringa_numerica &
Trim(CStr(Asc(crt) - Asc("A") + 10))
                End Select
            Next n
            resto_precedente = 0
            For n = 1 To Len(stringa_numerica) Step 5
                parte_stringa_numerica = Trim(CStr(resto_precedente)) &
Mid(stringa_numerica, n, 5)
                resto_precedente = (Val(parte_stringa_numerica) Mod 97)
            Next n
            Mid(iban, 3, 2) = Right(100 + ((98 - resto_precedente) Mod 97),
2)
        End If
    End If
End Function

 se no il carattere stesso perderebbe di significato.
In realtà le eccezioni esistono.
Tant'è che alcuni software mal fatti, che testano il CF e impediscono di
confermare un CF diverso da quello calcolato, creano a queste poche persone
una miriade di casini.
In effetti, se si considera che tutti i caratteri del CF, tranne l'ultimo,
sono parlanti, è evidente che possono esserci casi particolari.
Due persone nate lo stesso giorno, nello stesso comune, con lo stesso nome
(e in certe zone dove pochi cognomi sono molto diffusi, è tutt'altro che
impossibile), avranno lo stesso CF a meno dell'ultimo carattere, che viene
modificato forzatamente dall'ente emettitore, sul secondo che lo chiede.
Ricordo una collega, qualche anno fa, che non poteva ricevere lo stipendio
via bonifico, perchè il software dell'azienda non accettava la sua
anagrafica.
Ciao
Alberto

 In realtà le eccezioni esistono.
cerco di spiegarmi meglio...
le eccezioni di cui parli, riguardano il metodo per ricavare i primi
quindici caratteri del codice, a partire dal cognome, nome, data e luogo di
nascita. come dici tu, per evitare "omocodie", il ministero delle finanze
(ora delle entrate, mi pare :-) ) si prende la briga di cambiare qualche
lettera.
una volta stabiliti i primi quindici caratteri, il sedicesimo è rigidamente
stabilito, senza eccezione alcuna, se no verrebbe a cadere la sua funzione
di carattere di controllo.
dato che il cin, per quanto ho capito, è proprio un carattere di controllo,
mi sembra impossibile che diverse banche lo calcolino in modo diverso.
sono riuscito a spiegarmi?


 sono riuscito a spiegarmi?
Sì, mi sono capito. A me risultava che cambiassero il sedicesimo. Ma non
insisto. L'importante è che sia chiaro che un buon sw deve segnalare, ma
comunque accettare, anche CF diversi da quelli calcolati.
Anche a me sembra impossibile che il CIN sia 'personalizzabile', visto che
già la combinazione di Abi, Cab e CC dovrebbe essere univoca, quindi il CIN
non dovrebbe avere funzione di anti-alias.
Ciao
Alberto

 non insisto.
io, invece, sì
http://www.agenziaentrate.it/servizi/duplicatocf/algoritmo_calcolo_cf.htm
dalla lettura del quale si evince che ho indubitabilmente ragione
cica cica cica uno a zero per me :-)


 cica cica cica uno a zero per me :-)
Perchè non sei laziale.
Altrimenti sarebbe 4-0
Ciao
Alberto
PS: stanotte sono passato vicino a casa tua. Ma quando parli del lago,
intendi Garda o Iseo?
Ciao
Alberto

 intendi Garda o Iseo?
grande fonte di equivoci :-)
a brescia, tutti, parlano indistintamente del lago, senza mai specificare a
quale si riferiscono. oddio, se intendono il lago d'idro, il più delle volte
precisano; ma nessun indizio può indicarti se intendono garda o iseo. il più
delle volte si riferiscono al più vicino al loro domicilio, ma non è detto,
e comunque, per ciascuno di loro, esiste un solo lago degno di tal nome,
essendo l'altro a malapena degno di essere citato sulle cartine geografiche,
ma più per amore di completezza che per altro.
i fan del garda sostengono che il sebino sia una piccola poccia buia e
maleodorante, i patiti dell'iseo ritengono che il benaco sia una bolgia
caotica ed invivibile.
non mio caso, per provenienza familiare, faccio parte dei gardesani: madre
di padenghe, padre di maderno e estesi possedimenti terrieri solle colline
circostanti.
anzi, se questa estate non riesci ad andare sul befirst, vieni pure da me
per un qualche we.
