Página 1 de 1

Validador codigo de barras ean13 e ean8

Enviado: 15 Ago 2011 14:26
por rubens
Alguem tem uma rotina de validação destes codigos de barra?

tô penando muito aqui com clientes que tem lançados esses códigos errados na nota fiscal e na hora de validar dá erro...

Se alguém tiver aí e puder dar uma maozinha..

Vlw...

Rubens

Validador codigo de barras ean13 e ean8

Enviado: 15 Ago 2011 18:58
por Kiko Fernandes
Rubens, eu não tenho em clipper, mas vou te explicar creio que você não terá dificuldades para criar uma rotina.

No final, vou colocar a rotina que uso, porém a minha é feita para Visual Objects, é semelhante ao clipper. Não é a mesma coisa mas ajuda a dar uma esclarecida.

Vamos a um exemplo de como funciona o código.

EAN13

7909010155591 - Código de barras

790901015_5_5_9_1 -> Ignore os "_" estão ai só para fixar a posição dos números abaixo
12345678910111213 -> Posicao dos números de 1 a 13.

Posiçoes pares (Soma os numeros das posicoes pares 2+4+6+8+10+12 e o resultado multiplica-se por 3
2->9
4->9
6->1
8->1
10->5
12->9
(9+9+1+1+5+9)=34 (soma das posicoes pares)
34*3=102 (resultado multiplicado por 3)

Posicoes impares (somar os números das posicoes impares. Não somar o número da posição 13, apenas até o 11)
1->7
3->0
5->0
7->0
9->5
11->5
(7+0+0+0+5+5)=17 (resultado das posicoes impares)


Somar resultado dos pares + resultado dos impares. Pegar o ultimo digito.
102+17=119 (ult. digito=9)
10-9=1 (digito verificador= 10 (dez) menos o ultimo digito) - Se maior que 9 = 0

Aqui vc tem o verificador do número que é igual a 1, então agora basta ver se o número do digito é o mesmo que o resto da divisao do número por 10.

Exemplo:
7909010155591/10=790901015559,1

No clipper tem um operador que retorna o resto da divisao que seria
7909010155591%10=1

Na sua função digamos que vc de o nome de ValidaDigEAN ficaria assim
if ValidaDigEan(cCodBarr)!=Val(cCodBarr)%10
erro, digito verificador não confere
endif


Para o calculo do EAN8 muda pouca coisa, se não me engano é a soma dos impares que deve ser multiplicado por 3, mas se vc acrescentar 5 zeros
a esquerda, vc pode resolver com a mesma função do EAN13. Para isto use o STRZERO(num,13)

Exemplo:

78918344 (cod. EAN8)
0000078918344 (cod. EAN8 acrescentado de 5 zeros a esquerda para usar o mesmo calculo do EAN13)


Exemplo da minha rotina feita em Visual Objects

Código: Selecionar todos

FUNCTION Digito(c AS FLOAT)
LOCAL i as word,dim C1[12] as byte,x as REAL8

   FOR i:=1 to 12
          c1 [i] := Val(SubStr(StrZero(c,12,0),i,1))  
   NEXT

   x  := (3*(C1[2]+C1[4]+C1[6]+C1[8]+C1[10]+C1[12]))+C1[1]+C1[3]+C1[5]+C1[7]+C1[9]+C1[11]
   x  := x%10
   i  := Integer(10-x)

RETURN if(I>9,0,i)

Validador codigo de barras ean13 e ean8

Enviado: 15 Ago 2011 21:37
por janio
Os calculos do Kiko Fernando estão corretos. Sua explicação bate com o que encontrei na net nos links logo abaixo, lembrando que para calcular o EAN-8, basta acrescentar 05 zeros no codigo informado que a validacao é semelhante:

http://www.forumweb.com.br/foruns/topic ... ras-ean-8/
http://dqsoft.blogspot.com/2008/07/cdig ... ean-8.html

Pegando a função do Kiko Fernandes, resolvi fazer a minha função de uma maneira bem 'didática' :

Código: Selecionar todos

/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
Function ValidaEAN( CodigoBarras )
Local i, Vetor[12], SomaPares, SomaImpar
Local SomaResul, Unidade, Digito
	
	For i := 1 to 12 
   	Vetor[i] := Val( SubStr( StrZero( Val( AllTrim(CodigoBarras) ),13 ), i, 1 ) )
	Next
	
	SomaPares = ( Vetor[2] + Vetor[4] + Vetor[6] + Vetor[8] + Vetor[10] + Vetor[12] ) * 3
	SomaImpar = ( Vetor[1] + Vetor[3] + Vetor[5] + Vetor[7] + Vetor[09] + Vetor[11] )
	SomaResul = SomaPares + SomaImpar
	Unidade   = Val( Right( Str( SomaResul ), 1 ) )
	Digito    = If( ( 10 - Unidade ) > 9, 0, 10 - Unidade )
		 
Return Digito = Val( Right( AllTrim( CodigoBarras ), 1 ) )

/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/

CodBarras = Space(13)

Do While .t.
@ 10, 5 Say "Codigo de Barras" Get CodBarras Pict "9999999999999"
read

If !ValidaEAN( CodBarras )
   MSG("CODIGO DE BARRA INVALIDO")
   Loop
Endif

Exit

Enddo

Quem quiser algo mais 'profissional', pode usar a função feita pelo colega Maligno, que encontrei neste fórum:

Código: Selecionar todos

function CalcEAN13(cEAN) 
local nSoma := 0 
local i 
for i := 1 to 12 
    nSoma += Val(SubStr(cEAN,i,1)) * if(i%2>0,1,3) 
next 
return if(nSoma%10=0, "0", Str(((Int(nSoma/10)+1)*10)-nSoma,1)) 
  
//

function ValidEAN13(cEAN) 
return Len((cEAN := AllTrim(cEAN)))=13 .and. Right(cEAN,1) == CalcEAN13(cEAN) 

Validador codigo de barras ean13 e ean8

Enviado: 16 Ago 2011 08:23
por rubens
Blz.. Pessoal...

então melhor do que isso...

Agora ficou a dúvida... tenho alguns produtos que começam com 8 e tem 12 digitos... seriam calculados da mesma forma?

Exemplo: tenho um mouse aqui que o código é 882224004060

como ficaria esse?

Rubens

Validador codigo de barras ean13 e ean8

Enviado: 16 Ago 2011 09:11
por Kiko Fernandes
Rubens, acrescente 0 (zero) a esquerda até completar os 13 digitos.

882224004060 -> acrescentando zero a esquerda = 0882224004060

088222400_4_0_6_0 (cod. barra)
12345678910111213 (posição dos números)

soma pares: (8+2+2+0+4+6)= 22 x 3 = 66
soma impares: (0+8+2+4+0+0) = 14 (sempre somar até a posição 11)

66+14=80 (ult. digito=0)


0882224004060/10=10 ou 0882224004060%10= 10

Se o resultado for maior que 9 = 0

Validador codigo de barras ean13 e ean8

Enviado: 16 Ago 2011 10:31
por janio
A função que postei acrescenta à esquerda tantos zeros quanto forem necessário para que o CodigoBarras informado sempre tenha 13 posições.

Validador codigo de barras ean13 e ean8

Enviado: 19 Ago 2011 17:33
por Dr_Spock_Two
- Boa tarde Srs.(as)

- Segue abaixo rotina que acabei otimizando das acimas, incluindo a validação dos EAN 8, 13 e 14.
- Foram assumidos as seguintes regras para validação :
Ean8 : Incluido mais 5 zeros no inicio do código.
Ean13 : padrão.
Ean14 : Validado as 13 últimas posições, visto que a primeira identifica a "caixa" ou agrupamento do produto.

Código: Selecionar todos

@ Nlin, nCol Say "Codigo EAN :" Get cCodigoBarras Valid ValidaEAN(cCodigoBarras)
Read


Function ValidaEAN(cCodigoBarras)
Local nInd       := 0
Local nUnidade   := 0
Local nDigito    := 0
Local lRetorno   := .f.
Local aPosicao[12]
If StrZero(Len(Trim(cCodigoBarras)), 2,0) $ "08 13 14"
	If Len(Trim(cCodigoBarras)) == 8
		cCodigoBarras := StrZero(Val(AllTrim(cCodigoBarras)), 13, 0)
	ElseIf Len(Trim(cCodigoBarras)) == 14
		cCodigoBarras := Right(cCodigoBarras, 13)
	EndIf
	For nInd := 1 to 12
	   aPosicao[nInd] := Val(SubStr(cCodigoBarras, nInd, 1))
	Next
	nUnidade := Val(Right(Str(((aPosicao[2]+aPosicao[4]+aPosicao[6]+aPosicao[8]+aPosicao[10]+aPosicao[12])*3) + ( aPosicao[1]+aPosicao[3]+aPosicao[5]+aPosicao[7]+aPosicao[9]+aPosicao[11])), 1))
	nDigito  := If((10-nUnidade ) > 9, 0, 10-nUnidade)
	lRetorno := nDigito = Val(Right(AllTrim(cCodigoBarras), 1))
   If(!lRetorno, Alert("O digito verificador esta incorreto !"),)
Else
   Alert("O tamanho do campo devera conter 8, 13 ou 14 digitos !")
EndIf
Return lRetorno

Validador codigo de barras ean13 e ean8

Enviado: 24 Mar 2012 12:26
por microvolution
Prezados,
como recebi gratuitamente do amigo EOLO VENTURA informações que desde o ano 2003 eu procurava e não encontrava que é fazer com que o programa Clipper funcionasse sem ocupar o CPU no Win XP;
e agora tb com as informações dessa rotina de Código de Barras (apesar que eu já tinha uma); gostaria de compartilhar com todos as alterações que pra mim ficaram melhores na verificação do "digito verificador" do EAN-13.
A rotina é a abaixo, que é dividida em 2 partes e logo abaixo explico a todos que se interessarem:

Código: Selecionar todos

*** nova rotina do código barras ean13 - parte1 - 21/3/12w ***

if mCDPRODUTO <= 9 .or. mCDPRODUTO > 9999999999999
   MENSAGEM ('C¢digo do Produto deve estar entre 10 e 9999999999999 inclusive')
   return (.f.)
endif
 if !ValidaEAN( str(mCDPRODUTO) )
    MENSAGEM ("Alterei o 'dÖgito verificador' pra vocˆ para o n£mero correto, automaticamente")
    mCDPRODUTO := str(mCDPRODUTO,13)
    Digito     := alltrim(str(Digito))
    mCDPRODUTO := left(mCDPRODUTO,12 ) + Digito
    mCDPRODUTO := val(mCDPRODUTO)
    Digito     := val(Digito)
    return (.f.)
Endif

*** nova rotina do código barras ean13 - parte1 - 21/3/12w ***
**************************************************************
***************************************************************
*** nova rotina do código barras ean13 - parte2 - 21/3/12w ***

Function ValidaEAN( mCDPRODUTO )
Local i, Vetor[12], SomaPares, SomaImpar
Local SomaResul, Unidade
Local lRetorno   := .f. // acrescentado em 22/3/12w.

Public Digito // acrescentado em 21/3/12w.

For i := 1 to 12
    Vetor[i] := Val( SubStr( StrZero( Val( AllTrim(mCDPRODUTO) ),13 ), i, 1 ) )
Next

SomaPares = ( Vetor[2] + Vetor[4] + Vetor[6] + Vetor[8] + Vetor[10] + Vetor[12] ) * 3
SomaImpar = ( Vetor[1] + Vetor[3] + Vetor[5] + Vetor[7] + Vetor[09] + Vetor[11] )
SomaResul = SomaPares + SomaImpar
Unidade   = Val( Right( Str( SomaResul ), 1 ) )
Digito    = If( ( 10 - Unidade ) > 9, 0, 10 - Unidade )
lRetorno := Digito = Val(Right(AllTrim(mCDPRODUTO), 1))
Return Digito = Val( Right( AllTrim( mCDPRODUTO ), 1 ) )

*** nova rotina do código barras ean13 - parte2 - 21/3/12w ***
***************************************************************
Agora as explicações:
- No meu caso uso apenas códigos de 13 barras;
- toda vez que o usuário digitar qualquer número que tenha apenas uma unidade, ou seja menos que 2 caracteres ele responde com uma mensagem que a digitação deve ser entre 10 e 9999999999999 (entre 2 e 13 caracteres), isso impede que gere um código erroneo, pois o código pra começar deve no mínimo ser de 1 a 12, pois o 13º número é o dígito verificador;
- quando o usuário digita qualquer número acima de 2 caracteres (exemplo 99, 11, 12, etc), ele entende que o último caractere é o dígito verificador;
Nesse caso, ele faz 2 coisas; a primeira, e a mais simples, retorna pra função chamadora o resultado do código digitado e, se estiver correto, ele continua com os próximos campos, mas se tiver errado ele faz a próxima situação (ex.: se digitar "17", ele verifica que o 7 é o digito verificador do código 1, então dá se prosseguimento, já se digitarmos qualquer outro número, (10, 11, 12, 13...,18,19, etc) ele retorna para a próxima etapa que vou explicar detalhadamente (apesar da maioria dos usuários isso ser banal e muito simples, gostaria que me ajudasse a ajudar aqueles como eu que um dia precisava de coisas simples para tornar meu código mais seguro):

Código: Selecionar todos

if !ValidaEAN( str(mCDPRODUTO) )
   /* Esta linha já fala por si só, caso o código
      esteja errado (digito verificador incorreto),
      execute abaixo: */
   MENSAGEM ("Alterei o 'dÖgito verificador' pra vocˆ para o n£mero correto, automaticamente")
   /* esta linha é uma mensagem apenas pra conhecimento
      do usuário.
      Vamos às próximas linhas:
            como minhas variáveis (mCDPRODUTO) e (Digito)
            são do tipo numérico, nas duas linhas abaixo,
            converto-as temporariamente para "strings",
            através da função str():*/
   mCDPRODUTO := str(mCDPRODUTO,13)
   Digito     := alltrim(str(Digito))
   /* Agora que já temos as duas variáves como strings,
      fazemos agora o que acho de mais importante desta
      função, a concatenação ou junção do dígito correto
      ao código, bem como da exclusão do dígito errado,
      conforme linha abaixo: */
   mCDPRODUTO := left(mCDPRODUTO,12 ) + Digito
   /* já as 2 linhas abaixo, convertem novamente as variáveis
      para tipo "numéricas", como eram anteriormente: */
   mCDPRODUTO := val(mCDPRODUTO)
   Digito     := val(Digito)
   /* finalmente, você pode optar na linha abaixo por .f. ou .t.
      que vai acontecer 2 situações interessantes:
      - se optar .f., a mensagem que o dígito foi alterado
        para o número correto aparecerá e o usuário deverá
        pressionar enter novamente para que o aplicativo
        passe para o próximo campo (nome do produto, descrição, etc)
        que você designou no @ say get seguinte;
      - se colocar .t., o aplicativo mostra a mensagem do mesmo jeito
        e já passa automaticamente para o próximo GET. */
   return (.t.)
Endif
Por enquanto é só... ah!
estou tentando transferir meu aplicativo feito em Clipper 5.2 com o auxílio do SCULPTOR 3.3 (da Squadra) para xHARBOUR mas não tá dando certo.
Se alguém tiver alguma experiência adicional em Sculptor, agradeceria, pois o amigo EOLO VENTURA me mandou informações e rotinas, mas não consegui nada, então, ainda estou no clipper, com meu aplicativa na versão 3.3.1, estou querendo inovar para 4.0 com o ambiente Windows XP/VISTA/VII.
Vlw a todos.
Walcledson de Paula.

Validador codigo de barras ean13 e ean8

Enviado: 24 Ago 2012 21:50
por Danielmaximiliano
Ola: ler muitos fóruns e página principal www.gs1.org modificar uma função e, assim, ele pode ser usado com EAN13 e EAN8 agora GTIN13, GTIN8.
o mesmo tema é postado fórum Roberto Lopez http://hmgforum.com/viewtopic.php?f=9&t=2449

Você também pode ler sobre os códigos de país GS1 encontrados em http://www.gs1.org/barcodes/support/prefix_list

também postou no fórum por Roberto Lopez http://hmgforum.com/viewtopic.php?f=15&t=2439

eles as dicas de validação de código para GS1

Código: Selecionar todos

#include <hmg.ch>

//Compiled with HMG.3.0.42

Function Main
Local cEan13    := '7909010155591'
Local cEan8     := '78918344'


 GTIN_CHECK( SUBSTR( cEan13, 1 , 12 ) ) 
 GTIN_CHECK( SUBSTR( cEan8 , 1 , 7  ) )
Return

Function GTIN_CHECK(cCode) 
Local nTop := iif( Len( cCode ) = 12 , 6 , 4 )
Public nControl := 0
Public nFor     := 0
Public nPair    := 0                                        
Public nOdd     := 0
             
   for nFor= 1 to nTop
      nPair  := nPair + val( substr( cCode,( nFor * 2 )    , 1 ) )    // suma de pares     // Sum Digits Pair
      nOdd   := nOdd  + val( substr( cCode,( nFor * 2 ) - 1, 1 ) )    // suma de impares   // Sum Digits odd
   next
   
   // Por exemplo, considerando o código 7909010155591, o dígito 1 é obtido por
   // (9+9+1+1+5+9) * 3 + (7+0+0+0+5+5) = 119
   // 10 - (119 % 10) = 1
   // Por exemplo, considerando o código 78918344, o dígito 4 é obtido por
   // (7+9+8+4)*3 + (8+1+3) = 96
   // 10 - (96 % 10) = 4
           
   If nTop == 6          
   nControl :=  nPair * 3 
   nControl :=  nControl + nOdd
   nControl := Int( 10 -  ( nControl % 10 ) )             // Mod( nControl , 10 )     
   msgbox( "Is GTIN-13   : " + cCode+ "1"                   + chr(10) + ;
           "Sum pairs     : " + alltrim( STR ( nPair    ) ) + chr(10) + ;
           "Sum odd       : " + alltrim( STR ( nOdd     ) ) + chr(10) + ;
           "nControl      : " + alltrim( STR ( nControl ) ),;
           "Message                                   ")
   Else 
   nControl :=  nOdd  * 3 
   nControl :=  nControl  + nPair    
   nControl :=  Int( 10 - ( nControl % 10 ) )  
   msgbox( "Is GTIN-8    : " + cCode+ "4"                  + chr(10) + ;
           "Sum pairs    : " + alltrim( STR ( nPair    ) ) + chr(10) + ;
           "Sum odd      : " + alltrim( STR ( nOdd     ) ) + chr(10) + ;
           "nControl      : " + alltrim( STR ( nControl ) ),;
           "Message                                   ")
   Endif 
   
Return Alltrim( Str( nControl , 1 ) )
Saludos/saudações DaNiElMaXiMiLiAnO

Validador codigo de barras ean13 e ean8

Enviado: 26 Ago 2012 16:48
por Pablo César
Sea muy bien venido amigo Daniel a nuestro fórum ! Aqui puedes tambien postar tus mensajes en español o en ingles, hay muchos colegas aqui que entienden, principalmente cuando es algo técnico.

Y muchas gracias por tu contribuicion !

Validador codigo de barras ean13 e ean8

Enviado: 31 Ago 2012 21:09
por billy1943
Eu só queria alertar os colegas que existem fabricantes que, estão eles mesmas "criando" códigos de barras para seus produtos, e, o pior, estão os colocando nas NFE. como se fossem registrados, e se você for checá-los, bate o DV.

O que elas estão fazendo ?

Iniciam o código por 789
Colocam depois 5 zeros, pois nessas posições entra o código do fabricante
Entram depois com um código sequencial de 4 caracteres como se fosse o produto
Calculam o DV e o colocam na décima terceira posição.

Um código ficaria assim: 789000001234X
onde X é o DV

O que eu estou fazendo ?

Como não é possível haver uma sequencia de 5 zeros no meio do código, estou desprezando esse código e colocando nosso código interno.

Validador codigo de barras ean13 e ean8

Enviado: 05 Set 2012 19:45
por Danielmaximiliano
Olá Billy :
Recomiendo que utilize el prefijo 999. tambien guarde en una tabla el ultimo codigo generado.

ejemplo CANTIDAD.DBF

Código: Selecionar todos

CANTIDAD->CODIGO:= nULTINO_NUMERO_GENERADO
CANTIDAD->( DBCOMMIT() )
este es parte de mi codigo para generar un articulo interno.

Código: Selecionar todos

If Val(Stock.Text_1.Value) == 0                                         
   DBSElECTAREA("CANTIDAD")
   CANTIDAD->(DBGotop())
   cEAN13             := LEFT(Cantidad->CODIGO,12)                           // 999 000 000 001 [Digit control]
   nNumero            := VAL( cEAN13 ) + 1                                         //Sumamos uno mas
   cEAN13             := STR( nNumero , 12 ) + GTIN_CHECK(cEAN13)   // a esa suma le agregamos un digito validador
   Stock.Text_1.Value := cEAN13
   cNumero                := cEAN13
   lTrue              := .T.
   cMensaje           := ' ¿¿ Agrega Nuevo Artículo Interno ?? ' + CHR(10)+;
                                '                                     ' + CHR(10)+;
                                '    Codigo : ' + cNumero 
   cTitulo            :=    ' Artículo Interno Nuevo '

  If (MsgYesNo ( cMensaje  , cTitulo  ))
    lModificaArticulo  := .F.
    lArticuloNuevo     := .T. 
     IF !IsWindowDefined(Agregar)                           
        Load window .\Formularios\Agregar      // en esta ventana rellenamos los datos 
        hWnd := GetFormHandle ("Agregar")	
        Agregar.Center
        Agregar.Text_1.Value := cEAN13 
        Agregar.Text_3.SetFocus
        Agregar.Activate
     Else
        Agregar.Text_1.Value := cEAN13
        Agregar.Text_3.SetFocus
        Agregar.Restore
     Endif
     Borra()
     Return
     
   Endif //MsgYesNo
GS1 utiliza como normativa el prefijo 999 para productos internos, se llama Coupons.
si necesitas mas datos sobre GS1 GTIN8 - 13 - UPC solo escribeme a mi mail.
danielmaximiliano@yahoo.com.ar ya que a veces me olvido de entrar al foro y no lo reviso.
Saludos DaNiElMaXiMiLiAnO

Validador codigo de barras ean13 e ean8

Enviado: 05 Set 2012 20:00
por Danielmaximiliano
Hola a Todos :
disculpas por un Bug dentro del codigo sumistrado mas arriba.
resulta que los codigos terminado en '0' no eran reconocidos, mirando el codigo vi que faltaba una porcion de codigo.

Código: Selecionar todos

Function GTIN_CHECK(cCode) 
Local nTop := iif( Len( cCode ) >= 12 , 6 , 4 )
Public nControl := 0
Public nFor     := 0
Public nPair    := 0                                        
Public nOdd     := 0

   for nFor= 1 to nTop
      nPair  := nPair + val( substr( cCode,( nFor * 2 )    , 1 ) )    // suma de pares     // Sum Digits Pair
      nOdd   := nOdd  + val( substr( cCode,( nFor * 2 ) - 1, 1 ) )    // suma de impares   // Sum Digits odd
   next
   //          7 7 9 8 1 3 8 5 5 0 9 4 0
   // Pair :=    9 + 8 + 3 + 5 + 0 + 4 = 29 * 3 =  87
   // Odd  :=  7 + 9 + 1 + 8 + 5 + 9   = 49     +  49
   // Control                                     136
           
   If nTop == 6         
   nControl :=  nPair * 3 
   nControl :=  nControl + nOdd
   nControl := Int( 10 -  Mod(nControl , 10 ) )             // Mod( nControl , 10 )     
   Else 
   nControl :=  nOdd  * 3 
   nControl :=  nControl  + nPair    
   nControl :=  Int( 10 - Mod(nControl , 10 ) )  
   Endif 

   If nControl = 10                  // se agrego estas lineas
      nControl = 0                    //
   Endif                                 // 
   
Return Alltrim( Str( nControl , 1 ) )
cuaquier cosa miren el hilo que esta mas completo http://hmgforum.com/viewtopic.php?f=9&t=2449

Saludos / Regards DaNiElMaXiMiLiAnO

Validador codigo de barras ean13 e ean8

Enviado: 09 Out 2012 13:17
por JoséQuintas
Estranhei os fontes postados. Eu uso assim:

Código: Selecionar todos

@ 2, 2, Get cGtIn Picture "99999999999999" Valid Valida():GTIN(cGtIn)
Read

Method GTIN(cCodigo) Class Valida
   Local lOk := .t., nSoma := 0, nCont := 0, nMultiplicador := 0
   cCodigo := AllTrim(cCodigo)
   If Len(cCodigo) != 0
      cCodigo := Padl(cCodigo,14,"0")
      nMultiplicador = 3
      nSoma := 0
      For nCont = 1 To 13
         nSoma += ( Val(Substr(cCodigo,nCont,1)) * nMultiplicador )
         nMultiplicador := iif(nMultiplicador==1,3,1)
      Next   
      nSoma := nSoma - (Int(nSoma/10)*10)
      If nSoma != 0
         nSoma := 10 - nSoma 
      Endif
      If Right(cCodigo,1) != Str(nSoma,1)
         MsgExclamation("Codigo invalido! Deixe em branco ou preencha o codigo correto")
         lOk := .f.
      Endif   
   Endif   
   Return lOk
Achei interessante o fonte do Maximiliano usando "." ao invés de ":" pra OOP igual outras linguagens. Como conseguiu isso?