Validar CPF e CNPJ

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

ederxc
Usuário Nível 4
Usuário Nível 4
Mensagens: 619
Registrado em: 15 Set 2006 08:40
Localização: Pedreira -SP-

Validar CPF e CNPJ

Mensagem por ederxc »

vlw galera !
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Validar CPF e CNPJ

Mensagem por Maligno »

Apenas um detalhe: pelo que pude perceber, essas funções não verificam se a variável contém apenas zeros (00.000.000/0000-00). Esse valor, se não checado, passa no cálculo, o que é um erro. Minha função:

Código: Selecionar todos

function ValidCNPJ(cCNPJ)
local cDigs := ""
local nSTot := 0
local d,i,k := 1
local lRet
*
if (lRet := Len(cCNPJ) = 14 .and. Val(cCNPJ) > 0)
   for d := 1 to 2
       for i := 11+d to 1 step -1
           nStot += Val(SubStr(cCNPJ,i,1)) * (k += if(k=9, -7, 1))
       next
       cDigs += Str(if((nSTot %= 11) < 2, 0, 11-nStot),1)
       nSTot := 0
       k     := 1
   next
   lRet := cDigs = Right(cCNPJ,2)
end
return lRet
Além do que, as duas funções tem o que eu acho que é uma falha: além de validar, também dão um sinal de alerta. Pode não importar pra muita gente, mas a forma mais correta, e por correto entenda-se: mais flexível e seguro, é manter uma função executando apenas uma função. É o tipo de programação chamado de "black box". É fácil de perceber que, se amanhã ou depois, a interface criada for indesejável, essa "caixa preta" terá de ser reaberta. Numa função simples como essa, não causaria maiores transtornos, mas quando a função tem algumas centenas de linhas e/ou a interface se espalha pela função toda, a coisa começa a ficar crítica. É só uma opinião.

[]'s
Maligno
http://www.buzinello.com/prg
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Validar CPF e CNPJ

Mensagem por rochinha »

Amiguinho Maligno

Seria algo assim que deveria ser colocado no código de nossos colegas?

Código: Selecionar todos

...
@ ... GET cCNPJ ... VALID ValidCNPJ(cCNPJ)
...
Ao invés disto:

Código: Selecionar todos

if ValidCNPJ(cCNPJ)
   ? 'CGC Valido'
else
   ? 'CGC Invalido'
endif
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Validar CPF e CNPJ

Mensagem por Maligno »

Amiguinho Rochinha,

São várias situações que podem ser beneficiadas com a separação das funções. No exemplo que você postou, em minha opinião, poderia ser feito assim:

Código: Selecionar todos

@ ... GET cCNPJ ... VALID CriticaCNPJ(cCNPJ)

function CriticaCNPJ()
if !ValidCNPJ() // jamais informar com máscara
   Alert("CNPJ INVALIDO")
   Tone(100,100)
   return .f.
end
return .t.
Olhando isso, certamente você terá a impressão de que um maior volume de código terá de ser utilizado. Isso é correto e é natural. Então, qual é a vantagem?

A vantagem em separar a interface da validação está nos casos, por exemplo, em que uma interface não é necessária. Exemplo simples: eu faço importação de dados de arquivos de remessa do SINTEGRA. A inclusão é em lote. Eu jamais poderia utilizar a função dos colegas, que contém a interface. Não sem antes modificar a função, ou para remover a interface ou para inserir um parâmetro qualquer que "silencie" a função. Nesse primeiro caso, eu precisaria ter duas funções, ambas validando CNPJ (desperdício). No segundo caso, minha função de validação, que já está correta, não deveria ser modificada pra nada. É (ou deveria ser) uma "caixa preta". Não se deveria mexer em código que está testado e aprovado.

Há outros exemplos de casos em que não é desejável manter a interface com a validação. Vou citar mais um simples: inclusão de fornecedor. Ninguém quer dados redundantes. Se você colocar no seu VALID apenas o check do número pode estar deixando passar um CNPJ que já está cadastrado. Assim, obrigatoriamente, você deverá ter uma função de crítica como a que citei acima. Primeiro ela checa o número. Se válido, chega a unicidade. Se positivo, retorna TRUE e pronto. Ou seja, de qualquer maneira o código acima será necessário.

Mas há inúmeros outros casos em que esse estilo de programação modular é sempre muito melhor. Mesmo que isso signifique consumir um pouco mais de código. A vantagem de manter uma função única na sua tarefa é enorme. Você testa, comprova sua eficiência e embute numa LIB e a "esquece". Você só tem que se preocupar em saber quais são os dados de entrada e quais são os de saída. Como a coisa funciona por dentro não faz a menor diferença. Você já testou e aprovou seu funcionamento. Por isso que se chama "caixa preta". Afinal, é assim que você usa LIBs de terceiros, sem ter os fontes.
Não seria nada prático inserir as funções dos colegas em uma LIB. E se amanhã ou depois eles mudarem o estilo da interface? Vão ter que abrir a "caixa preta" e mexer no que deveria estar quieto. :)

[]'s
Maligno
http://www.buzinello.com/prg
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Validar CPF e CNPJ

Mensagem por rochinha »

Amiguinho

Estou de pleno acordo.

@braços :?)
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
Netavin
Usuário Nível 3
Usuário Nível 3
Mensagens: 306
Registrado em: 28 Fev 2007 08:37
Localização: Cacoal-RO

Validar CPF e CNPJ

Mensagem por Netavin »

Colegas do planeta Clipper, boa tarde!
Eu uso a seguinte função para validar o CNPJ (qualquer semelhança com funções dos amigos, NÃO é mera coincidência):

* function CGC(vcli_CGC) *
*********************
* separando os irmãos d¡gitos *
local dcgc[14]
If vcli_cgc=space(18)
Tone(1700,1)
alert("Obrigat¢rio CNPJ")
Set Cursor on
Return(.f.)
Endif

If (vcli_cgc) # space(18) .and. val(vcli_cgc) > 0
dcgc[01] := val( substr( vcli_CGC, 1, 1 ) )
dcgc[02] := val( substr( vcli_CGC, 2, 1 ) )
dcgc[03] := val( substr( vcli_CGC, 4, 1 ) )
dcgc[04] := val( substr( vcli_CGC, 5, 1 ) )
dcgc[05] := val( substr( vcli_CGC, 6, 1 ) )
dcgc[06] := val( substr( vcli_CGC, 8, 1 ) )
dcgc[07] := val( substr( vcli_CGC, 9, 1 ) )
dcgc[08] := val( substr( vcli_CGC, 10, 1 ) )
dcgc[09] := val( substr( vcli_CGC, 12, 1 ) )
dcgc[10] := val( substr( vcli_CGC, 13, 1 ) )
dcgc[11] := val( substr( vcli_CGC, 14, 1 ) )
dcgc[12] := val( substr( vcli_CGC, 15, 1 ) )
dcgc[13] := val( substr( vcli_CGC, 17, 1 ) )
dcgc[14] := val( substr( vcli_CGC, 18, 1 ) )
* Primeiro *
ncgcsoma := dcgc[01]*5 + dcgc[02]*4 + dcgc[03]*3 + dcgc[04]*2 + dcgc[05]*9 + dcgc[06]*8 +;
dcgc[07]*7 + dcgc[08]*6 + dcgc[09]*5 + dcgc[10]*4 + dcgc[11]*3 + dcgc[12]*2
ncgcresto := mod( ncgcsoma, 11 )

if ncgcresto = 0 .or. ncgcresto = 1
dcgcv1 := 0
else
dcgcv1 := 11 - ncgcresto
endif

if dcgcv1 # dcgc[13]
Tone(1700,1)
alert( "CNPJ Inválido!" )
Set Cursor on
return(.f.)
endif

* Segundo Digito *
ncgcsoma := dcgc[01]*6 + dcgc[02]*5 + dcgc[03]*4 + dcgc[04]*3 + dcgc[05]*2 + dcgc[06]*9 +;
dcgc[07]*8 + dcgc[08]*7 + dcgc[09]*6 + dcgc[10]*5 + dcgc[11]*4 + dcgc[12]*3 + dcgc[13]*2
ncgcresto := mod( ncgcsoma, 11 )

if ncgcresto = 0 .or. ncgcresto = 1
dcgcv2 := 0
else
dcgcv2 := 11 - ncgcresto
endif

if dcgcv2 # dcgc[14]
Tone(1700,2)
alert( "CNPJ Inválido!" )
Set Cursor on
return(.f.)
endif
Set Cursor on
return(.t.)
else
Tone(1700,1)
alert("Obrigat¢rio CNPJ")
Set Cursor on
Return(.F.)
Endif
... Porém se eu digitar 02.052.787/0001-6 (faltando o segundo dígito), ele passa pela crítica. Qual seria a solução ?
Uso variável alfanumérica no DBF, com 18 casas.
Agradeço antecipadamente.

[]´s
Netavin.
TK90 / TK95 / APPLE IIe / 286 / 386 / 486 / 586 / AMD Atlhon
" Sem saber que era impossível, foi lá e fez !! "
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Validar CPF e CNPJ

Mensagem por sygecom »

Código: Selecionar todos

*********
FUNC CNPJ
*********
aSal := savenv( 10, 02, 23, 79 ) //VL-Salva o ambiente
SET TALK OFF
SET STAT OFF
public vObsCGC:=SPACE(25)

T :=  TT :=  TTT :=  0
CCNPJ = SPACE(18)

PARTEA1 = SUBS(FCGC,1,2)  //   Divide a
PARTEA2 = SUBS(FCGC,3,3)  //   variavel
PARTEA3 = SUBS(FCGC,6,3)  //     em 5
PARTEA4 = SUBS(FCGC,9,4) //    partes
PARTEA5 = SUBS(FCGC,13,2) //    partes

CCNPJ = PARTEa1+PARTEa2+PARTEa3+PARTEa4 // Junta as 4 partes

FOR TT =  12 TO 5 STEP -1                         //
        T = T + VAL(SUBS(CCNPJ,TT,1)) * (14 - TT)  //
NEXT TT                                           //
FOR TT =  4 TO 1 STEP -1                          //
        T = T + VAL(SUBS(CCNPJ,TT,1)) * (6 - TT)   //   Processa
NEXT TT                                           //  os calculos
TT :=  T - (INT(T/11)*11)                         //     para
IF TT < 2                                         //   verificar
        TT :=  0                                  //   o primeiro
ELSE                                              //    digito
        TT :=  11 - TT                            //
ENDIF                                             //
CCNPJ =  CCNPJ + STR(TT,1) // Junta o primeiro digito com as 4 primeiras partes

T= 0 // Zera a variavel para inicio do novo calculo
FOR TT =  13 TO 6 STEP -1                         //
        T = T + VAL(SUBS(CCNPJ,TT,1)) * (15 - TT)  //
NEXT TT                                           //
FOR TT =  5 TO 1 STEP -1                          //
        T = T + VAL(SUBS(CCNPJ,TT,1)) * (7 - TT)   //    Processa
NEXT TT                                           //    o calculo
TT :=  T - (INT(T/11)*11)                         //  para verificar
IF TT < 2                                         //    o segundo
        TT :=  0                                  //     digito
ELSE                                              //
        TT :=  11 - TT                            //
ENDIF                                             //
CCNPJ =  CCNPJ + STR(TT,1) // Junta o segundo digito ao restante inicial

PARTE1 = SUBS(CCNPJ,1,2)  //
PARTE2 = SUBS(CCNPJ,3,3)  //  Divide novamente
PARTE3 = SUBS(CCNPJ,6,3)  //     a variavel
PARTE4 = SUBS(CCNPJ,9,4)  //  agora em 5 partes
PARTE5 = SUBS(CCNPJ,13,2) //
CCNPJ = PARTE1+PARTE2+PARTE3+PARTE4+PARTE5               // Monta a variavel conforme um CCNPJ verdadeiro
DO WHILE .T.
   IF CCNPJ != PARTEa1+PARTEa2+PARTEa3+PARTEa4+PARTEa5
      NOPC:= MsgBox1({"N§ do CNPJ informado esta errado!"},"Validador do CNPJ")
      vObsCGC="CNPJ Incorreto"
      FCGC=SPACE(18)
      CCNPJ=space(18)
   ELSE
      RstEnv (aSal)
      vObsCGC="CNPJ Correto"
   ENDIF
   FCGC=CCNPJ
   EXIT
ENDDO
RstEnv (aSal)
RETURN .T.
Tche, Testa ai....comigo ele nunca falhou !!!

Abraços
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Validar CPF e CNPJ

Mensagem por Maligno »

Netavin escreveu:Porém se eu digitar 02.052.787/0001-6 (faltando o segundo dígito), ele passa pela crítica. Qual seria a solução ?
Experimente uma função mais simples. Ela sempre funcionou pra mim.

Código: Selecionar todos

function ValidCNPJ(cCNPJ) 
local cDigs := "" 
local nSTot := 0 
local d,i,k := 1 
local lRet 
*
if (lRet := Len(cCNPJ) = 14 .and. Val(cCNPJ) > 0) 
   for d := 1 to 2 
       for i := 11+d to 1 step -1 
           nStot += Val(SubStr(cCNPJ,i,1))*(k += if(k=9,-7,1)) 
       next 
       cDigs += Str(if((nSTot %= 11)<2, 0, 11-nStot),1) 
       nSTot := 0 
       k     := 1 
   next 
   lRet := cDigs = Right(cCNPJ,2) 
end 
return lRet
Uso variável alfanumérica no DBF, com 18 casas.
Não é uma boa idéia armazenar os símbolos do número. É um desperdício de espaço. E nem é necessário.

[]'s
Maligno
http://www.buzinello.com/prg
Avatar do usuário
Netavin
Usuário Nível 3
Usuário Nível 3
Mensagens: 306
Registrado em: 28 Fev 2007 08:37
Localização: Cacoal-RO

Validar CPF e CNPJ

Mensagem por Netavin »

E aí colegas ? ... procurem descansar um pouco esse fim-de-semana.
.. Caros Malígno e Syge: relutei até hoje em retornar a esse assunto da crítica do CNPJ. Eu estava com vergonha de pedir de novo vossa ajuda. Mas o máximo que poderia acontecer é vocês me tirarem uma né !! É que durante todos esses dias tenho tentado formas de acertar essa rotina e não teve jeito. Com certeza estou "comendo bola" em algum ponto.
Abusando de vocês (no bom sentido) , seria possível "mastigar" mais ainda essa rotina para ver se consigo sair dessa ?

Saúde !

[]´s

Netavin
:(
TK90 / TK95 / APPLE IIe / 286 / 386 / 486 / 586 / AMD Atlhon
" Sem saber que era impossível, foi lá e fez !! "
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Validar CPF e CNPJ

Mensagem por Maligno »

procurem descansar um pouco esse fim-de-semana
Pra mim isso é impossível. :(
seria possível "mastigar" mais ainda essa rotina para ver se consigo sair dessa ?
Não entendi. Como assim "mastigar" mais? É só usar uma dessas funções que passamos. Não testei a do Leonardo, mas a minha vem funcionado corretamente há um bom tempo. Mas sem os símbolos da máscara, que acho desnecessários.

Mas se você quer acertar a rotina que tem, antes de tudo, critique o tamanho da variável recebida, depois de suprimir todos os espaços lateriais e interno. Se tiver tamanho 18 (com os símbolos, caso queira mantê-los), ótimo. Passa pra frente. Caso contrário, já retorne FALSE daí.

Ou entendi errado?

[]'s
Maligno
http://www.buzinello.com/prg
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Validar CPF e CNPJ

Mensagem por sygecom »

Tche..o povo no forum esta aqui pra ajudar e ser ajudado....mais descançar no fim de semana....isso jah não sei faz tempo.....agora por exemplo estou em SANTA MARIA...toh querendo ir pra POA-RS e chegando lah tem mais um milhão de serviço........

Mas vamos lah...abaixo um modo de usar a rotina que eu lhe mandei...

Código: Selecionar todos

fcgc    = space(18) 
fie      = space(15)
@ 06,01  get fcgc pict"@R !!.!!!.!!!/!!!!-!!"
@ 07,01  get fie      WHEN CNPJ()
Tche, se ainda tiver duvida.....não te acanha e pergunta o forum é pra isso mesmo..e tem mais...vergonha é roubar e não poder carregar......hehehe

Abraços
Leonardo Machado
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
Augusto
Usuário Nível 3
Usuário Nível 3
Mensagens: 473
Registrado em: 26 Ago 2003 17:50
Localização: Maricá/RJ
Contato:

Validar CPF e CNPJ

Mensagem por Augusto »

Netavin escreveu:... Porém se eu digitar 02.052.787/0001-6 (faltando o segundo dígito), ele passa pela crítica. Qual seria a solução ?
Uso variável alfanumérica no DBF, com 18 casas.
Parceiro... Eu não vou nem discutir as diversas formas de crítica de CNPJ oferecidas pelos colegas, até poderia prq utilizo uma outra diferente da deles que funciona tbm... hehe
Agora quanto a sua colocação (acima), é só criticar o GET se ele está preenchido com todos os campos tipo...

Código: Selecionar todos

if LEN(ALLTRIM(CCNPJ)) <> 18
   "Favor preencher TODO o campo" 
endif
Valeu ??
:xau Fui...
goulart@provsul.com.br

Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Validar CPF e CNPJ

Mensagem por Eolo »

Eu guardo o CNPJ em um campo com 14 dígitos, caracter, sem os pontos e a barra (que ocupam espaço e processamento à toa, e só atrapalham na hora da validação). No GET (ou SAY), uso o PICURE "@R 99.999.9999/9999-99": a cláusula R faz com que os pontos e a barra sejam mostrados, mas sem fazer parte do campo, e os "9" exigem que sejam digitados caracteres numéricos (só 0 a 9)...

vcnpj="02245322000135"
@10,10 get vcnpj -> "02245322000135"
@11,10 get vcnpj pict "@R 99.999.999/9999-99" -> "02.245.322/0001-35"

Na validação, boto um VALID CNPJ() e, nessa função CNPJ, checo primeiro se len(alltrim(vncpj))==14 e, se for, parto pra verificação dos dígitos de controle.
Avatar do usuário
Netavin
Usuário Nível 3
Usuário Nível 3
Mensagens: 306
Registrado em: 28 Fev 2007 08:37
Localização: Cacoal-RO

Validar CPF e CNPJ

Mensagem por Netavin »

Bom dia a todos!
...valeu meus amigos!! Eu não disse q estava comendo bola? Não deu nem nega!!
Com certeza todos os exemplos mostrados são eficientes. Porém uma coisa me chamou a atenção no exemplo do Augusto: ALLTRIM. Era tudo q faltava.
Acho que meus 48 anos estão já estão pesando ehehe
Valeu demais galera!!
Dúvidas eu as tenho ainda; sobre outras questões. Mas vamos devagar que o andor é de barro.

Um abraço a todos!
boa semana!

Netavin
TK90 / TK95 / APPLE IIe / 286 / 386 / 486 / 586 / AMD Atlhon
" Sem saber que era impossível, foi lá e fez !! "
ederxc
Usuário Nível 4
Usuário Nível 4
Mensagens: 619
Registrado em: 15 Set 2006 08:40
Localização: Pedreira -SP-

Validar CPF e CNPJ

Mensagem por ederxc »

Ola amigos , tambem fasso da mesma forma que o Eolo , na relaidade nem sei como funciona a validação de CNPJ e CPF , apenas Valido meu Get para a função :-$
C:\Xharbour\Xdev\Fw\VSX
Responder