Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
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');
Muito bom, cara!
Quebrou uma floresta!
Valeu mestre pela sugestão!
Realmente, não precisou alterar o código da rotina ou criar uma condição IF..THEN para a chamada CALL.
O QV cria os dois campos CPF e CNPJ derivados do campo original "contas_cpf_cnpj" da minha base de dados.
Outro esclarecimento : Caso eu queira criar um campo único para usar como dimensão com os campos CPF e CNPJ?
Grato mais uma vez
Edson Costa
Que bom que deu certo Edson.
Tem que entender melhor a situação, vou imaginar e escrever aqui, você avalia o caso.
1. Se na origem dos dados está junto, dependendo o volume, não separe, altere a rotina para fazer a formatação dependendo do tipo de dados, CPF uma coisa CNPJ outra. Com isso, no layout, já terá o dado no mesmo campo único, mas... para o usuário fazer pesquisa, não precisa está no mesmo campo, ele usa o objeto pesquisa e o próprio Qlik já resolve o problema. Só é necessário ter as duas informações no mesmo campo, se for fazer um gráfico, tabela... sei lá! Não faz sentido ter duas informações diferente no mesmo campo.
2. Se na origem está separado, faz a formatação antes de concatenar esses dois campos em um só, no entanto, vale o aviso anterior, não consigo imaginar uma análise onde ter essas duas informações sejam úteis.
Cada caso é um caso, você entende do teu negócio e deve ter algum detalhe para que isso seja útil.
Abraço.
Bom dia Aderlan e demais camaradas!
De fato a base de dados que eu possuo trás as informações de CPF e de CNPJ no mesmo campo (cerca de 17.000 registros). Os registros de CPF e de CNPJ vem no mesmo campo por que são utilizados como ID de pessoas (físicas e jurídicas) de contas bancárias.
Por isso que as duas informações estão no mesmo campo, porque estão sendo utilizadas como ID de titulares de contas bancárias (independente se forem pessoas físicas ou jurídicas).
Eu consegui criar dois campos, utilizando objeto LISTA, com as informações por CPF e CNPJ, porém ,o meu objetivo é apresentar os valores de CPF e de CNPJ formatados no mesmo campo.
Grato mais uma vez!
Edson Costa
Bom dia
Este script funciona perfeitamente para uma tabela. No meu caso, eu tenho diversas tabelas de diversas fontes ontem tem o campo CPF onde há tabelas que já vem com a mascara da fonte e outras que vem sem mascara.
Ao chamar o formata numero na primeira tabela, ele funciona perfeitamente, porem quando vou chamar pela segunda vez o pelo script do formata numero ela dropava o campo CPF de todas tabelas carregadas anteriormente. Resolvi isso colocando no script assim: DROP Field [$(Campo)] from [$(Tabela)];
Só que agora esta dando um segundo erro, pois a função RENAME não pode ser usada duas vezes para o mesmo campo, pois no script considera que ja foi renomeado uma vez (ao chamar o formata numero pela primeira vez) o campo CPF Formatado para CPF.
Alguma sugestão de como corrigir isso?
Precisava que esse Formata Numero fosse utilizado para cada tabela individualmente