Tratando entradas em formulários
Como você deve saber, podemos usar caixas de texto em formulários para digitação, que são muito úteis para obter dados pelo usuário. Porém, muitas vezes também precisamos impor restrições, para que a entrada do usuário não seja inválida e possa gerar erros no código.
O usuário pode, por exemplo, colocar espaços em branco antes
ou depois do texto. Isto pode ser um problema, por exemplo, quando for preciso
comparar a entrada com um dado existente, a fim de evitar duplicidade de dados.
Assim sendo, é uma boa prática sempre usar o método Trim quando receber entradas do usuário. Veja o exemplo abaixo:
Private Sub txtNome_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "[" & frmCadastro.txtNome & "]"
frmCadastro.txtNome =
Trim(frmCadastro.txtNome)
Debug.Print
"[" & frmCadastro.txtNome & "]"
End Sub
O evento Exit
atuará quando o cursor sair da caixa de texto txtNome. Executando um teste colocando " Fulano
" (três espaços de cada lado), teremos a seguinte saída na Verificação imediata:
[ Fulano ]
[Fulano]
A primeira linha exibe o texto recebido entre colchetes
(colocados aqui apenas para melhor visualizar os espaços extras) e a segunda
linha mostra o resultado após usar o Trim.
Porém, o usuário também pode colocar espaços a mais entre as palavras da
entrada. Neste caso, será necessário deixar o código um pouco mais sofisticado:
Private Sub txtNome_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "[" & frmCadastro.txtNome & "]"
frmCadastro.txtNome =
Trim(frmCadastro.txtNome)
Do While
InStr(frmCadastro.txtNome, "
")
frmCadastro.txtNome = Replace(frmCadastro.txtNome, " ", " ")
Loop
Debug.Print
"[" & frmCadastro.txtNome & "]"
End Sub
Aqui usei uma estrutura de repetição para verificar se há
dois espaços consecutivos. Se não houver, nem entrará na estrutura. Se houver,
ele executará a ação de substituir dois espaços por um até que não haja mais
ocorrências. Veja um exemplo da execução desse código:
[ Fulano de tal ]
[Fulano de tal]
Dependendo da necessidade, pode-se utilizar também os
métodos UCase e LCase caso precise que a entrada seja toda em maiúsculas ou
minúsculas, respectivamente.
É possível estipular um limite de caracteres em uma
entrada. Isso é feito utilizando a
propriedade MaxLength da caixa de
texto. Pode ser feito diretamente nas propriedades do objeto no formulário ou
via código:
frmCadastro.txtNome.MaxLength = 25
Este comando definirá o limite de 25 caracteres para a caixa
de texto txtNome, sendo a melhor
forma de cumprir um limite de tamanho, pois o usuário não conseguirá digitar
além dessa quantidade. Use quando houver restrição de espaço. Em campos de nome
provavelmente não haverá restrição, mas há outros casos em que é necessário.
Você pode preferir alterar nas propriedades do formulário, mas há casos em que pode ser necessário fazer isso via código. Por exemplo, você tem um campo que pode receber o número de CPF ou CNPJ. Neste caso, você precisará também de botões de opção para selecionar se é pessoa física ou jurídica e, com base nessa seleção, estipular se o limite de caracteres será 11 ou 14. Observe o código a seguir:
Private Sub optFisica_Click()
txtCPFCNPJ.Enabled = True
txtCPFCNPJ.MaxLength =
11
txtCPFCNPJ.SetFocus
End Sub
Private Sub optJuridica_Click()
txtCPFCNPJ.Enabled = True
txtCPFCNPJ.MaxLength =
14
txtCPFCNPJ.SetFocus
End Sub
Assim que o usuário clicar em uma das opções, a caixa de
texto txtCPFCNPJ será habilitada,
terá o tamanho máximo definido e receberá o foco do cursor. Note que para
funcionar adequadamente a propriedade Enabled
de txtCPFCNPJ deve ser definida como
False por padrão, evitando que entre no campo sem selecionar o tipo de pessoa
antes.
Para ficar melhor ainda, podemos restringir a digitação apenas a
números, evitando que o usuário digite letras, sinais de pontuação ou outros símbolos. Para isso
precisamos editar o evento KeyPress
da caixa de texto, que trata exatamente disso:
Private Sub txtCPFCNPJ_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
Select Case KeyAscii
Case
Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
Esse evento traz um parâmetro KeyAscii, que representa o caractere digitado. Só precisamos
validar o que está sendo recebido e permitir ou não o valor digitado. Asc permite que você possa usar a
própria representação do caractere entre aspas ao invés do código associado ao
caractere. É bem mais fácil entender Case Asc("0")
To Asc("9") do que Case 48
To 57, certo? Perceba que não há nenhuma instrução após essa linha, logo em
seguida vem Case Else. Mesmo sem
instrução, o Excel vai sair do Select Case e vai prosseguir quando se o caractere digitado estiver entre
0 e 9. Qualquer outro caractere que for digitado entrará no Case Else, que irá descartar esse
caractere.
Perceba que você pode permitir outros caracteres, adicionando um Case antes do Case Else. Assim você pode permitir traços, pontos, parênteses etc quando for preciso. Mas o usuário poderá digitar em posições erradas, o que vai comprometer a integridade do dado. Há uma forma melhor de colocar pontos, traços etc quando eles são fixos. Vejamos este exemplo de caixa de texto para telefone:
Private Sub txtTelefone_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
txtTelefone.MaxLength = 13
Select Case KeyAscii
Case
Asc("0") To Asc("9")
If
txtTelefone.SelStart = 0 Then
txtTelefone.SelText = "("
ElseIf
txtTelefone.SelStart = 3 Then
txtTelefone.SelText = ")"
ElseIf
txtTelefone.SelStart = 8 Then
txtTelefone.SelText = "-"
End If
Case Else
KeyAscii = 0
End Select
End Sub
Note que foi acrescentado um bloco If que atuará quando for digitado um número. A propriedade SelStart é um índice, determina a posição
do texto onde o cursor está. Fique atento que o índice inicia em zero. SelText irá acrescentar um caractere na
posição se for o caso. Há ainda a propriedade SelLength, que trata do comprimento do texto selecionado, mas não
precisamos usá-lo aqui. Experimente o código e veja como fica muito prático
deixar a própria caixa de texto colocando os parênteses e o traço do número de
telefone. Note que o limite está em 13 caracteres, para números de celular com
9 dígitos é preciso aumentar o limite e alterar a posição do hífen.
E se quisermos fazer o mesmo com o nosso campo de CPF/CNPJ
do exemplo anterior? Podemos melhorar o código, codificando a mesma validação
para as posições de cada um. Neste exemplo vou ainda acrescentar uma enumeração (se não conhece veja meu artigo 6) para determinar o tipo de pessoa:
Enum enumPessoa
Fisica = 0
Juridica = 1
End Enum
Private Pessoa As enumPessoa
Private Sub optFisica_Click()
Pessoa = Fisica
txtCPFCNPJ.Enabled =
True
txtCPFCNPJ.MaxLength =
14
txtCPFCNPJ.Value =
""
txtCPFCNPJ.SetFocus
End Sub
Private Sub optJuridica_Click()
Pessoa = Juridica
txtCPFCNPJ.Enabled =
True
txtCPFCNPJ.MaxLength =
18
txtCPFCNPJ.Value =
""
txtCPFCNPJ.SetFocus
End Sub
Private Sub txtCPFCNPJ_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
Select Case KeyAscii
Case Asc("0") To
Asc("9")
Select Case
Pessoa
Case
Fisica
If
txtCPFCNPJ.SelStart = 3 Or txtCPFCNPJ.SelStart = 7 Then
txtCPFCNPJ.SelText = "."
ElseIf
txtCPFCNPJ.SelStart = 11 Then
txtCPFCNPJ.SelText = "-"
End If
Case
Juridica
If
txtCPFCNPJ.SelStart = 2 Or txtCPFCNPJ.SelStart = 6 Then
txtCPFCNPJ.SelText = "."
ElseIf
txtCPFCNPJ.SelStart = 10 Then
txtCPFCNPJ.SelText = "/"
ElseIf
txtCPFCNPJ.SelStart = 15 Then
txtCPFCNPJ.SelText = "-"
End If
End Select
Case Else
KeyAscii = 0
End Select
End Sub
Alterei as rotinas de seleção de opção para definir o objeto
Pessoa, bem como esvaziar o campo txtCPFCNPJ quando a seleção for trocada,
porque senão os caracteres separadores permanecerão nas posições anteriores e
acaba gerando uma confusão. Se o usuário digitar alguns números e depois voltar
para o começo para acrescentar algum zero, os pontos não irão ficar no lugar.
Assim, o usuário pode deixar os dados com problemas. Para sanar isso temos duas
alternativas: verificar e atualizar enquanto digita o dado, o que é muito
complexo e trabalhoso, ou verificar após o cursor sair da caixa de texto. Esta opção
parece mais fácil de fazer. Analise o código abaixo:
Private Sub txtCPFCNPJ_Exit(ByVal Cancel As
MSForms.ReturnBoolean)
If Len(txtCPFCNPJ) > 0 Then
Select Case Pessoa
Case Fisica
If
Len(txtCPFCNPJ) < 14 Or Mid(txtCPFCNPJ, 4, 1) <> "." Or _
Mid(txtCPFCNPJ, 8, 1) <> "." Or Mid(txtCPFCNPJ, 11, 1)
<> "-" Then
txtCPFCNPJ = Trim(Replace(Replace(Replace(txtCPFCNPJ.Value, _
".", ""), "-", ""), "/",
""))
txtCPFCNPJ = String(11 - Len(txtCPFCNPJ),
"0") & txtCPFCNPJ
txtCPFCNPJ = Left(txtCPFCNPJ, 3) & "." &
Mid(txtCPFCNPJ, 4, 3) & _
"." & Mid(txtCPFCNPJ, 7, 3) & "-" & Right(txtCPFCNPJ, 2)
End If
Case Juridica
If
Len(txtCPFCNPJ) < 18 Or Mid(txtCPFCNPJ, 3, 1) <> "." Or _
Mid(txtCPFCNPJ, 7, 1) <> "." Or Mid(txtCPFCNPJ, 11, 1)
<> "/" Or _
Mid(txtCPFCNPJ, 16, 1) <> "-" Then
txtCPFCNPJ = Trim(Replace(Replace(Replace(txtCPFCNPJ.Value, _
".", ""), "-", ""), "/",
""))
txtCPFCNPJ = String(14 - Len(txtCPFCNPJ), "0") &
txtCPFCNPJ
txtCPFCNPJ = Left(txtCPFCNPJ, 2) & "." & Mid(txtCPFCNPJ,
3, 3) & _
"." & Mid(txtCPFCNPJ, 6, 3) & "/" & Mid(txtCPFCNPJ, 9, 4)
& _
"-" & Right(txtCPFCNPJ, 2)
End If
End Select
End If
End Sub
Aqui utilizamos o evento Exit
da caixa de texto txtCPFCNPJ, que
executa logo que o cursor sai da caixa de texto. A primeira validação serve
para verificar se há conteúdo, se algum número foi digitado. Se nada foi
digitado, nada acontece e o campo continua vazio. Se algo foi digitado, é
verificado se a pessoa é física ou jurídica, para verificar se o comprimento está no limite e se
os separadores estão nas posições corretas. Caso isso haja algo errado, o
número é reformatado, tirando os símbolos não numéricos e depois recompondo os
separadores nas posições corretas.
Experimente o código pronto e sinta-se livre para usá-lo em
algum formulário já existente. Pratique outras formas também, use o código como inspiração para outros modelos existentes.
Adendo:
O Excel tem um bug quando recebe datas pelo formulário. Acontece muito de datas como 04/12 serem transformadas em 12/04. Aparentemente, ele considera datas mm/dd/yyyy a menos que o mm seja maior do que 12, quando considera como dd/mm/yyyy. A solução que encontrei é usar DateValue() para converter a data apropriadamente. Esse comando deve ser usado quando você estiver trazendo o valor do campo do formulário, como no exemplo abaixo:
DataNascimento = DateValue(txtDataNascimento.Text)
Espero ter contribuído.
Adendo:
O Excel tem um bug quando recebe datas pelo formulário. Acontece muito de datas como 04/12 serem transformadas em 12/04. Aparentemente, ele considera datas mm/dd/yyyy a menos que o mm seja maior do que 12, quando considera como dd/mm/yyyy. A solução que encontrei é usar DateValue() para converter a data apropriadamente. Esse comando deve ser usado quando você estiver trazendo o valor do campo do formulário, como no exemplo abaixo:
DataNascimento = DateValue(txtDataNascimento.Text)
Pedro Martins
Formado em Tecnologia em Eletrônica Digital, já trabalhou como artefinalista, eletrotécnico, programador de CLP (para máquinas industriais) e analista de sistemas em sistema bancário, programando em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.
Esses artigos são muito bom! ParabensParabens!
ResponderExcluirGrato pela mensagem e por acompanhar os trabalhos Wando!
ExcluirObrigado pelo elogio ao nosso trabalho
ExcluirExcelente, Trovato!
ResponderExcluirObrigado por compartilhar conhecimento!
Queremos mais e mais!
Forte abraço!
Grato pela mensagem Robson! Vamos publicar conteúdo sempre que possível.
ExcluirE contribuidores são bem aceitos! Se quiser escrever um artigo este canal está aberto para todos!
Sucesso e bons estudos!
Estamos aqui para isso mesmo. Conhecimento restrito não é bom. Sempre é bom disseminar para que mais pessoas tenham conhecimento e possam espalhar por aí também.
ExcluirSimplesmente SENSACIONAL, obrigado por compartilhar seus conhecimentos!!!
ResponderExcluirMuito obrigado pela mensagem Mathias! Sucesso e bons estudos!
ExcluirObrigado pelo elogio. Temos muito ainda o que contribuir, pode aguardar mais pela frente.
ExcluirEste comentário foi removido pelo autor.
ResponderExcluirAlessandro, estou aprendendo com seu curso de VBA no Youtube, ainda sou novo nisso mas já comecei a criar alguns formulários para usar no trabalho. Porém, me deparei com uma situação que não consigo resolver:
ResponderExcluirComo fazer para a minha TextBox retornar a Data mais recente de um item escolhido na ComboBox?
Exemplo: tenho cadastrado o Produto A com várias datas diferentes e ao escolher ele na ComboBox queria que a TextBox retornasse a última data cadastrada (mais recente).
Obrigado pela dedicação em compartilhar seus conhecimentos, suas aulas são excelentes.
Muito bom o Artigo, porém gostaria de uma informação, sou iniciante em programação e estou fazendo um pequeno programa em VBA, estou procurando um código que valide se há um USUARIO já cadastrado no banco de dados e caso não tenha permita o cadastro.
ResponderExcluir