« EFD prorrogado para 01/2009 (COTEPE 11/07) | Home | Arranjo simples - Código delphi - Parte 1 »
Função para validar Inscrição Estadual (IE) de todos os estados
By Paulo (CincoBytes) | January 4, 2008
Em 2001 escrevi um função para validar as Inscrições Estaduais de todos os estados brasileiros; na época eu apenas estava iniciando no delphi. Passado 6 anos resolvi escrever uma nova função(algoritmo) só que compactando-a ao máximo.
Resultado?! um código com menos de 90 linhas.
Abraço a todos!
PS: Peço por gentileza que relatem possíveis erros para correção, e se possível testem a função com IE já validas por outros códigos.
function IE(IE, UF: string; ApenasDigitos: Boolean = True): boolean;
const
NUMERO: smallint = 37;
MASCARAS_: string = ' NNNNNNNNX- NNNNNNNNNNNXY- NNNNNNNNNNX-NNNNNNNNNNNNNX- NNNNNNYX- NNNNNNNNXY-' +
' NNNNNNNNNX- NNNNNNNNXNNY- NNNNNNNNXNNN- NNNNNNNXY';
PESOS_: string = 'GFEDCJIHGFEDCA-FEDCJIHGFEDCAA-GFEDCJIHGFEDAC-AAAAAAAAGFEDCA-AAAAABCDEFGHIA-AAAJIAAHGFEDCA-' +
'FEDCBJIHGFEDCA-IHGFEDCHGFEDCA-HGFEDCHGFEDCAA-ABCBBCBCBCBCAA-ADCLKJIHGFEDCA-AABDEFGHIKAAAA-AADCKJIHGFEDCA-' +
'AAAAAJIHGFEDCA-AAAAAIHGFEDCAA-AAAAAJIHGFEDCA-AAAAKJIHGFEDCA-';
PESO_: string = 'ABAAAAABBABAAAAAAJAAIGAHAADAEALLAFNOQ!A!!!!!CC!A!!!!!!K!!H!!!!!!!!!M!!!!P!';
ALFA_: string = 'ABCDEFGHIJKLMNOPQRS';
ROTINAS_: string = 'EE011EEEEEEEEEEEE2EEEEEE0EEEDEDDEEEE0!E!!!!!EE!E!!!!!!E!!E!!!!!!!!!D!!!!E!';
MODULOS_: string = '99999998999999999899999999997999999990900000890900000090090000000009000090';
INICIO_ : string = '0020000AB000111X2X11X11X2XXX2XXXX2XX2114333XXXX7XCC2X8X56X89X0XXX4XXXX9XX0';
MASCARA_: string = 'ABAAAAAEEABAAAACABAAFDAEAGADAAHIACAJG';
FATORES_: string = '0000100000001000000001000011000000000';
ESTADOS_: string = 'ACACALAPAPAPAMBABACEDFESGOGOMAMTMSMGPAPBPRPEPIRJRNRSRORORRSCSPSPSET0TOPERN';
var
c1, c2, alternativa, inicio, posicao, erros, fator, modulo, soma1, soma2, valor, digito: smallint;
mascara, inscricao, a1, a2, peso, rotina: string;
begin
// Copyright: www.cincobytes.net / suporte@cincobytes.net //
IE := trim(uppercase(IE));
result := ((IE = 'ISENTO') or (IE = 'EM ANDAMENTO') or ((UF = 'EX') and ((IE = '') or (IE = '00000000000000'))));
posicao := 0;
while ((not result) and (posicao < NUMERO) and (IE <> '')) do
begin
inc(posicao);
if (copy(ESTADOS_, posicao * 2 - 1, 2)) <> UF then
continue;
inscricao := '';
for C1 := 1 to 30 do
if pos(copy(IE, C1, 1), '0123456789') <> 0 then
inscricao := inscricao + copy(IE, C1, 1);
mascara := copy(MASCARAS_, pos(copy(MASCARA_, posicao, 1), ALFA_) * 15 - 14, 14);
if length(inscricao) <> length(trim(mascara)) then
continue;
inscricao := copy('00000000000000' + inscricao, length(inscricao) + 1, 14);
erros := 0;
alternativa := 0;
while (alternativa < 2) do
begin
inc(alternativa);
inicio := posicao + (alternativa * NUMERO) - NUMERO;
peso := copy(PESO_, inicio, 1);
if peso = '!' then
continue;
a1 := copy(INICIO_, inicio, 1);
a2 := copy(copy(inscricao, 15 - length(trim(mascara)), length(trim(mascara))), alternativa, 1);
if (not ApenasDigitos) and (((pos(a1, 'ABCX') = 0) and (a1 <> a2)) or
((pos(a1, 'ABCX') <> 0) and (pos(a2, copy('0123458888-6799999999-0155555555-0123456789',
(pos(a1, 'ABCX') * 11 - 10), 10)) = 0))) then
erros := 1;
soma1 := 0;
soma2 := 0;
for C2 := 1 to 14 do
begin
valor := StrToInt(copy(inscricao, C2, 1)) *
(pos(copy(copy(PESOS_, (pos(peso, ALFA_) * 15 - 14), 14), C2, 1), ALFA_) - 1);
soma1 := soma1 + valor;
if valor > 9 then
valor := valor - 9;
soma2 := soma2 + valor;
end;
rotina := copy(ROTINAS_, inicio, 1);
modulo := StrToInt(copy(MODULOS_, inicio, 1)) + 2;
fator := StrToInt(copy(FATORES_, posicao, 1));
if pos(rotina, 'A22') <> 0 then
soma1 := soma2;
if pos(rotina, 'B00') <> 0 then
soma1 := soma1 * 10;
if pos(rotina, 'C11') <> 0 then
soma1 := soma1 + (5 + 4 * fator);
if pos(rotina, 'D00') <> 0 then
digito := soma1 mod modulo;
if pos(rotina, 'E12') <> 0 then
digito := modulo - (soma1 mod modulo);
if digito = 10 then
digito := 0;
if digito = 11 then
digito := fator;
if (copy(inscricao, pos(copy('XY', alternativa, 1), mascara), 1) <> IntToStr(digito)) then
erros := 1;
end;
result := (erros = 0);
end;
end;
[ NOTAS ]
02/05/08 - Ajustes na validação de TO
11/07/08 - Ajustes para validar a nova inscrição de PE
31/07/08 - Ajustes na validação de RN com 10 digitos
31/07/08 - Ajustes na validação de RO quando o resultado do módulo era 10 ou 11


July 15th, 2008 at 8:48 am
Ótimo trabalho…
Ajuda bastante a comunidade…
Obrigado
Ricardo
July 30th, 2008 at 8:05 pm
Parabéns pelo código e pela iniciativa,
eu admiro muito atitudes despreendidas iguais a sua.
Um grande abraço.
Giba
July 31st, 2008 at 8:16 am
Parabéns,
Iniciativas como essa que todos precisavam ter.
Um forte abraço.
Pportellaa
July 31st, 2008 at 8:27 am
Parabens Paulo!
Excelente iniciativa.
Hélio
July 31st, 2008 at 9:45 am
Como todos já falaram,
parabéns pela iniciativa e sucessos.
August 27th, 2008 at 8:00 pm
Parabéns pelo trabalho.
Lógica muito boa.
October 27th, 2008 at 8:35 am
Parabens cara muito boa validação.
Eu faria apenas uma alteração,
ali onde vc usa :
IE := trim(uppercase(IE));
eu colocaria o mesmo para UF, pela maneira que vc testa logo abaixo.
IE := trim(uppercase(IE));
UF := trim(uppercase(UF));
Só isso, no mais perfeito.
Grande abraço!
November 19th, 2008 at 8:21 am
Olá, não funcionou para o estado MT, pois nem sempre são digitados os 0(zeros) a frente.
Alterei assim pra funcionar:
mascara := copy(MASCARAS_, pos(copy(MASCARA_, posicao, 1), ALFA_) * 15 - 14, 14);
while length(inscricao) < length(trim(mascara)) do
inscricao := ‘0′ + inscricao;
if length(inscricao) length(trim(mascara)) then
continue;
November 19th, 2008 at 9:15 am
A função deve receber como parâmetro a IE conforme a mascara definida para cada estado, assim sendo a abordagem inicial é valida.
Mesmo assim,obrigado pela sugestão…
[]’s