« 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



Topics: Delphi, Todos |

9 Responses to “Função para validar Inscrição Estadual (IE) de todos os estados”

  1. Ricardo Says:
    July 15th, 2008 at 8:48 am

    Ótimo trabalho…
    Ajuda bastante a comunidade…
    Obrigado
    Ricardo

  2. Giba do news Delphi Says:
    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

  3. Portella Says:
    July 31st, 2008 at 8:16 am

    Parabéns,
    Iniciativas como essa que todos precisavam ter.
    Um forte abraço.
    Pportellaa

  4. Hélio Oliveira Says:
    July 31st, 2008 at 8:27 am

    Parabens Paulo!
    Excelente iniciativa.
    Hélio

  5. Forrest® Says:
    July 31st, 2008 at 9:45 am

    Como todos já falaram,
    parabéns pela iniciativa e sucessos.

  6. Jonas Antunes Ramos Says:
    August 27th, 2008 at 8:00 pm

    Parabéns pelo trabalho.
    Lógica muito boa.

  7. Dayvid Ribeiro Says:
    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!

  8. Alosi Says:
    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;

  9. Paulo (CincoBytes) Says:
    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

Comments