VBA – Otimizando a entrada de dados com o InputBox

Em várias situações do dia a dia, precisamos coletar informações dos usuários para o correto funcionamento de nossas planilhas.

Isso normalmente é feito através de células evidenciadas através de formatação e outros recursos visuais. É possível até forçar a validação do valores de entrada, mas mesmo assim, não temos a garantia de que as informações foram coletadas. Para estas situações, o VBA disponibiliza uma função simples e muito eficaz, a função InputBox.

Com uma chamada simples, uma caixa de diálogo é mostrada ao usuário, disponibilizando também um caixa de texto para que este digite um valor de entrada.

Para simular o uso da função InputBox, imagine que você possui uma lista produtos cujos valores se baseiam na cotação do dólar do dia. O valor da cotação do dólar precisa ser informado, ou os cálculos não irão refletir os valores corretos dos produtos, podendo causar muitos problemas.

A idéia é tentar forçar com que o usuário insira o valor da cotação do dólar antes de efetuar qualquer operação na planilha. Porque não fazê-lo no momente em que este abre a pasta de trabalho? Para possibilitar isso, abra um novo arquivo do Microsoft Excel. Acione o VBA clicando em Ferramentas->Macros->Editor do Visual Basic ou clicando o atalho Alt+F11. A janela do VBA será mostrada conforme abaixo:

Janela de Projeto VBA

O que faremos é capturar o evento que é disparado quando uma pasta de trabalho é aberta. Para isso, dentro do VBA, na janela de Projeto, procure o item EstaPata_de_trabalho e clique duas vezes sobre ele para abrir a tela de código:

Janela de Projeto VBA

Com a tela de código aberta, logo acima da tela de código, existem duas caixas de seleção. Clique na caixa da esquerda e selecione o item Workbook:

Janela de Projeto VBA - Selecionando o objeto e o evento

Ao fazer isso, o código do evento que é disparado ao abrir a pasta de trabalho de nome Workbook_Open é criado conforme a seguir:

1
2
3
Private Sub Workbook_Open()
 
End Sub

É dentro deste código que trabalharemos com o InputBox. Como tudo o que estiver neleé executado quando o arquivo é aberto, vamos solicitar que o usuário que digite o valor da cotação do dólar no InputBox e colocar este valor em uma determinada célula. Supondo que a célula que contém o valor da cotação seja a célula A1 da Plan1, o código seria o seguinte

1
2
3
4
5
6
7
Private Sub Workbook_Open()
    Dim cotacao As String
 
    cotacao = InputBox("Digite a cotação do dólar do dia: ", "Cotação", "2,00")
 
    ThisWorkbook.Worksheets("Plan1").Range("A1").Value = cotacao
End Sub

O código declara uma variável na linha 2 que armazenará o valor da cotação informado pelo usuário. Ela precisa ser uma String pois é o tipo de retorno do InputBox. Em seguida, o valor da cotação é solicitado através do InputBox na linha 4 e armazenada na variável cotação. O resultado é colocado na célula A1 da planilha Plan1 na linha 6.

Execute o procedimento clicando em F5 ou fechando a planilha e abrindo-a novamente (lembre-se de ativar as macros). Veja o resultado:

InputBox em funcionamento

Clique em OK e veja o valor inserido na célula A1 da planilha Plan1:

A planilha com o valor digitado no InputBox

Com isso, temos o valor informado pelo usuário colocado em uma célula desejada. Tudo isso ocorre normalmente, se tudo for feito de forma correta pelo usuário

Porém, no código acima, temos dois problemas. O primeiro é, caso o usuário não informe um valor clicando no botão cancelar, o aplicativo retornará um erro. O segundo é, se a célula não estiver implicitamente configurada para valores numéricos, ela considerará o conteúdo no formato texto, que é o tipo padrão da variável cotacao. Tentaremos resolver os dois problemas de uma vez. Veja o código abaixo:

1
2
3
4
5
6
7
8
9
Private Sub Workbook_Open()
    Dim cotacao As String
 
    While cotacao = ""
        cotacao = InputBox("Digite a cotação do dólar do dia: ", "Cotação", "2,00")
    Wend
 
    ThisWorkbook.Worksheets("Plan1").Range("A1").Value = CDbl(cotacao)
End Sub

As mudanças feitas no código tratam o problema da seguinte maneira:

Na linha 4 a 6, a chamada do InputBox foi colocada dentro de um loop While com a condição de, caso a variável cotacao esta com o valor “”, ou seja, vazia, o que significa que o usuário clicou no botão cancelar, ele voltará a chamar o InputBox e isso acontecerá até que ele insira um valor e clique em OK. Na linha 8, ao invés de atribuir diretamente a variável cotacao à célula, usa-se a função CDbl() que força a conversão da variável passada por parâmetro para o tipo numérico Double.

Isso faz com que o valor seja passado com o formato numérico diretamente para a célula.

Execute o procedimento clicando em F5 ou fechando a planilha e abrindo-a novamente (lembre-se de ativar as macros). Ao aparecer a caixa de diálogo, tente clicar no botão Cancelar e veja o que acontece.

Conclusão

É possível melhorar mais ainda a inclusão de valores, fazendo verificações com funções de validação de tipo como foi o caso da CDbl(), usada neste artigo. Assim, o InputBox torna-se uma alternativa muito elegante para coletar dados do usuário.

VBA – Saindo do controle de fluxo (comando Exit)

O que é?

A instrução Exit sai de um bloco de código Do…Loop, For…Next, Function, Sub ou Property.

Estrutura:

Exit Do

Fornece um meio de sair de uma instrução Do…Loop. Pode ser usada somente dentro de uma instrução Do…Loop. Exit Do transfere o controle para a instrução seguinte à instrução Loop. Quando usada dentro de instruções Do…Loop aninhadas, Exit Do transfere o controle para o loop que está aninhado em um nível acima do loop onde ocorre Exit Do.

Exit For

Fornece um meio de sair de um loop For. Pode ser usada somente em um loop For…Next ou For Each…Next. Exit For transfere o controle para a instrução seguinte à instrução Next. Quando usada dentro de loops For aninhados, Exit For transfere o controle para o loop que está aninhado em um nível acima do loop onde ocorre Exit For.

Exit Function

Sai imediatamente do procedimento Function em que aparece. A execução continua com a instrução seguinte à instrução que chamou Function.

Exit Property

Sai imediatamente do procedimento Property em que aparece. A execução continua com a instrução seguinte à instrução que chamou o procedimento Property.

Exit Sub

Sai imediatamente do procedimento Sub em que aparece. A execução continua com a instrução seguinte à instrução que chamou o procedimento Sub.

Exemplo

Um exemplo útil para o uso das instruções é Exit é no caso de um loop For…Next. Supondo que estivéssemos buscando um determinado valor dentro de uma coleção de itens de 10 posíções. A alternativa mais comum é verificar a lista item a item comparando-os até que encontrar o item que se deseja. Caso o item estivesse na 10º posição, não haveria tanto problemas. Mas se ele estivesse na 2º posição, porque continuar o executando o código até a 10º posição se já achamos o item?

Veja o código abaixo:

Function ProcuraNome(nome As String) As Boolean
    Dim nomes(10) As String
    Dim i As Long
    Dim quantInteracoes As Long
    Dim resultado As Boolean
 
    nomes(0) = "João"
    nomes(1) = "Maria"
    nomes(2) = "Júlio"
    nomes(3) = "Fabio"
    nomes(4) = "Guilherme"
    nomes(5) = "Roberto"
    nomes(6) = "Francisco"
    nomes(7) = "Juliana"
    nomes(8) = "Fabiana"
    nomes(9) = "Alex"
 
    For i = 0 To 9 Step 1
        quantInteracoes = i + 1
        If nome = nomes(i) Then
            resultado = True
        End If
    Next
 
    MsgBox quantInteracoes
 
    ProcuraNome = resultado
End Function

O código declara uma matriz de tamanho 10 com nomes de pessoas e todas as suas posições. Passando um nome por parâmetro, a função retorna VERDADEIRO se o nome existir na lista e FALSO caso contrário. A matriz é preenchida entre as linhas 7 e 16 e a busca é feita em uma laço For…Next nas linhas 18 a 23.

A variável quantInteracoes foi criada para verificar quantas vezes o laço For…Next do código faz interações, quantidade esta que é mostrada numa caixa de mensagem na linha 25.

Para testar a função, em qualquer célula de sua planilha e digite =ProcuraNome(“João”). Veja que a função retona o valor VERDADEIRO, o que significa que o nome consta na lista. Se informar qualquer outro nome, por exemplo “Sérgio”, a função retornará FALSO. Note que independente do nome informado, exista ele ou não na lista, uma caixa de mensagem com a quantidade 10 sempre. Isso significa que, mesmo que o laço encontre o nome na primeira posição, ele continua executando o laço até a última posição. Se a lista contivesse 1000 nomes, o código ficaria muito demorado.

Mas como apenas queremos saber se o nome existe na lista, não há necessidade de continuar executando o laço quanto a condição da linha 20 for atendida. Então, veja a modificação feita na código:

    ...
    For i = 0 To 9 Step 1
        quantInteracoes = i + 1
        If nome = nomes(i) Then
            resultado = True
            Exit For
        End If
    Next
    ...

Adicionando a cláusula Exit For como feito no código acima, ao atender a condição da linha 20, o código sairá do laço For…Next e continuára a exeução na linha 24. Depóis de fazer a modificação, em qualquer célula de sua planilha e digite =ProcuraNome(“João”). Veja que ao invés do valor 10, a caixa de mensagem mostrará 1. Se colocar =ProcuraNome(“Maria”), a caixa de mensagem apresentará 2 e assim por diante.

Além de evitarmos trabalho desnecesário, aumentamos a performance da função para a maior parte dos casos em que ela for utilizada.

Comentários

Não confunda instruções Exit com instruções End. Exit não define o fim de uma estrutura.

Como a instrução Exit desvia a execução do código, é aconselhável usá-la somente se o código da função estiver bem estruturado, principalmente para os casos de Function e Sub.

VBA – Passagem de parâmetros por valor e por referência (ByVal, ByRef)

As estruturas para criação de funções do VBA, Sub e Function possibilitam o envio de informações para uso destas. Estas são infomadas em seu cabeçalho, entre parênteses e logo após o nome da função. São normalmente conhecidas como parâmetros ou argumentos da função.

Exemplo:

Public Sub Soma(x As Long, y As Long)
... código
End Sub

No código acima, uma Function poderia ter sido utilizada no lugar da Sub. As variáveis declaradas no topo da função devem ser informadas em sua chamada. A partir disso, a código interno terá acesso aos valores destas variáveis e fazer uso destes para suas operações.

Existem duas formas de passar valores para funções no VBA. São elas ByVal (por valor) e ByRef (por referência).

Caso a forma não seja informada, o VBA considera por padrão que os valores são passados em modo ByVal. Ou seja, o código acima poderia ser escrito desta forma sem alterar suas funcionalidades:

Public Sub Soma(ByVal x As Long, ByVal y As Long)
... código
 End Sub

Mas o que quer dizer por valor ou por referência?

Na passagem de parâmetro por valor, ao iniciar a execução, a função faz uma cópia dos valores passados para serem utilizados nas operações. Supondo que o valor passado para a função fosse uma variável criada por você. Uma cópia deste valor seria efetuada durante a execução da função, não alterando em nada o valor original de sua variável. Para entender melhor, veja o exemplo de código abaixo:

Public Sub Teste()
'cria a sua variável
 Dim var As Long
'atribui um valor a ela
var = 2
'chama a função Dobro passando a variável para esta
Call Dobro(var)
'mostra o valor da variável após a execução do código
MsgBox var
End Sub
Public Sub Dobro(ByVal x As Long)
x = x * 2
End Sub

A função teste cria uma variável do tipo numérica na linha 3 a atribui o valor ‘2’ a ela na linha 5. Em seguida, é chamada a função valor que recebe o valor da variável var e o multiplica por 2. Em seguida o valor da variável é mostrado na linha 9. Veja o resultado da execução do código:

Note que por mais que tenhamos passado o valor por parâmetro para a função Dobro, a variável var permaneceu com seu valor original. Isso aconteceu porque como explicado, ao iniciar sua execução, a função cria uma cópia em memória do valor da variável passado por parâmetro, deixando seu valor original intacto.

Esse problema pode ser facilmente resolvido utilizando uma Function ao invés de uma Sub e retornar o valor no final de final da execução. Mas se precisássemos alterar ou mesmo retornar mais de um valor? É isso que queremos contornar e é nesse ponto que entra o ByRef. Veja o código alterado abaixo:

Public Sub Teste()
'cria a sua variável
 Dim var As Long
'atribui um valor a ela
var = 2
'chama a função Dobro passando a variável para esta
Call Dobro(var)
'mostra o valor da variável após a execução do código
MsgBox var
End Sub
Public Sub Dobro(ByRef x As Long)
x = x * 2
End Sub

Note que alteramos a passagem do parâmetro de ByVal para ByRef. Veja o resultado da execução da função Teste:

O que aconteceu desta vez? Quando a declração de uma variável passada como parâmetro de uma função é feita bom ByRef, o VBA ao invés de efetuar uma cópia como o ByVal, faz um referência ou ligação à variável que foi passada. No caso do código acima, a mudança da forma de passagem do parâmetro para ByRef faz com que exista um vínculo entre a variável x na função Dobro e a variável var na função Teste.

Ou seja, qualquer alteração feito no valor x dentro da função será automaticamente refletida na variável var.

Como você pode passar mais de uma parâmetro as funções no VBA, esta se torna uma forma de poder retorna vários valores com uma única função. Veja o código alterado abaixo:

Public Sub Teste()
'cria as variáveis
 Dim var1 As Long
 Dim var2 As Long
 Dim var3 As Long
 'atribui valores
var1 = 1
 var2 = 2
 var3 = 3
 'chama a função Dobro
Call Dobro(var1, var2, var3)
'mostra o valor das variáveis após a execução do código
MsgBox var1 & vbNewLine & var2 & vbNewLine & var3
End Sub

Public Sub Dobro(ByRef x As Long, ByRef y As Long, ByRef z As Long)
x = x * 2
y = y * 2
z = z * 2
End Sub

Veja que todos as valores das variáveis foram alterados. Apenas para informação, o operador ‘&’ é utilizado para concatenar textos eo ‘vbNewLine’ causa uma quebra de linha, similar a um Enter no Word.

As formas de passagem de parâmetros podem ser utilizadas tanto para Sub com para Function. No caso da Function, o valor de retorno tradicional não sofre nenhuma alteração. Porém, é bom frisar que parâmetros passados em funções de planilha não sofrem alterações mesmo se passados como ByRef.

Conclusão
Vimos que o VBA disponibiliza dois tipos de passagem de parâmetros para funções, ByVal e ByRef. A forma padrão é ByVal e nela, uma cópia do valor passado por parâmetro é utilizada na execução da função. Com ByRef, uma referência à variável é passada para a função, fazendo com que todas as alterações feitas sejam refletidas na variável original.

Utilizando o recurso de passagem de parâmetros para funções e conhecendo suas forma de trabalhar, é possível resolver a grande maioria de nosso problemas na construção de aplicativos em VBA.byvalbyref1byvalbyref1

Dicas – Sistema calcula chances de conseguir emprego

Fonte: Dica dada pela MetroPoint

Trabalhador pode consultar seu grau de empregabilidade

Que está em busca de emprego acaba de ganhar uma ferramenta que permite calcular as chances de consguir uma vaga no mercado de trabalho. O sistema, batizado de Termômetro Nacional do Emprego, está disponível no endereço eletrônico www.termometrodoemprego.sp.gov.br.

Para consultar seu grau de empregabilidade, o trabalhador precisa reposder a algumas questões pessoais como idade, sexo, grau de instrução, estado civil e número de filhos, além de informação profissionais, como experiência e renda mensal.

A ferramenta também fornece uma estimativa média de remuneração e calcula o tempo que o trabalhor deverá permanecer no novo emprego.

Acesse o site do Termômetro Nacional do Emprego clicando no link abaixo:

www.termometrodoemprego.sp.gov.br

Termômetro Nacional do Emprego
Termômetro Nacional do Emprego