Skip to content

Instantly share code, notes, and snippets.

@davidalves1
Last active January 24, 2024 21:06
Show Gist options
  • Star 88 You must be signed in to star a gist
  • Fork 26 You must be signed in to fork a gist
  • Save davidalves1/3c98ef866bad4aba3987e7671e404c1e to your computer and use it in GitHub Desktop.
Save davidalves1/3c98ef866bad4aba3987e7671e404c1e to your computer and use it in GitHub Desktop.
Função para formatar CNPJ e CPF, disponível em PHP e JS

PHP

function formatCnpjCpf($value)
{
  $CPF_LENGTH = 11;
  $cnpj_cpf = preg_replace("/\D/", '', $value);
  
  if (strlen($cnpj_cpf) === $CPF_LENGTH) {
    return preg_replace("/(\d{3})(\d{3})(\d{3})(\d{2})/", "\$1.\$2.\$3-\$4", $cnpj_cpf);
  } 
  
  return preg_replace("/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/", "\$1.\$2.\$3/\$4-\$5", $cnpj_cpf);
}

JS

function formatCnpjCpf(value) {
  const CPF_LENGTH = 11;
  const cnpjCpf = value.replace(/\D/g, '');
  
  if (cnpjCpf.length === CPF_LENGTH) {
    return cnpjCpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/g, "\$1.\$2.\$3-\$4");
  } 
  
  return cnpjCpf.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/g, "\$1.\$2.\$3/\$4-\$5");
}

Oracle PL/SQL (by @claudioacioli)

create function formatCnpjCpf(value varchar2) return varchar2
is
  cnpj_cpf varchar2(14) := regexp_replace(value, '(\D)', ''); 
begin
  if length(cnpj_cpf) = 11 then
    return regexp_replace(cnpj_cpf, '(\d{3})(\d{3})(\d{3})(\d{2})','\1.\2.\3-\4');
  end if;  
  return regexp_replace(lpad(cnpj_cpf, 14, '0'),'(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})','\1.\2.\3/\4-\5');
end;
@steniomoreira
Copy link

Muito bom, showw!!

@CeruttiMaicon
Copy link

Perfeito!

@danielverissimo
Copy link

Show, obrigado.

@geevb
Copy link

geevb commented Aug 6, 2020

Excelente, obrigado!

@jassriver
Copy link

Haha, incrível :D
Obrigado!

@naothomachida
Copy link

Top

@paccamicio
Copy link

Thanks a lot man. +repo

@Robson70x7
Copy link

Muito bom obrigado, já me adiantou muito não precisar fazer isso.

@gruporsf
Copy link

Muito obrigado de muita utilidade.

@vitorpedeo
Copy link

Muito obrigado, me ajudou muito.

@laanchiesi
Copy link

Valeu David, resolveu meu problema.

@samucawebdesign
Copy link

Ganhei bons minutos no meu dia rsrs, valeu!

@tiago-pontomais
Copy link

Valeu cara! Estou testando aqui

@alcantararafael
Copy link

Top!

@jubacchi
Copy link

Pessoal, não sou muito bom emfunções, tem alguma maneira de disponibilizar a aplicação no input? Não consigo fazer o retorno do tratamento.

@tiagofrancafernandes
Copy link

@jubacchi posso tentar te ajudar, mas preciso entender o que precisa.
Outra coisa, onde vc quer utilizar isso? Pra que? Talvez alguma biblioteca te ajude mais.

@allanmedeiros71
Copy link

allanmedeiros71 commented Jul 17, 2022

Obrigado.
Aproveitei a função de @claudioacioli e fiz uma versão para postgreSQL.

CREATE OR REPLACE FUNCTION public.formatCpfCnpj(cpfcnpj character varying)
 RETURNS character varying
 LANGUAGE plpgsql
AS $function$
	DECLARE
		cnpjcpf_only_numbers varchar;
	BEGIN
		cnpjcpf_only_numbers = regexp_replace(cpfcnpj, '(\D)', ''); -- Remove todos os caracteres, exceto números
		case length(cnpjcpf_only_numbers)
			when 11 then
				return regexp_replace(cnpjcpf_only_numbers, '(\d{3})(\d{3})(\d{3})(\d{2})','\1.\2.\3-\4');
			when 14 then
				return regexp_replace(cnpjcpf_only_numbers, '(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})','\1.\2.\3/\4-\5');
			else
				return cnpjcpf_only_numbers;
		END case;
	END;
$function$
;

@davidalves1
Copy link
Author

Pessoal, não sou muito bom emfunções, tem alguma maneira de disponibilizar a aplicação no input? Não consigo fazer o retorno do tratamento.

Opa, aqui tem um exemplo bem simples aplicando num input @jubacchi: https://jsfiddle.net/wbu8dgr1/
Porém, como o @tiago-pontomais bem pontuou, tem que entender o que quer fazer para saber qual o melhor caminho a seguir.

@FlavioSuarez
Copy link

FlavioSuarez commented Dec 9, 2022

Muito obrigado!!
Testei a versão PHP e deu certo, porém está falhando quando o CNPJ possui somente 13 dígitos.
Deveria adicionar '0' à esquerda...

No fim, usei str_pad() para preencher com "0"s à esquerda.
Também separei a lógica em 2 funções, uma de CNPJ e outra de CPF...
Ficou assim:

function format_CNPJ($value)
{
    $CNPJ_LENGTH = 14;
    $cnpj = preg_replace("/\D/", '', $value);
  
    if (strlen($cnpj) < $CNPJ_LENGTH) {
        $cnpj = str_pad($cnpj, $CNPJ_LENGTH, 0, STR_PAD_LEFT);
    } 

    return preg_replace("/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/", "\$1.\$2.\$3/\$4-\$5", $cnpj);        
}

function format_CPF($value)
{
    $CPF_LENGTH = 11;
    $cpf = preg_replace("/\D/", '', $value);
  
    if (strlen($cpf) < $CPF_LENGTH) {
        $cpf = str_pad($cpf, $CPF_LENGTH, 0, STR_PAD_LEFT);
    } 
  
    return preg_replace("/(\d{3})(\d{3})(\d{3})(\d{2})/", "\$1.\$2.\$3-\$4", $cpf);
}

Valeu!!

@MauricioSarmento
Copy link

MauricioSarmento commented Jan 8, 2023

em php eu consegui esta

echo $cpf = formatar_cpf_cnpj('039.943.865-35');

function formatar_cpf_cnpj($doc) {

    $doc = preg_replace("/[^0-9]/", "", $doc);
    $qtd = strlen($doc);

    if($qtd >= 11) {

        if($qtd === 11 ) {

            $docFormatado = substr($doc, 0, 3) . '.' .
                            substr($doc, 3, 3) . '.' .
                            substr($doc, 6, 3) . '.' .
                            substr($doc, 9, 2);
        } else {
            $docFormatado = substr($doc, 0, 2) . '.' .
                            substr($doc, 2, 3) . '.' .
                            substr($doc, 5, 3) . '/' .
                            substr($doc, 8, 4) . '-' .
                            substr($doc, -2);
        }

        return $docFormatado;

    } else {
        return 'Documento invalido';
    }
}

@prophetarum
Copy link

boa

@FlavioSuarez
Copy link

em php eu consegui esta

echo $cpf = formatar_cpf_cnpj('039.943.865-35');

function formatar_cpf_cnpj($doc) {

    $doc = preg_replace("/[^0-9]/", "", $doc);
    $qtd = strlen($doc);

    if($qtd >= 11) {

        if($qtd === 11 ) {

            $docFormatado = substr($doc, 0, 3) . '.' .
                            substr($doc, 3, 3) . '.' .
                            substr($doc, 6, 3) . '.' .
                            substr($doc, 9, 2);
        } else {
            $docFormatado = substr($doc, 0, 2) . '.' .
                            substr($doc, 2, 3) . '.' .
                            substr($doc, 5, 3) . '/' .
                            substr($doc, 8, 4) . '-' .
                            substr($doc, -2);
        }

        return $docFormatado;

    } else {
        return 'Documento invalido';
    }
}

Eu já peguei CNPJ válido com 13 dígitos e CPF válido com 10... Por isso separei a lógica e completei com zeros à esquerda...

@claudioacioli
Copy link

em php eu consegui esta

echo $cpf = formatar_cpf_cnpj('039.943.865-35');

function formatar_cpf_cnpj($doc) {

    $doc = preg_replace("/[^0-9]/", "", $doc);
    $qtd = strlen($doc);

    if($qtd >= 11) {

        if($qtd === 11 ) {

            $docFormatado = substr($doc, 0, 3) . '.' .
                            substr($doc, 3, 3) . '.' .
                            substr($doc, 6, 3) . '.' .
                            substr($doc, 9, 2);
        } else {
            $docFormatado = substr($doc, 0, 2) . '.' .
                            substr($doc, 2, 3) . '.' .
                            substr($doc, 5, 3) . '/' .
                            substr($doc, 8, 4) . '-' .
                            substr($doc, -2);
        }

        return $docFormatado;

    } else {
        return 'Documento invalido';
    }
}

Olá @MauricioSarmento, procure sempre utilizar as expressões regulares como na função escrita pelo @davidalves1, ela será mais performatica, deixando o php fazer o trabalho sujo por vc.

@claudioacioli
Copy link

Muito obrigado!! Testei a versão PHP e deu certo, porém está falhando quando o CNPJ possui somente 13 dígitos. Deveria adicionar '0' à esquerda...

No fim, usei str_pad() para preencher com "0"s à esquerda. Também separei a lógica em 2 funções, uma de CNPJ e outra de CPF... Ficou assim:

function format_CNPJ($value)
{
    $CNPJ_LENGTH = 14;
    $cnpj = preg_replace("/\D/", '', $value);
  
    if (strlen($cnpj) < $CNPJ_LENGTH) {
        $cnpj = str_pad($cnpj, $CNPJ_LENGTH, 0, STR_PAD_LEFT);
    } 

    return preg_replace("/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/", "\$1.\$2.\$3/\$4-\$5", $cnpj);        
}

function format_CPF($value)
{
    $CPF_LENGTH = 11;
    $cpf = preg_replace("/\D/", '', $value);
  
    if (strlen($cpf) < $CPF_LENGTH) {
        $cpf = str_pad($cpf, $CPF_LENGTH, 0, STR_PAD_LEFT);
    } 
  
    return preg_replace("/(\d{3})(\d{3})(\d{3})(\d{2})/", "\$1.\$2.\$3-\$4", $cpf);
}

Valeu!!

@FlavioSuarez, vc não precisa colocar o if strlen... se não quiser ser bem explícito, o str_pad fará por vc.

Outro ponto é, se o CNPJ com 13 e o CPF com 10 no final precisa adicionar um 0 antes para formatar corretamente, eu adicionaria esse preenchimento fora da função mantendo a função estável.

@FlavioSuarez
Copy link

OK, obrigado pelas observações!

@davidalves1
Copy link
Author

davidalves1 commented Feb 7, 2023

Hey @FlavioSuarez, obrigado pela contribuição. Como optou por separar as funções de CPF e CNPJ, não vejo a necessidade de fazer a validação, pois você já sabe quantos caracteres deve ter o CNPJ ou CPF. Assim, é só adicionar os 0 a esquerda antes de fazer a formatação, mais ou menos assim:

function format_CNPJ($value)
{
    $CNPJ_LENGTH = 14;
    $cnpj = str_pad(preg_replace("/\D/", '', $value), $CNPJ_LENGTH, 0, STR_PAD_LEFT);

    return preg_replace("/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/", "\$1.\$2.\$3/\$4-\$5", $cnpj);        
}

Ainda se preferir deixar em uma função só (que é a minha opção nesse caso), pode só mudar a verificação:

function formatCnpjCpf($value)
{
  $CPF_LENGTH = 11;
  $CNPJ_LENGTH = 14;

  $clear_value = preg_replace("/\D/", '', $value);
  $is_cpf = strlen($clear_value) <= $CPF_LENGTH;
  $pad_length = $is_cpf ? $CPF_LENGTH : $CNPJ_LENGTH;
  $cnpj_cpf = str_pad($clear_value, $pad_length, 0, STR_PAD_LEFT);
  
  if ($is_cpf) {
    return preg_replace("/(\d{3})(\d{3})(\d{3})(\d{2})/", "\$1.\$2.\$3-\$4", $cnpj_cpf);
  } 
  
  return preg_replace("/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/", "\$1.\$2.\$3/\$4-\$5", $cnpj_cpf);
}

var_dump(formatCnpjCpf("11111111111")); // string(14) "111.111.111-11"
var_dump(formatCnpjCpf("22222222222222")); // string(18) "22.222.222/2222-22"
var_dump(formatCnpjCpf("3333333333")); // string(14) "033.333.333-33"
var_dump(formatCnpjCpf("4444444444444")); // string(18) "04.444.444/4444-44"

Ainda assim, tem muita lógica fazendo dessa forma e, na minha visão, deixa muita responsabilidade para o método que deveria apenas formatar.

@kllaudyo
Copy link

kllaudyo commented Feb 7, 2023

Inclusive, @FlavioSuarez, se ainda estiver no projeto que percebeu essa circunstância, se possível, verifique ou se o campo esteja como númerio no banco de dados ou se em algum lugar o PHP antes da inserção/alteração ele esteja convertendo em numerico.
Caso seja numerico, ele remove o 0 da esquerda e acaba fazendo você necessitar adicionar depois.

@FlavioSuarez
Copy link

Vou verificar...
Obrigado @davidalves1 e @kllaudyo pelas dicas!!

@acmat
Copy link

acmat commented Mar 3, 2023

Brigadão, David!

@Edilson3012
Copy link

Muito obrigado! \o/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment