Reaproveitando validações em formulários
Em artigos anteriores certamente você deve ter visto rotinas
de validações de dados nos formulários. Esses códigos estavam
sempre atrelados ao próprio controle do formulário, como boa
parte dos desenvolvedores praticam.
de validações de dados nos formulários. Esses códigos estavam
sempre atrelados ao próprio controle do formulário, como boa
parte dos desenvolvedores praticam.
Entretanto, caso você tenha vários campos similares, o código
ficará repetido em vários pontos do formulário. Isso pode ser
resolvido criando uma sub-rotina no formulário e fazendo os
campos chamarem essa sub-rotina. Porém, se você tiver vários
formulários, essa solução não funcionaria e teria duas opções:
copiar o código para o outro formulário (o que duplicaria o
código) ou colocar o código em um módulo à parte, de forma que
seria acessível aos diversos formulários. Esta seria uma
melhor opção.
ficará repetido em vários pontos do formulário. Isso pode ser
resolvido criando uma sub-rotina no formulário e fazendo os
campos chamarem essa sub-rotina. Porém, se você tiver vários
formulários, essa solução não funcionaria e teria duas opções:
copiar o código para o outro formulário (o que duplicaria o
código) ou colocar o código em um módulo à parte, de forma que
seria acessível aos diversos formulários. Esta seria uma
melhor opção.
Vejamos um exemplo simples, onde precisamos remover espaços
adicionais de campos de nomes. É um procedimento que deve ser
colocado em campos de nomes de usuários, de clientes, de
fornecedores, de produtos, de marcas etc. Resumindo, é uma
tarefa corriqueira que será repetida em praticamente todos os
formulários. Podemos criar uma função que arrume esse texto de
maneira bem simples:
adicionais de campos de nomes. É um procedimento que deve ser
colocado em campos de nomes de usuários, de clientes, de
fornecedores, de produtos, de marcas etc. Resumindo, é uma
tarefa corriqueira que será repetida em praticamente todos os
formulários. Podemos criar uma função que arrume esse texto de
maneira bem simples:
Function EspacosArrumados(Texto As String)
EspacosArrumados = Trim(Texto)
Do While InStr(EspacosArrumados, ”
“)
“)
EspacosArrumados
= Replace(EspacosArrumados, ” “, ” “)
= Replace(EspacosArrumados, ” “, ” “)
Loop
End Function
Essa função será usada da seguinte forma:
Private Sub txtNome_Exit(ByVal Cancel As
MSForms.ReturnBoolean)
MSForms.ReturnBoolean)
frmCadastro.txtNome =
EspacosArrumados(frmCadastro.txtNome)
EspacosArrumados(frmCadastro.txtNome)
End Sub
Essa função certamente atenderá muitas necessidades. Podemos
ainda aperfeiçoar a função, acrescentando um parâmetro
adicional para o caso de querer que o texto seja convertido em
maiúsculas, minúsculas ou iniciais maiúsculas e o resto em
minúsculas, evitando que essa codificação seja feita no módulo
do formulário. Esse parâmetro pode vir na forma de
enumeração:
ainda aperfeiçoar a função, acrescentando um parâmetro
adicional para o caso de querer que o texto seja convertido em
maiúsculas, minúsculas ou iniciais maiúsculas e o resto em
minúsculas, evitando que essa codificação seja feita no módulo
do formulário. Esse parâmetro pode vir na forma de
enumeração:
Enum enumConversao
Nenhuma = 0
Maiuscula = 1
Minuscula = 2
IniciaisMaiusculas = 3
PrimeiraMaiuscula = 4
End Enum
Function EspacosArrumados(Texto As String, _
Optional Conversao As enumConversao =
Nenhuma) As String
Nenhuma) As String
EspacosArrumados = Trim(Texto)
Do While InStr(EspacosArrumados, ”
“)
“)
EspacosArrumados
= Replace(EspacosArrumados, ” “, ” “)
= Replace(EspacosArrumados, ” “, ” “)
Loop
Select Case Conversao
Case
Maiuscula
Maiuscula
EspacosArrumados = UCase(EspacosArrumados)
Case
Minuscula
Minuscula
EspacosArrumados = LCase(EspacosArrumados)
Case
IniciaisMaiusculas
IniciaisMaiusculas
EspacosArrumados = StrConv(EspacosArrumados,
vbProperCase)
Case
PrimeiraMaiuscula
PrimeiraMaiuscula
EspacosArrumados = UCase(Left$(EspacosArrumados, 1)) &
_
LCase(Mid$(EspacosArrumados, 2, Len(EspacosArrumados) –
1))
End Select
End Function
O parâmetro Conversao foi criado como opcional, usando
a opção Nenhuma como padrão. Assim, se o campo não
precisar de conversão basta não acrescentar o parâmetro.
a opção Nenhuma como padrão. Assim, se o campo não
precisar de conversão basta não acrescentar o parâmetro.
O mesmo processo pode ser utilizado para campos com formatos
específicos, como datas. Neste caso temos duas abordagens:
quando o número está sendo digitado e quando sai do campo. O
segundo caso é mais simples, pois apenas efetua uma validação
de data, podendo inclusive verificar se a data é passada ou
futura, de acordo com a necessidade. Esta abordagem será vista
mais adiante.
específicos, como datas. Neste caso temos duas abordagens:
quando o número está sendo digitado e quando sai do campo. O
segundo caso é mais simples, pois apenas efetua uma validação
de data, podendo inclusive verificar se a data é passada ou
futura, de acordo com a necessidade. Esta abordagem será vista
mais adiante.
Quando vamos formatar um campo numérico pelo próprio módulo
do formulário, o código normalmente é algo assim:
do formulário, o código normalmente é algo assim:
Private Sub txtDataNascimento_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
MSForms.ReturnInteger)
Select Case KeyAscii
Case Asc(“0”) To
Asc(“9”)
Asc(“9”)
If Me.txtDataNascimento.SelStart = 2 Or
Me.txtDataNascimento.SelStart = 5 _
Then
Me.txtDataNascimento.SelText = “/”
End If
Case Else
KeyAscii = 0
End Select
End Sub
Entretanto, para fazer o mesmo efeito em um módulo à parte é
preciso fazer uma abordagem diferente. Observe o código a
seguir:
preciso fazer uma abordagem diferente. Observe o código a
seguir:
Function DataFormatada(ValorAtual As String, Tecla As
MSForms.ReturnInteger) As String
MSForms.ReturnInteger) As String
Dim Digito As String
Dim Valor As String
Dim Comprimento As Integer
Select Case Tecla
Case Asc(“0”)
To Asc(“9”)
To Asc(“9”)
Digito = Chr$(Tecla)
Case Else
Digito = “”
End Select
Valor = Replace(ValorAtual, “/”, “”)
& Digito
& Digito
Comprimento = Len(Valor)
If Comprimento > 4 Then
Valor =
Left$(Valor, 2) & “/” & Mid$(Valor, 3, 2) _
Left$(Valor, 2) & “/” & Mid$(Valor, 3, 2) _
& “/” & Mid$(Valor, 5, Comprimento – 4)
ElseIf Comprimento > 2 Then
Valor =
Left$(Valor, 2) & “/” & Mid$(Valor, 3, Comprimento
– 2)
Left$(Valor, 2) & “/” & Mid$(Valor, 3, Comprimento
– 2)
End If
If Len(Valor) > 10 Then
Valor =
Left$(Valor, 10)
Left$(Valor, 10)
End If
DataFormatada = Valor
End Function
A função recebe dois parâmetros: ValorAtual e
Tecla. ValorAtual será o conteúdo atual do campo
de data que recebe um novo dígito, enquanto Tecla é o
caractere recebido. No começo há um Select Case para
verificar se Tecla é numérico ou não. Caso positivo,
armazena na variável Digito. Depois a variável
Valor recebe o conteúdo do parâmetro
ValorAtual sem as barras separadoras da data. Mais
adiante Comprimento recebe o tamanho do texto de
Valor, que recebe as barras separadoras de acordo com o
tamanho. Por fim há ainda uma validação para ver se o
comprimento final passou de 10, limitando Valor aos 10
primeiros dígitos.
Tecla. ValorAtual será o conteúdo atual do campo
de data que recebe um novo dígito, enquanto Tecla é o
caractere recebido. No começo há um Select Case para
verificar se Tecla é numérico ou não. Caso positivo,
armazena na variável Digito. Depois a variável
Valor recebe o conteúdo do parâmetro
ValorAtual sem as barras separadoras da data. Mais
adiante Comprimento recebe o tamanho do texto de
Valor, que recebe as barras separadoras de acordo com o
tamanho. Por fim há ainda uma validação para ver se o
comprimento final passou de 10, limitando Valor aos 10
primeiros dígitos.
Agora podemos substituir o código do evento de pressionamento
de tecla para que o campo receba o conteúdo da função. Em
tese, precisaríamos de apenas uma linha de código, mas há uma
segunda. Observe:
de tecla para que o campo receba o conteúdo da função. Em
tese, precisaríamos de apenas uma linha de código, mas há uma
segunda. Observe:
Private Sub txtDataNascimento_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
MSForms.ReturnInteger)
Me.txtDataNascimento.Value =
DataFormatada(Me.txtDataNascimento.Value, KeyAscii)
DataFormatada(Me.txtDataNascimento.Value, KeyAscii)
KeyAscii = 0
End Sub
Lembre-se que a sub-rotina se refere a um evento e que
a variável KeyAscii é o caractere digitado. Se não
houver nenhum tratamento nessa variável, seu conteúdo é
acrescentado ao final do campo. Por isso devemos associar o
valor 0 para que o caractere digitado não seja
duplicado.
a variável KeyAscii é o caractere digitado. Se não
houver nenhum tratamento nessa variável, seu conteúdo é
acrescentado ao final do campo. Por isso devemos associar o
valor 0 para que o caractere digitado não seja
duplicado.
A validação da data normalmente é efetuada quando saímos do
campo. Vamos criar uma função que receba dois parâmetros: a
data a ser validada e uma enumeração que indique se a data que
queremos validar é passado, futuro ou tanto faz, pois datas de
nascimento devem pertencer ao passado, assim como novas datas
de pagamento devem pertencer ao futuro. Vejamos:
campo. Vamos criar uma função que receba dois parâmetros: a
data a ser validada e uma enumeração que indique se a data que
queremos validar é passado, futuro ou tanto faz, pois datas de
nascimento devem pertencer ao passado, assim como novas datas
de pagamento devem pertencer ao futuro. Vejamos:
Enum enumPeriodoData
Nenhum = 0
Passado = 1
Futuro = 2
End Enum
Function DataValidada(ValorData As String, _
Optional PeriodoData As enumPeriodoData
= Nenhum) As Boolean
= Nenhum) As Boolean
If Not IsDate(ValorData) Then
DataValidada =
False
False
Exit
Function
Function
End If
Select Case PeriodoData
Case Nenhum
DataValidada = True
Case Passado
If CDate(ValorData) < Now Then
DataValidada = True
Else
DataValidada = False
End If
Case Futuro
If CDate(ValorData) > Now
Then
DataValidada = True
Else
DataValidada = False
End If
End Select
End Function
Perceba que esta função só indicará se a data é válida ou não
a partir dos parâmetros recebidos. Não indicará se o erro é
uma data inválida ou se ela está fora do intervalo exigido
para o campo. Neste caso o ideal é ter uma variável
Mensagem onde possamos escrever uma mensagem de erro
para ser exibida no formulário. Nos casos em que não houver
erro será preciso apagar a mensagem para que não exiba uma
mensagem antiga. Entretanto, será preciso que essa variável
Mensagem seja pública, para poder ser acessada por todo
o projeto. Uma alternativa mais elegante é transformar todo o
módulo com as validações de dados para um módulo de classe,
que servirá como um repositório de funções de validação de
dados.
a partir dos parâmetros recebidos. Não indicará se o erro é
uma data inválida ou se ela está fora do intervalo exigido
para o campo. Neste caso o ideal é ter uma variável
Mensagem onde possamos escrever uma mensagem de erro
para ser exibida no formulário. Nos casos em que não houver
erro será preciso apagar a mensagem para que não exiba uma
mensagem antiga. Entretanto, será preciso que essa variável
Mensagem seja pública, para poder ser acessada por todo
o projeto. Uma alternativa mais elegante é transformar todo o
módulo com as validações de dados para um módulo de classe,
que servirá como um repositório de funções de validação de
dados.
Comece seu módulo validador de dados com uma ou duas funções
e vá substituindo as existentes de um projeto, verificando se
o funcionamento está normal e nenhum bug apareceu. Com
o tempo, vai acrescentando mais algumas funções e fazendo o
mesmo, até o momento em que todas suas validações estejam
presentes no módulo. Assim, quando for iniciar algum projeto
novo, importe esse módulo validador e uma boa parte do seu
trabalho já estará pronta, bastando usar as funções
existentes, testadas e aprovadas em projetos anteriores.
e vá substituindo as existentes de um projeto, verificando se
o funcionamento está normal e nenhum bug apareceu. Com
o tempo, vai acrescentando mais algumas funções e fazendo o
mesmo, até o momento em que todas suas validações estejam
presentes no módulo. Assim, quando for iniciar algum projeto
novo, importe esse módulo validador e uma boa parte do seu
trabalho já estará pronta, bastando usar as funções
existentes, testadas e aprovadas em projetos anteriores.
Para dúvidas sobre o artigo, comentários ou sugestões,
utilize os comentários abaixo. Até o próximo artigo!
utilize os comentários abaixo. Até o próximo artigo!
Pedro Martins
Pós-graduando em Business Intelligence e Big Data pela
Faculdade Impacta de Tecnologia. Formado em Tecnologia em
Eletrônica Digital com Ênfase em Microprocessadores
Catálogo de aulas (NOVIDADE)
Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.