Essa biblioteca é uma coleção de funções para validar CNPJ, CPF, Inscrições Estaduais e chaves de acesso de documentos eletrônicos. Opcionalmente, também retorna a formatação adequada no caso do CNPJ e CPF, ou um objeto com alguns dados da chave de acesso (como o número da nota fiscal ou CNPJ emissor por exemplo). Um fato interessante é que notei que a maioria dos cálculos de dígitos verificadores se baseia no modulo 11. Então fiz uma função somente para calcular o módulo 11 para reaproveitá-la em outras situações.
Devo confessar que não fiz testes exaustivos, pois minha base de dados continha majoritariamente inscrições estaduais de MG. Por favor, reportem possíveis problemas que irei corrigir.
Code: Select all
; Autor: pedro45_vs
; AutoHotkey v2.0.2
#Requires AutoHotkey v2.0
; Parâmetros
; ----------------------------------------------------------------------------
; CNPJ => String. CNPJ a ser validado. Não importa se está com ou sem pontuação
; pad => VarRef, Opcional. Variável de retorno da string com padding de zeros à esquerda
; form => VarRef, Opcional. Variável de retorno da string formatada com pontuação
;
; Saida => Boleano. Verdadeiro se for um CNPJ válido.
validaCNPJ(CNPJ, &pad:='', &form:='')
{
CNPJ := RegExReplace(CNPJ, '\D'), pad := Format('{:014}', CNPJ)
form := SubStr(pad, 1, 2) '.' SubStr(pad, 3, 3) '.'
. SubStr(pad, 6, 3) '/' SubStr(pad, 9, 4) '-' SubStr(pad, 13, 2)
return validaMod11(SubStr(pad, 1, 13)) and validaMod11(SubStr(pad, 1, 14)) ? true : false
}
; Parâmetros
; ----------------------------------------------------------------------------
; CPF => String. CPF a ser validado. Não importa se está com ou sem pontuação
; pad => VarRef, Opcional. Variável de retorno da string com padding de zeros à esquerda
; form => VarRef, Opcional. Variável de retorno da string formatada com pontuação
;
; Saida => Boleano. Verdadeiro se for um CPF válido.
validaCPF(CPF, &pad:='', &form:='')
{
CPF := RegExReplace(CPF, '\D'), pad := Format('{:011}', CPF)
form := SubStr(pad, 1, 3) '.' SubStr(pad, 4, 3) '.' SubStr(pad, 7, 3) '-' SubStr(pad, 10, 2)
if CPF = '00000000000' or CPF = '11111111111' or CPF = '22222222222' or CPF = '33333333333'
or CPF = '44444444444' or CPF = '55555555555' or CPF = '66666666666'
or CPF = '77777777777' or CPF = '88888888888' or CPF = '99999999999'
return false
soma:=0
For n in [10,9,8,7,6,5,4,3,2]
soma += n * SubStr(pad, A_Index, 1)
dv := 11 - Mod(soma, 11) > 9 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(pad, 10, 1)
return false
soma:=0
For n in [11,10,9,8,7,6,5,4,3,2]
soma += n * SubStr(pad, A_Index, 1)
dv := 11 - Mod(soma, 11) > 9 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(pad, 11, 1)
return false
return true
}
; A documentação das regras de validação foram extraídas do site Sintegra.
; AM, CE, ES, PB, PI, SC e SE usam o mesmo cálculo do dígito verificador
; AC e DF também usam a mesma fórmula
; Obs.: A fórmula do Tocantins está errada no site do Sintegra
; Parâmetros
; -------------------------------------------------------------------------------
; IE => String da inscrição estadual. Não importa se está com ou sem pontuação
; UF => Abreviação da UF ou código do IBGE para validação
; IEpad => VarRef, Opcional. string formatada com o padding dos zeros à esquerda
;
; Saída => Boleano. Verdadeiro se for uma IE válida.
validaIE(IE, UF, &IEpad:='')
{
IE := RegExReplace(IE, '\D')
if UF = 'AM' or UF = 13 or UF = 'CE' or UF = 23 or UF = 'ES' or UF = 32 or UF = 'PB' or UF = 25
or UF = 'PI' or UF = 22 or UF = 'SC' or UF = 42 or UF = 'SE' or UF = 28
{
if StrLen(IE) > 9 or !validaMod11(IE)
return false
IEpad := Format('{:09}', IE)
return true
}
if UF = 'AC' or UF = 12 or UF = 'DF' or UF = 53
{
if StrLen(IE) > 13 or !validaMod11(SubStr(IE, 1, 12)) or !validaMod11(SubStr(IE, 1, 13))
return false
IEpad := Format('{:013}', IE)
return true
}
if UF = 'MT' or UF = 51
{
if StrLen(IE) > 11 or !validaMod11(IE)
return false
IEpad := Format('{:011}', IE)
return true
}
if UF = 'RS' or UF = 43
{
if StrLen(IE) > 10 or !validaMod11(IE)
return false
IEpad := Format('{:010}', IE)
return true
}
if UF = 'RO' or UF = 11
{
if StrLen(IE) > 14 or !validaMod11(IE)
return false
IEpad := Format('{:014}', IE)
return true
}
if UF = 'MA' or UF = 21
{
if SubStr(IE, 1, 2) != 12 or StrLen(IE) != 9 or !validaMod11(IE)
return false
IEpad := IE
return true
}
if UF = 'MS' or UF = 50
{
if SubStr(IE, 1, 2) != 28 or StrLen(IE) != 9 or !validaMod11(IE)
return false
IEpad := IE
return true
}
if UF = 'PA' or UF = 15
{
if SubStr(IE, 1, 2) != 15 or StrLen(IE) != 9 or !validaMod11(IE)
return false
IEpad := IE
return true
}
if UF = 'TO' or UF = 17
{
if StrLen(IE) != 9 or SubStr(IE, 1, 2) != 29 or !validaMod11(IE)
return false
IEpad := IE
return true
}
if UF = 'GO' or UF = 52
{
if StrLen(IE) != 9 or !validaMod11(IE)
return false
d := SubStr(IE, 1, 2)
if d != 10 and d != 11 and d != 20 and d != 29
return false
IEpad := IE
return true
}
if UF = 'MG' or UF = 31
{
IE := IEpad := Format('{:013}', IE)
if StrLen(IE) != 13
return false
strTrb := SubStr(IE, 1, 3) '0' SubStr(IE, 4, 8)
soma := 0
Loop 12
somaAlgarismos .= SubStr(strTrb, A_index, 1) * (Mod(A_Index, 2) ? 1 : 2)
Loop StrLen(somaAlgarismos)
soma += SubStr(somaAlgarismos, A_index, 1)
sub := (SubStr(soma, 1, -1) . 0) + 10 - soma
dv := sub = 10 ? 0 : sub
if dv != SubStr(IE, 12, 1)
return false
soma := 0
For n in [3,2,11,10,9,8,7,6,5,4,3,2]
soma += n * SubStr(IE, A_Index, 1)
dv := Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(IE, 13, 1)
return false
return true
}
if UF = 'AL' or UF = 27
{
if StrLen(IE) != 9 or SubStr(IE, 1, 2) != 24
return false
soma := 0
For n in [9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
produto := soma * 10
resto := produto - Integer(produto / 11) * 11
dv := resto = 10 ? 0 : resto
if dv != SubStr(IE, 9, 1)
return false
IEpad := IE
return true
}
if UF = 'PR' or UF = 41
{
IE := IEpad := Format('{:010}', IE)
if StrLen(IE) != 10
return false
soma := 0
For n in [3,2,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(IE, 9, 1)
return false
soma := 0
For n in [4,3,2,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(IE, 10, 1)
return false
return true
}
if UF = 'RJ' or UF = 33
{
IE := IEpad := Format('{:08}', IE)
if StrLen(IE) > 8
return false
soma := 0
For n in [2,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
if dv != SubStr(IE, 8, 1)
return false
return true
}
if UF = 'RR' or UF = 14
{
if StrLen(IE) != 9 or SubStr(IE, 1, 2) != 24
return false
soma := 0
For n in [1,2,3,4,5,6,7,8]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 9)
if dv != SubStr(IE, 9, 1)
return false
IEpad := IE
return true
}
if UF = 'AP' or UF = 16
{
IE := IEpad := Format('{:09}', IE)
if SubStr(IE, 1, 2) != '03' or StrLen(IE) != 9
return false
strTrb := SubStr(IE, 1, 8)
if strTrb >= 03000001 and strTrb <= 03017000
p := 5, d := 0
if strTrb >= 03017001 and strTrb <= 03019022
p := 9, d := 1
if strTrb >= 03019023
p := 0, d := 0
soma := p
For n in [9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := 11 - Mod(soma, 11) = 10 ? 0 : 11 - Mod(soma, 11) = 11 ? d : 11 - Mod(soma, 11)
if dv != SubStr(IE, 9, 1)
return false
return true
}
if UF = 'BA' or UF = 29
{
if StrLen(IE) > 9
return false
if StrLen(IE) = 8
{
if SubStr(IE, 1, 1) <= 5 or SubStr(IE, 1, 1) = 8
{
soma := 0
For n in [7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 10) ? 10 - Mod(soma, 10) : 0
if dv != SubStr(IE, 8, 1)
return false
soma := 0
For n in [8,7,6,5,4,3]
soma += SubStr(IE, A_Index, 1) * n
soma += 2 * SubStr(IE, 8, 1)
dv := Mod(soma, 10) ? 10 - Mod(soma, 10) : 0
if dv != SubStr(IE, 7, 1)
return false
return true
}
if SubStr(IE, 1, 1) = 6 or SubStr(IE, 1, 1) = 7 or SubStr(IE, 1, 1) = 9
{
dv := modulo11(SubStr(IE, 1, 6))
if dv != SubStr(IE, 8, 1)
return false
str := SubStr(IE, 1, 6) . SubStr(IE, 8, 1)
dv := modulo11(str)
if dv != SubStr(IE, 7, 1)
return false
return true
}
}
if StrLen(IE) = 9
{
if SubStr(IE, 2, 1) <= 5 or SubStr(IE, 2, 1) = 8
{
soma := 0
For n in [8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma, 10) ? 10 - Mod(soma, 10) : 0
if dv != SubStr(IE, 9, 1)
return false
soma := 0
For n in [9,8,7,6,5,4,3]
soma += SubStr(IE, A_Index, 1) * n
soma += 2 * SubStr(IE, 9, 1)
dv := Mod(soma, 10) ? 10 - Mod(soma, 10) : 0
if dv != SubStr(IE, 8, 1)
return false
return true
}
if SubStr(IE, 2, 1) = 6 or SubStr(IE, 2, 1) = 7 or SubStr(IE, 2, 1) = 9
{
dv := modulo11(SubStr(IE, 1, 7))
if dv != SubStr(IE, 9, 1)
return false
str := SubStr(IE, 1, 7) . SubStr(IE, 9, 1)
dv := modulo11(str)
if dv != SubStr(IE, 8, 1)
return false
return true
}
}
}
if UF = 'PE' or UF = 26
{
if StrLen(IE) <= 9
{
IEpad := Format('{:09}', IE)
if !validaMod11(SubStr(IE, 1, 8))
return false
if !validaMod11(SubStr(IE, 1, 9))
return false
return true
}
else if StrLen(IE) > 9 and StrLen(IE) <= 14
{
IE := IEpad := Format('{:014}', IE)
soma := 0
For n in [5,4,3,2,1,9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
resto := 11 - Mod(soma, 11)
dv := resto > 9 ? 10 - resto : resto
if dv != SubStr(IE, 14, 1)
return false
return true
}
else
return false
}
if UF = 'RN' or UF = 24
{
if SubStr(IE, 1, 2) != 20 or StrLen(IE) > 10
return false
if StrLen(IE) = 9
{
soma := 0
For n in [9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma * 10, 11) > 9 ? 0 : Mod(soma * 10, 11)
if dv != SubStr(IE, 9, 1)
return false
IEpad := IE
return true
}
else if StrLen(IE) = 10
{
soma := 0
For n in [10,9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := Mod(soma * 10, 11) > 9 ? 0 : Mod(soma * 10, 11)
if dv != SubStr(IE, 10, 1)
return false
IEpad := IE
return true
}
else
return false
}
if UF = 'SP' or UF = 35
{
if SubStr(IE, 1, 1) = 'P'
{
soma := 0
For n in [1,3,4,5,6,7,8,10]
soma += SubStr(IE, A_Index, 1) * n
dv := SubStr(Mod(soma, 11), -1)
if dv != SubStr(IE, 10, 1)
return false
}
else
{
IE := IEpad := Format('{:012}', IE)
if StrLen(IE) > 12
return false
soma := 0
For n in [1,3,4,5,6,7,8,10]
soma += SubStr(IE, A_Index, 1) * n
dv := SubStr(Mod(soma, 11), -1)
if dv != SubStr(IE, 9, 1)
return false
soma := 0
For n in [3,2,10,9,8,7,6,5,4,3,2]
soma += SubStr(IE, A_Index, 1) * n
dv := SubStr(Mod(soma, 11), -1)
if dv != SubStr(IE, 12, 1)
return false
}
return true
}
}
; Parâmetros
; ----------------------------------------------------------------------------
; Chave => String. Chave de acesso. Não importa se está com ou sem pontuação
; obj => VarRef. Opcional. Objeto com as propriedades da chave de acesso
; Saida => Boleano. Verdadeiro se for um Chave válida válido.
; Se especificado, a função também retornará um objeto com as seguintes propriedades:
; ----------------------------------------------------------------------------------
; UF -> abreviação do estado
; data -> ano e mês de emissão da nota
; CNPJ -> CNPJ do emissor da nota
; modelo -> modelo da nota. NFe, CTe, etc...
; serie -> série do documento eletrônico
; nNF -> número do documento já convertido em inteiro
; tpEmissao -> tipo de emissão da nota. Normal, Contingência, etc...
validaChave(chave, &obj:='')
{
chave := RegExReplace(chave, '\D')
if StrLen(chave) != 44 or !validaMod11(chave)
return false
cUF := Map(11, 'RO', 12, 'AC', 13, 'AM', 14, 'RR', 15, 'PA',
16, 'AP', 17, 'TO', 21, 'MA', 22, 'PI', 23, 'CE', 24, 'RN',
25, 'PB', 26, 'PE', 27, 'AL', 28, 'SE', 29, 'BA', 31, 'MG',
32, 'ES', 33, 'RJ', 35, 'SP', 41, 'PR', 42, 'SC', 43, 'RS',
50, 'MS', 51, 'MT', 52, 'GO', 53, 'DF' )
obj := {UF: cUF[+SubStr(chave,1,2)], data: '20' SubStr(Chave,3,4),
CNPJ: SubStr(chave,7,14), modelo: SubStr(chave,21,2), serie: SubStr(chave,23,3),
nNF: +SubStr(chave,26,9), tpEmissao: SubStr(chave,35,1)}
return true
}
; Retorna verdadeiro se o digito verificador estiver correto
; Esta é uma fórmula muito comum e por isso a função pode ser
; reutilizada em diferentes validações
validaMod11(str)
{
peso := [2,3,4,5,6,7,8,9], soma := 0
Loop StrLen(str) - 1
{
i := Mod(A_Index, 8) ? Mod(A_Index, 8) : 8
soma += peso[i] * SubStr(str, -A_index -1, 1)
}
dv := Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
return dv = SubStr(str, -1) ? true : false
}
; Retorna o dígito verificador do módulo 11
; Usei essa função para tentar simplificar o cálculo da BA
modulo11(str)
{
peso := [2,3,4,5,6,7,8,9], soma := 0
Loop StrLen(str)
{
i := Mod(A_Index, 8) ? Mod(A_Index, 8) : 8
soma += peso[i] * SubStr(str, -A_index, 1)
}
return Mod(soma, 11) < 2 ? 0 : 11 - Mod(soma, 11)
}