[Ahk v2] - Valide CNPJ, CPF, Ins Est e Chave de acesso

Compartilhe seus scripts, funções, ferramentas e programas

Moderator: Gio

pedro45_vs
Posts: 39
Joined: 28 Jun 2020, 18:46

[Ahk v2] - Valide CNPJ, CPF, Ins Est e Chave de acesso

22 Feb 2023, 16:44

Às vezes precisamos checar se um valor está digitado corretamente, seja para prevenir erros de digitação ou para validar algum dado em um banco de dados.

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)
}
pedro45_vs
Posts: 39
Joined: 28 Jun 2020, 18:46

Re: [Ahk v2] - Valide CNPJ, CPF, Ins Est e Chave de acesso

22 Feb 2023, 16:53

Aqui está alguns exemplos de uso:

Por motivos óbvios, todos esses dados são fictícios, gerados ou copiados de exemplos disponíveis na internet.

Code: Select all

#Include valida.ahk

MsgBox validaCPF('72353373038',, &form) ; -> 1 
MsgBox form ; -> 723.533.730-38

Msgbox validaCNPJ(9947384000129, &pad, &form) ; -> 1
MsgBox pad '`n' form 
; -> 09947384000129 
; -> 09.947.384/0001-29

Msgbox validaIE('062.307.904/0081', 'MG') ; -> 1

MsgBox validaChave('2219090144272100012355001000005418117417368–1', &obj)
MsgBox obj.cnpj '`n' obj.data '`n' obj.modelo '`n' obj.nNF '`n' obj.serie
; -> 01442721000123
; -> 201909
; -> 55
; -> 5418
; -> 001
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: [Ahk v2] - Valide CNPJ, CPF, Ins Est e Chave de acesso

23 Feb 2023, 08:57

Excelente Pedro45_vs, obrigado por compartilhar :thumbup:

Isso será de grande ajuda para as telas de cadastros de quem estiver criando programas empresariais (cliente, fornecedor, etc).

Return to “Scripts e Funções”

Who is online

Users browsing this forum: No registered users and 90 guests