Bom eu não tenho conhecimento quase algum de Delphi, mas vendo a lógica foi fácil montar em xBase. Só que fiz para que aceitasse desde a linha de comando. Observem que tem duas funções de validação, uma com o código novo (até 9 dígitos e 2 verificadores) e para código antigo (8 dígitos e 1 verificador, o chamado de PGU - Prontuário Geral Único). Acho que a difrenciação pelo DETRAN é dado por: "Carteira com foto e sem foto".
Código: Selecionar todos
PARAMETERS xCnh
IF xCnh=NIL
? "Falta parƒmetro"
QUIT
ELSE
nCnh:=VAL(xCnh)
ENDIF
IF valida_new_cnh(nCnh) .or. valida_old_cnh(nCnh)
? "CNH OK"
ELSE
? "CNH INCORRETO"
ENDIF
function valida_new_cnh(nCnh)
Result := .F.
NumIguais := .T.
cCnh := strzero(nCnh,11,0)
Soma := 0
// Validando se todos o numeros sao iguais
for i := 2 to len(cCnh)-1
if !(substr(cCnh,1,1) = substr(cCnh,i,1))
NumIguais := .F.
endif
next
if NumIguais
RETURN Result
endif
for i := 1 to len(cCnh)-2
Soma := Soma + (val(substr(cCnh,i,1)) * (i + 1))
next
Conta := (Soma / 11) * 11
if (Soma - Conta) < 2
Dv := 0
else
Dv := 11 - (Soma - Conta)
endif
Digito := val(substr(cCnh,10,1))
if Digito = Dv
Result := .T.
endif
RETURN Result
function valida_old_cnh(nCnh)
Result := .F.
NumIguais := .T.
cCnh := strzero(nCnh,9,0)
Soma := 0
// Validando se todos o numeros sao iguais
for i := 2 to len(cCnh)-1
if !(substr(cCnh,1,1) = substr(cCnh,i,1))
NumIguais := .F.
endif
next
if NumIguais
RETURN Result
endif
for i := 1 to len(cCnh)-1
Soma := Soma + (val(substr(cCnh,i,1)) * (i + 1))
next
Digito := val(substr(cCnh,9,1))
Conta := mod(Soma,11)
if Conta = 10
Conta := 0
endif
if Digito = Conta
result := .T.
endif
RETURN result
Eu testei e funcionou, não tenho total certeza quanto ao
StrToInt(CnhN[10]) se está pegando o caracter da posição 10 ou apartir da posição 10 (seria os caracteres de posição 10 e 11). Cabe testar e mudar no caso. Talvez o Maligno consiga nos dizer algo...