Como Validar Código de Barras GTIN, antigo EAN13 no SQL SERVER 2008
Com as exigências da SEFAZ, no tocante a Nota Fiscal Eletrônica, tornou-se uma exigência do Governo Federal Brasileiro o uso do código de barras EAN13 ou GTIN (Global Trade Item Number), válido.
Então segue uma store function desenvolvida em T-SQL do SQL Server 2008, para validar esse troço.
Depois vai ser o chip na mão e na testa ... Espero está na Glória com Cristo, para não vê o resultado final... 666 tá chegando...
Mas, enquanto não chega, segue uma store function para aliviar o stress de quem trabalhar com isso...
-- Nome Artefato/Programa..: sp_valida_ean13.sql -- Autor(es)...............: Emerson Hermann (emersonhermann [at] gmail.com) O Peregrino (http://www.emersonhermann.blogspot.com) -- Data Inicio ............: 20/11/2011 -- Data Atualizacao........: 22/11/2011 -- Versao..................: 0.01 -- Compilador/Interpretador: T-SQL (Transact SQL) -- Sistemas Operacionais...: Windows -- SGBD....................: MS SQL Server 2005/2008 -- Kernel..................: Nao informado! -- Finalidade..............: store procedure (function) para testa se um um código de barras (EAN13-GTIN) é valido ou não, retorna 1 para verdadeiro e 0 para falso -- OBS.....................: -- IF EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_valida_ean13]') AND type IN (N'FN') ) DROP FUNCTION sp_valida_ean13; GO CREATE FUNCTION sp_valida_ean13(@number varchar(max)) RETURNS smallint AS BEGIN DECLARE @c bigint DECLARE @r smallint DECLARE @i smallint DECLARE @x smallint DECLARE @sum smallint DECLARE @mult smallint DECLARE @number_split varchar(1) SET @x = 0 SET @sum = 0 SET @i = 1 SET @c = len(@number) -- se cb for maior que 13 IF @c > 13 BEGIN SET @r = 0 END -- se cb for menor que 13 IF @c < 13 BEGIN SET @r = 0 END --se for nulo IF @number IS NULL BEGIN SET @r = NULL END ELSE BEGIN --se não for nulo pode ser válido SET @x = (SELECT CASE WHEN patindex('%[^0-9]%', @number) > 0 THEN 0 ELSE 1 END) IF @c = 13 AND @x = 1 BEGIN WHILE @i<=(@c-1) BEGIN --fazendo um split do cb SET @number_split=substring (@number,@i,1) --multiplicam-se os digitos do cb por 1 e por 3, em sequencia repetitiva de 1 e 3; IF (@i % 2) = 0 BEGIN SET @sum = @sum + cast(@number_split as int) * 3 END ELSE BEGIN SET @sum = @sum + cast(@number_split as int) * 1 END --incremento SET @i=@i+1 END --com a soma do resultado das multiplicacoes... --sera necessario encontrar o multiplo de 10 mais proximo do resultado da soma. --atencao: o multiplo de 10 deve ser maior ou igual ao resultado da soma (nunca menor). SET @mult = ( ( 1 + cast(@sum / 10 as int) ) * 10 ) --subtraindo o resultado da soma do multiplo que foi encontrado SET @mult = @mult - @sum --o resultado desta subtracao será o digito verificador --entao se o ultimo digito do cb, isto e, --13o numero for igual ao resultado desta subtracao entao e um cb valido IF cast(substring(@number,13,1) as int) = @mult BEGIN SET @r = 1 END ELSE BEGIN SET @r = 0 END END ELSE BEGIN SET @r = 0 END END --fim_se RETURN (@r) END; GO -- Exemplo de Uso: -- Exemplo: 01, uso simples -- O EAN13 impresso na Lata de Leite Ninho 400g -- SELECT dbo.sp_valida_ean13('7891000142202'); --retorna 1, pois é valido -- Exemplo: 02, descobrir todos os produtos com EAN13 ou GTIN inválido -- SELECT * FROM produto WHERE dbo.sp_valida_ean13(gtim)=0; -- GO
Parabéns!!!
ResponderExcluirAtt,
Claudio Estezi
:)
ResponderExcluirFantástico!
ResponderExcluirJá coloquei em uso aqui na empresa onde desenvolvo e quebrou um puta galho, pois algumas de nossas fiscais não estavam sendo autorizadas pelo Sefaz pois o EAN era inválido... ...e pra descobrir no "olhometro" é impossível!
Parabéns!
Já passei pelo mesmo problema ... Sucesso!
ExcluirEste código já me tirou do sufoco várias vezes. Contudo, ele ainda traz alguns resultados falsos. Exemplo:
ResponderExcluir0885370314670
0790069343100
7945045858410
7892509072670
7898560270420
8713439198560
7899403703375
só o último tá inválido, porém, o script aponta todos estes.
create Function UDF_Valida_Ean_13(@Ean varchar(13)) returns varchar(1) as
ResponderExcluirbegin
--declare @Ean varchar(13) = '5010017088439' -- 088537031467
declare @12Dig varchar(12)
declare @Valor1 int
declare @Valor2 int
declare @Valor3 int
declare @Mult10 int
declare @DigVerificador int
declare @DigVerifCalculado int
declare @Retorno varchar(1)
set @DigVerificador = convert(int,substring(@Ean,13,1))
set @12Dig = SUBSTRING(@Ean,1,12)
-- Soma Posições Pares e Multiplica por 3
set @Valor1 = convert(int,SUBSTRING(@Ean,2,1)) +
convert(int,SUBSTRING(@Ean,4,1)) +
convert(int,SUBSTRING(@Ean,6,1)) +
convert(int,SUBSTRING(@Ean,8,1)) +
convert(int,SUBSTRING(@Ean,10,1)) +
convert(int,SUBSTRING(@Ean,12,1))
set @Valor1 = @Valor1 * 3
-- Soma Posições Impares
set @Valor2 = convert(int,SUBSTRING(@Ean,1,1)) +
convert(int,SUBSTRING(@Ean,3,1)) +
convert(int,SUBSTRING(@Ean,5,1)) +
convert(int,SUBSTRING(@Ean,7,1)) +
convert(int,SUBSTRING(@Ean,9,1)) +
convert(int,SUBSTRING(@Ean,11,1))
set @Valor3 = @Valor1 + @Valor2
-- Verifica Próximo Múltiplo de 10
if (@Valor3 <= 10)
set @Mult10 = 10
else
if ((@Valor3 % 10) = 0)
set @Mult10 = @Valor3
else
begin
if (@Valor3 >= 100)
set @Mult10 = (convert(int,Substring(convert(varchar(3),@Valor3),1,2)) + 1) * 10
else
set @Mult10 = (convert(int,Substring(convert(varchar(2),@Valor3),1,1)) + 1) * 10
end
-- Subtrai o Múltiplo de 10 pelo valor calculado para achar o Dígito Verificador
set @DigVerifCalculado = @Mult10 - @Valor3
if (@DigVerifCalculado = @DigVerificador)
set @Retorno = 'S'
else
set @Retorno = 'N'
return(@Retorno)
end
Obrigado Lukinhas pela sugestão de solução, não testei, mas espero que tenha corrigindo o BUG, apresentado por Daniel Viana, estava sem tempo para corrigir.
ExcluirO bom da internet é isso, compartilhar o conhecimento.
Desde já agradeço.
Como faço para adptar esse código para vb6 ?
ResponderExcluirSugiro vê o algoritmo do EAN13 [1], inclusive tem apresentação codificada em Transact SQL SERVER(outro forma de se chegar ao mesmo resultado) e em outras linguagens
Excluir[1] https://pt.wikipedia.org/wiki/EAN-13
Boa sorte!
/* FIZ EM MYSQL, VALIDA TUDO CERTINHO */
ResponderExcluirDELIMITER $$
DROP FUNCTION IF EXISTS `Valida_Ean_13` $$
CREATE FUNCTION `valida_ean_13`(ean varchar(255)) RETURNS BOOLEAN
BEGIN
IF(length(ean)!=13) THEN RETURN FALSE; END IF;
SET @ean=ean;
SET @digverificador = cast(substring(@ean, 13, 1) AS unsigned);
SET @factor='3';
SET @sum='0';
/* soma todos os digitos multiplicando os impares pelo factor;*/
SET @sum=(
(cast(substring(@ean, 1, 1) AS unsigned)*1)
+ (cast(substring(@ean, 2, 1) AS unsigned)*@factor)
+ (cast(substring(@ean, 3, 1) AS unsigned)*1)
+ (cast(substring(@ean, 4, 1) AS unsigned)*@factor)
+ (cast(substring(@ean, 5, 1) AS unsigned)*1)
+ (cast(substring(@ean, 6, 1) AS unsigned)*@factor)
+ (cast(substring(@ean, 7, 1) AS unsigned)*1)
+ (cast(substring(@ean, 8, 1) AS unsigned)*@factor)
+ (cast(substring(@ean, 9, 1) AS unsigned)*1)
+ (cast(substring(@ean, 10, 1) AS unsigned)*@factor)
+ (cast(substring(@ean, 11, 1) AS unsigned)*1)
+ (cast(substring(@ean, 12, 1) AS unsigned)*@factor));
SET @digverifcalculado=((1000 - @sum) % 10);
IF (@digverifcalculado = @digverificador) THEN
SET @retorno = TRUE;
ELSE
SET @retorno = FALSE;
END IF;
RETURN @retorno;
END $$
DELIMITER ;
/* EM MYSQL VALIDANDO GTIN-8 , 12 E 13 */
ResponderExcluirDELIMITER $$
DROP FUNCTION IF EXISTS `valida_ean` $$
CREATE FUNCTION `valida_ean`(codigo varchar(255)) RETURNS int(11)
BEGIN
IF(length(codigo)!=8
&& length(codigo)!=12
&& length(codigo)!=13)
THEN RETURN FALSE; END IF;
SET @ean=codigo;
SET @factor='3';
SET @sum='0';
SET @digverifcalculado=null;
SET @numLenSemDv = (length(@ean) - 1);
SET @digverificador = cast(substring(@ean, @numLenSemDv+1, 1) AS unsigned);
SET @index = @numLenSemDv;
##################################
loop_while: LOOP
-- -- -- -- -- -- -- -- -- -- --
SET @sum = (@sum+(cast(substring(@ean, @index, 1) AS unsigned)*@factor));
SET @factor = (4 - @factor);
-- -- -- -- -- -- -- -- -- -- --
SET @index = (@index - 1);
IF @index = 0 THEN
LEAVE loop_while;
END IF;
END LOOP loop_while;
##################################
SET @digverifcalculado=((1000 - @sum) % 10);
IF (@digverifcalculado = @digverificador) THEN
SET @retorno = TRUE;
ELSE
SET @retorno = FALSE;
END IF;
RETURN @retorno;
END $$
DELIMITER ;
Exelente aporte, muchas gracias
ResponderExcluirpessoal há como validar o DUN14?
ResponderExcluir