Formatar Números (CPF, CNPJ, CEP, Telefone e Celular 9 digitos)

    Olá pessoal,

     

    << versão nova 12/01/17 >>

     

    Há muitas dúvidas na comunidade sobre formatação de números.

     

    Realmente é algo que nos faz falta, entre tantas centenas de funções, ter uma que nos permita definir uma máscara personalizada e o número ser formatado adequadamente, então, inspirado pelo documento que fiz a um tempo atrás (Exportar para TXT (Sem Rótulos - No Labels)), resolvi criar uma outra rotina para formatação de números.

     

    Para quem usa Personal Edition, segue script:

    ///$tab SUB

    SUB FormataNumero(Tabela,Campo,Máscara)

     

                 //**************************************************************\\

                //                 Curitiba, 11 de janeiro de 2017                  \\

               //                Desenvolvido por Aderlan Rodrigues                    \\

              //                                                                    \\

             //                                VERSÃO 1.2                                  \\

            //                                                                          \\

           // Permitido "Números", ".", "-", "/", "(", ")" e "+" na primeira posição,  \\

          //  outros caracteres devem ser evitados ou tratados adequadamente na rotina. \\

         //      O campo ID é ncessário para evitar multiplicação da linha no JOIN             \\

        //********************************************************************************\\

     

        TRACE ## Aplicar máscara "$(Máscara)" no campo [$(Campo)] da tabela [$(Tabela)];

     

        If Mid('$(Máscara)',1,1) = '0' THEN

            LET vDigito = 1; // Começa em 1 (um) para uso na correta posição dos números

            LET vMids = 'Mid([$(Campo) Preenchido],1,1)'; // Inicializa o primeiro dígito quando numérico, para montagem dos comando que será usado no LOAD

        ELSE

            LET vDigito = 0; // Começa em 0 (zero) para uso na correta posição dos números

            LET vMids = 'Mid('&Chr(39)&'$(Máscara)'&Chr(39)&',1,1)'; // Inicializa o primeiro dígito quando textual, para montagem dos comando que será usado no LOAD

        ENDIF

     

        FOR vPosição = 2 to Len('$(Máscara)') // Percorre os caracteres da máscara para fazer a distribuição dos números abaixo

     

            SWITCH Mid('$(Máscara)',$(vPosição),1)

                CASE '0'

                     LET vDigito = $(vDigito)+1;

                    LET vMids = '$(vMids)&'&Chr(13)&

                         'Mid([$(Campo) Preenchido],'&$(vDigito)&',1)';

                CASE '.'

                    LET vMids = '$(vMids)&'&

                        Chr(39)&'.'&Chr(39);

                CASE '-'

                    LET vMids = '$(vMids)&'&

                        Chr(39)&'-'&Chr(39);

                CASE '/'

                    LET vMids = '$(vMids)&'&

                        Chr(39)&'/'&Chr(39);

                CASE '(' // O primeiro é tratado do IF, os demais são tratados aqui, caso a máscara inicie com "+", por exemplo

                    LET vMids = '$(vMids)&'&

                        Chr(39)&'('&Chr(39);

                CASE ')'

                    LET vMids = '$(vMids)&'&

                        Chr(39)&')'&Chr(39);

                CASE ' '

                    LET vMids = '$(vMids)&'&

                        Chr(39)&' '&Chr(39);

            ENDSWITCH

     

        NEXT

     

        Left Join ([$(Tabela)]) // Inclui o campo formatado a tabela de origem

        LOAD Distinct [$(Campo)],

            Dual($(vMids),[$(Campo)]) as [$(Campo) Formatado]; // Usada a função DUAL para manter a ordenação numérica após a máscara

        LOAD Distinct [$(Campo)],

            Repeat(0,SubStringCount('$(Máscara)','0')-Len([$(Campo)]))&[$(Campo)] as [$(Campo) Preenchido] // Preenche com zeros pela definição da máscara

        Resident [$(Tabela)]

        //Where IsNull([$(Campo)]);

        Where Len([$(Campo)])>0; // Na versão que foi desenvolvido a função IsNull não estava funcionando, alternativamente, foi feito dessa forma

     

        DROP Field [$(Campo)];

        RENAME Field [$(Campo) Formatado] to [$(Campo)];

     

        LET vPosição = ;

        LET vDigito = ;

        LET vMids = ;

     

    END SUB

    ///$tab Exemplo de Uso

    // Dados aleatórios para demonstração

    Pessoas:

    LOAD Num(Right(PurgeChar(Rand(),'.,'),11)) as CPF,

        'Fulano '&RecNo() as Nome,

        Num(Right(PurgeChar(Rand(),'.,'),11)) as Celular,

        KeepChar('() 9875-3200','0123456789') as Texto // O campo deve ser tratado, para manter apenas os número, antes da chamada da função

    AutoGenerate Ceil(Rand()*1000);

     

    Empresas:

    LOAD Num(Right(PurgeChar(Rand(),'.,'),14)) as CNPJ,

        'Empresa '&RecNo() as [Razão Social],

        Num(Right(PurgeChar(Rand(),'.,'),8)) as CEP,

        Num(Right(PurgeChar(Rand(),'.,'),8)) as Telefone

    AutoGenerate Ceil(Rand()*100);

     

    Concatenate (Pessoas) // Simulação de valores nulos

    LOAD * Inline [

        Código, CPF, Nome, Celular, Texto

        99, , Nulo 1, ,

        98, , Nulo 2, ,

        97, , Nulo 3, ,

    ];

     

    CALL FormataNumero('Pessoas','CPF','000.000.000-00');

    CALL FormataNumero('Pessoas','Celular','(00) 0 0000-0000');

    CALL FormataNumero('Pessoas','Texto','(00) 0 0000-0000');

     

    CALL FormataNumero('Empresas','CNPJ','00.000.000/0000-00');

    CALL FormataNumero('Empresas','CEP','00.000-000');

    CALL FormataNumero('Empresas','Telefone','+00 (00) 0000-0000');