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.