Você está na página 1de 333

DOMINE O ACCESS VBA

1
FICHA CATALOGRÁFICA

MACHADO, Eduardo Vieira

Domine o Access VBA

Rio de Janeiro: Editora Livrorama Ltda., 2018.

1. Informática

2
EDUARDO V MACHADO (GOOD GUY)

DOMINE O ACCESS VBA

1ª Edição

Rio de Janeiro
Editora Livrorama
Ano 2018

3
4
DEDICATÓRIA

Dedico este livro em primeiro lugar à minha esposa


Eunice, companheira dedicada e minha maior
incentivadora; ao meu pai Wilson Machado (In
Memoriam), à minha mãe Irailde, e a todas crianças e
jovens de nossa família que se sentiram felizes e
incentivados a estudar informática com meu primeiro
livro e, finalmente, a toda a juventude estudiosa de
nosso país.

5
6
AGRADECIMENTOS

Quero agradecer ao bom Deus por tudo o que aprendi ao


longo desses anos e por todo incentivo que recebi de
amigos dos fórums Máximo Access e Expert Access, além
de colegas de trabalho e, especialmente, de minha
esposa Eunice quem sempre acreditou em mim.

7
8
PREFÁCIO

Olá. Sou membro de vários fóruns de programação


em Access VBA, mais conhecido como Good Guy(Um cara
prestativo). Assumi este pseudônimo para demonstrar que vivo
a doutrina cristã de relacionamento com o próximo.
Recentemente, fui premiado como um dos melhores
programadores em Access VBA na comunidade internacional,
principalmente a Lusófona. Isto aconteceu em outubro de 2011.
Estudei Engenharia Operacional Civil, tentei
concluir a Engenharia Plena, passando para Engenharia
Elétrica, mas desisti por causa do excesso de engenheiros
sendo lançados no mercado que já estava saturado na época.
Em 1985, iniciei meus estudos em Tradução Literária/Técnica
com um dos melhores linguistas reconhecidos aqui na América
Latina, prof. Daniel Brilhante de Brito. Incentivado por este
ilustríssimo professor, procurei fazer o curso de
Letras(Português/Inglês) com especialização em Inglês e
aproveitei este conhecimento para adentrar, mais tarde,
precisamente em 1998, no universo da informática através dos
cursos de Lógica de Programação com a linguagem C até
culminar como Analista de Java/Web estudando a Linguagem
Orientada a Objetos e, em seguida, a Linguagem Orientada a
Eventos escolhendo a plataforma Access VBA pela qual me
apaixonei e dedicado maior tempo de estudo.
Apesar de não ser formado em Ciência da
Computação, sou apaixonado por TI. Vou contar um pouco da
minha estória de como isso se tornou uma realidade. Quando
resolvi estudar informática queria que fosse de forma
diferencial, isto é, queria fazer a diferença na empresa, pois me
sentia sub-avaliado e desatualizado com o avanço da

9
informática. Meu Deus, pensei, preciso crescer como
profissional, sair da rotina. A princípio, procurei fazer uma
faculdade de Ciência da Computação, mas desisti para
valorizar o meu casamento recente.
Na época quando fiz Letras não havia informática
como hoje existe, só o estudo da linguagem de programação
Fortran. Só tinha uma coisa a fazer, ou resolvia estudar por
conta própria e através de cursos caros, mas de bom conteúdo
e ser bom em Programação ou ser bom em Técnica de
Reparos em Computadores. Bem, vamos devagar, pensei,
investindo em estudo de hardware. Comecei, fazendo cursos
de manutenção e trabalhei algum tempo como técnico de
computadores. Mas com o tempo percebi que estava gastando
mais dinheiro em livros e cursos do que conseguia com
reparos. Foi quando resolvi atacar a programação, mas quando
vi os códigos em sites e livros me desesperei e comecei a
chorar de medo daquela linguagem indecifrável dos códigos
que se repetiam a cada capítulo dos livros. Decidi fazer então
cursos de Lógica de Programação e com a ajuda de
profissionais amigos dos fórums, fui perdendo o medo e
sentindo satisfação com meus resultados.
Desde então, tenho estudado com dedicação a
linguagem VBA para o Access há muitos anos, fazendo cursos
com grandes mestres da programação e participando
ativamente de fórums como Máximo Access, Expert Access,
It Lab Forum, The Code Cage Forum e Access World
Forums. Cheguei a ser premiado internacionalmente com
meus aplicativos na comunidade lusófona de programadores e
convidado para ser moderador de fórum. Hoje tenho um site de
informática, chamado Good Guy Sistemas, Aplicativos e
Jogos cujo endereço é www.goodguyaccessvba.com.br. Tenho

10
também uma página no Facebook e um blog com assuntos
variados de tecnologia. Sou também o autor de dois outros
livros sobre Access, Técnicas Especiais de Access VBA e
Engenharia de Software com Access VBA.
Há alguns anos vinha sonhando em preparar um
livro que esmiuçasse certos rudimentos da linguagem VBA
para Access como fruto de minha experiência profissional
adquirida nesses grandes fórums, a fim de preparar futuros
programadores no domínio dessa ferramenta tão necessária
para capacitar o profissional de TI no desenvolvimento de
poderosos sistemas de informação. Sabia que não seria fácil
escrever um livro sobre este assunto em face de já existir
muitos bons livros já escritos por excelentes mestres. Mestres
como Flávio Morgado, autor da coleção Programando em
Access VBA de quem comprei toda a sua coleção e com quem
aprendi muito, Bernardo Leite, autor do livro VBA para
Microsoft Access, André Bernardes autor de diversos artigos
em sites sobre VBA e José Carlos Macoratti também. Aprendi
muito com João Paulo um dos grandes moderadores do fórum
Máximo Access; Avelino Sampaio criador do site Usando
Access que me proporcionou com sua grande capacidade e
didática, muito conhecimento; Alexandre Neves outro excelente
programador, moderador do fórum Máximo Access com sua
agilidade e inteligência ao codificar e, me cobrando atenção e
dedicação; Alexandro de Andrade (Mc Feba) inteligente
programador que também me abriu os olhos para boas
técnicas de programação, amigos programadores geniais
assim como Dilson Marcos criador do Blog Access do
Programador, meu maior incentivador e grande amigo; o
habilidoso Plínio Mabesi, criador do site Mabesi.com que muito
me incentivou; Harysohn Pina, inteligente e inovador, criador de

11
um sistema de biometria no Access e,finalmente, o Valdino
Campos, mais conhecido como Criquio, também fera em
programação.
A nenhum desses trato como concorrentes, mas
como irmãos e amigos, porque somos uma grande família nos
fórums. Com isto em mente, este livro se propõe a ensinar a
arte de desenvolver aplicativos para solucionar problemas do
dia-a-dia. Você aprenderá a ser um excelente Desenvolvedor
de Soluções em TI. Esta é uma carreira promissora e vantajosa
e que lhe abrirá as portas não só da realização pessoal bem
como da realização financeira.
Ao longo deste livro alguns leitores poderão já se
sentir mais familiarizados com certos tópicos como o uso da
Janela Verificação Imediata na IDE onde você poderá
depurar seus códigos e corrigir os erros antes mesmo de rodar
o aplicativo. Estudaremos também a janela Pesquisador de
Objeto onde o leitor poderá obter, ao estudar essas janelas,
um bom domínio de programação ao utilizar métodos e
propriedades dos objetos de forma mais eficaz. Ao longo de
cada capítulo, o leitor poderá avaliar os seus conhecimentos
com exercícios práticos e assim começar a dominar a arte da
programação.

Quero me desculpar com alguns programadores


mais exigentes acerca de um ponto, não segui à risca as regras
de prefixo das minhas variáveis, porque quase todos os
exercícios aqui apresentados foram coletados ao longo de
minha carreira quando no início não dava muita atenção a esse
detalhe e pela falta de tempo para correção. O meu maior
objetivo, porém, é tornar o estudante apto a trabalhar o
raciocínio para lidar com os diversos problemas do cotidiano,

12
desenvolvendo soluções práticas, e assim sobressair-se em
qualquer situação conflitante da vida real. Para isso, no
entanto, vai depender de você com sua perseverança, alcançar
este nível de profissionalismo. Planejar e corrigir um bom
programa ou sistema aliado à Lógica de Programação, sua
análise de que a que fim se propõe é o passo número um a
dominar e imprescindível em todo e qualquer bom profissional
de programação.

Eduardo V. Machado (Good Guy)

13
ÍNDICE

Pág.

Introdução .................................................................... 18
Avaliação ...................................................................... 29

CAPÍTULO 1 – O FUNDAMENTO

1. Lógica de Programação Estruturada ............... 30


2. Algoritmos .......................................................... 31
2.1 Criando Seu Primeiro Algoritmo ............ 36
2.2 Fluxogramas .............................................. 40
3. Declaração de Variáveis .................................. 45
4. Regras para Declaração de Variáveis............... 50
5. Modelagem de Dados de Uma Tabela ............. 54
6. Relacionamentos entre Tabelas (ou Tuplas) .... 68
7. Analisador de Desempenho .............................. 96
8. Analisador de Tabelas ....................................... 98
9. Cálculo em Tabelas ............................................ 101
Avaliação ................................................................... 102

CAPÍTULO 2 – SQL EM AÇÃO (CONSULTAS)

1. SQL no MsAccess (1ª Parte) .............................. 107


2. SQL no MsAccess (2ª Parte) .............................. 124
3. Criando Consultas Inserção............................... 133
4. Criando Consultas Exclusão .............................. 139
5. Criando Consultas Atualização.......................... 140
6. Criando Consultas União.................................... 141

14
7. Criando Consultas com Referência Cruzada.... 144
8. Criando Consultas com Duplicação de Dados........ 146
9. O Uso de SEIMED para Criar Consultas com
Campo Calculado ................................................................ 146
10. Otimizando Consultas .............................................. 148

Avaliação ............................................................................... 149

CAPÍTULO 3 – DOMINANDO O ACCESS VBA I


(FORMULÁRIOS)
1. A Barra de Ferramentas ................................... 152
2. Uso de InputBox e MsgBox ............................... 158
3. Sub-Rotina x Função ......................................... 170
4. A Janela Pesquisador de Objetos ..................... 187
5. A Família DoCmd .............................................. 195
6. Uso do Recordset ................................................ 203
7. Biblioteca DAO .................................................. 206
8. Uso da Janela de Propriedades dos Objetos..... 208
9. Adicionando um Registro via DAO..... ............ 212
10. Alterando um Registro via DAO
(Propriedade BeginTrans, CommitTrans e Rollback) ..... 214
11. Criando Um Procedimento na IDE pela
Barra de Ferramentas .......................................................... 221
12. Uso da Janela Imediata no Ambiente de
Código (IDE) ......................................................................... 224
13. Desativando Avisos do Access em Códigos com
Instrução SQL ...................................................................... 226
14. A Estrutura de Controle IF THEN…
ELSE…END IF......................................................... 231
14.1 Aninhamento de IF’s .............................. 233
15. Estruturas de Controle com SELECT CASE
END SELECT........................................................... 234
16. Constantes e Enumeradores …...………........ 236
17. Propriedades Height e Width …...….............. 237

15
18. Os Controles Principais Usados em
Formulários com Suas Propriedades e Métodos ............. 240
18.1 Combobox ............................................ 241
18.2 Listbox ............................................. .... 247
18.2.1 Calculando Totais com Listbox 255
18.3 TextBox .................................................. 257
18.4 CheckBoxes ............................................ 261
18.5 Option Buttons ...................................... 262
18.6 Subforms .............................................. 262
18.6.1 Calculando Totais com Subforms 262
19. Principais Eventos de Um Controle …........... 267
19. 1 O Evento NotInList...................................... 269
20. Controles-guias …………………………........ 275
21. Formatação Condicional em Formulários..... 278
22. Inserindo Dados em Uma Tabela a Partir de
Outra .................................................................. 281
23. Alterando Dados em Uma Tabela a Partir de
Outra ............................................................... 282
24. Função Aleatório (Randomize)........................ 283
25. Trabalhando com o Form_Timer .................. 291
25.1 Time........................................................ 293
26. Tratamentos de Erros ..................................... 293
27. Módulos ............................................................ 300
28. Aplicativos em Rede ........................................ 303
Avaliação............................................................................... 306

CAPÍTULO 4 – DOMINANDO O ACCESS VBA II


(RELATÓRIOS)

1. Criando Relatórios com Níveis e Agrupados ... 320


2. Criando Relatórios com Campo Calculado ..... 323
3. Impressão de Relatórios via Access VBA ........ 326
4. Criando Relatórios do Tipo Álbum por
Categoria .............................................................................. 329
Avaliação .............................................................................. 331

16
17
INTRODUÇÃO

Desenvolvendo o Primeiro Programa.

A maioria dos programadores aprenderam a gostar de


programação, animados com o famoso “Hello, World” ou
“Alô Mundo”. Vamos aprender como se faz isto.

1.º Passo: Pela aba Criar, selecione o modo Design de


Formulário.

2.º Passo: Clique em Design de Formulário.

18
3.º Passo: Clique no modo Design e selecione um botão
na barra de ferramentas.

19
4.º Passo: Clique em Cancelar e renomeie o botão pela
aba Outra, ao clicar com o botão direito do mouse em
cima do botão.

20
Insira agora o seguinte código pela aba Evento, Clicar do
botão:

Public Sub cmdAbrir_Click ()


MsgBox “Alô, Mundo !!!” ==========
End Sub

21
Pronto, o primeiro programa está criado. Mas é preciso ir
mais além na codificação para melhorar a apresentação
dessa simples mensagem. Que tal colocarmos um ícone
de informação nesta caixa de mensagem e uma
referência ao programa como título desta mensagem?

Public Sub cmdAbrir ()

MsgBox “Alô, Mundo !!!”, vbInformation, “Primeiro


Programa” „vbInformation é o complemento que faltava
para „buscar‟ na biblioteca de imagens do Access o ícone
de informação. Primeiro Programa entre aspas é o título
da caixa aberta.

End Sub

ATENÇÃO: Salve o seu trabalho e dê um nome ao seu


formulário. Por exemplo, frmAula1.

Agora e se quisermos que esta mensagem apareça ao


abrir o programa? O melhor lugar para a colocarmos é no
evento Ao Abrir(Open) do formulário.

Private Sub Form_Open(Cancel As Integer)


MsgBox “Alô, Mundo !!!”, vbInformation, “Primeiro
Programa”
End Sub

Existem três eventos de aberturas de um formulário no


Access que seria interessante você saber. São eles os

22
eventos Ao Abrir (Form_Open), Ao
Carregar(Form_Load) e Ao Ativar(Form_Activate).
Alguns fundamentos de desenvolvimento são necessários
você dominar para tornar a codificação mais fácil e
dinâmica.

Importante:Se você estiver trabalhando com várias


MsgBox na abertura do programa, por exemplo, três
MsgBox, a primeira que surgirá é a que estiver no evento
(1)Form_Open(Ao Abrir); em seguida, a que estiver no
evento(2) Form_Load(Ao Carregar); e, por último a que
estiver no evento(3) Form_Activate(Ao Ativar). Teste
com as seguintes MsgBox:
(1) MsgBox "Hoje é dia !!!", vbInformation,
"Primeiro Programa" (Form_Open)

(2) MsgBox "Sistema pronto !!!", vbInformation,


"Primeiro Programa" (Form_Load)

(3) MsgBox "Alô, Mundo !!!", vbInformation,


"Primeiro Programa" (Form_Activate)

Repetindo: Ordem de surgimento das MsgBox. Primeiro,


no evento Ao Abrir; Segundo no evento Ao Carregar e,
por último, no evento Ao Ativar.

Configurações Importantes
Vamos examinar as opções de configurações de seu
aplicativo em Access. Antes de criar ou concluir um

23
aplicativo, você precisa aprender a configurá-lo de modo
que possa ser prático o manuseio dele para realizar as
alterações necessárias para o seu pleno funcionamento e
análise. Quando você abre o Access ele exibe a seguinte
janela:

Altere o nome do arquivo à sua direita para um nome


sugestivo temporário antes que você decida por um nome
final. Em seguida, clique em Criar, logo abaixo. Surgirá
uma tabela com somente um campo, entre na sua
estrutura e adicione novos campos.

24
Clique com o botão direito a Tabela1 à sua esquerda.
Selecione o Modo Design. Salve a sua tabela como um
nome também sugestivo (Ex. tblMeusDados) .

25
Adicione novos campos à sua tabela, logo abaixo de
código.

Em seguida, clique no botão Arquivo, opções, Banco de


Dados Atual e dê um título ao seu aplicativo à sua
esquerda. Dê OK e somente volte para aí quando
aprender a criar formulários.

26
Para que seu aplicativo rode sem segurança de macros, o
que impede que o seu código VBA funcione, faça o
seguinte: Siga para a Central de Confiabilidade logo
abaixo e clique no botão Configurações da Central de
Confiabilidade, Configurações de Macro e selecione à sua
direita “Habilitar todas as macros”. ATENÇÃO: Não faça
isso se você receber um aplicativo de terceiros que você
não tenha certeza que é uma fonte confiável.

27
Pronto, clique em OK, em seguida OK de novo. Você
agora está pronto para trabalhar com Access VBA.

28
AVALIAÇÃO:

1) Crie um aplicativo que ao abrir lembre que hoje é o


dia de aniversário de um amigo(a) seu(ua). Neste
programa deverá aparecer 3(três) MsgBox com um
tipo diferente de saudação sucessivos.

2) Crie um programa que faça o mesmo do item


anterior através de um botão.

29
CAPÍTULO 1 – O FUNDAMENTO

LÓGICA DE PROGRAMAÇÃO ESTRUTURADA

A ciência de computação é trabalhar com a lógica. Lógica


exige bom senso, é a arte de fazer conclusões com base
matemática ou com base experimental. Todo ser humano
civilizado aplica a lógica de uma forma inconsciente todos
os dias.

Exemplo de raciocínio lógico conceitual baseado na vida


real.

1- Diversos cupins entraram na sala atraídos pela


lâmpada acesa
2- Ao apagar das luzes eles se dispersaram
3- Logo, apaguei as luzes e abri as janelas
4- Os cupins saíram pela janela em busca de luz
5- Fechei as janelas
6- Reacendi a lâmpada.

Outro exemplo de raciocínio lógico:

1. Lucas é mais velho que Paulo 8(oito) anos


2. Paulo é mais velho que João 2(dois) anos
3. Pedro tem a mesma idade de João.
4. Logo Pedro é mais novo que Lucas 10(dez)
anos.

30
Isso é lógica de programação. Todo ser humano segue
um programa diário de atividades. Um programa de
computador também obedece esta lógica como veremos
ao longo deste livro. Chamamos a este tipo de sequencia
lógica de algoritmo.

ALGORITMOS

O que é um algoritmo? Algoritmo é uma elaboração


sequencial lógica de uma atividade que levam à solução
de um problema, podem ser representados por diagrama
de blocos ou por pseudolinguagem.

Exemplo de um algoritmo da vida real.

1- Sentar-se na cama,
2- calçar os chinelos,
3- ir ao banheiro,
4- abrir o armário,
5- pegar as escovas de dentes,
6- pegar a pasta,
7- passar a pasta na escova,
8- escovar os dentes,
9- lavar a boca, lavar a escova,
10- guardar a escova e a pasta no armário.
11- Posso agora tomar o meu café.

Na criação de um programa raciocinamos por etapas.


É semelhante a composição de uma carta. Temos o

31
início, o corpo do texto e a conclusão ou mesmo, para
ser mais exato, semelhante a receita de um bolo ou de
um prato qualquer. Assim como há diferentes tipos de
bolos assim temos diferentes tipos de receitas para o
seu preparo, seguindo esta regra geral:

INÍCIO - Ingredientes Declarar Variáveis


--- Se ocorrer isso... Então faça assim......Fim
CORPO - Modo de fazer  Linguagem de alto
nível --| Selecione controle
Caso seja A

Faça assim
Caso seja B

Faça assado
Fim da seleção
CONCLUSÃO - Pronto para ser servido  Fim do
Programa

O que faremos no início? Se estamos falando de receita


de um bolo por exemplo, então incluiríamos os
ingredientes, certo? Em programação, os ingredientes são
as variáveis. Variável é a portadora de um valor que pode
variar, como o próprio nome já diz, de um valor para outro
pelo usuário do programa. Exemplo prático seria uma

32
variável que recebesse nomes de pessoas, ou de
telefones, ou de bairros, ou de cidades, etc.

Linguagem de baixo nível e Linguagem de alto nível

Na linguagem de alto nível temos expressões de


pensamento, semelhantes ao pensamento humano,
conhecidas como estruturas de controle de fluxo do
programa que são expressões lógicas de raciocínio. Por
exemplo em linguagem de programação estruturado:

Se coloco os igredientes então


A massa se forma
Coloco na forma
Acendo o forno
O bolo sai
Senão
O bolo não sai
Fim do Programa

Essa é a forma de “interpretar” do computador o


pensamento humano, isto é, da plataforma de linguagem
processar as informações imputadas pelo usuário. É a
linguagem de alto nível.

Exemplos de linguagem de programação de alto nível:

 ASP
 ActionScript

33
 C/C++
 C#
 Pascal/Object Pascal
 Euphoria
 Java
 Lua
 MATLAB
 PHP
 Python
 R
 Ruby
 Tcl
 Basic/Visual Basic

O que seria então linguagem de baixo nível? A Wikipedia


dá a seguinte definição:

“Trata-se de uma linguagem de programação que


compreende as características da arquitetura do
computador. Assim, utiliza somente instruções do
processador, para isso é necessário conhecer os
registradores da máquina. Nesse sentido, as linguagens
de baixo nível estão diretamente relacionadas com a
arquitetura do computador. Um exemplo é a linguagem
Assembly (não Assembler) que trabalha diretamente com
os registradores do processador, manipulando dados.

As linguagens de baixo nível são divididas em duas


categorias: primeira geração e segunda geração.

34
Primeira geração: A linguagem de primeira geração, ou
1GL, é o código de máquina. É a única linguagem que um
microprocessador pode entender nativamente. O código
de máquina não pode ser escrito ou lido por um editor de
texto, e portanto é raramente usado por uma pessoa
diretamente.

Segunda geração: A linguagem de segunda geração, ou


2GL, é a linguagem Assembly. É considerada de segunda
geração pois embora não seja uma linguagem nativa do
microprocessador, um programador que use a linguagem
Assembly ainda deve compreender as características da
arquitetura do microprocessador (como registradores e
instruções).”

No meu entender é a linguagem entendida pelo


processador, são os códigos binários que representam as
letras do alfabeto e os números. Mais diretamente falando
podemos interpretar esses códigos binários através da
tabela ASCII. O que é a tabela ASCII? Uma resposta bem
descritiva veremos novamente no Wikipédia:

“ASCII (acrônimo para American Standard Code for


Information Interchange, que em português significa
"Código Padrão Americano para o Intercâmbio de
Informação", mas comumente utilizamos a sigla em inglês
para referencia direta) é uma codificação de caracteres de
sete bits baseada no alfabeto inglês. Cada sequencia de
códigos na tabela ASCII corresponde a um caractere,
comumente representados pelos 8 bits (equivalente a um
byte), sendo que o oitavo bit (da direita para a esquerda)

35
serve como um bit de paridade, utilizado para detecção de
erro. Os códigos ASCII representam texto em
computadores, equipamentos de comunicação, entre
outros dispositivos que trabalham com texto.
Desenvolvida a partir de 1960, grande parte das
codificações de caracteres modernas a herdaram como
base.

A codificação define 128 caracteres, preenchendo


completamente os sete bits disponíveis em 2 7=128
sequências possíveis. Desses, 33 não são imprimíveis,
como caracteres de controle atualmente não utilizáveis
para edição de texto, porém amplamente utilizados em
dispositivos de comunicação, que afetam o
processamento do texto.”

CRIANDO SEU PRIMEIRO ALGORITMO

Vamos então para o nosso primeiro programa com


Linguagem de Programação Estruturada:

Exemplo 1:

Algoritmo Calcular_Idade

1- Saber o ano de nascimento


2- Saber o ano atual
3- Subtrair o ano atual do ano de nascimento
4- Apresentar o resultado

36
Programa Calcular_Idade()

Var„Declarando as variáveis. Objetos de valor


transitório.

sAno1
Tipo: longo
sAno2
Tipo: longo
sIdade
Tipo: inteiro

sAno1 = Digite o ano de nascimento


„Dando um valor a variável sAno1 (Comentário)
sAno2 = Digite o ano atual
„Dando um valor a variável sAno2 (Comentário)

Se sAno1 Não for Nulo ou sAno1 for diferente de


vazio então „Condição para o cálculo

sIdade = sAno2 – sAno1


Calcular_Idade = sIdade„Função Calcular_Idade
recebe o resultado da operação entre as
variáveis

Senão
Sair do programa

Fim

O que acabamos de desenvolver é um programa a partir


de um algoritmo usando a pseudo-linguagem ou pseudo-
código. Este programa pode se escrever,(em linguagem
de programação de alto nível), em qualquer tipo de
linguagem de programação. O código abaixo é visto como

37
uma função (por quê?) porque retorna um valor (ou traz
um valor de retorno), no caso, a idade de uma pessoa.

Vamos codificar essa linguagem que acabamos de


estudar, agora em Access VBA. Nosso programa ficaria
assim:

Function Calcular_Idade()

Dim sAno1 As Long


Dim sAno2 As Long
Dim sIdade As Integer

sAno1 = InputBox(“Digite o ano de nascimento:


“)
sAno2 = InputBox(“Digite o ano atual:”)

If Not IsNull(sAno1) or sAno1 <> “” Then

sIdade = sAno2 – sAno1


Calcular_Idade = sIdade
„Na fonte de controle de uma caixa de texto
pela „caixa de propriedades da mesma
„=Calcular_Idade()
„Ou poderíamos exibir o resultado em uma caixa
de „texto diretamente a partir do código
„Me.txtIdade = sIdade
„Ou poderíamos exibir o resultado através de
uma „mensagem de texto (MsgBox)
„MsgBox “Sua idade é “ & sIdade

Else
Exit Sub

End If

38
Chame esta função através de um botão no formulário.

Sub cmdCalcular()

Call Calcular_Idade„A instrução Call invoca a


função „Calcular_Idade

End Sub

Quais seriam então os passos para construir um


algoritmo?

Segundo o prof. Dr. Abel Gomes cuja proposição achei


bem interessante e objetiva foi esta:

Existem três fases distintas na elaboração de programas:

1- a análise do problema (especificação do problema,


análise de requisitos, pressupostos, etc.)
2- a concepção do algoritmo.
3- a tradução desse algoritmo na linguagem de
programação.

PROBLEMA  ALGORITMO  PROGRAMA

PASSOS NA CONSTRUÇÃO DE ALGORITMOS

a- Compreender o problema
b- Identificar os dados de entrada
c-Identificar os dados de saída
d- Determinar o que é preciso para transformar dados
de entrada em dados de saída:

39
1- usar a estratégia do dividir-para-conquistar
2- observar regras e limitações
3- identificar todas as ações a realizar
4- eliminar ambiguidades

e- Construir o algoritmo
f- Testar o algoritmo
g- Executar o algoritmo

REPRESENTAÇÕES DE ALGORITMOS

 Linguagem Natural
 Fluxograma
 Pseudo-linguagem

Gosto mais de trabalhar com pseudo-linguagem ou


também conhecido como pseudo-código para descrever
os passos a dar em minha codificação. Não vou me
estender muito em algoritmos porque não é a finalidade
principal de meu livro.

FLUXOGRAMAS

Para se criar um fluxograma ou o também conhecido


diagrama em blocos, trabalharemos a partir da proposta
do problema. Levantamos os dados, criamos as propostas
de solução(ou condições) e consequências de cada
decisão até chegarmos a uma solução satisfatória.

Exemplo de fluxogramas:

(A)

40
(B)

41
Para criarmos um fluxograma convencionalmente correto
em programaçãoe planejar o desenvolvimento de um
programa, as etapas seriam assim distribuídas nos blocos
e estes também dever seguir uma padronização como
esta no exemplo abaixo:

(A)

42
Observe que após o cálculo o programa recomeça a
tomada de decisão ou o início da condição proposta,
chamamos isso de looping.

(B)

43
Início

Ler o primeiro
número – N1

Ler o segundo
Número – N2

Falso N2=0 Verdadeiro

Calcular a divisão Mostrar um video


De N1 por N2 - DIVISÃO “Não é permitido
divisão por zero”

Mostrar em video
O valor da DIVISÃO FIM

O significado dos blocos em um fluxograma de Tomada


de Decisão:

44
DECLARAÇÃO DE VARIÁVEIS

O primeiro passo para codificar um objeto (botão, caixa de


texto, caixa de listagem, caixa de combinação, etc) que
fará parte de seu programa é declarar as variáveis que
esses objetos receberão ou que serão trabalhados. Isto

45
nada mais é que criar um receptador dos dados digitados
ou inputados no seu programa(do inglês Input, que
significa introduzir) . As variáveis armazenam os valores
temporariamente na memória do computador. Uma
variável pode, por assim dizer, armazenar diversos
valores para serem manipulados um de cada vez. É
imprescindível para que um bom programa funcione a
contento que haja variáveis declaradas no seu escopo de
códigos.

Declarar uma variável também serve para modelar os


dados que esta variável receberá. Uma variável pode ser
do tipo String (que recebe dados de texto); do tipo
Integer (que recebe dados de números inteiros dentro de
uma determinada faixa); do tipo Date (que recebe dados
do tipo Data/Hora), etc. Para início de estudo estes são os
tipos de dados mais comuns empregados rotineiramente.

Entre no ambiente de código VBA(IDE) de seu aplicativo


Access. Observe que ele sempre terá o seguinte código
como cabeçalho:

Option Compare Dabase

Acrescente a seguinte instrução abaixo dela, caso ela não


esteja lá:

Option Explicit

46
No ambiente de código, deixe sempre declarada esta
linha pela barra de ferramentas Opções, pois é
extremamente necessária para forçar a declaração de
variáveis, tornando o código bem estruturado e
aumentando o bom desempenho do programa evitando
'bugs' indesejados.

Option Compare Database


Option Explicit

Pode-se também tornar padrão esta inclusão em todos os


seus programas pela barra de ferramentas: Ferramentas,
Opções, Editor,Requerer Declaração de Variável.

Por exemplo, o termosNome será nossa variável que


receberá dados de nomes de nosso cadastro. Lembre-se
de não criar variáveis que tenha o mesmo nome de
métodos ou propriedades do Access, isto é, palavras
reservadas dessa linguagem. Existem certas regras na
criação de variáveis que serão estudadas ao final deste
capítulo.

A instrução empregada para declarar as variáveis chama-


se Dim (uma abreviatura de Dimensionar)

Dim sNome As String (Significa „dimensionar a


variável sNome como um valor do tipo Texto‟)

47
Dim é uma palavra reservada da biblioteca Access VBA
usada para reservar espaço para uma variável na
memória.

Parece que estamos dando uma ordem a alguém, não é?


Na verdade, estamos nos comunicando com o compilador
em uma linguagem de máquina de alto nível*, para que
entenda que sNome receberá dados do tipo texto e
aprove a decisão e compile como correto. O Visual Basic
é um exemplo de linguagem de alto nível, suas bibliotecas
estão preparadas para „entender‟ o que o programador
digita dentro do escopo de linguagem de suas bibliotecas.

Vamos modificar o nosso programa inicial para introduzir


estes novos elementos que comporão um programa.
Vamos trabalhar somente com o evento Form_Open.

1º Caso: Quando o valor da nossa variável do tipo String


vem encorpada por duas aspas(“”)

Private Sub Form_Open(Cancel As Integer)


Dim sNome As String
sNome = “Eduardo”
MsgBox “Alô, ” & sNome, vbInformation,
“Primeiro Programa” „Ao referenciá-
la(variável) usamos uma aspas e um & (lê-se E)
comercial
End Sub

48
2º Caso: Quando o valor da nossa variável do tipo String
NÃO vem encorpada por duas aspas. Nesse caso
estamos trabalhando ou com o valor da caixa de texto ou
combo a que ela se refere ou com o valor inserido em
uma InputBox*.

(a) Private Sub Form_Open(Cancel As


Integer)

Dim sNome As String


sNome = NomeCliente „Nome da
caixa de texto
MsgBox “Alô, ” & sNome, vbInformation,
“Primeiro Programa”
End Sub

(b) Private Sub Form_Open(Cancel As Integer)

Dim sNome As String


sNome = InputBox("Digite o nome: ")
MsgBox “Alô, ” & sNome, vbInformation,
“Primeiro Programa”
End Sub

*InputBox : É uma caixa de inserção de dados gerada pela seguinte sintaxe:

InputBox(prompt[, title][,default] [, xpos] [, ypos] [, helpfile, context])

Os argumentos em destaque são opcionais e serão estudados em


ocasião oportuna.

49
REGRAS PARA DECLARAÇÃO DE VARIÁVEIS(*)

Existem regras para a nomenclatura de variáveis no VBA:

-Variáveis devem começar obrigatoriamente com letras,


ou seja, números ou dígitos não são permitidos. No
entanto, estes podem aparecer no meio e no fim.

-O nome de uma variável não pode ter mais que 200


caracteres;

Nota: Palavras Reservadas do VBA Não São


Permitidas como Variáveis

-Uma variável não pode ter o mesmo nome de um dos


objetos/classes das bibliotecas referenciadas no projeto.
Por exemplo, se você estiver utilizando o Word, não pode
chamar uma variável de Document, pois esta já existe na
biblioteca Microsoft Word 14.0 Object Library, por
exemplo;

-Não pode haver espaço no nome da variável. Você pode,


entretanto, usar hifens ou letras maiúsculas para
organizar o nome delas, como por exemplo,
strPrimeiroNome ou str_Primeiro_Nome;

As boas práticas de programação sugerem que se deve


usar uma terminologia organizada para não se perder nos
nomes das variáveis.

No Access, não é permitido utilizar palavras reservadas,


como Print, Date, Single, Name, etc.

50
Declaração por Sufixos(*)

Caso deseje definir uma variável através de um sufixo,


utilize a tabela abaixo:

Alternativa de sufixo
Sufixo Tipo de dado
& Long
! Single
# Double
% Integer
$ String

Ou seja, os procedimentos Ex1 e Ex2 exemplificados


abaixo têm o mesmo efeito:

Sub Exemplo1()
Dim strNome As String
Dim lngIdade As Long
Dim dblPosicao As Double
Dim intn As Integer

EndSub

Sub Exemplo2()
Dim strNome$
Dim lngIdade&
Dim dblPosição#
Dim intn%

End Sub

51
TABELA DE TIPOS DE VARIÁVEIS MAIS COMUMENTE
USADAS

Variant * Tipo Genérico

Obs: Variáveis Ex: Dim X


sem declaração
de tipo
assumem o tipo
Variant

True ou False (Verdadeiro ou Falso) ou (-


Boolean 1/0)

Byte Número inteiro de 0 a 255

Integer Número inteiro de -32.768 a 32.767

Long Número inteiro de -2.147.483.648 e


2.147.783.647

Single Números reais de precisão simples entre


-3,40e³8 e -1,40e-45 para números
negativos, e 1,40e-45 e 3,40e38 para
números positivos

Double Número entre -1,79769313486232E308 e -


4.94065645841247E-324 ou
1,74769313486232E308 e
4.94065645841247E-324

Currency Quantia monetária entre -


922.337.203.685.477,5808 e

52
922.337.203.685.477,5807

Date Data ebtre 1/Janeiro/0100 e


31/Dezembro/9999

String Texto com até 2 bilhões de caracteres.

Variant Para armazenar Data/Horas ou qualquer


tipo de informação

Obs: Cuidado ao utilizar variáveis do tipo Variant pois


podem assumir qualquer tipo de dados e apresentar
problemas na compilação e resultados. Sempre que
possível especifique o seu tipo de variável.

Você pode declarar várias variáveis em uma mesma


instrução sem ter que repetir o mesmo tipo de dados,
separando-os com vírgulas.

Ex: Dim strNome, strEndereco, strTelefone As String

Você pode declarar uma variável por inferência de tipo.

Ex: Dim Num = 5 „Infere-se que esta variável é do tipo


Integer

Nota: Não é obrigatório acrescentar o tipo de dados de


uma variável, mas recomenda-se sua classificação para
maior clareza em sua identificação.

53
MODELAGEM DE DADOS DE UMA TABELA:

Em geral, quando vamos desenvolver algum aplicativo, a


primeira coisa a fazer é saber quantas tabelas terá nosso
aplicativo e para cada tabela saber que tipo de dados
primitivos terá cada campo da mesma e o espaço que
cada campo ao ser preenchido ocupará. Outras
modificações essenciais são que tipo de formato terá
determinado campo específico; se terá uma máscara de
entrada; se aceitará só números ou só letras; ou se será
alfanumérico. Chamamos de Tipos Primitivos de Dados
as características de cada campo da tabela. São esses
campos que abrigarão os nossos dados, ou registros ou
recordset. Lembrando que esses dados podem ser
comutados, sendo assim, são chamados de variáveis.

 Anexo como fotos digitais. Vários arquivos podem ser


associados por registro. Esse tipo de dados não está
disponível em versões anteriores do Access.
 AutoNumeração Os números gerados automaticamente
para cada registro.
 Moeda Valores monetários.
 Data/Hora Datas e horas. Pode possuir uma máscara de
entrada como na fig. abaixo.
 Hiperlink Hiperlinks, como endereços de email ou sites.
 Memorando Longos blocos de texto e texto que usam
formatação. Um uso típico de um campo Memorando seria
uma descrição detalhada do produto.

54
 Número Valores numéricos, como as distâncias. Observe
que há um tipo de dados separado para moeda.
 Objeto OLE como documentos do Word, imagens.
 Texto Curto, valores alfanuméricos, como um sobrenome
ou um endereço.
 Sim/Não Valores booleanos.

A Microsoft estabelece um quadro ilustrativo bem


detalhado que entendi por bem dispor aqui neste capítulo
para melhor elucidação do assunto.

Tipos de dados

A tabela a seguir fornece uma lista dos tipos de dados


disponíveis no Microsoft Office Access 2007, além das
diretrizes de uso e das capacidades de armazenamento
de cada tipo.

TIPO DE USO TAMANHO


DADOS

Texto Use para caracteres Até 255 caracteres


alfanuméricos, inclusive texto,
ou texto e números, que não
são usados em cálculos (por
exemplo, uma identificação do
produto).

Memorando Use para textos com Até 1 gigabyte de


comprimento maior do que 255 caracteres ou 2
caracteres ou para textos com gigabytes de
formatação rich text. Exemplos armazenamento (2

55
incluem anotações, descrições bytes por caractere),
longas e parágrafos que usam dos quais você pode
formatação de texto, como exibir 65.535
negrito ou itálico. caracteres em um
Use a propriedade Formato do único controle.
Texto de um campo OBSERVAÇÃO O
Memorando para especificar se tamanho máximo de
o campo oferece suporte a um arquivo de
texto formatado. banco de dados do
Defina a propriedade Office Access 2007
Acrescentar Somente de um é de 2 gigabytes.
campo Memorando como Sim
para manter versões anteriores
do valor do campo quando o
valor for alterado.
Número Use para armazenar valores 1, 2, 4, 8 ou 12
numéricos (inteiros ou bytes (16 bytes
fracionados) que serão usadosquando usado para
em cálculos, exceto para uma ID de
valores monetários. replicação)
OBSERVAÇÃO Use o tipo de Para obter mais
dados Moeda para valores informações,
monetários. consulte a entrada
Número Tamanho
do Campo da
tabela de
referências das
propriedades do
campo.
Data/Hora Use para armazenar valores de 8 bytes
data e hora. Observe que cada
valor armazenado inclui um
componente de data e um
componente de hora.
Moeda Use para armazenar valores 8 bytes
monetários (Moeda).
AutoNumeração Use para gerar valores 4 bytes (16 bytes
exclusivos que podem ser quando usada para

56
usados como uma chave ID de replicação)
primária, inserida pelo Access
quando um registro é
adicionado. Observe que
campos AutoNumeração
podem ser incrementados
seqüencialmente, por um
incremento especificado ou
atribuídos aleatoriamente.
Sim/Não Use para valores booleanos: 1 bit (0,125 bytes)
Sim/Não, Verdadeiro/Falso ou
Ativado/Desativado.
Objeto OLE Use para armazenar Objetos Até 1 gigabyte
OLE de outros programas do
Microsoft Windows.
Anexo Use para armazenar arquivos Para anexos
binários (ou seja, arquivos que compactados, 2
você não pode ler usando um gigabytes. Para
editor de texto), como imagens anexos
digitais (fotos e elementos descompactados,
gráficos) ou arquivos criados aproximadamente
usando outros produtos 700KB, dependendo
Microsoft Office. do grau de
Você pode anexar mais de um compactação do
arquivo por registro para um anexo.
campo Anexo. OBSERVAÇÃO O
tamanho máximo de
um arquivo de
banco de dados do
Office Access 2007
é de 2 gigabytes.
Hiperlink Use para armazenar hiperlinks, Até 1 gigabyte de
que fornecem acesso de clique caracteres ou 2
único para páginas da Web por gigabytes de
meio de uma URL (Uniform armazenamento (2
Resource Locator) ou para bytes por caractere),
arquivos por meio de um nome dos quais você pode
em UNC (Uniform Resource exibir 65.535

57
Locator). Você também pode caracteres em um
criar links para objetos do único controle.
Access que estão armazenados OBSERVAÇÃO O
em um banco de dados. tamanho máximo de
um arquivo de
banco de dados do
Office Access 2007
é de 2 gigabytes.
Assistente de Use para iniciar o Assistente de Se o campo de
Pesquisa Pesquisa para que você possa pesquisa estiver
criar um campo que usa uma associado a uma
caixa de combinação para tabela ou uma
pesquisar um valor em outra consulta, terá o
tabela, consulta ou lista de tamanho da coluna
valores. Observe que o associada.
Assistente de Pesquisa, na Se o campo de
realidade, não é um tipo de pesquisa não estiver
dados. associado a outra
coluna (e armazenar
uma lista de
valores), terá o
tamanho do campo
Texto usado para
armazenar a lista.

Veja este exemplo na figura abaixo:

58
O que você observa de importante sobre o que
estudamos?

Tamanho do campo – 15 (isto é, cabe somente 15


caracteres neste campo)
Máscara de entrada – 0.000.000;0_ (O preenchimento
deste campo obrigatoriamente segue esta formação.
Clique nos três pontinhos e selecione a máscara de
entrada de seu interesse.
Legenda– RG
Requerido – Sim
Indexado – Sim (Duplicação não autorizada)

59
Qual é a diferença entre Formato e Máscara de
entrada?

FFormato - Determina a forma em que o campo é


omostrado quando exibido ou impresso em folhas de
rdados ou em formulários ou relatórios vinculados ao
M
campo. Você pode definir um formato personalizado para
M
um campo. Por exemplo, formato Moeda (R$,$...),
Data/Hora(Data Abreviada, Data Longa, etc). Geralmente
para campos do tipo Número, há uma lista de formatos à
sua escolha, da mesma maneira para campos do tipo
Data/Hora.

Máscara de entrada- As máscaras de entrada oferecem


um formato definido para entrada de dados em um campo
usando caracteres e símbolos. Quando você aplica uma
máscara de entrada a um campo, qualquer um que insira
dados no campo deverá seguir o padrão específico
definido pela máscara de entrada. Por exemplo, se o
usuário do banco de dados inserir um número de telefone
sem o código de área, nesta máscara em particular, (___)
555-0187, o usuário não poderá salvar os dados até que
os dados do código de área sejam adicionados. O
comportamento preciso depende de como o criador de
banco de dados configura a máscara de entrada.

As máscaras de entrada oferecem validação a uma


grande quantidade de dados e impedem que os usuários
digitem dados inválidos (como um número de telefone em

60
um campo de data). Além disso, ajudam a garantir que
usuários digitem dados de maneira consistente. Essa
consistência facilita a localização dos dados, bem como a
manutenção de seu banco de dados.

Caracteres que definem máscaras de entrada

A tabela a seguir lista os caracteres literais e para espaço


reservado para uma máscara de entrada e explica como
ela controla a entrada de dados:
CARACTERE EXPLICAÇÃO
0 O usuário deve inserir um dígito (0 a 9).
9 O usuário pode inserir um dígito (0 a 9).
# O usuário pode inserir um dígito, um espaço
ou um sinal de mais ou de menos. Se
ignorado, o Access inserirá um espaço em
branco.
L O usuário deve inserir uma letra.
? O usuário pode inserir uma letra.
A O usuário deve inserir uma letra ou um dígito.
A O usuário pode inserir uma letra ou um
dígito.
& O usuário deve inserir um único caractere ou
um espaço.
C O usuário pode inserir caracteres ou espaços.
.,:;-/ Espaços reservados de decimais e milhares,
separadores de data e hora. O caractere que

61
você selecionar dependerá das configurações
regionais do Microsoft Windows.
> Converte todos os caracteres seguintes em
letras maiúsculas.
< Converte todos os caracteres seguintes em
letras minúsculas.
! Faz com que a máscara de entrada seja
preenchida da esquerda para a direita, e não
da direita para a esquerda.
\ Os caracteres seguintes serão exibidos
literalmente.
"" Os caracteres entre aspas duplas serão
exibidos literalmente.

Veja este outro exemplo na figura abaixo:

62
Observe que para cada campo de sua tabela corresponde
a um tipo de dados. Quando tratamos de campos do tipo
Texto, estaremos lidando com variáveis do tipo String em
VBA que referenciarão a este campo específico do tipo
Texto. Por exemplo, no campo Nome poderão ser
inseridos a cada registro um nome diferente, certo? Logo,
podemos dizer que o campo Nome poderá ter valores que
variarão ao longo do tempo. Para ocorrerem modificações
neste campo via programação será necessário que
trabalhemos com certos termos referentes a estes
campos que damos o nome de variáveis.

63
Por exemplo, para o campo Nome temos uma variável
com determinado termo que chamaremos de
sNome(termo criado pelo programador seguindo as
regras para sua declaração, isto é, respeitando as
palavras reservadas do Access ao NÃO utilizá-las)

Private Sub cmdTestar_Click ()

Dim strNome As String „Declaramos


strNome como do tipo String (uma cadeia de
caracteres)

strNome = Nome „A variável


strNome conterá o valor digitado no campo
Nome

Pronto, agora podemos trabalhar com a


string contida no campo Nome. Por exemplo:

Dim strNome As String


Dim intn As Integer
strNome = Nome
intn = Len(Nome) „A função Len
tem como parâmetro uma
string cujos caracteres
ela conta

Debug.Print strNome „Permite a


impressão do nome na Janela „Verificação
Imediata‟*

64
Debug.Print intn

MsgBox "O seu nome é " & strNome


MsgBox "Possui " & intn & " caracteres"

End Sub
REGRAS PARA PREFIXOS DE NOMES DE OBJETOS

Algumas regras precisam ser seguidas para definir


nomes de objetos de seu aplicativo. Essas regras
seguem uma convenção internacional, chamada
regras de Reddick.
TABELAS CONSULTAS FORMULÁRIOS MÓDULOS

tblNome tbl_Nome cnsNome qryNome frmNome modNome basNome

CAIXA
DE RÓTULO COMBOBOX LISTBOX CHECKBOX OPTION BUTTON
TEXTO

txtNome lblNome cboNome lstNome chkNome optNome

REGRAS PARA PREFIXOS(MARCAS) DE VARIÁVEIS

Marca Tipo de Objeto

byt Byte
f Boleano (Lógico)

65
int Integer
lng Long
sng Single
dbl Double
cur Currency
dat Date
obj Object
str,s String
stf String (comprimento fixo)
var Variant
Alguns exemplos:
Dim lngCount As Integer
Dim intValue As Long
Dim strInput As String

Nota: Evite declarações de variáveis na mesma linha.


Declare cada variável separadamente, isto é, linha por
linha a cada variável.

DESCRIÇÃO DO CÓDIGO

Outro padrão internacional estabelecido é descrever o


que seu código faz em alguns trechos, descrevendo-o

66
ao lado da linha de código ou acima deste dentro do
evento de algum controle, função ou sub-rotina. Em
conjunto com o nome dado aos objetos acima,
podemos dizer que assim será possível que diferentes
programadores possam entender o seu código e assim
operar as modificações que se fizerem necessário em
caso da manutenção de uma linha de código.

Ex:
Função que retorna a soma dos valores de uma
determinada coluna de uma listbox.

Private Function SomarTotal()


On Error Resume Next
Dim lngx As Long
Dim lngsoma As Long
lngsoma = 0

„Looping For .... Next


For lngx = 1 To Me.lstProdutos.ListCount -
1
lngsoma = lngsoma +
Me.lstProdutos.Column(3, x)

67
„3ª coluna percorrendo do índice 0 até o
último índice menos 1, pega os valores da
coluna Quantidade
Next
SomarTotal = lngsoma

End Function

RELACIONAMENTOS ENTRE TABELAS (OU TUPLAS)


O princípio de relacionar tabelas torna possível a criação
de consultas com base na relação existente entre elas,
considerando principalmente os códigos indexados(Não
permitem duplicação) de registros identificados e
precedidos de uma chave.

Em uma tabela, o principal campo indexado terá uma


chave chamada chave primária (ou Primary Key). Esta
chave identifica todos os atributos do campo Pai que são
encontrados no campo Filho de forma exclusiva. Por
exemplo, todo cidadão só poderá possuir um único CPF
ou RG e através dele ser identificado. Assim poderíamos
ter várias compras realizadas pelo mesmo
consumidor(Cliente) identificado por um
código(CodigoCliente) único na tabela Clientes presente
também na tabela Vendas. Faríamos então um
relacionamento da tabela Clientes para a tabela

68
Vendas(um-para-muitos), vincunlando-se os campos
CodigoCliente. Se surgir o erro: Nenhum índice exclusivo
foi encontrado para o campo referido da tabela
primária.Faltava o índice exclusivo. No modo Design da
tabela Funcionários, clique em Índices e modifique para
Sim o campo com índice exclusivo que é a sua chave
primária.

O segundo campo indexado terá outra chave chamada


chave estrangeira(ou ForeignKey/Secondary Key).
Estes campos precisam ser selecionados ao mesmo
tempo para que com o botão direito do mouse possamos
inserir as referidas chaves. Vamos começar interpretando
o seguinte relacionamento abaixo, onde estabelecemos
que a tabela Produtos está subordinada à tabela
Categorias e, esta por sua vez, à tabela Grupos.

Observe também que pelo menos um campo de cada


tabela possui uma chave à sua direita que determina que
este é o campo Pai e o que está vinculado a ele é o
campo Filho. Pai só existe um, não é?, portanto este
campo é indexado, isto é, não permite duplicação. Um
campo Pai pode ter muitos filhos que não possuem chave
alguma (não são indexados), daí temos, um
relacionamento do tipo um-para-muitos. Um campo da
tabela Grupos pode ter várias Categorias, mas na tabela
Categorias, cada campo Filho, pode ser campo Pai para a
tabela Produtos, isto é, uma Categoria pode ter vários
Produtos relacionados a ela (Categoria).

69
Assim, teremos a seguinte visualização dos dados (ou
registros). Em VBA chamamos de Recordset:

70
Verificamos que na tabela Grupos que seria a tabela
principal da cadeia, existe ramificações identificadas pelo
sinal (+) de outras tabelas sujeitas a ela. Quais seriam? A
segunda tabela sujeita ao campo Grupo é a tabela
Categorias. Assim, cada grupo especificado em cada
registro da tabela Grupos possui um conjunto de outros
registros da tabela Categorias, subordinados a cada um
desses grupos. Visualize a segunda cadeia de registros
abaixo:

71
Note que o grupo de registro número 1 possui
subordinado a ele, um conjunto de categorias no total de
29, isto é, um recordset com 29 registros. Você verá
agora que cada categoria desse conjunto possui outro
conjunto de registros(recordset) a ele subordinado que
agora será de Produtos. Atente para a figura abaixo:

72
Como isso foi possível? Vinculando na área de
relacionamentos o código do produto ao código de
categoria e este por sua vez ao código do grupo. Vamos
ver isso na prática. Observe as figuras:

(1) Clique em Ferramentas de Banco de Dados e em


seguida em Relações:

73
(2) Clique com o botão direito dentro desta área e
insira as tabelas Grupos, Categorias e Produtos.

74
Agora, clique duas vezes em cima de CodGrupo e
vincule as tabelas Grupos e Categorias e campos
CodGrupo de cada tabela respectivamente. Isso também
é possível ao clicar e arrastar para o outro campo em
comum da outra tabela. Faça a mesma coisa com as
tabelas Categorias e Produtos com os campos
CodCategoria de cada tabela. Teremos aqui um
relacionamento do tipo Um-para-muitos, isto é, para cada
registro de Grupos muitas Categorias e, por sua vez na
tabela Categorias, para cada registro de Categorias
muitos Produtos.

Do site da Microsoft:

“Um relacionamento de tabela é uma associação


estabelecida entre campos comuns (colunas) de duas
tabelas. Um relacionamento pode ser um-para-um, um-
para-muitos ou muitos-para-muitos.

Uma associação é uma operação SQL que combina


dados de duas origens em um registro em um conjunto de
registros de uma consulta com base nos valores de um
campo especificado que as origens possuem em comum.
Uma associação pode ser uma associação interna,
uma associação externa à esquerda ou uma associação
externa à direita.

Quando você cria um relacionamento de tabela ou


adiciona uma associação a uma consulta, os campos

75
conectados devem ter os tipos de dados iguais ou
compatíveis. Por exemplo, você não pode criar uma
associação entre um campo Número e um campo Texto,
mesmo que os valores desses campos coincidam.

OBSERVAÇÃO Em um relacionamento ou em uma


associação, os campos definidos com o tipo de dados
AutoNumeração serão compatíveis com campos definidos
com o tipo de dados Número caso a propriedade
Tamanho do Campo do último seja Inteiro Longo.

DICA Em uma consulta, algumas vezes você pode usar o


operador Como em um critério de campo para comparar
campos com tipos de dados incompatíveis.

Não é possível alterar o tipo de dados ou a


propriedade Tamanho do Campo de um campo
envolvido em um relacionamento de tabela. Você pode
excluir temporariamente o relacionamento para alterar a
propriedade Tamanho do Campo, mas se o tipo de dados
for alterado, você não será capaz de recriar o
relacionamento sem primeiro mudar o tipo de dados do
campo relacionado.”

Agora, clique no botão Tipo de associação, selecione a


segunda opção:

76
O objetivo do relacionamento é tornar possível no
formulário principal a criação de sub-formulários
relacionados aos registros do formulário principal
baseados em um único código de mesmo nome presente
entre as tabelas que se relacionam entre si. Assim,
teríamos uma forma estruturada de visualização vinculada
aos campos indexados(códigos) ou campos com chave
primária(Não permite duplicação de registro com o
mesmo nome) de cada tabela. Outro aproveitamento é
organizar ou encadear os registros das tabelas que tem
algum vínculo associativo. Vejamos um exemplo desta
finalidade:

77
Observe neste formulário o campo Produto, o campo
Categoria e o campo Grupo. Com base nos
relacionamentos existentes entre essas tabelas foi
possível correlacioná-las na forma que você vê acima:

O Produto Biscoito Maisena exibe a Categoria Biscoito


e, por sua vez, exibe o GrupoMercearia Doce a que
pertence, principalmente, porcausa do relacionamento
existente entre essas tabelas.

Mas precisamos do VBA para finalizar a exibição dessa


forma:

78
Campo Produto(Não Acoplado) e seu Valor
respectivamente na fonte do controle:
=DPesquisa("[Produto]";"[Produtos]";"[CodigoProd]=[
cboCodProduto]")
=DPesquisa("[ValordeVenda]";"[Produtos]";"[CodigoPr
od]=[cboCodProduto]")

Campo Categoria(Não Acoplado


=DPesquisa("[Categoria]";"[qryProdutos]";"[CodigoPr
od]=[cboCodProduto]")

Campo Grupo(Não Acoplado):


=DPesquisa("[Grupo]";"[GrProdutos]";"[CodigoProd]=[
cboCodProduto]")

O código acima entra na Fonte do Controle da caixa de


texto Categoria. A função de pesquisa é
DLookup(DPesquisa) que pesquisará qual Categoria da
consulta qryProdutos existe que tenha o campo
CodigoProd igual a cboCodProduto.

Por que qryProdutos e não a tabela Produtos? A


sintaxe da função DLookup é pelo Ajuda do Access:

DLookup(expr, domínio [, critérios] )

Onde expr é o nome do campo pesquisado que se


encontra na tabela(domínio) e que obedeça a um critério
de pesquisa(critérios)

79
A resposta é que preciso nesse caso que a tabela
Produtos venha associada a tabela Categorias, isto é,
relacionando-se entre si. Para que isso ocorra, preciso
criar uma consulta(qryProdutos). Como as tabelas já
estão relacionadas, basta incluí-las que imediatamente o
relacionamento surgirá. Veja a figura abaixo:

80
E que também a tabela Categorias venha relacionada
com a tabela Grupo. É só criar outra
consulta(GrProdutos)e incluir as tabelas.
Semelhantemente como na consulta qryProdutos é só
incluí-las que o relacionamento surgirá imediatamente.:

81
Há mais dois outros tipos de relacionamentos que
convém estudar. A partir do mesmo raciocínio

82
poderemos ter relacionamentos do tipo muitos-para-
muitos e um-para-um.

Relacionamento um-para-um:

Ocorre ao contrário do relacionamento um-para-


muitos onde o campo Filho(CodigoCliente), isto é, da
tabela secundária não deve ser exclusivo, somente o
campo Pai(CodigoCliente) da tabela primária.

Vamos pegar esta simples definição do site da


Microsoft: “Neste tipo de relacionamento, os dois
campos comuns (normalmente os campos de chave
primária e chave estrangeira) devem ter um índice
exclusivo. Isso significa que a propriedade Indexado
desses campos deve ser definida como
Sim(Duplicação Não Autorizada). Se ambos os
campos tiverem um índice exclusivo, o Access criará
uma relação um-para-um.”

Vejamos um exemplo prático:

Imagine uma escola com um Cadastro de Alunos na


tabela Alunos, destes apenas uma pequena parte
participa da Banda da Escola. Por questões de projeto

83
do Banco de Dados, podemos criar uma Segunda
Tabela "Alunos da Banda", a qual se relaciona com a
tabela Alunos através de um relacionamento do tipo
Um para Um. Cada aluno somente é cadastrada uma
vez na Tabela Alunos e uma única vez na tabela Alunos
da Banda. Poderíamos utilizar o Campo Matrícula do
Aluno como o Campo que relaciona as duas Tabelas.*

*Exemplo extraído de “Tipos de Relacionamentos de


um bd” (Julio Fabris Battisti)

Relacionamento muitos-para-muitos:

Este tipo de relacionamento "aconteceria" em uma


situação onde em ambos os lados do relacionamento
os valores poderiam se repetir. Mas isso é impossível
de se fazer com apenas 2(duas) tabelas. Suponhamos
que tivéssemos uma tabela Pedidos e outra Produtos,

84
teríamos que repetir o Número do Pedido, Nome do
Cliente, Nome do Funcionário, Data do Pedido, etc,
para cada item do pedido. Concluímos que não
poderíamos indexar qualquer campo das tabelas se os
campos tivessem que se repetir, isto é, com um
relacionamento muitos-para-muitos. Como identificar
os produtos diferentes para um único cliente, ou
melhor, como selecionar vários produtos entre vários
pedidos para um único cliente?

Neste tipo de relacionamento trabalha-se com mais


uma tabela a mais, DetalhesdoPedido, quando
poderemos indexar um campo da tabela Produtos e
um campo da tabela Pedidos e esta terceira tabela
receberia muitos pedidos e muitos produtos. Ao invés
de termos um relacionamento do tipo Vários para
Vários, teremos dois relacionamentos do tipo um para
vários, conforme descrito pela próxima tabela:

Veja um exemplo na figura abaixo:

85
Vamos fazer um teste:

(1)Definamos que na primeira tabela, digamos, uma


tabela de atletas (tblAtletas)com seu CodigodoAtleta,
NomedoAtleta, CodigodoClube e
CodigodaModalidade . Só existe um atleta com seu
respectivo clube, certo? O atleta, porém, pode
praticar outras modalidades dentro do mesmo clube
ou não, mas defender um único clube em uma só
modalidade. (2) Na segunda tabela teremos os
detalhes pertinentes a estes atletas que se
repetem(DetalhesdoAtleta), os campos
CodigodoClube, CodigodoAtleta,
CodigodaModalidade, Modalidade, Idade, etc.,

86
porque reúne vários atletas de diversos clubes. (3) Na
terceira e última tabela(tblClubes) os campos
CodigodoClube e NomedoClube. Neste caso, para
cada clube só existe um código.

Como se vê, o relacionamento se tornou de muitos-


para-muitos, respeitando o termo, ainda que
controlada por uma tabela-pivô. Teríamos muitos
atletas de diversas modalidades de diversos clubes,
centralizados na tabela DetalhesdoAtleta. Vamos às
ilustrações após inserir alguns dados.

87
(1) A tabela tblClubesfica assim:

(2) A tabela (tblAtletas) ficaria assim:

88
(3) Finalmente, a tabela (DetalhesdoAtleta) ficaria
assim:

89
Agora vamos fazer os testes dos relacionamentos:
Observe que o jogador Neymar, neste exemplo, joga
somente futebol em um único clube, o Santos (Código
8)

Já o jogador Fred, defende o Fluminense(Código 4) e


pratica Natação em outro clube o Vasco (Código 5).
Isso é só uma mera suposição para mostrar a
possibilidade.

90
E quais são os atletas dos clubes?

91
Analise bem. Quem joga no Santos é o Neymar(Código
1), na modalidade Futebol, com 21 anos de idade. Quem
joga no São Paulo é o Ganso(Código 3) na modalidade
Futebol com 22 anos de idade.

Resumo da ópera: Veja bem para cada relacionamento


entre tabelas embora seja possível não é o ideal o
relacionamento de irmão pra irmão como muita gente faz
e sim de pai pra filho. Um pai pode ter muitos filhos,
portanto os relacionamentos de forma geral em todas as
linguagens são deste tipo, com pequenas variações.

Na tabela-Pai você tem um campo que possui chave


primária e que não aceite duplicação, por exemplo, a
tabela Clientes seria a tabela-Pai pois os nomes dos
clientes cadastrados não podem se repetir.

Cada cliente possui um código, certo? É deste campo que


parte o relacionamento para outra ou outras tabelas que
possuem o mesmo campo(e mesmo nome), isto é, código
de cliente que por sua vez podem se repetir.

Ex: CodCliente (1).........( ) CodCliente

Vou deixar pra você entender o por quê. No final, você vai
perceber que é muito fácil criar relacionamentos. Tem que
ter os sinais gráficos 1 para oo (infinito) . Crie uma
integridade referencial, isto é, permitir atualizações em
todas as tabelas a partir da tabela-Pai e se preferir
exclusões dos nomes dos clientes em todas as tabelas.
Cuidado com esta última opção.

92
Na mesma janela para criar o relacionamento leia com
atenção qual é o nível de relacionamento, se é 1, 2 ou 3
que se baseia na paridade ou semelhança entre os
campos existentes entre as tabelas.

Faça a mesma coisa com relação a todas as tabelas que


você deseja ter relacionamentos, sempre a partir de
códigos de campo e também com o mesmo nome de
preferência para facilitar o tipo de relacionamento
existente.

Matrix inicial de relacionamentos entre as tabelas:

Matrix secundária de relacionamentos na consulta:

93
Criei um relacionamento um-para-muitosde nível 2
entre a tabela OBRA e a tabela ASO e entre os campos
codigo de cada tabela OBRA e ASO de nível 1 para que
as informações se repitam em outros registros do sub-
formulário e também entre os campos
ID_FUNCIONARIO e ID_FUNCIONARIO entre as tabelas
tbFuncionario e OBRA. Pronto !!! Esta consulta servirá
de fonte de controle.

O que é um relacionamento um-para-muitos de nível


1?

94
R: Somente unir as linhas quando os campos unidos
de ambas as tabelas forem iguais.

O que é um relacionamento um-para-muitos de nível


2?

R: Incluir TODOS os registros de ‘tbFuncionario’ e


somente os registros de ‘OBRA’ quando os campos
unidos forem iguais.

Verifique também nas propriedades do sub-formulário


como estão os vínculos campos mestres e vínculos
campos filho. Precisam estar como os da figura abaixo.

95
Um fato a considerar em relacionamentos entre
tabelas:

ANALISADOR DE DESEMPENHO
A Microsoft disponibiliza um recurso muito
importante que muitos programadores desconhecem.
É o Analisador de Desempenho. O que ele faz? Analisa
todos os objetos de seu banco como tabelas,
consultas, formulários e relatórios, verificando falhas
na modelagem da tabela, excesso de campos, erros no
relacionamento de tabelas, excesso de objetos do
formulário que poluem o seu visual, etc. Abra a aba
Ferramentas de Banco de Dados e selecione Analisar
desempenho.
(1)

96
(2)

97
(3)

ANALISADOR DE TABELAS
Você tem dúvidas sobre a funcionalidade de sua
tabela? Estaria muito inflada e gostaria de torná-la
mais prática e com menos campos? Utilize também
este recurso da Microsoft. O assistente vai explicando
o que será feito e só completará a fragmentação de
sua tabela se você concordar no final. Criará um

98
relacionamento entre as novas tabelas, facilitando a
sua vida.

99
100
CÁLCULO EM TABELAS
Você pode usar expressões nas propriedades Fonte do
Controle e Valor Padrão para um controle. Além disso, é
possível usá-las na propriedade Regras de Validação de
um campo da tabela
Coluna(1) de um campo vazio

Exemplo(1)*:

Preço com Desconto: CCur([Pedido].[Preço


Unitário]*[Quantidade]*(1-
[Desconto])/100)*100

* Ajuda do Microsoft Office

101
Exemplo(2): (Regras de Validação)

(1)
[Quantidade] * [Preço Unitário]
(2)
[Peso]+[Pontos]

AVALIAÇÃO:

1 – Em uma dada empresa três sócios aplicaram os


seguintes montantes financeiros: O primeiro sócio aplicou
R$ 20.000,00, o segundo sócio aplicou R$ 15.000,00 e o
terceiro sócio aplicou R$ 30.000,00. Ao final de um ano, a
empresa apresentou um lucro de 5% em cima de todo o
capital investido. Quanto recebeu cada sócio segundo a
proporção do capital investido? Qual foi a porcentagem
designada para cada sócio pelo contador da empresa?
Construa um algoritmo que descreva o passo-a-passo
feito pelo contador.

2 – Em uma determinada turma de escola, um terço dos


alunos passaram com notas acima de 8, dentro deste um
terço 40% eram meninos e 60% eram meninas; um terço
dos alunos passaram com notas entre 5 e 8 sendo que
60% eram meninos e 40% eram meninas e, um terço
foram reprovados com notas abaixo de 5, sendo que 50%
eram meninos e 50% eram meninas. Sabendo que esta
turma tinha 50 alunos, quantos alunos foram aprovados e
quantos alunos foram reprovados? Construa um algoritmo

102
que faça este cálculo e que aponte também quantos
alunos eram meninos e quantos eram meninas em cada
faixa de aprovados e reprovados.

3 – Com base no relacionamento muitos-para-muitos


estudado, implemente o relacionamento com mais
dados, incluindo as seguintes tabelas:

tblModalidades
tblDetalhesAdic

Veja como deve ficar o relacionamento:

103
Acrescente dados às tabelas tblClubes, tblAtletas,
tblModalidades, tblDetalhesAdic(Posição do Jogador)
e DetalhesdoAtleta ao criar um formulário com um
sub-formulário que esteja baseado neste tipo de
relacionamento.

4 – Baseado no mesmo exercício anterior crie as


seguintes consultas:

4.1 - cnsAtletas (Pelo modo Design, acrescente


as tabelas tblAtletaseDetalhesdoAtleta)

4.2 – cnsClubes(Pelo modo Design, acrescente


as tabelas
tblClubes e DetalhesdoAtleta)

4.3- cnsDadosdosAtletas(Pelo modo Design,


acrescente as tabelas tblClubes,
tblModalidades e DetalhesdoAtleta.
O que acontece quando as referidas tabelas são
inseridas em cada consulta?

104
Para melhor entender os relacionamentos, estude o
aplicativo Clubes contido no cd incluso.

E quando eu dependo de várias outras informações


que estão em mais de duas tabelas e preciso trazê-las
para meu sub-formulário em meu formulário
principal?

Vamos dividir esta dúvida em duas etapas:

(1) Primeiro, você cria as heranças, qual é a tabela pai


e qual é ou são as tabelas filhas. Quantos dados há
em comum entre elas para determinar o nível de
relacionamento Pai-Filho (1,2 ou 3)? (2) Para fonte
de controle do seu subformulário crie uma
consulta à parte, inclua todas as tabelas. Os
relacionamento virão automaticamente, mas não
precisam ficar necessariamente como da matrix
inicial. Faça alguns testes variando os
relacionamentos em sua consulta para especificar
que tipo de relacionamento melhor atenderá o
que você quer. Teste a consulta até chegar ao seu
objetivo. Após a conclusão dos testes coloque-a
como fonte de controle de seu sub-formulário.

105
(Veja um exemplo dentro do cd chamado CEEME
V.15 que se baseia em uma dúvida atendida por
mim no fórum Maximo Access.)

106
CAPÍTULO 2 – SQL EM AÇÃO (CONSULTAS)

SQL NO MSACCESS: 1ª PARTE

SQL é uma linguagem de consulta estruturada, do


inglês Structured Query Language . É uma linguagem de
pesquisa declarativa para banco de dados relacional
(base de dados relacional). Muitas das características
originais do SQL foram inspiradas na álgebra relacional.
Sem entrar em detalhes quanto a sua origem, os
comandos SQL tornaram mais fácil as rotinas de consulta
no banco de dados Access.

É possível visualizar uma sintaxe SQL elaborada


automaticamente pelo próprio Access quando criamos
uma consulta à tabela no ambiente Access.
Consideremos, por exemplo, a figura abaixo:

Temos uma tabela chamada “SuaTabela” com os


seguintes campos:

107
108
Criamos então uma consulta que tenha o registro de
maior quantidade em ordem decrescente:

Este é o modo Design da sua consulta onde você pode


trabalhar quaisquer tabelas que queira inserir no ambiente
superior. Abaixo, temos as colunas referentes aos
campos da tabela com seus campos modificadores:
Classificação(Crescente ou Decrescente) e Critérios.

Em Critérios, podemos criar a nossa lógica de pesquisa


com operadores lógicos que determinarão que tipo de
consulta desejamos. Por exemplo, valores maiores que
500, nomes que comecem com a letra “A”, etc.

109
Vamos, agora, visualizar esta mesma consulta no modo
SQL:

110
A sintaxe criada foi:

SELECT TOP 1 SuaTabela.Código, SuaTabela.Data,


SuaTabela.Quantidade
FROM SuaTabela ORDER BY SuaTabela.Quantidade
DESC;
Cujo resultado gerado será:

Observe que só retornou um só registro. Este resultado foi


determinado pela cláusula TOP 1. Se quiséssemos mais
de um, era só aumentar o valor depois de TOP. Portanto,
nossa consulta nos trouxe como resultado o registro que
possui o maior número para quantidade em ordem
decrescente.

111
COMANDO SELECT (SELECIONAR)

A interrogação de qualquer base de dados relacional faz-


se utilizando o comando SELECT. A sintaxe do comado é
a seguinte:

SELECT Campo1 , Campo2 , ... ,


CampoN , *
FROM Tabela1 , ... , TabelaK
[WHERE condição]
[GROUP BY … ]
[HAVING … ]
[ORDER BY … ]

As cláusulas entre [ ] são opcionais; no entanto, sempre


que aparecerem terá de ser pela ordem indicada;

Cláusula FROM (DE, TEM ORIGEM EM)


Especifica a origem da consulta, de onde ela vem.
Significa „DE‟ (tem origem em). Geralmente tem origem
em tabelas.

Se a cláusula WHERE (ONDE) for omitida, a condição


será considerada verdadeira;

Se indicarmos * no SELECT em vez de campos, serão


seleccionados todos os campos das tabelas envolvidas;

112
O resultado de uma consulta de SQL com o comando
SELECT é sempre uma tabela;

A ordem dos campos de saída é a que consta no


SELECT, e pode ser diferente daquela usada na criação
da tabela;

Podemos fazer selecção de expressões ou constantes:

Ex.: nomes e idades daqui a cinco anos

SELECT nome, idade +5


FROM pessoas

Se pretendermos eliminar os duplicados usamos:

SELECT DISTINCT Campo1, ........;

SELECT ALL Campo1, ........ é equivalente a SELECT


Campo1, ........;
Cláusula WHERE (ONDE)
A cláusula WHERE admite os seguintes operadores:

Relacionais
= igual a
> maior que
>= maior ou igual a
< menor que

113
<= menor ou igual a
<> (mais vulgar) ou != diferente

Lógicos
cond1 AND cond2 conjunção
cond1 OR cond2 disjunção
NOT condição negação

Especiais
campoN [NOT]BETWEEN valor1 verifica intervalos de
AND valor2 valores
campoN [NOT]IN (valor1, ..., verifica conjuntos de
valorN) valores
campoN IS [NOT] NULL trata valores NULL
campoN LIKE '.......' compara strings
tabela1 [NOT] CONTAINS tabela2 compara tabelas
[NOT] EXISTS tabela verifica tabelas vazias

Nota: um campo tem valor NULL quando não está


preenchido;

Ex.1: nomes dos clientes moradores em cidades


onde existem vendedores

SELECT DISTINCT nome


FROM clientes

114
WHERE cidade IN (SELECT DISTINCT cidade
FROM vendedores)

Ex.2: nomes dos clientes com o mesmo número e


a mesma cidade de algum
Vendedor

SELECT DISTINCT nome


FROM clientes
WHERE <cidade, n_cliente> IN (SELECT
DISTINCT cidade, n_vend FROM vendedores)

Ex.3: procura nomes de clientes cuja cidade vem


especificada.

SELECT nome
FROM clientes
WHERE cidade = “NITERÓI”

Precedência dos operadores:


Ordem ( ) Parêntesis
decrescente *,/ multiplicação, divisão
+,- soma, subtracção
NOT negação lógica
AND conjunção lógica
OR disjunção lógica

Cláusula AS (COMO)

115
Esta cláusula renomeia um campo de saída;

Ex.: SELECT idade AS idade_agora, idade +5 AS


idade_depois
FROM pessoas

Cláusula GROUP BY(AGRUPAR POR)

Os dados selecionados na sentença "SELECT" que leva o


"GROUP BY" devem ser:

 Uma constante.

 Uma função de grupo (SUM, COUNT, AVG…)

 Uma coluna expressa no GROUP BY.

A cláusula GROUP BY serve para calcular propriedades


de um ou mais conjuntos de filas. Se se seleciona mais de
um conjunto de filas, GROUP BY controla que as filas da
tabela original sejamagrupadas em um temporário.

A cláusula HAVING se emprega para controlar qual dos


conjuntos de filas se visualiza. Avalia-se sobre a tabela
que devolve o GROUP BY. Não pode existir sem GROUP
BY.

HAVING é parecido ao WHERE, porém trabalha com


grupos de filas; pergunta por uma característica de grupo,

116
ou seja, pergunta pelos resultados das funções de grupo,
o qual WHERE não pode fazer.

Ex.: Temos a seguinte tabela “Pedidos”:

Codigo DatadoPedido ValordoPedido Cliente


1 12/11/2008 1000,00 Eduardo

2 23/10/2008 1600,00 Lucas

3 02/09/2008 700,00 Eduardo

4 03/09/2008 300,00 Eduardo

5 30/08/2008 2000,00 Mateus

6 04/10/2008 100,00 Lucas

Agora, queremos encontrar a soma total(pedido total) de


cada cliente.

Temos que usar a cláusula GROUP BY para agrupar os


Clientes.

Usamos a seguinte cláusula SQL:

SELECT Cliente,SUM(ValordoPedido) FROM Pedidos


GROUP BY Cliente

117
O conjunto de resultados se parecerá com isto:

Cliente SUM(ValordoPedido)
Eduardo 2000,00

Lucas 1700,00

Mateus 2000,00

Vamos ver o que acontece se omitirmos a cláusula


GROUP BY.

SELECT Cliente,SUM(ValordoPedido) FROM Pedidos

O conjunto de resultados se parecerá com isto:

Cliente SUM(ValordoPedido)
Eduardo 5700,00

Lucas 5700,00

Eduardo 5700,00

Eduardo 5700,00

Mateus 5700,00

118
Lucas 5700,00

Como vê, o conjunto de resultados acima não é o que


queremos.

Explicação de por que não se deve usar a cláusula


SELECT omitindo GROUP BY: A cláusula SELECT
acima possui 2 colunas específicas (Cliente e
SUM(ValordoPedido). O “SUM(ValordoPedido)” retorna
um valor inteiro(que é a soma total da coluna
“ValordoPedido”), enquanto “Cliente” retorna 6 valores
(um valor para cada linha na tabela “Pedidos”). Isto,
portanto, não nos dá o resultado correto. Contudo, você
observou que a cláusula GROUP BY resolve este
problema?

GROUP BY com Mais de Uma Coluna

Podemos também usar a cláusula GROUP BY em mais


de uma coluna, dessa maneira: Separando com vírgula as
colunas:

SELECT Cliente,DatadoPedido,SUM(ValordoPedido)
FROM Pedidos
GROUP BY Cliente,DatadoPedido
Cláusula HAVING

119
A cláusula HAVING vem adicionada a SQL porque a
palavra-chave (ou cláusula)WHERE não se pode usar
com funções agregadas.

Sintaxe SQL HAVING


SELECT nome_da_coluna, função agregada
(nome_da_coluna)
FROM nome_da_tabela
WHERE valor do operador da coluna_nome
GROUP BY coluna_nome
HAVING função agregada(coluna_nome) valor do
operador

Exemplo de SQL HAVING

Temos a seguinte tabela de “Pedidos”:

Codigo DatadoPedido PrecodoPedido Cliente

1 2008/11/12 1000,00 Eduardo

2 2008/10/23 1600,00 Lucas

3 2008/09/02 700,00 Eduardo

4 2008/09/03 300,00 Eduardo

120
5 2008/08/30 2000,00 Fernando

6 2008/10/04 100,00 Lucas

Agora queremos achar se algum dos clientes tem um


pedido total cujo valor seja menor que 2000.

Emprega-se a seguinte sintaxe SQL:

SELECT Cliente,SUM(PrecodoPedido) FROM Pedidos


GROUP BY Cliente
HAVING SUM(PrecodoPedido)<2000

O conjunto de resultados se parecerá assim:

Cliente SUM(PrecodoPedido)

Lucas 1700,00

Agora queremos saber se os clientes “Eduardo” ou


“Fernando” tem um pedido total cujo valor seja maior que
1500.

Acrescentamos uma cláusula WHERE à sintaxe SQL:

SELECT Cliente,SUM(PrecodoPedido) FROM Pedidos


WHERE Cliente='Eduardo' OR Cliente='Fernando'

121
GROUP BY Cliente
HAVING SUM(PrecodoPedido)>1500

O conjunto de resultado se parecerá assim:

Cliente SUM(PrecodoPedido)

Eduardo 2000,00

Fernando 2000,00

Cláusula ORDER BY (ORDENAR POR)

A sua sintaxe é:

ORDER BY campo1[ASC|DESC],
campo2[ASC|DESC],...

A ordem assumida é ascendente (ASC); no entanto,


podemos explicitar essa ordem escrevendo ASC, que não
terá nenhum efeito prático;

Podemos indicar o campo de ordenação pela sua posição
no comando SELECT:

Problema dado:

122
Selecionar na tabela Comissão o valor a receber, o
montante do imposto (17%) e o valor líquido, para os
indivíduos cujo Id é 14 ou 25, apresentando a
ordenação por Id e Imposto:

SELECT Id, Valor AS líquido,


Valor*0,17 AS Imposto,
Valor+Valor*0,17 AS Bruto

FROM comissão
WHERE Id IN (14,25)
ORDER BY Id, Valor*0,17

Este comando é pouco eficiente, na medida em que, se


quisermos alterar o valor da expressão do imposto,
teremos que o fazer em vários locais; a expressão mais
eficiente seria:

SELECT Id, Valor AS líquido,


Valor*0,17 AS Imposto,
Valor+Valor*0,17 AS Bruto

FROM comissão
WHERE Id IN (14,25)
ORDER BY Id, 3 (posição do
campo no comando SELECT)

123
SQL NO MSACCESS: 2ª PARTE

CLÁUSULA INSERT (INSERIR)


Esta é a cláusula que mais gosto de usar ao trabalhar
com tabela auxiliares para inclusão.

É possível escrever a cláusula INSERT INTO de duas


maneiras:

A primeira maneira não especifica os nomes da coluna


onde os dados serão inseridos, somente seus valores:

INSERT INTO NomedaTabela


VALUES (valor1, valor2, valor3,...)

A segunda maneira especifica tanto os nomes das


colunas quanto os valores que serão inseridos:

INSERT INTO NomedaTabela (coluna1, coluna2,


coluna3,...)*
VALUES (valor1, valor2, valor3,...)
* Entenda-se coluna e campo da tabela como sinônimos.
Em codificação VBA no Access nos referiremos ao termo
column(coluna) quando formos trabalhar, referindo-nos
aos campos da tabela.Ex: NomedoCampo.Column(0)

Exemplo de SQL INSERT INTO

124
Temos a seguinte tabela “Pessoas”:

Codigo UltimoNome PrimeiroNome Endereco Cidade


1 Machado Eduardo Rua Artur Campo
Rios, 1474 Grande

2 Andrade Mario Rua Inhaúma


Honorio,
65

3 Pimenta Carlos Rua Conde Tijuca


de Bonfim,
35

Agora, queremos inserir uma nova linha na tabela


Pessoas.

Vamos usar a seguinte cláusula:

INSERT INTO Pessoas


VALUES (4,'Couto', 'Lucia', 'Voluntários da Pátria, 42',
'Botafogo')

A tabela “Pessoas” vai parecer como esta:

Codigo UltimoNome PrimeiroNome Endereco Cidade

125
1 Machado Eduardo Rua Artur Campo
Rios, 1474 Grande

2 Andrade Mario Rua Inhaúma


Honorio, 65

3 Pimenta Carlos Rua Conde Tijuca


de Bonfim,
35

4 Couto Lucia Voluntários Botafogo


da Pátria, 42

Insira dados em colunas específicas

É possível também somente adicionar dados em colunas


específicas.

A seguinte cláusula adicionará uma nova linha, mas


somente adicionará dados nas colunas
“Codigo”,”UltimoNome” e “PrimeiroNome”:

INSERT INTO Pessoas (Codigo, UltimoNome,


PrimeiroNome)
VALUES (5, 'Borges', 'Luccas')

A tabela “Pessoas” agora se parecerá como esta:

126
Codigo UltimoNome PrimeiroNome Endereco Cidade
1 Machado Eduardo Rua Artur Campo
Rios, 1474 Grande

2 Andrade Mario Rua Inhaúma


Honorio, 65

3 Pimenta Carlos Rua Conde Tijuca


de Bonfim,
35

4 Couto Lucia Voluntários Botafogo


da Pátria, 42

5 Borges Luccas

CLÁUSULA UPDATE
Emprega-se a cláusula UPDATE para atualizar registros
emuma tabela.

Sintaxe da SQL UPDATE


Exemplo de SQL UPDATE

A tabela “Pessoas”:

127
Codigo UltimoNome PrimeiroNome Endereco Cidade

1 Machado Eduardo Rua Artur Campo


Rios, 1474 Grande

2 Andrade Mario Rua Inhaúma


Honorio,
65

3 Pimenta Carlos Rua Conde Tijuca


de Bonfim,
35

4 Couto Lucia Voluntários Botafogo


da Pátria,
42

5 Borges Luccas

Agora queremos atualizar a pessoa “Borges,Luccas” na


tabela “Pessoas”.

Vamos usar a seguinte declaração SQL:

UPDATE Pessoas
SET Endereco='Rua Ferreira Borges, 67', Cidade='Campo
Grande'

128
WHERE UltimoNome='Borges' AND
PrimeiroNome='Luccas'

A tabela “Pessoas” vai parecer como esta:

Codigo UltimoNome PrimeiroNome Endereco Cidade

1 Machado Eduardo Rua Artur Campo


Rios, 1474 Grande

2 Andrade Mario Rua Inhaúma


Honorio, 65

3 Pimenta Carlos Rua Conde Tijuca


de Bonfim,
35

4 Couto Lucia Voluntários Botafogo


da Pátria, 42

5 Borges Luccas Rua Ferreira Campo


Borges, 67 Grande

AVISO: SQL UPDATE


Tenha cuidado quando for atualizar registros. Se
tivéssemos omitido a cláusula WHERE no exemplo acima,
dessa forma:

129
UPDATE Pessoas
SET Endereco='Rua Ferreira Borges, 67', Cidade='Campo
Grande'

A tabela “Pessoas” se pareceria dessa forma:

Codigo UltimoNome PrimeiroNome Endereco Cidade

1 Machado Eduardo Rua Campo


Ferreira Grande
Borges, 67

2 Andrade Mario Rua Campo


Ferreira Grande
Borges, 67

3 Pimenta Carlos Rua Campo


Ferreira Grande
Borges, 67

4 Couto Lucia Rua Campo


Ferreira Grande
Borges, 67

130
5 Borges Luccas Rua Campo
Ferreira Grande
Borges, 67

CLÁUSULA INNER JOIN*

Revendo a consulta (qryProdutos) do capítulo anterior.


Seu código SQL seria este:

SELECT Produtos.CodigoProd, Produtos.Produto,


Produtos.CodGrupo, Produtos.ValordeVenda,
Produtos.Quantidade, Produtos.CodCategoria,
Categorias.Categoria
FROM Categorias INNER JOIN Produtos ON
Categorias.CodCategoria = Produtos.CodCategoria;

Interpretando: Selecione o CodigoProd, ...etc. e


Categoria da tabela Categorias e faça união com a tabela
Produtos quando o CodCategoria da tabela Categorias for
igual ao CodCategoria da tabela Produtos.

*INNER JOIN ... ON: significa faça a união interna entre


as duas tabelas quando determinado código comum
entre elas forem iguais.

CLÁUSULA UNION E UNION ALL:

131
UNION
A cláusula UNION se aplica para selecionar informação
relacionada a partir de duas tabelas, parecido com a
cláusula JOIN. No entanto, quando se aplica a cláusula
UNION todas as colunas selecionadas precisam ser do
mesmo tipo de dados. Além disso, com UNION, apenas
valores únicos ou distintos são selecionados.

UNION ALL

A cláusula UNION ALL se assemelha à cláusula UNION,


exceto pelo fato de que UNION ALL seleciona todos os
valores.
A diferença entre UNION e UNION ALL está no fato de
que UNION ALL não eliminará os registros duplicados, em
vez disso, exibe todos os registros das tabelas que
integram a sua consulta e os combina em uma única
tabela.

Uma cláusula UNION efetivamente retorna uma


seleção do tipo SELECT DISTINCT no resultado.

NOTA: Se você já souber que todos os registros que


se pretende buscar são únicos nesta união, use
UNION ALL em vez disso, apresenta resultados mais
rápidos.

Exemplos:

132
SELECT Nome FROM tbClientes UNION SELECT
Nome FROM tbFornecedores ORDER BY Nome

Resultado, Observe que Marcelo Machado aparece apenas uma


única vez:

Nome

Fernando César
Gustavo Tannure
Luccas Borges
Paulo Sérgio
Marcelo Machado

UNION ALL

SELECT Nome FROM tbClientes UNION ALL SELECT


Nome FROM tbFornecedores ORDER BY Nome

Resultado, observe que Marcelo Machado aparece duas vezes:

Nome

Luccas Borges
Fernando César
Paulo Sérgio
Gustavo Tannure
Marcelo Machado
Marcelo Machado

CRIANDO CONSULTAS INSERÇÃO

133
O Access dispõe de assistente para este tipo de consulta,
mas prefiro criar as minhas próprias.

Todas as consultas no Access são geradas tendo por


base um código ou cláusula SQL. Você pode visualizar
isso pelo botão Modo de Exibição à sua esquerda na
barra de ferramentas. Assim quando pretendemos criar
uma consulta específica, primeiro criamos uma estrutura
dela e acrescentamos uma ou mais tabelas que farão
parte da mesma. Em segundo lugar, modificamos a
sintaxe SQL pelo modo SQL desta consulta. Mas façamos
a seguinte pergunta: Quando devemos criar uma consulta
inserção e não uma consulta atualização?

Eu, particularmente, crio consultas inserção quando


desejo pegar dados de uma tabela e inserir em outra.
Neste caso os dados serão acrescentados aos registros já
existentes, mas no segundo caso poderão substituir os
dados já existentes. Por isso, cuidado ao utilizar uma ou
outra. Podemos, naturalmente, inserir dados em uma
tabela seguindo uma sequência em uma tabela vazia a
partir da numeração de um código do tipo numeração
automática ou do tipo numérico com chave primária em
ambos os tipos.

ATENÇÃO: Quando trabalhamos com código para


inserção de dados, os campos do seu formulário devem
ficar desacoplados da tabela, senão haverá duplicação de

134
registros inseridos.

Vamos agora praticar criando consultas inserção,


seguindo as observâncias acima.

(1) Consulta inserção para inserir dados em uma tabela


vazia com campo Código do tipo numeração
automática.

Private Sub cmdinserir_Click()


Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim sNome As String
Dim sEndereco As String
Dim sBairro As String

Set db = rs.OpenRecordset("SuaTabela1",
dbOpenTable)

sNome = Forms!SeuForm!Nome
„Ou Me!Nome
sEndereco = Forms!SeuForm!Endereco
„Ou Me!Endereco
sBairro = Forms!SeuForm!Bairro
„Ou Me!Bairro

135
CurrentDb.Execute " INSERT INTO
SuaTabela1 (nome, endereco, bairro) VALUES
(„” & sNome & “‟,‟” & sEndereco & “‟,
„” & sBairro & “‟)

db.Close

Set db = Nothing
DoCmd.SetWarnings False

End Sub

À medida que você vai acrescentando dados por registro


e clica no botão de inserção, os dados são inseridos na
tabela em sequência por causa do campo Codigo com
numeração automática.

(2) Consulta inserção para inserir dados de uma tabela


em outra.

Private Sub cmdinserir_Click()


Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim nCod As Integer

Set db = OpenRecordset("SuaTabela",
dbOpenTable)

136
nCod = InputBox("Digite o código: ",
"Inserindo Dados")

CurrentDb.Execute " INSERT INTO SuaTabela1


" _
& "SELECT * " _
& "FROM SuaTabela2 WHERE Código = " & nCod

db.Close

Set db = Nothing
DoCmd.SetWarnings False
End Sub
(3) Consulta inserção para inserir dados em uma tabela
vazia a partir de um campo código do tipo numérico com
contador. Esse modo é um pouco mais complexo. Criou-
se uma função que faz a contagem progressiva. É de
autoria de um amigo chamado Wagner McFeba que
disponibilizou para uso livre.

Public Function Contador(strCampo As


String, SuaTabela1 As String) As Long
Dim strSQL As String, rkt As
DAO.Recordset

strSQL = "SELECT Max" & "(" & strCampo &


")" & " As MaxValor"
strSQL = strSQL & " FROM " &SuaTabela1

137
Set rkt =
DBEngine(0)(0).OpenRecordset(strSQL,
dbOpenForwardOnly)

Contador = Nz(rkt("MaxValor")) + 1

rkt.Close: Set rkt = Nothing


End Function

Coloque a função acima dentro do ambiente de código de


seu formulário principal. Precisamos agora chamar esta
função para servir ao seu propósito. Qual é? Inserir no
campo código um contador auto-numerável, mas que
pode ser editado sem gerar conflitos na auto-numeração
como acontece no campo com numeração automática.

No evento Form_Current fazemos a chamada com


parâmetros.

Private Sub Form_Current()


'Se está em um novo registro gera o número
de serie
If Me.NewRecord Then
Me.Codigo = Contador("Codigo", "Sua
Tabela1")
End If
End Sub

138
E no evento Form_BeforeInsert:

Private Sub Form_BeforeInsert(Cancel As


Integer)
Me.Codigo = Contador("Codigo",
"SuaTabela1")
End Sub

À medida que você vai acrescentando dados por registro


e clica no botão de inserção, os dados são inseridos na
tabela em sequência numérica crescente, mas editável
manualmente pelo programador caso ache necessário.

CRIANDO CONSULTAS EXCLUSÃO

O Access dispõe de assistente para este tipo de consulta,


mas prefiro criar a minha própria.
Vamos então criar uma consulta exclusão:

Private Sub cmdAlterar_Click()


On Error Resume Next
Dim strSQL As String
Dim nProd As Integer
Dim nomeProd As String

strSQL = "DELETE * FROM tblProdutos WHERE


ProdutoID = Forms!Produtos!Pedido"

139
DoCmd.RunSQL strSQL „Ou Currentdb.Execute
strSQL
End Sub

*ATENÇÃO: Cuidado com consultas exclusão de tabelas


relacionadas. Se duas ou mais tabelas estiverem
relacionadas você poderá excluir registros dessas tabelas
também que tenham algum vínculo com o código do
produto. Por exemplo, você pode excluir um produto da
tabela Produtos quando você só queria excluir uma
compra deste produto. O programador terá então que
criar uma consulta exclusão que só exclua uma
determinada compra de um produto da tabela Vendas.

CRIANDO CONSULTAS ATUALIZAÇÃO

O Access dispões de assistente para este tipo de


consulta, mas prefiro criar a minhas própria.
Seguindo o mesmo procedimento das consultas inserção,
vamos criar uma consulta atualização. :
O destaque está em grifo no exemplo abaixo. Precisamos
especificar qual registro que sofrerá alteração através de
seu código.
Estamos solicitando que o programa atualize(UPDATE) a
tabela tblProdutos, ao alterar (SET) o campo Produto pelo
valor novo existente neste campo, mas onde (WHERE) o
código do produto é igual ao existente no campo Pedido.

140
Exemplo:

Private Sub cmdAlterar_Click()


On Error Resume Next
Dim strSQL As String
Dim nProd As Integer
Dim nomeProd As String

strSQL = "UPDATE tblProdutos SET Produto =


Forms!Produtos!Produto WHERE ProdutoID =
Forms!Produtos!Pedido"
DoCmd.RunSQL strSQL „Ou Currentdb.Execute
strSQL
End Sub

COM DOIS OU MAIS CRITÉRIOS


UPDATE LISTADEFR SET ENDEREÇO = UCase([ENDEREÇO]), BAIRRO =
UCase([BAIRRO]), CONSUMIDOR = UCase([CONSUMIDOR]),
MOTIVOVISTORIA = UCase([MOTIVOVISTORIA]), SERVIDOR =
UCase([SERVIDOR]), ENTREGUEA = UCase([ENTREGUEA]), RESP =
UCase([RESP]);

CRIANDO CONSULTAS UNIÃO

O Access dispõe de assistente para este tipo de consulta,


mas se preferir crie a sua própria.
A sintaxe SQL da consulta união já foi estudada. (v.
capítulo que trata deste assunto: SQL NO MSACCESS:
2ª PARTE - tópico UNION ou UNION ALL). Há

141
praticidade no emprego deste tipo de consulta quando,
por exemplo, segundo alguns colegas do fórum ItLab,
precisamos unir as tabelas de Clientes, Fornecedores e
Funcionários para mandarmos cartões de Natal, por
exemplo, então preparamos uma consulta união e
colocamos os campos que necessitamos: nome,
endereço, etc. Os campos a serem unidos não precisam
ter o mesmo nome.

Vou deixar um exemplo prático de uma consulta união


que me retornou dados de vários anos de diferentes
tabelas, isto é, tabelas de cada ano presente no mesmo
bd.

Exemplo:

No modo SQL da consulta:

SELECT MATRICULA,
DATADAENTRADA,ORGAO,ENDERECO,BAIRRO,MOTIVOVISTO
RIA FROM ListadeFR2011 UNION ALL SELECT
MATRICULA,
DATADAENTRADA,ORGAO,ENDERECO,BAIRRO,MOTIVOVISTO
RIA FROM ListadeFR2012 UNION ALL SELECT
MATRICULA,
DATADAENTRADA,ORGAO,ENDERECO,BAIRRO,MOTIVOVISTO
RIA FROM ListadeFR2013 UNION ALL SELECT
MATRICULA,
DATADAENTRADA,ORGAO,ENDERECO,BAIRRO,MOTIVOVISTO
RIA FROM ListadeFR2014;

142
Observe que as tabelas(em azul) formam um recordset de
4(quatro) anos que foram sendo armazenados no bd.
Começamos com SELECT (em vermelho) e selecionamos
os campos discriminados da primeira tabela e em
seguida, temos a UNION ALL (unir tudo sem repetir
registros) mais a SELECT com dados da tabela seguinte
e repetimos o processo para as demais tabelas tantas
quanto necessárias para fundamentarmos nossa
pesquisa. Veja como fica:

Ao selecionarmos uma determinada matrícula na


combobox obtemos resultados de todos os anos, caso
existam, em ordem crescente. Neste exemplo, ao
selecionar uma determinada matrícula obtive dois
resultados, no ano de 2012 e de 2013. Logicamente esta
consulta tem que entrar na fonte de registros deste

143
formulário. Ao clicar no botão de filtro, obtemos então o
resultado pretendido ou pelo evento After_Update da
combobox:
Private Sub cboMatricula_AfterUpdate()
On Error Resume Next
Dim sMatr As String

sMatr = Me.cboMatricula.Column(0)
Me.RecordSource = "SELECT * FROM cnsInclusao
WHERE MATRICULA = '" & sMatr & "'"
End Sub

CRIANDO CONSULTAS COM REFERÊNCIA CRUZADA

Uma das principais ferramentas que já lancei mão para


finalizar um relatório foi este tipo de consulta. À princípio,
não a entendia muito bem, mas depois que aprendi a
entender o assistente do Access, tudo ficou mais fácil.
Costumo utilizar um campo auxiliar (Alias) para receber
os resultados de campos calculados, isto é, que não
existe na tabela de onde estamos obtendo os dados para
a consulta. Chama-se consulta com referência cruzada
porque ela cruza informações, agrupando-as com base
em um campo específico. Sua sintaxe em geral é esta
abaixo com campos e tabela fictícios:

TRANSFORM Count(Órgãos.Loja) AS
ContarDeLoja

144
SELECT Órgãos.Órgão, Count(Órgãos.Loja) AS
[Total de Lojas]
FROM Órgãos
WHERE (((Órgãos.Órgão) Is Not Null))
GROUP BY Órgãos.Órgão
PIVOT Órgãos.Código;

Pela sintaxe acima o código informa o total de lojas


existentes para cada órgão de uma empresa.
O procedimento de sua criação é o seguinte pelo
assistente:
1- Criar => Assistente de Consulta
2- Assistente de Consulta de tabela de referência
cruzada.
3- Selecione Tabelas, Consultas ou Ambas. Vamos
trabalhar com Tabelas.
4- Selecione os campos para ficarem na horizontal
por linha. Você pode selecionar até três campos
para simples informação.
5- O assistente então pergunta: Que valores de
campo você deseja como títulos de coluna?
6- Logo em seguida vem a seguinte pergunta: Que
número você deseja calcular para cada interseção
de linha e coluna? É aí que está o “X” da questão,
você deve selecionar um campo calculado, isto é,
um campo que apresente o resultado de um
cálculo disponibilizado pelas funções informadas:
Contagem, Desv (Desvio Padrão), Máx(Valor

145
Máximo), Méd(Média), Mínimo, Primeiro, Soma,
Último e Var. Sabe qual o campo que utilizo para
criar uma planilha com total de valores? Em geral,
um campo que não existe na proposta inicial, este
campo dou o nome de Total na tabela principal,
você deve criá-lo na tabela e selecioná-lo como
título de coluna que receberá o cálculo desejado,
Contagem, Soma, Média, etc.

CRIANDO CONSULTAS COM DUPLICAÇÃO DE


DADOS

O Access também fornece um assistente para este fim.


Sua sintaxe SQL é esta abaixo colocada como exemplo.

SELECT DISTINCTROW Órgãos.Bairro, Órgãos.Loja,


Órgãos.Órgão
FROM Órgãos
WHERE (((Órgãos.Bairro) In (SELECT [Bairro]
FROM [Órgãos] As Tmp GROUP BY [Bairro] HAVING
Count(*)>1 )))
ORDER BY Órgãos.Bairro;

O USO DE SEIMED PARA CRIAR CONSULTAS COM


CAMPO CALCULADO

146
Podemos realizar cálculos em consultas utilizando uma
coluna vazia.

Exemplo(1)

Total 1: ([Peso]+[Pontos])

Total 2: DSoma("[Peso]";"tblTeste")

Total 3: DSoma("[Pontos]";"tblTeste")

Com a função SEIMED que é o mesmo que a função IIF


(IF THEN...ELSE...END IF) na horizontal.

Exemplo(2)

Valor: SeImed(“ValorPago >=


ValorDebito”;ValorPago-ValorDebito;0)

Exemplo(3)

Situação: SeImed([Resultado] > 5,


“Aprovado”, “Reprovado”)

Exemplo(4)

O uso de vários SEIMED* para especificar uma consulta.

Resultado=SeImed([uf]="m3";[comprimento]*Fo
rmulario![Largura]*[espessura];SeImed([uf]=

147
"m2";[comprimento]*Formulario![Largura];[co
mprimento]))*

OTIMIZANDO CONSULTAS

As consultas no Access nada mais são do que utilizar o


poder da SQL.

No modo Design (Estrutura) podemos manualmente


inserir uma ou mais tabelas que servirão de base da
pesquisa. Como vimos anteriormente no estudo de
relacionamentos entre tabelas que as mesmas surgirão
vinculadas, obedecendo o tipo de relacionamento criado.

Na linha Critérioinsira a fórmula de consulta ou sintaxe de


consulta desejada. Existem várias delas:

(1) Entre[Digite a Data Inicial:]E[Digite a Data Final]–


Filtra registros entre duas datas baseado no campo
desta coluna que seja no formato de Data.

(2) [Digite uma Data:] – Filtra registros que contenham a


data digitada baseado no campo desta coluna
semelhantemente ao item 1.

(3) <> Null (ou É Negado Nulo) – Elimina campos ou


registros com dados nulos. O contrário é É Nulo.

(4) “*” & [Digite uma palavra chave:] & “*” – Pesquisa
registros que contenham a palavra digitada ou que
iniciam com partes da palavra.

148
(5) Como R*–Retorna registros para todos as palavras que
comecem com R.

(6) Não Como R* –Retorna registros para todos as


palavras que NÃO comecem com R.

(7) Como “*ina” – Retorna registros para todos os nomes


de palavras que terminam em "ina". Exemplo: China e
Argentina. O contrário é Não Como “*ina”.

Esses são apenas exemplos que a Microsoft disponibiliza


para consulta. Outros exemplos você pode encontrar
neste site:

http://office.microsoft.com/pt-br/access-help/exemplos-de-
criterios-de-consulta-HA010066611.aspx
*O uso de vários seimed‟s só é possível com a devida referência ao
campo(Forms!NomedoFormulário!NomedoCampo) tanto na consulta
quanto no formulário. Este exemplo é de uma dúvida de um colega do
fórum Máximo Access.

AVALIAÇÃO

SQL no MsACCESS – 1ª PARTE:

1) Crie uma tabela com os seguintes campos : Id(ou


Codigo),Nome, Bairro, Cidade. Insira alguns dados em
sua tabela fictícios em um total de 10 a 20 registros. Dê
o nome a sua tabela (tblClientes). Crie uma consulta a
esta tabela (cnsClientes) e inclua todos os campos.

149
Selecione o modo SQL de sua consulta e faça as
seguintes pesquisas em SQL:

1.1 - Uma consulta com todos os clientes


1.2 - Usando SQL renomeie(crie um Alias*) o campo
Nome para Cliente e faça a seleção de todos os
clientes
2) Utilizando os mesmos dados anteriores, crie uma
consulta com clientes de um determinado bairro
específico.
3) Modifique os dados de sua tabela (tblClientes) e
coloque dados iguais em alguns registros. Crie uma
consulta que apresente todos os dados sem registros
repetidos.Obs: Exclua de sua consulta o campo código.
4) Crie uma nova tabela(tblConsumidores) com os
mesmos campos da tabela anterior. Insira valores
fictícios de consumidores adultos e jovens. Acrescente
o campo Idade. Crie uma consulta de todos os
consumidores que terão mais de 30 anos daqui a 10
anos, inclusive com 30 anos.
5) Crie uma tupla(tabela) cujo nome é Pedidos com os
seguintes campos Cliente, DatadoPedido, Mês,
ValordoPedido, Endereco, Bairro e Cidade . Inclua
valores fictícios para cada campo em todos os registros
no total de 10 registros. Modele os tipos de dados
dessa maneira, Cliente do tipo Texto, DatadoPedido do
tipo Data/Hora, Mês do tipo Texto, ValordoPedido do
tipo Currency, Bairro e Cidade do tipo Texto. Crie uma
consulta calculando o somatório dos pedidos de todos
os clientes de todo o mês de Janeiro, por exemplo.
Considere que cada cliente fez mais de um pedido ao
longo do mês de Janeiro.

SQL no MsACCESS – 2ª PARTE:

150
(1) Com base no estudo de relacionamento muitos-para-
muitos estudado no capítulo anterior, abra as consultas
criadas na última avaliação no modo SQL. Estude a sintaxe
SQL criada pelo Access. Aprenda como é feito os vínculos entre
as tabelas através da cláusula INNER JOIN.
(2) Crie um formulário que faça as consultas utilizando a
técnica estudada no tópico Otimizando Consultas pelo
evento BeforeUpdate de uma combo.

151
CAPÍTULO 3 – DOMINANDO O ACCESS VBA I
(FORMULÁRIOS)

A BARRA DE FERRAMENTAS

Antes que aprendamos a trabalhar com os principais


controles da barra de ferramentas, seus métodos e
propriedades no formulário, vamos nos dedicar a dominar
o uso da barra de ferramentas onde estes mesmos
controles estão.

152
Os principais controles que podemos “arrastar e
largar”(drag-and-drop) para o nosso formulário
são:
 a Caixa de Texto (TextBox)
 a Caixa de Combinação (ComboBox)
 o Botão (Button)
 a Caixa de Listagem (ListBox)
 o Subformulário/Sub-relatório (SubForm/SubReport)
 o Rótulo (Label)
 o Grupo de Opções (Option Group) – Permite uma
só seleção de cada vez
 a Caixa de Seleção (CheckBox) – Permite várias
seleções
 o Botão de Opção (Option Button or Toggle Button)
 o Controle Guia (Page Control)

Para que você possa visualizar e identificar esses


controles e outros, basta encostar o mouse em cada um
deles que serão identificados.

Cada um desses controles possuem métodos e


propriedades associados a eles pelo nome que recebem
pelo modo Design do formulário, com o botão direito do

153
mouse clicado sobre cada um deles e assim, entrando na
caixa de propriedades. Cada um desses controles
possuem cinco abas com os seguintes nomes: Formato,
Dados, Evento, Outra e Todas.

Se você for trabalhar com cadastro de dados, seria


necessário aprender a configurar as propriedades de cada
controle para facilitar ao usuário, por exemplo, a
tabulação dos campos. Caso você queira uma melhor
visualização de uma string SQL por exemplo em sua fonte

154
de controle na aba Dados, com o cursor do mouse dentro
dessa propriedade, pressione a tecla SHIFT junto com a
tecla F2 e depois solte. Você terá um Zoom desta
propriedade.

Abra a aba Outra e em Índice de Tabulação, verifique se o


mesmo é sequencial. O primeiro valor é 0. Na mesma
aba, em Auto-Tabular configure como Sim.

155
156
Principais propriedades do formulário que devem ser
configuradas para uma melhor visualização pelo usuário.

 Legenda (Digite o nome mais apropriado para o seu


formulário principal)
 Pop-up (uma pequena visualização do formulário)
 AutoCentralizar: Sim
 AutoRedimensionar: Sim
 Ajustar à Tela: Sim
 Estilo da Borda: Fino
 Seletores de Registro: Não
 Botões de Navegação: Sim (Se você não for criar os
seus próprios)
 Linhas Divisórias: Não
 Barras de Rolagem: Não

157
Com o tempo você irá se acostumar a fazer estas
configurações para tornar seu aplicativo bem simpático
em seu impacto visual para o seu cliente ou usuário.

O USO DE INPUTBOX E MSGBOX

Em primeiro lugar é preciso diferenciar uma MsgBox de


uma InputBox. A primeira exibe um resultado já calculado
ou estipulado para simples informação e a segunda
trabalha com o recebimento da informação, isto é, faz a
entrada de dados, daí o nome Input (Inserir) mais
Box(Caixa). Poderíamos dizer Caixa de Inserção de
Dados ou algo semelhante.

Vamos conhecer primeiramente a última que me parece


por ora, mais interessante porque é uma função muito útil
na programação em VBA. Como você sabe, programar é

158
trabalhar com dados. Podemos fazer paralelo com um
cozinheiro na cozinha. O que ele faz? Ele trabalha com os
itens da receita, mas precisa de certos utensílios para
prepará-la, certo? A função InputBox nada mais é que
um utensílio que pelo nome já diz é de extrema
funcionalidade na criação de programas (pratos da
receita). Enquanto as InputBox recebem e inserem
dados, as MsgBox exibem os dados que podem ser
qualquer coisa como resultado dos cálculos com estes
dados, por exemplo, fornecidos ao final do programa.

Bem, já falamos bastante, agora vamos aos exemplos


práticos para o uso de uma InputBox:

Uso de InputBox

Sintaxe:

InputBox(prompt[, title][,default] [, xpos] [, ypos] [, helpfile, context])

Os dados em azul são opcionais.


Exemplo1:

Dim Perguntas As String


Perguntas = InputBox("Digite abaixo a sua
dúvida:", "CIDASA - Consulta Instantânea de
Dados do SASB", Default:="Regras
Básicas",100,100)
Onde:

prompt(comando) é “Digite abaixo a sua dúvida:”

159
title(Título):"CIDASA - Consulta Instantânea de Dados do SASB"

default(padrão): Default:=”Regras Básicas”

Xpos Opcional. Expressão numérica que especifica, em twips, a


distância horizontal da borda esquerda da caixa de diálogo em
relação à borda esquerda da tela. Se xpos for omitido, a caixa de
diálogo será centralizada horizontalmente.

Ypos Opcional. Expressão numérica que especifica, em twips, a


distância vertical da borda superior da caixa de diálogo em
relação ao alto da tela. Se ypos for omitido, a caixa de diálogo
será posicionada verticalmente na terça parte inferior da tela.

Helpfile Opcional. Expressão de seqüência de caracteres que


identifica o arquivo de Ajuda a ser utilizado para fornecer ajuda
sensível ao contexto relativa à caixa de diálogo. Se helpfile for
fornecido, contexto também deverá ser fornecido.

Context Opcional. Expressão numérica que é o número de


contexto da Ajuda atribuído ao tópico da Ajuda apropriado por
seu autor. Se context for fornecido, helpfile também deverá ser
fornecido.

Comentários: Quando helpfile e context são fornecidos, o


usuário pode pressionar F1 (Windows) ou AJUDA(Macintosh)
para visualizar o tópico de Ajuda que corresponde ao context. Se
o usuário clicar em OK ou pressionar , a função InputBox
retornará o que estiver na caixa de texto. Se o usuário clicar em
Cancelar, a função retornará uma seqüência de caracteres de
comprimento zero ("").

160
Observação: Para especificar mais que o primeiro argumento
nomeado, você deve utilizar InputBox em uma expressão. Para
omitir alguns argumentos posicionais, você deve incluir o
delimitador de vírgula correspondente.

Neste exemplo acima, a função InputBox solicita ao usuário que


digite um valor. Se as posições x e y forem omitidas, a caixa de
diálogo será automaticamente centralizada em relação aos
respectivos eixos.

A variável Perguntas contém o valor digitado pelo usuário se ele


clicar em OK ou pressionar a tecla ENTER. Se o usuário clicar
em Cancel, será retornada uma seqüência de comprimento zero.

Exemplo 2:

Às vezes queremos que nossa Inputbox forneça uma


informação extra para auxiliar o usuário na tomada de
decisão de inserir algum dado. Em termos de software,
chamamos isso de default (padrão). Na falta ou ausência
de algum valor(parâmetro) fornecido é este que vigorará.
Veja a sintaxe da InputBox em sua forma original como
fica em um botão:
Dim Perguntas As String

Perguntas = InputBox(Prompt:="Digite abaixo a


sua dúvida:", Title:="CIDASA - Consulta
Instantânea de Dados do SASB", Default:="Regras
Básicas")

161
Logicamente, neste exemplo se o usuário não souber o
que inserirá, ao simplesmente pressionar OK para atender
ao default "Regras Básicas", o programa deverá fornecer
esta informação desejada através de uma ...(você já sabe
o quê?) uma MsgBox.

162
A sintaxe inicial pode ser simplificada sem qualquer
problema para a seguinte:
Dim Perguntas As String

Perguntas = InputBox("Digite abaixo a sua


dúvida:", "CIDASA - Consulta Instantânea de
Dados do SASB", Default:="Regras Básicas")

Existe também o método Application.InputBox diferente


da função Inputbox por exigir mais parâmetros em sua
aplicação à diferença das InputBox pura e simplesmente.
Quem quiser saber mais sobre este método que não é
alvo deste estudo, leia o excelente artigo de Thomás
Vasquez através deste link:

163
http://www.tomasvasquez.com.br/blog/microsoft-
office/vba-a-diferencas-entre-inputbox-e-application-
inputbox

Acho interessante frisar que o uso de InputBox é


extremamente essencial na criação de programas,
podendo surgir em sub-rotinas, funções e módulos.

Vamos a um terceiro exemplo.

Exemplo 3:Vejamos a seguinte função de cálculo.

Option Compare Database


Option Explicit

„Nota: É bom lembrar também que o tipo de retorno do


InputBox é „sempre uma String. Caso deseje „efetuar cálculos
numéricos ou „mesmo capturar valores de data, utilize as
funções de conversão do „VBA „(CInt, CDate, CDbl,
IsNumeric) para efetuar as conversões e „validações
necessárias.

Function CalculaRenda(valorLucro as Double,


valorTotal as Double)
Dim valor As double
Dim NumDado As Integer

NumDado = CInt(InputBox("Digite o valor da


percentagem: ","Valor Percentual"))„Valor
Percentual é o título da InputBox

164
valor =
([valorDolar]*[TaxaDolar])'valorDolar e
TaxaDolar são variáveis fornecidos pelo
usuário e inseridas em caixas de texto
valorLucro = [valorDolar]*NumDado/100
valorTotal = [valor]+[valorLucro]

End Function

Voce chamará esta função através de um botão.


Private Sub cmdCalculo_Click ()

Call CalculaRenda (txtvalorLucro,txtvalorTotal)

End Sub

Repare que no Exemplo 1 a função InputBox recebe um


valor que é fornecido pelo usuário de forma diferente da
que é fornecido pelo mesmo no preenchimento de duas
caixas de texto(valorDolar e TaxaDolar) talvez porque o
valor da percentagem é um importante diferencial para
definir o lucro gerado que incidirá sobre a renda.

Aqui o programador está colocando a percentagem como


valor a ser destacado dos demais dados necessários para
a elaboração do cálculo. Isso torna o programa mais
atrativo e funcional. Poderíamos dizer que uma InputBox
trabalha com variáveis e caixas de texto com constantes,
mas isso não seria necessariamente verdade, mas
elucida melhor a sua utilização e practicidade.

165
Uso de MsgBox

Sintaxe:

MsgBox (prompt [, buttons][, title][, helpfile, contexto]

Vejamos o seguinte exemplo:

Exemplo 1:
MsgBox ("Você precisa precisa preencher este
campo !"), vbInformation, "Cadastro de Reserva"

ou sem os parênteses:
MsgBox "Você precisa precisa preencher este
campo !", vbInformation, "Cadastro de Reserva"

Exemplo 2*:

Interagindo com uma variável informada por InputBox do


tipo String:(Aspas Duplas + E Comercial+Variável+ E
Comercial+ Aspas Duplas)

Dim sNome As String


sNome = InputBox("Digite o seu nome: ",
"Cadastro de Reserva")

MsgBox "Meu nome é " & sNome , vbInformation,


"Cadastro de Reserva"

Nota: Há casos que se usa o apóstrofo antes das aspas


sempre quando vamos referenciar uma variável do tipo

166
String. Certas pesquisas que fazemos utilizando uma
função de cálculo, (função DCount*), por exemplo,
intercala-se o apóstrofo antes e depois das aspas:

Em um certo botão de um formulário coloque o seguinte


código:

Private Sub cmdCalc_Click()

Dim MesA As String


Dim valor As Integer
Dim totalOS As Integer

MesA = InputBox("Digite o Mês(JAN,FEV,etc...)


de Consulta: ", "Controle de Ordem de Serviço")

totalOS = DCount("*", "tbl_OS", "MES = '" &


MesA & "'") „O “*” refere-se aos registros da
tabela

MsgBox “Foram encontrados “ & totalOS & “


ordens de serviço no mês de “ & MesA

End Sub

Ou

Private Sub cmdCalc_Click()

Dim MesA As String


Dim valor As Integer
Dim totalOS As Integer

167
MesA = InputBox("Digite o Mês(JAN,FEV,etc...)
de Consulta: ", "Controle de Ordem de Serviço")

totalOS = DCount("MATRICULA", "tbl_OS", "MES =


'" & MesA & "'") „Ambos matricula e mês
referem-se aos nomes dos campos na tabela
tbl_OS.

MsgBox “Foram encontradas “ & totalOS & “


matrículas registradas no mês de “ & MesA

End Sub

Exemplo 3:

Interagindo com uma variável informada por InputBox do


tipo Integer ou Long:( Aspas Duplas + E Comercial +
Variável + E Comercial + Aspas Duplas + Aspas Duplas)

Dim sNum As Integer


sNum = InputBox("Digite um número inteiro: ",
"Cadastro de Reserva")

MsgBox "O número é " & sNum & "",


vbInformation, "Cadastro de Reserva"

Exemplo 4:

Interagindo com uma variável informada por InputBox do


tipo Double com dois dígitos na casa decimal. Aqui
neste caso use a função Format para ajudá-lo:
Dim sNum As Double

168
sNum = InputBox("Digite o valor pago: ",
"Cadastro de Reserva")

MsgBox "O valor pago foi " & (Format(sNum,


"##,##0.00")), vbInformation, "CADASTRO DE
RESERVA"

ou usando R$ e um ponto final:


MsgBox "O valor pago foi R$ " & (Format(sNum,
"##,##0.00")) & ".", vbInformation, "CADASTRO
DE RESERVA"

Exemplo 5:

Interagindo com uma variável informada por InputBox


usando funções de conversão do tipo Integer ou Double
tendo como parâmetro de conversão uma expressão do
tipo String:

Coloque este código em um botão:


Dim Nprods As Integer
Dim sPreco As Double

Nprods = CInt(InputBox("Entre com a quantidade


de laranjas:")) 'CInt converte um suposto valor
fracionado fornecido em inteiro
sPreco = CDbl(InputBox("Preço de uma
dúzia:"))'CDouble converte um valor
fornecido em duplo, isto é, com duas casas

169
decimais independente do número de casas
decimais.

MsgBox "O total de laranjas é : " & Nprods


MsgBox "O preço de uma dúzia é: " & sPreco

Exemplo 6:

Uso de MsgBox com a instrução Eval:


Coloca em negrito a informação exibida pela MsgBox
veiculada pela InputBox.

Private Sub cmdPergunta_Click()

Call IniciarPesquisa

End Sub

SUB-ROTINA X FUNÇÃO
Em se tratando de procedimentos, sub-rotinas retornam
uma ou mais informações; são partes de uma solução
final; podem ser reutilizadas em outros programas e
funções retornam valores que em geral, são resultantes
de cálculos em função dos seus argumentos em sua
elaboração e que funcionam na chamada da função com
seus parâmetros correlatos.

Vamos primeiramente dar uma olhada em funções e


como elas podem ser úteis para resolver inúmeros
problemas em VBA. Vou destacar algumas que já criei

170
para que você programador possa ir já aprendendo a
desenvolvê-las e utilizá-las em seus aplicativos. Vamos
ver então primeiramente funções sem parâmetros.

FUNÇÕES PRÁTICAS

(1)
Private Function Tabuada()
Dim i As Integer
„Bloco For...Next
„**********************************************
For i = 1 To 10
Tabuada = Valor * i
MsgBox "O valor " & Valor & " vezes " & i & " é
" & Tabuada, vbInformation, "Tabuada"
Next i
„**********************************************
End Function

(2) Public Function Substituir() As String

On Error Resume Next

Dim sRua As String


Dim sAvn As String
Dim sEtr As String
If Not IsNull(Endereco) Then„Endereco é o nome
do campo em sua tabela presente no formulário
sRua = Replace(Endereco, "Rua",
"R")'Expression(ou nome do campo), Find(procura
a string antiga), Replace(Substitui por esta
nova string) Endereco = sRua sEtr =
Replace(Endereco, "Estrada",
"Etr")'Expression(ou nome do campo),
Find(procura a string antiga),

171
Replace(Substitui por esta nova string)
Endereco = sEtr sAvn = Replace(Endereco,
"Avenida", "Avn")'Expression(ou nome do campo),
Find(procura a string antiga),
Replace(Substitui por esta nova string)
Endereco = sAvn
Substituir= Endereco„Aqui a função recebe o
valor Resultante
Else
Exit Function
End If
End Function

Agora vamos aprender a criar funções parametrizadas ou com


parâmetros.

(1) Com um parâmetro

Public Function EncontreErrosOrtográficos(nTexto As String)

On Error Resume Next

nTexto = CInt(InputBox("Você pretende fazer uma correção


ortográfica?" & vbCrLf & _

"1 - Yes " & vbCrLf & _


"2 - No ", "Erros Ortográficos"))
Select Case nTexto
Case Is = 1
DoCmd.RunCommand acCmdSpelling
Case Is = 2
Exit Function
End Select

172
nTexto = Resposta 'Resposta é o nome da caixa de texto do tipo
Texto ou do tipo Memorando
EncontreErrosOrtográficos = nTexto
End function

Código da saída da caixa de texto Resposta.

Private Sub Resposta_Exit(Cancel As Integer)


Call EncontreErrosOrtográficos(txtResposta)
‘txtResposta é uma caixa de texto do formulário
End Sub

(2) Função para identificar o usuário com dois parâmetros

Public Function VerificaLogin(sLogin As String, sSenha As String)


Dim nLogin As String
Dim nSenha As String

nLogin = login 'login é o nome da caixa de


texto do formulário de Login nSenha = senha
'senha é o nome da caixa de texto do formulário
de Login
sLogin = Nz(DLookup("login", "tblCadastro",
"login = '" & nLogin & "'"))

„A função Nz deixa o campo zerado caso não


exista informação. Ela evita o surgimento de
uma mensagem de erro acusando um campo nulo,
deixando brecha para acesso ao código.

sSenha = Nz(DLookup("senha", "tblcadastro",


"login = '" & sLogin & "'"))

173
If sLogin <> "" Then MsgBox "Nome OK",
vbInformation, "Testa Login" End If
If sSenha = nSenha Then
MsgBox "Senha válida !!!", vbInformation,
"Testa Login"
DoCmd.OpenForm "frmteste", acNormal'Se a senha
for válida abre o formulário principal
MsgBox "Senha inválida !!!", vbInformation,
"Testa Login"
End If
End Function

Exemplo de Sub-Rotina N.º 1

Private Sub IniciarPesquisa()


On Error Resume Next
Dim intRetVal As Integer
Dim strMsg As String
Dim strTitle As String
Dim Perguntas As String

Perguntas = InputBox("Digite abaixo a sua


dúvida:", "CIDASA - Consulta Instantânea de
Dados do SASB", Default:="Regras Básicas")

Select Case Perguntas

Case Is = "Abastecimento Precario"


Eval ("MsgBox ('Fornecimento de água em
situação irregular !' " & "& chr(13)&chr(10)&"

174
& " '@" & "Pesquisa Especial CIDASA @
',0,'Ajuda')")

Case Is = "Atualizacao da Ufir" „A função Eval


com esta sintaxe especial com @(arroba) deixa
em Negrito a MsgBox
Eval ("MsgBox ('Você pode atualizar o valor da
Ufir anualmente no formulário de atualização
para posteriores consultas !' " &
"&chr(13)&chr(10)&" & " '@" & "Pesquisa
Especial CIDASA @ ',0,'Ajuda')")
strTitle = "Dúvida"
strMsg = "Deseja abrir o formulário de
atualização? É necessário cadastrar-se e
incluir senha individual, ou encerre sua
pesquisa. Selecione 'Sim' para a primeira opção
e 'Não' para a segunda opção."
intRetVal = MsgBox(strMsg, vbYesNo +
vbQuestion, strTitle)
Select Case intRetVal
Case vbYes
strTitle = "Dúvida"
strMsg = "Deseja cadastrar-se ou já é
cadastrado? Selecione 'Sim' para a primeira
opção e 'Não' para a segunda opção."
intRetVal = MsgBox(strMsg, vbYesNo +
vbQuestion, strTitle)
Select Case intRetVal
Case vbYes
DoCmd.OpenForm "Cadastro de
Usuários", acNormal

175
Case vbNo
DoCmd.OpenForm "Form_Ufir",
acNormal
End Select
Case vbNo
strTitle = "Dúvida"
strMsg = "Deseja encerrar a pesquisa ou iniciar
uma nova? Selecione 'Sim' para a primeira opção
e 'Não' para a segunda opção."
intRetVal = MsgBox(strMsg, vbYesNo +
vbQuestion, strTitle)
Select Case intRetVal
Case vbYes
DoCmd.CancelEvent

Case vbNo
Perguntas =
InputBox(Prompt:="Digite abaixo a sua dúvida:",
Title:="CIDASA - Consulta Instantânea de Dados
do SASB", Default:="Por favor, repita a
operação !!!")
End Select
End Select
Case Is = "Abastecimento Predial"
Eval ("MsgBox ('Abastecimento de prédio ou de
parte de prédio dotado de instalação autônoma!'
" & "& chr(13)&chr(10)&" & " '@" & "Pesquisa
Especial CIDASA @ ',0,'Ajuda')")
..........
End Sub

176
Exemplo 6

177
Private Sub cmdConsulta_Click()
Dim strConsulta As String
strConsulta = InputBox("Selecione o tipo de
consulta desejada: " & vbCrLf & _
"1 - Total de funcionários cadastrados " &
vbCrLf & _
"2 - Total de funcionários ativos " & vbCrLf &
_
"3 - Total de funcionários inativos ",
"Consulta Geral")

Select Case strConsulta


Case Is = 1
....
Case Is = 2
....
Case Is = 3
....
End Select
End Sub
Uso de MsgBox com StrMsg (Variável) do Tipo String:

É de praxe em meus programas utilizar MsgBox com


StrMsg (Uma string criada para auxiliar o usuário na
tomada de decisão que a MsgBox requer quando se
acrescenta mais que um simples botão OK)

Vejamos um exemplo prático universal quando preciso de


um título (strTitle ou strTitulo) e um variável chamada
intRetVal (Valor de Retorno do tipo Integer) além, é
claro, da strMsg.

178
Primeiro declaramos as variáveis:
Dim strTitle As String
Dim strMsg As String
Dim IntRetVal As Integer

strTitle = "CADASTRO DE RESERVA"


strMsg = "Deseja realmente cadastrar este
nome?"
intRetVal = MsgBox(strMsg,vbYesNo,strTitle)'A
MsgBox se transforma em um "método" com três
"parâmetros"
'Aqui precisamos de uma forma condicional para
a tomada de decisão
Select Case intRetVal
Case vbYes
MsgBox "Nome adicionado com
sucesso!",vbInformation, "CADASTRO DE RESERVA"
Case vbNo
Exit Sub
End Select

179
Nota: intRetVal é uma variável do tipo Integer que
significa valor de retorno do tipo inteiro porque trabalha
com constantes representadas por vbYesNo, vbOkOnly,
vbInformation, vbCritical, vbExclamation, vbQuestion, etc.
No programa ela recebe o valor destas constantes em
forma de MsgBox:

180
Obs: Algumas formas são aceitáveis nesta elaboração
como o uso de "+" entre os parâmetros nesta sintaxe
quando se quer acrescentar um ícone à MsgBox que
identifica que tipo de MsgBox se trata. Exemplos:

intRetVal = MsgBox(strMsg,vbYesNo+
vbInformation,strTitle)
OU
intRetVal = MsgBox(strMsg,vbYesNo+
vbCritical,strTitle)
OU
intRetVal = MsgBox(strMsg,vbYesNo +
16,strTitle)

181
Constantes para função MsgBox() extraídas do livro
Programando Microsoft Access VBA do Prof Flávio
Morgado, volume 1:

Valor Constante Significado


0 VbOKOnly Exibe apenas o botão
OK
1 VbOKCancel Exibe os botões OK e
Cancelar
2 VbAbortRetryIgnore Exibe os botões
Abortar, Repetir e
Ignorar
3 VbYesNoCancel Exibe os botões Sim,
Não e Cancelar
4 VbYesNo Exibe os botões Sim e
Não
5 VbRetryCancel Exibe os botões Repetir
e Cancelar

Valor Constante Ícone a ser exibido Ícone


16 VbCritical Exibe o ícone de X
mensagem crítica
32 VbQuestion Exibe o ícone de ?
interrogação
48 VbExclamation Exibe o ícone de !
mensagem de aviso
64 VbInformation Exibe o ícone de i
mensagem de
informação

182
Poderíamos também desejar fragmentar na forma de um
parágrafo a nossa MsgBox. Para isso, precisamos inserir
um quebra-linhas com a instrução vbCrLf. Estude este
exemplo:

Exemplo 1:
Private Sub cmdMessageBox_Click()
MsgBox "Suas credenciais de logon foram
checadas." & vbCrLf & "Antes de dar início ao
seu aplicativo, por favor " & _
"preencha a seguinte pesquisa", vbExclamation,
"Pesquisa"
End Sub

183
Finalmente, estude estas formas de uso de InputBox e
MsgBox respectivamente, em meus aplicativos.

Exemplo de Sub-Rotina N.º 2

Private Sub IdentificarPeca()

On Error Resume Next


Dim IdErro As String

IdErro = InputBox("Selecione o tipo de mau


funcionamento do Aparelho: " & vbCrLf & _
"1 - Desgaste das Peças Internas " & vbCrLf & _
"2 - Defeito de Fabricação " & vbCrLf & _
"3 - Perda da Capacidade de Magnetização " &
vbCrLf & _
"4 - Violação ou Danificação do Medidor " &
vbCrLf & _
"5 - Vazamento na Cúpula do Aparelho",
"Defeitos do Aparelho")

Select Case IdErro


Case Is = 1
Eval ("MsgBox('É ocasionada pelo tempo de uso
ou pela passagem da água em uma " & vbCrLf & _
"vazão elevada (acima da capacidade nominal do
medidor " & vbCrLf & _
„..........................................

184
"de +8,0%.!@" & "Identificação do
Aparelho.@',0,'Informação')")„O uso de Eval ao
lado de uma MsgBox deixa em negrito esta linha.
Acompanha o arroba na forma como é colocado
seguido de zero entre vírgulas

Case Is = 2
Eval ("MsgBox('Quando acarreta folga nos
roletes da relojoaria ou " & vbCrLf & _
"permite que o eixo da mesma caia de seus
mancais quando submetido " & vbCrLf & _
............................
"@" & "Identificação do
Aparelho.@',0,'Informação')")

Case Is = 3
Eval ("MsgBox('Quando se trata de perda da
capacidade de magnetização " & vbCrLf & _
"dos imãs do sistema de transmissão o medidor
tende a parar, ou apresentar " & vbCrLf & _
„.............................................
"@" & "Identificação do
Aparelho.@',0,'Informação')")

Case Is = 4

Eval ("MsgBox('Na violação ou danificação do


medidor com o objetivo de " & vbCrLf & _
"alterar a leitura, sendo o mais comum: " &
vbCrLf & _

185
"1 - Furar a cúpula da relojoaria e utilizar
uma agulha para trancar " & vbCrLf & _
"os roletes, retirando-a quando na época de
leitura. " & vbCrLf & _
"2 - Retirar o aparelho, retirar o filtro e
injetar no " & vbCrLf & _
"mesmo impurezas(como cola, pedrinhas,
barbante, etc.) " & vbCrLf & _
"ou furar a câmara de medida com o objetivo de
parar a turbina. " & vbCrLf & _
"3 - Inverter o aparelho no quadro, deixando-o
funcionar apenas " & vbCrLf & _
"metade do tempo no sentido correto. " & vbCrLf
& _
"4 - Romper o lacre, abrir o aparelho e frear
os roletes com calços " & vbCrLf & _
"(palitos, pregos, etc.). " & vbCrLf & _
"5 - Golpear ou queimar a cúpula do aparelho
com a intenção " & vbCrLf & _
"de danificá-lo." & vbCrLf & _
"@" & "Identificação do
Aparelho.@',0,'Informação')")

Case Is = 5
Eval ("MsgBox('Vazamento na cúpula do aparelho,
a água sai por cima do medidor.: " & vbCrLf & _
"* O aperto dado no anel da cúpula quando da
montagem não foi suficiente " & vbCrLf & _
„.............................................

186
"** É bastante comum o usuário confundir os
vazamentos no quadro ou cavalete, " & vbCrLf &
_
"informando que é o aparelho que está vazando.
Sem dúvida, a troca de um " & vbCrLf & _
„.............................................
"@" & "Identificação do
Aparelho.@',0,'Informação')")
End Select
End Sub

Veja como fica o resultado do código na caixa de diálogo


suspensa:

A JANELA PESQUISADOR DE OBJETOS

187
188
Na janela que se abre você tem uma combo no lado
superior à esquerda que informa as bibliotecas contidas.
Para facilitar o estudo, escolha a biblioteca Access.

Na coluna Classes escolha a família(Classe) DoCmd que


é um objeto com finalidades práticas dentro do código. No
código de um botão em seu formulário digite este
comando seguido de um ponto:

Observe a lista de controles possíveis de se utilizar que


se desenrola. O ícone “pastilha” verde em movimento
significa método.

189
A “mão” segurando um folha de papel refere-se
àpropriedade do controle (caixa de texto, combo, caixa de
listagem) ou como no exemplo abaixo:

190
O ícone de raio que não visualizado aqui mais em outras
classes significa um evento. A classe de métodos é a
mais utilizada no ambiente de código. É formada por
diversos que se tornam membros da família DoCmd.
Vamos selecionar o método Maximize e, em seguida,
clicar no ponto de interrogação na parte superior à direita.
Este ao ser clicado nos fornece a informação pertinente a
este método. O que ele faz em termos de código e como
deve ser usado.

191
Alguns métodos exigem uma exemplo demonstrativo e o
Ajuda do Access vai exibi-los para maior clareza e ajudá-
lo a codificar o seu programa. Observe grifado em azul
um exemplo demonstrativo do método CopyObject da
família(Classe) DoCmd.

192
DoCmd.CopyObject, "Employees Copy", acTable,
"Employees"

Não vou entrar em detalhes acerca do que este código


faz. É necessário ter um planejamento anterior ou se ter
idéia do que ele pode fazer para que possa ser utilizado
no devido momento. O conhecimento da língua inglesa
ajuda muito nessas horas, pois não dá pra sair por aí
traduzindo tudo, mas é certo de que o código só
funcionará na língua inglesa.

Vamos nos ater a um exemplo demonstrativo do poder


desta janela. Precisei de um código que ao abrir o
programa, localizasse imediatamente um determinado
registro com uma informação específica. Ao observar a

193
lista de métodos desta família encontrei o método
FindRecord(Ache o registro). Não perdi tempo com a
explicação dos parâmetros ou argumentos do método e
procurei por um exemplo de aplicação.

Cliquei no ponto de interrogação e descobri um bom


exemplo.

DoCmd.FindRecord "Smith",, True,, True

Apliquei o código no evento Form_Load de meu


formulário, com as devidas alterações no objeto de minha
procura, troquei Smith por um dado qualquer que fosse
único, no meu caso, a matrícula 1111111-1 que só existia
em um único registro porque na tabela este campo estava

194
como Requerido : Sim. Isto obrigava o usuário a digitar
um valor no campo. Para evitar uma codificação que
cobrasse do usuário a sua digitação, criei uma código no
evento de um botão que adicionasse um novo registro
com a inclusão da String 1111111-1. E funcionou muito
bem !!! Ao abrir o formulário, o registro com esta String
1111111-1 era localizado com o método FindRecord.

DoCmd.FindRecord "111.11111-1", , True, ,


True

É lógico que eu preciso entender bem todos os


parâmetros ou argumentos de meu objeto DoCmd se eu
achar importante devido a natureza do método, mas isso
é com o programador e os tipos de pesquisas que terá
pela frente a pedido do Cliente. Lembrando que este tipo
de classe só possui métodos e não propriedades. Estes
só existem quando nos referimos a objetos que possuem
propriedades também ao inserimos no formulário. Por
exemplo: ComboBox, ListBox e CheckBox.

A FAMÍLIA DOCMD

Existem 66(sessenta e seis) membros (métodos*) que


fazem parte dessa família. Se você clicar em Exibir na
IDE e em seguida, em Pesquisador de Objetos e digitar
DoCmd você encontrará todos eles e sua função
respectiva na definição da classe DoCmd.

195
Para saber a que biblioteca pertence para ser utilizada na
codificação, clique em Access nesta mesma janela(Class
DoCmd).

196
*Os métodos referentes a família DoCmd assim como os referentes aos
objetos no formulário tem a forma de uma pastilha verde em movimento.

O resultado será: Microsoft Access 14.0 Object Library

Vá então em Referências e selecione esta biblioteca para


poder trabalhar com todos os membros(métodos) dessa
família.

A seguinte lista de métodos DoCmd exibe os commandos


mais comumente usados. O format geral para o
commando é Docmd.Action. Existem com frequência um
ou mais opções para este métodos de ação. Os exemplos
de método & definição na tabela abaixo foram
parafraseados a partir do Ajuda do Access para servir de

197
exemplos de códigopara melhor clareza e portanto foram
adicionados.

Comandos Descrição

O exemplo de comando AddMenu


demonstra como adicionar um item para
DoCmd Add Menu customizer menus dropdown no topo da
tela do banco de dados do Microsoft
Access.

Exemplo de Docmd ApplyFilter:


O seguinte exemplo emprega o método
DoCmd.ApplyFilter para exibir somente
registros que contenham o estado RJ no
campo Estado:

DoCmd.ApplyFilter , "Estado = 'RJ'"


DoCmd Apply
Filter Um método alternativo é utilizar a
propriedade de filtro de um formulário
diretamente. Neste exemplo podemos
utilizar uma combo box para selecionar o
estado:

frmPedidos.Form.Filter = "Estado='" &


Me.cboEstados& "'"
frmPedidos.Form.Filteron = True

198
Abaixo temos uma tabela sumário
mostrando que eventos são passíveis de
cancelamento utilizando o método Cancel
Event.

ApplyFilter Dirty MouseDown


BeforeDelConfirm Exit NoData

DoCmd Cancel BeforeInsert Filter Open


Event BeforeUpdate Format Print
DblClick KeyPress Unload
Delete

Um método semelhante ao DoCmd Cancel


Event é o Me.Undo que desfaz a inclusão
de um registro por exemplo.

Emprego este método para fechar o


formulário atual e abrir um outro. Por
exemplo, fechar o formulário principal e
abrir o formulário do Menu de Controle. A
DoCmd Close sintaxe é esta:

DoCmd Close acForm,


“NomedoMeuForm”, acSaveYes

DoCmd.OpenForm “Menu de Controle”,

199
acNormal

DoCmd Copy Docmd.CopyObject permite a você


Object duplicar qualquer objeto database.

O método DoCmd Delete Object


DoCmd Delete executa uma operação de exclusão nos
Object objetos do Access como tabelas,
consultas, formulários e relatórios.

O método DoCmd.FindRecord executa a


ação de encontrar o registro em Visual
Basic. Usa-se este comando com
DoCmd Find
frequência em conjunto com
Record
Docmd.FindNext para automatizar a
busca por registros da folha de dados
baseados na digitação feita pelo usuário.

Encontra o registro seguinte que


corresponde ao critério especificado pela
DoCmd Find Next
ação de encontrar o registro anterior ou
encontrar um campo por caixa de diálogo.

Move o foco para o campo indicado ou


DoCmd Goto controle no registro atual do formulário
Control aberto, folha de dados, tabela ou
consulta.

DoCmd Hour Mudar o ponteiro do mouse para um

200
Glass ícone de ampulheta (ou um outro ícone
de sua escolha) enquanto o programa
está correndo. Aplica-se este método
quando estiver rodando um procedimento
de VBA que demora para rodar.

Minimiza a janela ativa do formulário para


baixo, a um tamanho mínimo disponível
para ser restaurado enquanto o usuário
DoCmd Minimize
ainda estiver mostrando os outros
formulários. O formulário minimizado
exibe ícones de menos(-) e de mais(+).

O comando Maximize restaura ou amplia


a janela do formulário do Access até o
máximo tamanho permitido pela
DoCmd Maximize aplicação ativa do Access. Normalmente
este comando é inserido nos eventos
Form_Open, Form_Load ou
Form_Activate.

Docmd Restore restaura o tamanho do


formulário ativo até o tamanho ajustado
DoCmd Restore
anteriormente ou funciona como uma
execução de maximização/minimização.

Abre um formulário específico no modo


DoCmd Open
formulário, folha de dados, pronto para
Form
impressão ou estrutura de formulário.

201
Ex: DoCmd Open Form,”NomedoFormulário”,...

Abre uma consulta no modo estrutura,


folha de dados ou pronto para impressão.
DoCmd Open Ou, mesmo, executa uma consulta ação a
Query partir de um script VBA.

Ex: DoCmd Open Query,”NomedaConsulta”,...

Abre um relatório no modo estrutura ou


no modo pronto para impressão, ou
DoCmd Open imprime o relatório diretamente na
Report impressora padrão.

Ex: DoCmd Open Report,”NomedoRelatório”,...

Gera uma saída de dados a partir do bd


ativo (uma folha de dados, formulário,
DoCmd Output To relatório, módulo, DAP) para um arquivo
em Excel, DOS text (*.txt), ou no formato
rich-text.

Executa uma consulta ação SQL ao usar o


DoCmd Run SQL comando SQL. É possível também rodar
uma consulta DDL.

DoCmd Send Inclue a folha de dados específica,


Object formulário, relatório, módulo ou página
de acesso a dados em uma mensagem de

202
email que pode ser visualizado e enviado.

O método TransferText envia/recebe


registros de/para um banco de dados ou
DoCmd Transfer projeto e um arquivo em seu hd ou disco
Text rígido. O método TransferText é também
aplicável para estabelecer vínculos de
tabelas entre banco de dados.

Importa ou exporta dados de/para o


banco de dados ativo (.mdb) ou projeto
TransferDatabase
(.adp) e outros banco de dados tais como
FoxPro, dBase, e banco de dados ODBC.

USO DO RECORDSET

O objeto recordset possui duas coleções:

1. Fields - Contém todos os Objetos Fields do


objeto Recordset
2. Properties - Contém todas os objetos Property
para uma instância específica do objeto
Recordset.

O objeto recordset possue dezenove métodos:

1. Addnew - Cria um novo registro


2. CancelUpdate - Cancela atualizaçoes pendentes
3. Clone - Cria uma cópia de um objeto recordset

203
4. Close - Fecha um objeto recordset
5. Delete - Exclui o registro atual de um objeto
recordse aberto.
6. GetRows - Retorna múltiplos registros de um
recordset em um vetor.
7. Move - Muda a posição do registro atual.
8. MoveFirst - Muda a posição do registro para o
primeiro registro do recordset e o torna o registro
atual.
9. MoveLast - Muda a posição do registro para o
último registro do recordset e o torna o registro
atual.
10. MoveNext - Muda a posição do registro para o
próximo registro.
11. MovePrevious - Muda a posiçãodo registro para
o registro anterior.
12. MoveNextRecordset - Retorna o próximo objeto
recordset.
13. Open - Abre um Cursor.
14. Requery - Atualiza os dados de um recordset
executando novamente a consulta que o gerou.
15. Resync - Atualiza os dados de um objeto
recordset.
16. Supports - Informa a funcionalidade que o
objeto recordset suporta.
17. Update - Salva as alterações feitas no registro
atual.
18. UpdateBatch - Escreve todas as atualizações
pendentes em lote para o disco.

O objeto Recordset contém dezessete propriedades:

204
1. AbsolutePage - Informa o número da 'página' de
localização do registro atual.
2. AbsolutePosition - Determina a posição do
registro atual.
3. ActiveConnection - Informa a qual conexão o
objeto recordset pertence.
4. BOF - Informa que o registro atual está antes do
primeiro registro.(Início do Arquivo)
5. Bookmark - Retorna o bookmark que identifica
o registro atual ou atribui ao registro atual o
bookmark de um outro registro do recordset.
6. CacheSize - Informa o número de registros do
recordset que estão na memória.
7. CursorType - Informa o tipo de cursor usado em
u recordset.
8. EditMode - Mostra o status da edição que esta
sendo realizada no registro atual.
9. EOF - Informa que o registro atual está
posicionado depois do último registro.(Fim de
Arquivo)
10. Filter - Informa um filtro para os dados em um
recordset.
11. LockType - Informa o tipo de bloqueio dos
registros durante a edição.
12. MaxRecords - Informa o número máximo de
registros que serão retornados de uma consulta.
13. PageCount - Informa o número de páginas de
dados que um recordset contém.
14. PageSize - Mostra quantos registros constituem
uma página no recordset.
15. RecordCount - Informa o número de registros
em um recordset.

205
16. Source - Informa a fonte de dados em um objeto
recordset ou o nome do objeto ou aplicação que
gerou um erro.
17. Status - Informa o status do registro atual.

BIBLIOTECA DAO

Esses métodos e propriedades do Recordset podem ser


tanto aplicados com a Biblioteca DAO quanto a ADO.
Neste livro só trabalharemos com a biblioteca DAO por
ser mais simples e mais empregada no desenvolvimento
de aplicativos.

206
Antes de seguirmos adiante, adicione a biblioteca DAO
em Ferramentas, Referências* no ambiente de código:

_________

*Referências: Trata-se de um conjunto de bibliotecas utilizadas pelo Access para


fazer funcionar o seu aplicativo. Bibliotecas de tipos, bibliotecas de objetos ou uma
biblioteca de controle. Esta fica à disposição ao ser selecionada a opção desejada e a
partir da digitação do ponto ao lado do controle os seus métodos e propriedades são
disponibilizados e validados após a compilação do código.

207
Quando você precisar trabalhar com os objetos database
e recordset com os membros de suas coleções, digite
assim no cabeçalho do módulo da IDE ou de um
procedimento:

Dim db As DAO.Database
Dim rs As DAO.Recordset

Com esta variável “rs” você poderá percorrer todo o


Recordset e aplicar os diversos métodos desse objeto.

USO DA JANELA DE PROPRIEDADES DOS OBJETOS


À esquerda da janela ambiente de códigos temos a janela
de propriedades de todos os objetos de nosso sistema
com seus formulários, relatórios e módulos.

208
Em seguida, vamos selecionar um objeto do formulário,
por exemplo, uma caixa de texto e voltar para a janela de
propriedades.

Veja como fica à sua esquerda.

209
A caixa de texto selecionada apresenta suas propriedades
tais como cor, altura, largura, etc desta caixa de texto
específica.

Agora, volte para o formulário e analise as propriedades


dessa caixa de texto sob outro ângulo. Clique com o
botão direito a sua caixa de texto e selecione
Propriedades no menu que se abrirá.

É aqui que todo programador tem que ter domínio para


modelar todas as informações pertinentes a esta caixa de
texto. Selecione todas as abas e estude suas
propriedades tais como Máscara de Entrada, Fonte do
Controle, Ativado ou Bloqueado, Valor Padrão, Formato,
Casas Decimais, índice de tabulação, etc. Vamos tentar

210
estudar estas propriedades de forma prática para
desenvolvermos nossos aplicativos com profissionalismo.

De volta ao ambiente de código, selecione Ferramentas,


Referências e inclua todas as bibliotecas necessárias
para um bom desenvolvimento. As principais são:

Visual Basic For Applications


Microsoft Access 14.0 Object Library
OLE Automation
Microsoft DAO 3.6 Object Library

211
Veja um exemplo do uso da biblioteca DAO em um
programa:

ADICIONANDO UM REGISTRO VIA DAO

Exemplo (1)

Private Sub cmdAdic_Click()

Dim db As DAO.Database „Database é a base


de dados em si onde estão as tabelas,
consultas, formulários, relatórios e módulos
com seus métodos e propriedades
Dim rs As DAO.Recordset „Recordset é o
conjunto de registros criado(tabelas) com seus
métodos e propriedades do Access para inserção,
exclusão, atualização etc
Set db = CurrentDb
Set rs = db.OpenRecordset("tblClientes",
dbOpenDynaset)„Ou dbOpenTable, ou dbSnapshot
são constantes para identificar o tipo de
recordset criado. Já OpenRecordset é um método
da biblioteca DAO para abrir o recordset criado
(tabela)
rs.AddNew „AddNew é um método
rs!Codigo = Me!Codigo'Aqui o Campo Codigo da
Tabela(rs!Codigo) recebe o conteúdo do Campo
Codigo do Formulário (Me!Codigo)
rs!Nome = Me!Nome
rs!Fone = Me!Fone
rs.Update'Update é um método para atualizar
dados. Aqui ele salva o registro

212
rs.Close „Fecha o recordset
db.Close „Encerra o banco de dados

Set rs = Nothing „Limpa orecordset da RAM


Set db = Nothing'Remove o BD da RAM
DoCmd.SetWarnings False„Desativa qualquer aviso
de inserção do Access
End Sub
Exemplo (2)

Private Sub cmdAdic_Click()

Dim db As DAO.Database „Database é a base


de dados em si onde estão as tabelas,
consultas, formulários, relatórios e módulos
com seus métodos e propriedades
Dim rs As DAO.Recordset „Recordset é o
conjunto de registros criado(tabelas) com seus
métodos e propriedades do Access para inserção,
exclusão, atualização etc
Set db = CurrentDb
Set rs = db.OpenRecordset("tblClientes",
dbOpenDynaset)„Ou dbOpenTable, ou dbSnapshot
são constantes para identificar o tipo de
recordset criado. Já OpenRecordset é um método
da biblioteca DAO para abrir o recordset criado
(tabela)
With rs
.AddNew
!Codigo = 8

213
!Nome = “JOÃO BATISTA”
!Fone = 2332-4812
End With
If MsgBox("Salvar alterações?", vbYesNo) =
vbYes Then
r.Update 'Salva
MsgBox "Registro adicionado com
sucesso",vbInformation, “Adicionar”
Else
r.CancelUpdate 'Cancela cadastramento
End If
r.Close
Set d = Nothing
End Sub

ALTERANDO UM REGISTRO VIA DAO

PROPRIEDADES BEGINTRANS, COMMITTRANS e


ROLLBACK

BeginTrans - Inicia uma transação do Banco de Dados


CommitTrans - Salva as alterações feitas
RollBack - Desfaz as alterações, mesmo depois que já
tenham sido salvas com o Update

Exemplo 1:

Private Sub cmdAlterar_Click()

Dim ws As DAO.Workspace*

214
Dim db As DAO.Database
Dim rs As DAO.Recordset
„*Um Workspace é um objeto não-persistente que
define como seu aplicativo interage com os
dados ao utilizar o motor de banco de dados do
Ms Access. Use o objeto Workspace para
trabalhar a sessão corrente ou para iniciar uma
sessão adicional. Em uma sessão, você pode
abrir múltiplos bancos de dados ou conecções e,
trabalhar transações.

Dim Trans As Boolean


Dim sMens As String

On Error GoTo Erro

Trans = False
Set ws = DBEngine.Workspaces(0) 'Referir-se ao
Workspace padrão
Set db = CurrentDb 'Banco de Dados corrente
Set rs = db.OpenRecordset("Funcionarios",
dbOpenTable)
ws.BeginTrans
Trans = True

rs.MoveFirst 'Garantir que iniciará no


primeiro registro
Do Until rs.EOF 'Faça
enquanto não chegar ao final da Tabela

215
If rs!FuNome = "EDUARDO VIEIRA MACHADO" Then
„Considere que haja um registro com o seguinte
nome
Me!FuNome = rs!FuNome „Ou rs.Fields("FuNome")
sMens = MsgBox("Confirma alteração?", vbYesNo,
"Confirmação")

If sMens = vbYes Then


rs.Edit 'Abre para alterações
rs!FuNome = "JOÃO BATISTA" „Este nome
substituirá o anterior
„Ou dessa forma:
„rs.Fields("FuNome") = "JOÃO BATISTA"
rs.Update
End If
End If
rs.MoveNext 'Mover para o próximo registro
Loop
If MsgBox("Salvar alterações?", vbQuestion +
vbYesNo, "Salvar") = vbYes Then
ws.CommitTrans 'Salva alterações
Else
ws.Rollback 'Desfaz alterações
End If

Sair:
rs.Close
Set db = Nothing
Set ws = Nothing
Exit Sub

216
Erro:
MsgBox "Erro"
If Trans Then „Ou Trans = True
ws.Rollback
End If

Resume Sair
End Sub

Exemplo 2:

Private Sub cmdAlterar_Click()

Dim ws As DAO.Workspace
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim Trans As Boolean
Dim sMens As String
Dim sNome As String
Dim tNome As String

On Error GoTo Erro

Trans = False
Set ws = DBEngine.Workspaces(0) 'Referir-se ao
Workspace padrão
Set db = CurrentDb 'Banco de Dados corrente
Set rs = db.OpenRecordset("Funcionarios",
dbOpenTable)
ws.BeginTrans

217
Trans = True

sNome = InputBox("Digite o nome a alterar:",


"Alterar?")
tNome = InputBox("Digite o novo nome: ",
"Alterar?")

rs.MoveFirst 'Garantir que iniciará no


primeiro registro
Do Until rs.EOF 'Faça enquanto não chegar ao
final da Tabela
If rs.Fields(“FuNome”) = sNome Then
Me!FuNome = rs.Fields("FuNome") ' Ou
rs!FuNome
sMens = MsgBox("Confirma alteração?", vbYesNo,
"Confirmação")

If sMens = vbYes Then


rs.Edit 'Abre para alterações
rs.Fields("FuNome") = tNome
rs.Update
End If
End If
rs.MoveNext 'Mover para o próximo registro
Loop

If MsgBox("Salvar alterações?", vbQuestion +


vbYesNo, "Salvar") = vbYes Then
ws.CommitTrans 'Salva alterações
Else
ws.Rollback 'Desfaz alterações

218
End If

Sair:
rs.Close
Set db = Nothing
Set ws = Nothing
Exit Sub

Erro:
MsgBox "Erro"
If Trans = True Then
Exit Sub
End If

Resume Sair
End Sub

Exemplo (3.a)

Sub TrocaBairro(d As Database, r As Recordset,


Criterio As String, sBairro As String)
Set d = CurrentDb
Criterio = "Bairro = 'Montese'"
sBairro = "Parquelândia" „Substitua por
InputBox(“Forneça o nome do
bairro:”,”Informação)
Set r = d.OpenRecordset("Clientes",
dbOpenDynaset)
r.FindFirst Criterio

Do Until r.NoMatch „Início do laço

219
With r
.Edit „Utilizando o método Edit. Abre a
possibilidade de alteração do campo
!Bairro = sBairro
.Update „Atualiza pelo novo nome do campo
.FindNext Criterio
End With
Loop „Fim do laço
r.Close
Set d = Nothing
End Sub

Exemplo (3.b)

Sub DAO_MoveAndEdit()
Dim db as DAO.Database
Dim rs As DAO.Recordset

Set rs = db.OpenRecordset(“SELECT * FROM


Clientes”,dbOpenDynaset)

Do While Not rs.EOF


Debug.Print rs!País
If rs!País = “USA” Then
rs.Edit
rs.País = “EUA”
End If
Rs.MoveNext
Loop
rs.Close
db.Close

220
End Sub

Exemplo (4)

Esta consulta tem a mesma finalidade do Método Edit,


sendo que é mais eficiente.

Sub TrocaBairro(d As Database, s As String)


Set d = CurrentDb
s = "UPDATE Clientes SET Bairro =
'Parquelândia'" _
& "WHERE Bairro = 'Montese'"
d.Execute s
MsgBox d.RecordsAffected
Set d = Nothing
End Sub

CRIANDO UM PROCEDIMENTO NA IDE PELA BARRA


DE FERRAMENTAS

Observe à sua esquerda o menu aberto Módulo, Módulo


de Classe e Procedimento.

221
Clique em Procedimento...

222
Descreva o seu procedimento se será uma sub-rotina,
uma função ou uma propriedade e se seu escopo será de
natureza Pública ou Privada no seu projeto. Dê um nome
ao seu procedimento e clique em OK.
Normalmente, ao criarmos uma função, declaramos os
argumentos da função que entram dentro do parênteses.
Quando chamamos a função, podemos utilizá-la como
origem de um controle de uma caixa de texto ou dentro de
uma linha de código dentro de um evento qualquer de
algum controle(caixa de texto, combobox, etc), como Exit,
Ao Clicar, AfterUpdate, etc. Neste controle o valor
inserido em cada objeto como caixa de texto, combobox,
etc servirão de parâmetro da função, isto é, ocuparão o

223
lugar dos argumentos da função e servirão de elementos
do cálculo que porventura existir na função criada pelo
programador.

*Antes de distribuir um aplicativo seria importante


testarmos o código para ver se está funcionando bem.
Para isso debugamos o código com a visualização dos
resultados nesta Janela.

USO DA JANELA IMEDIATA NO AMBIENTE DE CÓDIGO


(IDE)
Uma vez escrito seus procedimentos VBA e obtido uma
compilação limpa, sem erros, você está pronto para
empreender o passo mais importante em programação:
debugar e testar. Muitos programadores se tornam
complacentes diante de um código escrito e compilado
sem problemas. Estes são somente os primeiros passos.
Os mais importantes, no entanto, são aqueles que os
programadores dão a mínima importância: debugar e
testar o código.

Esta página descreve as várias formas de debugar


disponíveis no editor do VBA (VBE) e como usá-las. Estas
são as descrições básicas das várias ferramentas de
diagnóstico e como usá-las.

A Janela Imediata é uma janela no VBE em que você


pode entrar com comandos, visualizar e mudar os

224
conteúdos das variáveis enquanto você codifica no modo
de Interrupção. O modo de Interrupção é o estado do VBA
quando a execução do código é pausada no ponto de
interrupção. Para exibir a Janela Imediata, pressione
CTRL+G ou selecione-a no menu Exibir.

Entre no formulário e clique no botão. Após a exibição das


duas MsgBoxes, entre no ambiente de código e ative a
Janela de Verificação Imediata. As seguintes informações
aparecerão:

O uso da Janela „Verificação Imediata‟ auxilia na


checagem de um código limpo, isto é, sem erros.

225
Aprovado o código após a verificação na Janela
„Verificação Imediata‟, coloque-o no evento Click de um
botão de um formulário, com os seguintes acréscimos
grifados:

Private Sub Comando0_Click()


Dim n As Integer
Dim sNome As String

sNome = InputBox("Digite um Nome: ")


n = Len(sNome)
If sNome = "" Then
Exit Sub
End If

MsgBox "O seu nome é " & sNome


MsgBox "Possui " & n & " caracteres"

„Ou
„MsgBox “Este nome “ & sNome & “ contém “ & n
& “ caracteres

End Sub

DESATIVANDO AVISOS DO ACCESS EM CÓDIGOS


COM INSTRUÇÃO SQL

Pegando um gancho no último exemplo de como utilizar a


biblioteca DAO, vamos ver como desativar as mensagens

226
do Access em procedimentos que requerem uma
atualização de dados, por exemplo, e colocar a nossa
própria mensagem personalizada.

Suponhamos que em seu código exista a seguinte


instrução, como exemplo:

Private Sub cmdAlterar_Click()


On Error Resume Next
Dim strSQL As String
Dim nProd As Integer
Dim nomeProd As String

strSQL = "UPDATE tblProdutos SET Produto =


Forms!Produtos!Produto WHERE ProdutoID =
Forms!Produtos!Pedido"
DoCmd.RunSQL strSQL
End Sub

O seguinte aviso surgirá:

227
Mas se incluirmos o seguinte código de desativação
acima e abaixo da instrução SQL com sua MsgBox
personalizada ficará assim:

Private Sub cmdAlterar_Click()


On Error Resume Next
Dim strSQL As String
Dim strMsg As String
Dim intRetVal As Integer

DoCmd.SetWarnings False <====


strSQL = "UPDATE tblProdutos SET Produto =
Forms!Produtos!Produto WHERE ProdutoID =
Forms!Produtos!Pedido"
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True <====

228
„Seu código personalizado
„*********************************************
strMsg = "Deseja realmente efetuar a
alteração?"
intRetVal = MsgBox(strMsg, vbQuestion +
vbYesNo, "Alterar?")
Select Case intRetVal
Case vbYes
DoCmd.RunCommand acCmdRefresh „Atualiza a
ListBox
MsgBox "Alteração realizada com sucesso !!!",
vbInformation, "Sistema PDV"
Case vbNo
MsgBox "Nenhuma alteração foi feita !!!",
vbInformation, "Sistema PDV"
End Select
End Sub

229
230
A ESTRUTURA DE CONTROLE If Then...Else...End If
E Select Case…End Select

IF THEN…ELSE…END IF

Aprendemos em Lógica de Programação a pensar de


forma a trazer soluções ao nosso problema através do
cumprimento de certas condições e caso não nenhuma
delas satisfaça a condição exigida, o certo é “tirarmos o
corpo fora”. Como é isso? Por exemplo, vamos
estabelecer o seguinte raciocínio:

Proposição: Só visto camisas GG


Logo:
Se eu ganhar uma camisa P então
Não caberá em mim
E se eu ganhar uma camisa M então
Também não caberá em mim
E se eu ganhar uma camisa G então
Também não caberá em mim
Caso contrário
Esta camisa GG caberá em mim. Obrigado !!!
Fim

Em VBA:

Dim MinhaCamisa As String„Declarando uma


variávelMinhaCamisa

231
„Lembrando que P, M, G e GG são variáveis à minha
proposição, isto é, escolhidas aleatoriamente e inseridas
em uma caixa de texto do meu formulário
MinhaCamisa=Camisa„Camisa é o nome da caixa
de texto que recebe a variável MinhaCamisa

If MinhaCamisa = “P” Then


MsgBox “Este tamanho não cabe em
mim!!!”
ElseIf MinhaCamisa = “M” Then
MsgBox “Este tamanho não cabe em
mim!!!”
ElseIf MinhaCamisa = “G” Then
MsgBox “Este tamanho não cabe em
mim!!!”
Else
MsgBox “Este tamanho GG cabe em mim.
Obrigado!!!”
End If

Observe que nesta estrutura com IF...THEN...ELSE...END


IF caso nenhuma solução satisfaça às condições
apresentadas, o programa responderá que não foi
encontrada uma solução para a proposição do usuário,
quaisquer que sejam elas que não satisfaçam as
condições apresentadas.

232
ANINHAMENTO DE IF‟s

Em sequência ao estudo de estrutura de controle


IF...THEN...ELSE...END IF vamos aprender sobre o
aninhamento dos IF‟s. O que é isto? Podemos sobrepor
os IF‟s para testarmos inicialmente se o campo está vazio
ou nulo, antes de validarmos o conteúdo deste campo.

Ex.:
If Not IsNull(Campo1) Or Campo1 = “”
Then„Testa „se o campo está nulo ou vazio
(1)
If IsNumeric(Campo1) Then„Testa se o campo
é numérico (2)
If Campo1 > 0 Then„Testa se o valor do
campo é maior que 0 (3)
MsgBox “Valor Positivo !!!”,
vbInformation, “Teste de IF‟s”
Else
MsgBox “Valor Negativo !!!”,
vbInformation, “Teste de IF‟s”
End If (3)
Else
MsgBox “Valor Não É Numérico !!!”,
vbInformation, “Teste de IF‟s”
End If (2)
Else

233
MsgBox “O Campo Está Vazio
!!!”,vbInformation, “Teste de IF‟s”
End If (1)

Estruturas de Controle com SELECT CASE... END


SELECT

Proposição: Só visto camisas GG


Logo:

Selecione uma Camisa


Caso eu ganhe uma camisa P
Não caberá em mim
Caso eu ganhe uma camisa M
Também não caberá em mim
Caso eu ganhe uma camisa G
Também não caberá em mim
Caso eu ganhe uma camisa GG
Esta camisa caberá em mim. Obrigado !!!
Fim da Seleção
Em VBA:

Dim MinhaCamisa As String„Declarando uma


„variável MinhaCamisa

234
„Lembrando que P, M, G e GG são variáveis à minha
proposição, isto é, escolhidas aleatoriamente e inseridas
em uma caixa de texto do meu formulário
MinhaCamisa=Camisa„Camisa é o nome da caixa
de texto que recebe a variável MinhaCamisa
Select Case MinhaCamisa
Case Is = “P”
MsgBox “Este tamanho não cabe em mim!!!”
Case Is = “M”
MsgBox “Este tamanho não cabe em mim!!!”
Case Is = “G”
MsgBox “Este tamanho não cabe em mim!!!”
Case Is = “GG”
MsgBox “Este tamanho cabe em mim. Obrigado
!!!”
End Select
No caso de usarmos SELECT CASE ... END SELECT,
estabelecemos condições onde só será satisfeita uma
delas também, mas o programa não dará uma resposta
automática de negação às proposições apresentadas que
rejeite qualquer uma que não satisfaça as condições
fornecidas pelo programador, só rejeitará apenas as que
você como programador estabelecer.

SELECT CASE ... END SELECT e IF THEN...


ELSE...END JUNTOS

235
Podemos inserir o primeiro dentro do segundo, isto é, o
select case dentro de if’s e também ao contrário:

Exemplo:

If rst![Use] = True Then


„................................................
Set frm = Forms(strFormName)
For Each ctl In frm.Controls
strControlName = ctl.Name
lngControlType = ctl.ControlType
fUnbound = False
„................................................

Select Case lngControlType


'Controls with control source only
Case acTextBox
strPrefix = "txt"
i = ControlCS(ctl, strPrefix, fTag)

Case acComboBox
strPrefix = "cbo"
i = ControlCS(ctl, strPrefix, fTag)

Case acCheckBox
strPrefix = "chk"
strControlSource = ctl.ControlSource
If fUnbound = False Then
i = ControlCS(ctl, strPrefix, fTag)
Else
i = ControlNA(ctl, strPrefix, fTag)
End If
„.................................................

CONSTANTES E ENUMERADORES

CONSTANTES

236
Usamos constantes para fixar um valor que estará
presente ao longo do código sem alterações ou para
estabelecer uma regra de cálculo para conversões de
dados. Na verdade ela difere da variável porque ao se
atribuir um valor, o programa ao ser compilado, esse valor
permanece inalterável.
Exemplo de constantes:

Const double pi = 3.14159265358979323846264338327950


const TW = 567 ‘Uma twip é usada como medida padrão no Visual
Basic 6 e em outras versões anteriores e também no Access VBA
quando no modo "Fontes pequenas" do Windows, 15 twips são iguais
a um pixel, e 567 twips equivale a 1 cm para efeito de definição de
largura e altura de um objeto no formulário.

Propriedades HEIGHT e WIDTH

Exemplo prático de Constantes:

Option Compare Database


Option Explicit

Public Function Redimensionar(sLargura As


Double, sAltura As Double) As String
On Error Resume Next
Dim sValor1 As Double
Dim sValor2 As Double

Const TW As Integer = 567 'Uma twip é usada


como medida „padrão no Visual Basic 6 e em
outras versões anteriores

237
'e também no Access VBA quando no modo "Fontes
„pequenas" do Windows, 15 twips são iguais a um
pixel,
'e 567 twips equivale a 1 cm para efeito de
definição de „largura e altura de um objeto no
formulário.

sValor1 = Nz(Forms!frmConstantes!txtLargura)
sValor2 = Nz(Forms!frmConstantes!txtAltura)

If Forms!frmConstantes!txtLargura = sValor1
Then

Forms("frmConstantes").Controls("MinhaFig
ura").Width = sValor1 * TW
End If

If Forms!frmConstantes!txtAltura = sValor2 Then

Forms("frmConstantes").Controls("MinhaFig
ura").Height = sValor2 * TW

End If

End Function
Private Sub cmdMostrar_Click()
Call Redimensionar(txtLargura, txtAltura)
End Sub

ENUMERADORES

Os enumeradores, na minha concepção, são um tipo de


constante utilizada para assumir valores predefinidos pelo

238
programador para representar os membros de uma
classe.

Exemplo de enumeradores:

Option Compare Database


Option Explicit
Private Enum DiasdeTrabalho

Segunda = 2
Terca = 3
Quarta = 4
Quinta = 5
Sexta = 6
Sabado = 7

End Enum

Private Function
ObterDiadaSemana(ValordeEntrada As Dias
deTrabalho) As String

Select Case ValordeEntrada


Case Is = 2
MsgBox "Segunda-Feira", vbInformation,
"Dia da Semana"
Case Is = 3
MsgBox "Terça-Feira", vbInformation, "Dia
da Semana"
Case Is = 4
MsgBox "Quarta-Feira", vbInformation,
"Dia da Semana"
Case Is = 5
MsgBox "Quinta-Feira", vbInformation,
"Dia da Semana"

239
Case Is = 6
MsgBox "Sexta-Feira", vbInformation, "Dia
da Semana"
Case Is = 7
MsgBox "Sábado", vbInformation, "Dia da
Semana"
End Select

End Function

Coloque uma caixa de texto no seu formulário com o


nome txtValor e rótulo com a expressão Digite uma Valor
de 1 a 7:

Private Sub cmdTestar_Click()


Call ObterDiadaSemana(txtValor)
End Sub

OS CONTROLES PRINCIPAIS USADOS EM


FORMULÁRIOS COM SUAS PROPRIEDADES E
MÉTODOS

Uma propriedade muito empregada no Access é a


Column(coluna ou fileira). Esta é muito utilizada para
referenciar o valor de uma ComboBox ou ListBox. Veja
sua sintaxe:

expression.Column(Index, Row)

240
Index (Índice) exige Long. Um inteiro longo que pode variar do
0 ao valor ajustado da propriedade ColumnCount menos
um(ColumnCount-1).

Row (Linha)Variant Opcional. Um inteiro que pode variar do 0


até ao valor ajustado da propriedade ListCount menos
1(ListCount – 1).

COMBOBOX (Caixa de Combinação)

Podemos ter como exemplo uma ComboBox simples:

cboNome.Column(0) „A ComboBox(cboNome) mais o


ponto exibe uma lista de métodos e propriedades. Com a
propriedade column(0) com índice 0 nos retornará o
primeiro nome da lista de nomes da combo ou de sua
cadeia de nomes da origem de linha que geralmente é
uma tabela, consulta ou lista de valores. O índice 0
corresponde ao primeiro elemento de uma matriz de
dados unidimensional, ou seja, trata-se do primeiro vetor
buscado. Neste exemplo:

EXEMPLO :

Caso (1) : Se o tipo de origem de linha da combobox for


uma tabela ou consulta e, se nesta tabela o primeiro
campo for o código e o segundo campo for o nome,
teremos:

cboNome.Column(1) = “EDUARDO VIEIRA MACHADO”

241
OBS: Para exibir este nome digamos em uma MsgBox ou
fazermos qualquer referência a ele ao longo de seu
código temos que organizar a nossa caixa de
propriedades. Na aba Formato, o número de colunas
será 2(dois) ou mais, dependendo da posição do campo
Nome na tabela.

Número de Colunas: 2

A largura das colunas terá a seguinte configuração:

Larguras das colunas: 0cm;5cm

Coluna acoplada: 2

O valor 5cm dependerá do comprimento do texto(no caso,


Nome) existente na tabela referente a este campo.

A origem da linha poderá ter uma sintaxe SQL que


organizará por ordem alfabética ou numérica a lista de
nomes ou códigos.

Origem da linha: SELECT * FROM tblNomes ORDER BY


Nome;

Caso (2): Se o tipo de origem de linha da combobox for


uma lista de valores, o índice pode variar de 0 até o total
de registros, correspondendo aos nomes deste campo no
total de registros. Logo, o primeiro nome desta lista será:

cboNome.Column(0) = “EDUARDO VIEIRA MACHADO”

242
O índice zero neste caso é porque não temos o campo
Código por não se tratar de referência a uma tabela e sim
a uma lista de valores, isto é, neste caso, nomes em
série.

A origem da linha poderá ter uma sintaxe SQL que


organizará por ordem alfabética ou numérica a lista de
nomes ou códigos.

Origem da linha: SELECT * FROM tblNomes ORDER BY


Nome;

243
No exemplo acima observamos que EDUARDO VIEIRA
MACHADO é o primeiro nome de uma lista. Mas de onde
vem esta lista? Vamos mudar para o modo Design
(Estrutura) do formulário.

244
A fonte de controle do objeto, no caso uma ComboBox de
nome FuNome, é a tabela Funcionários. Veja porém que
o campo Nome segue logo após RG. Conclui-se que é a
segunda coluna da tabela Funcionários.
Para efeito de ComboBox é a segunda coluna (column)
que estamos analisando, por isso a ordem dela na tabela
como segunda coluna é importante saber para que
possamos exibir a lista de nomes em nossa ComboBox.

245
Observe que o campo Nome é a segunda coluna da
tabela. Ok? Vamos então fazer algumas alterações na
propriedade de nossa ComboBox (ou controle) que é
também, por assim dizer, um objeto do formulário
Funcionários.

Na aba Formato de nossa ComboBox (cboNome)

246
Alteramos o Número de colunas a exibir na
ComboBox(cboNome) para 2, isto é, RG(FuRG) e
Nome(FuNome), mas ocultamos o primeiro campo,
colocando o valor (0cm) como primeiro valor da linha
Larguras das colunas e x cm(x=1 ou 2 cm, etc) separados
por ponto e vírgula. Colocaremos tantos 0cm quanto
necessários separados por ponto e vírgula(;) quando
quisermos exibir a coluna desejada.

LISTBOX

A ListBox ou Caixa de Listagem possui 123 (cento e vinte


e três) propriedades, 7(sete) métodos e 14(catorze)
eventos. É o controle para visualização congelada, isto é,
sem permissão para edição direta, em que podemos

247
atribuir diversos métodos para contar e informar total de
registros implantados, somar valores de uma determinada
coluna, selecionar registros, etc.
Exemplo(1)
Contagem de registros:
(1) Propriedade ListCount.

Contando o total de registros implantados.

Nossa ListBox de nome Lista9 gerada pelo Access


quando da sua inserção no formulário (podendo ser
alterado pelo programador) pode utilizar a propriedade
ListCount para contar o total de registros na tabela. Mas
por que utilizar a propriedade diminuindo -1 do total dos
registros? Ao realizar a contagem o total de registros
contados inicia a partir do valor 0. Subtraimos então 1 do

248
total, porque senão teríamos no total da contagem o valor
6 contados do total de registros.

Private Sub Lista9_Click()


MsgBox "Temos " & Me.Lista9.ListCount - 1 & "
registros já cadastrados !!!", vbInformation,
"Total de Registros"
End Sub

(2) Propriedade ColumnCount


Realiza a mesma função da propriedade ListCount

O código no evento Click é:

Private Sub Lista9_Click()


MsgBox "Temos " & Me.Lista9.ColumnCount
& " registros já cadastrados !!!",
vbInformation, "Total de Registros"
End Sub

249
Exemplo 2:

Propriedade Column.

Técnica N.º 1:

Vamos agora tentar identificar e informar com um simples


clique qual o valor existente na 2.ª coluna da caixa de
listagem.

O código no evento Click da ListBox será:

Private Sub Lista9_Click()

250
MsgBox "O valor existente na 2a coluna é "
& Me.Lista9.Column(1) & ".", vbInformation,
"Registro procurado"
End Sub

A técnica para identificar a coluna desejada na ListBox é


usar a propriedade Column. Mas por que utilizar como
índice da coluna o valor 1? Por que a contagem dos
campos é a partir do 0. Na tabela, o primeiro campo tem
índice 0, o segundo campo, índice 1.

Posso escolher outra linha diferente e será identificado o


valor da 2.ª coluna correspondente àquela linha.

Técnica N.º 2:

Suponhamos que todas as suas colunas estejam ocultas


para minimizar espaço em seu formulário, a solução seria
utilizar a propriedade Column através de uma MsgBox

251
para exibir a informação completa desta coluna e de todas
as outras no formato matriz de dados, em um só clique.

Como faço isso? Utilizando o seguinte código no evento


Click de sua ListBox:

Private Sub Lista9_Click()

MsgBox "O valor existente na " & vbCrLf &_


"1.ª coluna é :" & Me.Lista9.Column(0) & vbCrLf
& _
"2.ª coluna é : " & UCase(Me.Lista9.Column(1))
& vbCrLf & _

252
"3.ª coluna é : " & Me.Lista9.Column(2) &
vbCrLf & _
"4.ª coluna é : " & Me.Lista9.Column(3) & "",
vbInformation, "Registro procurado"

End Sub

Técnica N.º 3:

Se você quiser apenas identificar a partir de um campo da


listbox o registro com o mesmo nome.

Private Sub Lista_AfterUpdate()


Call Selecionado
End Sub

Private Function Selecionado() As Boolean


On Error Resume Next
Dim i As Integer

For i = 1 To Me.Lista.ListCount - 1
If Lista.ItemsSelected(i) = True Then
If Lista.Column(i) =
Forms![NomedoSeuFormulário]!NomedoSeuCampo Then

MsgBox "Item selecionado e encontrado!!!"


End If
Else
Exit Function
End If

253
Next i

End Function

Exemplo 3:

Utilizando a propriedade Bookmark para localizar um


registro do formulário.

Private Sub SuaListBox_AfterUpdate()


Dim rs As DAO.Recordset

If Not IsNull(Me.SuaListBox) Then


If Me.Dirty Then
Me.Dirty = False
End If

Set rs = Me.RecordsetClone
rs.FindFirst "[IDCodigo] = """ & Me.SuaListBox
& """"
If rs.NoMatch Then
MsgBox "Registro Não
Encontrado.",vbInformation,"Localizar ..."
Else
'Exibe o registro no formulário
Me.Bookmark = rs.Bookmark
End If
Set rs = Nothing
End If
End Sub

254
CALCULANDO TOTAIS COM LISTBOX

Agora, vamos supor que o caso seja somar os valores de


uma ListBox(Quantidade) e também contar quantos
produtos tem.

Ao clicar na ListBox (lstProdutos):

Private Sub lstProdutos_Click()


„TotItens e Total são os nomes das caixas de
texto abaixo da ListBox
Me.TotItens = Me.lstProdutos.ListCount – 1 „O
método ListCount conta os registros menos 1 que
é o registro de índice 0.

255
Me.Total = SomarTotal „SomarTotal é a função
que realiza o cálculo e nos retorna um valor.
End Sub

„Exemplo de Função N.º 1


Private Function SomarTotal()
On Error Resume Next
Dim x As Long
Dim soma As Long
soma = 0

„Looping For .... Next


For x = 1 To Me.lstProdutos.ListCount - 1
soma = soma + Me.lstProdutos.Column(3, x) „3ª
coluna percorrendo do índice 0 até o último
índice menos 1, pega os valores da coluna
Quantidade
Next
SomarTotal = soma

End Function

O resultado será:

256
TEXTBOX (CAIXAS DE TEXTO)

A textbox possui 140 (cento e quarenta) propriedades,


5(cinco) métodos e 17(dezessete) eventos. Das
propriedades convém destacar as seguintes:
altura(Height), largura(Width), alinhamento de texto
(TextAlign), etc. Vamos estudar uma função que trabalha
algumas das propriedades de uma caixa de texto:

Propriedades:
TextAlign (Alinhamento de texto)
RightMargin (Margem à direita)
LeftMargin (Margem à esquerda)
TopMargin (Margem superior)

257
BottomMargin (Margem inferior)

Public Function ModificaCaixa ()


On Error Resume Next

„TextAlign (Alinhamento de texto)

If CurrentProject.AllForms("Logos").IsLoaded
Then„Se o formulário Logos estiver aberto faça
assim
If Forms!Catálogo!cboPosicao.Column(0) = "À
Direita" Then
Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").TextAlign = 3 „Alinha o texto à
direita
ElseIf Forms!Catálogo!cboPosicao.Column(0) = "À
Esquerda" Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").TextAlign = 1 „Alinha o texto à
esquerda

ElseIf Forms!Catálogo!cboPosicao.Column(0) =
"Centro" Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").TextAlign = 2 „Alinha o texto no
centro

ElseIf Forms!Catálogo!cboPosicao.Column(0) =
"Justificado" Then

258
Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").TextAlign = 4 „Alinha o texto
justificado

Else
Exit Sub
End If
End Function

Configurando a distância da margem direita e esquerda


da caixa de texto ou memorando.

Public Function ModificaCaixa ()


On Error Resume Next
Dim sValor1 As Double
Dim sValor2 As Double
Dim sValor3 As Double
Dim sValor4 As Double
Dim sLarg As Double
Dim sAltura As Double

Const TW As Integer = 567

sValor1 = Nz(Forms!Catálogo!cboMargDireita)
„Valor na combo em cm.
sValor2 = Nz(Forms!Catálogo!cboMargEsq)
sValor3 = Nz(Forms!Catálogo!cboMargSuperior)
sValor4 = Nz(Forms!Catálogo!cboMargInferior)

„RightMargin (Margem à Direita)

259
If Forms!Catálogo!cboMargDireita = sValor1 Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").RightMargin = sValor1 * TW

„LeftMargin (Margem à Esquerda)

ElseIf Forms!Catálogo!cboMargEsq = sValor2 Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").LeftMargin = sValor2 * TW

„TopMargin (Margem Superior)

ElseIf Forms!Catálogo!cboMargSuperior = sValor3


Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").TopMargin = sValor3 * TW

„BottomMargin (Margem Inferior)

ElseIf Forms!Catálogo!cboMargInferior = sValor4


Then

Forms("MeuFormulário").Controls("MinhaCaixadeTe
xto").BottomMargin = sValor4 * TW

260
Else
Exit Sub
End If

End Sub

CHECKBOXES (Ou Caixas de Seleção)

São controles do tipo Sim/Não na tabela que são


identificados como valores do tipo Boolean em linguagem
codificada ou de alto nível na IDE(Integrated Development
Enviromment ou melhor, Ambiente Integrado para
Desenvolvimento). Na seleção pode-se clicar em mais
de uma caixa para atribuir determinada tarefa no
programa. Os checkboxes assumesm os seguintes
valores:

True (Ou -1) => Quando são clicados ou selecionados


False (Ou 0) => Quando ocorre o contrário

Exemplo de uma variável do tipo checkbox:

Dim chkExibirNome As Boolean

If chkExibirNome = True Then „Ou = -1


................

261
OBTION BUTTONS (Ou Botões de Opção)

Os Option Buttons ou botões de opção funcionam de


maneira diferente. Só se seleciona um botão de cada
vez para cada tarefa desejada. Veja as regras de
Reddick no capítulo 1 quanto à sua nomenclatura em
linguagem de código. Ao criar uma variável esta recebe
um valor True(-1) ou False(0) com referência ao controle
ou objeto inserido no formulário.

Exemplo de uma variável do tipo option button:

Dim optValor1 As Boolean

If optValor1 = True Then „Ou = -1


......................

SUBFORMS(Subformulários)

CALCULANDO TOTAIS COM SUBFORMS

Analise a figura abaixo:

262
No campo TOTAL PAGO temos a soma de todos os
valores em Reais dos produtos comprados pelo cliente
José Maria de Azevedo, filtrados no sub-formulário. Como
fizemos essa soma? Observe o modo Design deste
formulário.

263
Na fonte do controle do campo txtTotal(Total) do sub-
formulário, temos:

=Soma([Total]) „O campo Total recebe o valor de um


produto de um cliente. O método Soma([arg1]) soma
todos os valores de um consumidor específico.

Vamos agora pegar essa soma total do sub-formulário e


transferi-la para o campo TOTAL PAGO(txtTotal) de
mesmo nome, não acoplado.
A fonte do controle deste campo terá o seguinte código:

=[Produtos subformulário]![txtTotal]

264
O resultado será este.

O total pago (R$39,75) é o resultado da soma de todos os


produtos comprados pelo cliente José Maria de Azevedo.

Vamos ver como é possível exibir um item de venda no


sub-formulário de um sistema PDV. Este código
desenvolvi para um sistema PDV de uma mercearia.
Observe que estou fazendo a união entre duas tabelas: a
tabela Produtos e a tabela tblSelecao. Esta foi criada
simplesmente para receber os items de produtos que são
vendidos para um determinado cliente.

265
Public Sub AtualizarSaldo()
On Error Resume Next
Dim strSQL As String

strSQL = "SELECT [tblSelecao].[CodigoCliente],


[tblSelecao].[CodigoProduto],"
strSQL = strSQL & "[tblSelecao].[Produto],
[tblSelecao].[ValordeVenda], "
strSQL = strSQL & "[tblSelecao].[Quantidade],
[tblSelecao].[Total],"
strSQL = strSQL &
"[tblSelecao].[DataVenda],[tblSelecao].[Pago],"
strSQL = strSQL & "[Produtos].[Quantidade] FROM
tblSelecao "
strSQL = strSQL & "INNER JOIN Produtos ON "
strSQL = strSQL &
"[tblSelecao].[CodigoProduto]=[Produtos].[Codig
oProd] "
strSQL = strSQL & "WHERE CodigoCliente = '" &
cboCodigoCliente.Column(0) & "' "
strSQL = strSQL & "AND DataVenda = " &
sDataVenda & "ORDER BY"
strSQL = strSQL & "[tblSelecao].[ValordeVenda]
ASC" „A fonte de registro do subformulário é
fornecida „pela variável strSQL gerada pela
informação da „tabela tblSelecao em conjunto
com a tabela Produtos
[Produtos subformulário].Form.RecordSource =
strSQL
[Produtos subformulário].Requery
End Sub

266
PRINCIPAIS EVENTOS DE UM CONTROLE

Como você já observou o Access é orientado a eventos.


Para cada formulário, os objetos inseridos dentro dele
podem ter diversos tipos de comportamento a critério do
programador em observância às necessidades do usuário
solicitante.

Evento Propriedade do Evento


Activate Ao Ativar
AfterDelConfirm Após ConfirmarExclusão
AfterInsert Após Inserir
AfterUpdate Após Atualizar
ApplyFilter Ao Aplicar Filtro
BeforeDelConfirm Antes De ConfirmarExclusão
BeforeInsert Antes De Inserir

267
BeforeUpdate Antes De Atualizar
Change Ao Alterar
Click Ao Clicar
Close Ao Fechar
Current No Atual
DblClick Ao Clicar Duas Vezes
Deactivate Ao Desativar
Delete Ao Excluir
Enter Ao Entrar
Error Ao Ocorrer Erro
Exit Ao Sair
Filter Ao Filtrar
Format Ao Formatar
GotFocus Ao ReceberFoco
Initialize nenhuma
ItemAdded nenhuma
ItemRemoved nenhuma
KeyDown Ao Apertar Tecla
KeyPress Ao Pressionar
TeclaKeyUp Ao Liberar Tecla
Load Ao Carregar
LostFocus Ao Perder Foco
MouseDown Ao Apertar Mouse
MouseMove Ao Mover Mouse
MouseUp Ao Liberar Mouse
NoData Se Nenhum Dado
NotInList Se Não Estiver Na Lista
Open Ao Abrir
Page Na Página
Print Ao Imprimir
Resize Ao Redimensionar

268
Os eventos principais dos controles mais usados são (Not
In List, AfterUpdate, BeforeUpdate, Change, Current,
Enter, Click, Double-Click, GetGocus, LostFocus e Exit)

Vamos nos ater a estudar apenas o evento Not In List,


pois exige maior atenção.

O EVENTO Not InList (Não está na lista)

Com formulário desvinculado à tabela

Exemplo 1:

Private Sub cboComodo_NotInList(NewData As


String, Response As Integer)
On Error Resume Next
Dim strSQL As String
Dim i As Integer
Dim Msg As String
Dim NovoCodigo As String

' Cria um NovoCodigo (CargodoContato) à


esquerda do item adicionado
' Ao subtrair os 10 primeiros caracteres da
'string'
' Convertendo para Maiúscula e salvando na
tabela
If NewData = "" Then Exit Sub

NovoCodigo = UCase(Trim(left(NewData, 6)))

269
Msg = "'" & NewData & "' NÃO ESTÁ NA LISTA DE
COMODOS." & vbCr & vbCr
Msg = Msg & "VOCÊ DESEJA ADICIONÁ-LO?"

i = MsgBox(Msg, vbQuestion + vbYesNo, "COMO


NÃO ESPECIFICADO...")
If i = vbYes Then
strSQL = "Insert Into tblComodos
([CodComodo],[Comodo]) values('" & NovoCodigo &
"','" & NewData & "') "
CurrentDb.Execute strSQL,
dbFailOnError*
Response = acDataErrAdded**
Else
Response = acDataErrContinue***
End If

End Sub
_________
* É uma constante do Access. Devolve as atualizações se
ocorrer um erro (apenas espaços de trabalho do Microsoft
Access). Fonte: Ajuda do Access
** Definindo o valor do argumento Response para esta
constante, você indica ao Access que o valor digitado na lista
foi adicionado à tabela definida na propriedade Origem da linha
da caixa de combinação(combobox). Isso fará com que a lista
seja automaticamente reconsultada, passando a exibir entre
seus itens o valor digitado (como ocorre com a caixa de diálogo
Executar do Windows) Fonte: Programando Microsoft Access
com VBA, Vol. 3, pág. 13, Flávio Morgado)

270
*** Definindo o argumento Response para esse valor, indica-se
ao Access para não reconsultar a lista e não exibir uma
mensagem de erro para o item inexistente. Neste caso, o item
digitado será aceito como o novo valor da caixa de
combinação, apesar da propriedade Limitar a Uma Lista estar
definida para Sim;
Fonte: Programando Microsoft Access com VBA, Vol. 3, pág.
13, Flávio Morgado)

Você pode esperar que uma caixa de


combinação(combobox) acumule valores adicionados
nela. Este evento abre esta possibilidade, mas é
necessário para que funcione que no modo
Design(Estrutura) as seguintes propriedades estejam
habilitadas:

Limitar a uma lista : Sim


Permitir Edições da Lista de Valores: Sim
Herdar Lista de Valores: Sim

E que para este campo exista uma tabela referencia


(tblComodos)com dois campos apenas:

CodComodo
Comodo

Lembre-se de que esta tabela NÃO é a tabela principal


com todos os campos, mas somente uma tabela

271
criada para receber os valores referentes aos
comodos.
Crie uma consulta referente a esta tabela como o seguinte
nome cnsComodos com dois campos apenas. No modo
Design, Propriedade, Valores Exclusivos configurado
como Sim.

Observe a figura exemplo abaixo:

272
O que acontece se essas propriedades não estiverem
configuradas corretamente? Logicamente, você não
poderá inserir nenhuma informação. O contrário acontece
se estiver com informação.

273
Vamos tentar inserir um comodo que não está na lista e
ver o que acontece.

274
Como sua resposta deverá ser Sim, o novo comodo é
adicionado à lista.

CONTROLES-GUIAS

Um dos controles que dão um ar mais profissional aos


formulários é o controle-guia. É uma ferramenta por assim
dizer que invariavelmente lanço mão para aprimorar meus
formulários. No entanto, é preciso que você saiba que não
basta ir inserindo páginas ao seu controle que depois é só
jogar os campos. Existe uma regra principal que está
vinculada à propriedade PageIndex ou melhor, página do
índice de tabulação. A começar do zero, corre o índice
pela propriedade de cada página e a partir daí podemos

275
formular um código para diferenciar a sua pesquisa de
dados de uma página para a outra.

Veja como inserir uma página no seu controle-guia. Clique


com o botão direito do mouse e em Inserir Página. Cada
página inserida já vem com seu pageindex (índice de
página) em escala crescente, começando a partir do 0
(zero).

O segundo ponto é a fonte de registro ou fontes de


registros, isto é, quais tabelas serão consultadas?
Utilizando o método Recordsource podemos consultar
tabelas diferentes em cada página.

276
Exemplo:

„CtlGuia34 é o nome do controle-guia pelo


evento „alterar(Change)

Private Sub CtlGuia34_Change()


Dim tbc As control, pge As Page
Set tbc = Me.CtlGuia34
Set pge = tbc.Pages(tbc)

Select Case pge.PageIndex


Case 0
Me.lstCodigo.visible = True
Me.lstCodigo.SetFocus
Me.tbl_Produtos.visible = False
Me.Gráfico62.visible = False
Me.RecordSource = "SELECT * FROM
tbl_Vendas"

Me.lblStatus.Caption = "EXIBINDO
VENDAS..."
Case 1
Me.lstCodigo.visible = False
Me.tbl_Produtos.visible = True
Me.Gráfico62.visible = False
Me.RecordSource = "SELECT * FROM
tbl_Produtos"
Me.lblStatus.Caption = "EXIBINDO
ESTOQUE..."
Case 2
Me.lstCodigo.visible = False

277
Me.tbl_Produtos.visible = False
Me.Gráfico62.visible = True
Me.Gráfico62.Requery
Me.lblStatus.Caption = "EXIBINDO
GRÁFICO..."
End Select
End Sub

FORMATAÇÃO CONDICIONAL EM FORMULÁRIOS

Observe a figura abaixo:

278
Naturalmente, você notou que na linha 4 o nome AMAURI
DAMIÃO XAVIER DE ANDRADE aparece em destaque
na cor vermelha. Ao selecionar com o mouse aquela linha
este efeito acontece. Como se faz isso?
Primeiramente, o seu formulário deve ser criado no
formato tabular ou modificado pelo modo
Design(Estrutura) e em propriedades do formulário, na
aba Formato, o modo Padrão dever ser Formulário
Contínuo.

Selecione o campo desejado para obter o efeito


demonstrado inicialmente. Em nosso caso é o campo
PREPOSTO. Pela barra de ferramentas, abra a aba
Design e clique em Condicional.

279
Selecione no espaço Condição 1 o item „A Expressão‟ e
no campo ao lado digite [STATUS]=-1 e a cor da fonte
desejada.

No evento GotFocus deste campo deverá existir o


seguinte código:

280
Private Sub PREPOSTO_GotFocus()
Me!PREPOSTO.SelStart = Len(Me!PREPOSTO &
"") „Propriedade SelStart ajusta o ponto
inicial do texto selecionado
End Sub

INSERINDO DADOS EM UMA TABELA A PARTIR DE


OUTRA

Exemplo

Neste exemplo, vamos admitir que tanto os campos da


tabela 1 quanto da tabela 2 são iguais e que a tabela 1
está sem dados à diferença da tabela 2. Costumo utilizar
muito esta prática em meus aplicativos para computar
pontuação de jogos que são zerados depois da partida.
Há diversas outras utilizações para este recurso. Pense
em uma.

Private Sub cmdinserir_Click()


Dim db As DAO.Database
Dim nCod As Integer
nCod = InputBox("Digite o código: ",
"Inserindo Dados")
Set db = OpenRecordset("SuaTabela",
dbOpenTable)
CurrentDb.Execute " INSERT INTO SuaTabela1
" _
& "SELECT * " _

281
& "FROM SuaTabela2 WHERE Código = " & nCod

db.Close
Set db = Nothing
DoCmd.SetWarnings False

End Sub

ALTERANDO DADOS EM UMA TABELA A PARTIR DE


OUTRA

Após a inserção de dados, caso você queira alterar os


dados de algum campo por registro ou em todos os
registros, utilize a cláusula UPDATE agregando um
critério de busca para esta alteração por registro
específico ou se desejar todos os registros
simultaneamente. Neste caso, você não vai precisar
lançar mão de um critério de busca.

Exemplo:

Private Sub cmdAlterar_Click()


Dim db As DAO.Database
Dim nCod As Integer
nCod = InputBox("Digite o código: ",
"Inserindo Dados")

Set db = OpenRecordset("SuaTabela",
dbOpenTable)

282
CurrentDb.Execute " UPDATE SuaTabela1 SET
Campo1 = „Rio de Janeiro‟ WHERE Código = " &
nCod „Campo1 poderia ser Cidade

db.Close

Set db = Nothing
DoCmd.SetWarnings False

End Sub

FUNÇÃO ALEATÓRIO (RANDOMIZE)

A função Randomize se aplica como o nome já diz para


exibir resultados aleatórios.
Vamos praticar gerando números aleatórios em uma
MsgBox. Em um formulário coloque um botão com o
seguinte código no evento Click:

Exemplo (1):

Private Sub cmdExibir_Click()


Dim ExibirValor As Integer
Dim i As Integer
' Gerando valores aleatórios entre 1 e 6.
For i = 1 To 6„O total de exibições não
pode passar de 6

283
ExibirValor = Int((6 * Rnd) + 1)„Serão
exibidos seis números que podem se repetir
aleatoriamente
MsgBox ExibirValor, vbExclamation, "Função
Round(Rnd)"
Next i
End Sub

Exemplo(2): Exibindo um número aleatório de registro de


uma tabela

Private Sub cmdAleatorio_Click()


Dim k As Long
Dim rs As DAO.Recordset
Dim sCod As Long

Set rs =
CurrentDb.OpenRecordset("tblClientes",
dbOpenTable)

k = rs.RecordCount

Dim LRandomNumber As Integer

LRandomNumber = Int((k - 1 + 1) * Rnd + 1)


'k é o número máximo de registros e 1 é o
primeiro registro

284
MsgBox "Registro: " & LRandomNumber,
vbExclamation, "Aleatorio"

End Sub

Encontrei seu emprego para diversos aplicativos em


conjunto com vetores como nos exemplos abaixo:

(1) Exibindo mensagens aleatórias


MsgBox ("Caro Usuário, Seja Bem-Vindo ao
Aplicativo CONTROLE DE SR ANO BASE 2005!")
'Declação de variáveis
Dim Hora As Date
Dim Tipo(1 To 10) As String
'Inicio
Tipo(1) = "Como anda seu serviço, nenhuma
inclusão ou alteração a fazer?"
Tipo(2) = "Continue sempre assim!!!"
Tipo(3) = "A família vai bem?"
Tipo(4) = "Como está seu dia?"
Tipo(5) = "Qual a notícia mais importante
hoje?"
Tipo(6) = "Tem certeza de que não esqueceu
de incluir alguma SR hoje?"
Tipo(7) = "A pressa é inimiga da
perfeição!"
Tipo(8) = "Não desmereça em nada o seu
trabalho, seja competente!"
Tipo(9) = "Eu não disse que você era
capaz?"

285
Tipo(10) = "Não disse que você iria tirar
de letra?"
Hora = Time
Call Randomize„Chamada da função do tipo Rnd de
„valores inteiros que exibirá o total de 10
„mensagens(vetores) aleatoriamente
„Tipo(Int(10*Rnd)+1)

If (Hora >= CDate("00:00:00") And Hora <


CDate("12:00:00")) Then
Call MsgBox("Bom-Dia!" & vbCrLf & vbCrLf &
Tipo(Int(10 * Rnd) + 1), vbInformation, "OLÁ!")
ElseIf (Hora >= CDate("12:00:00") And
Hora < CDate("18:00:00")) Then
Call MsgBox("Boa-Tarde!" & vbCrLf &
vbCrLf & Tipo(Int(10 * Rnd) + 1),
vbInformation, "OLÁ")
Else
Call MsgBox("Boa-Noite!" & vbCrLf & vbCrLf
& Tipo(Int(10 * Rnd) + 1), vbInformation,
"OLÁ")
End If

OBS: Antes de chamar a função Rnd, use a instrução


Randomize sem um argumento para inicializar o gerador
de número aleatório com uma semente baseada no timer
do sistema. (do site da Microsoft)

(2) Exibindo palavras aleatórias em jogos como Forca


......

286
(3) Exibindo sinais gráficos como a letra O e X em jogos
como Jogo da Velha

Exemplo:

Public Function Aleatorio()„Função que criei


para o Jogo da Velha
'Função para a Casa1

Dim pal(8) As String„Vetor com 8(oito) índices

If Casa1 = "X" Then


pal(1) = "O"„O primeiro elemento do vetor é
puro. É só a letra O maiúsculo.
pal(2) = "'O'"„O segundo elemento do vetor vem
intercalado por 2(dois) apóstrofos
pal(3) = "O*"„O terceiro elemento do vetor vem
seguido de um asterisco e assim vai..
pal(4) = "O!"
pal(5) = "O@"
pal(6) = "O%"
pal(7) = "O$"
pal(8) = "O&"

Call Randomize „A função Randomize gerará o


sortimento aleatório dos vetores a cada evento
de um clique duplo, no caso, da casa escolhida.

Chave = pal(Int(8 * Rnd) + 1)„Chave é uma caixa


de texto que deixo com sua propriedade Visible
igual a False. Ela receberá os valores

287
alternados ou aleatórios sorteados pela função
Randomize definida a quantidade de vezes
especificada entre parênteses em conjunto com a
função Rnd(Random). Random significa Aleatório.

If Chave = pal(1) Then„pal(1) é o primeiro


vetor de um conjunto de vetores com 8 índices
If IsNull(Casa2) Or Casa2 = "" Then
Casa2 = Chave„No primeiro vetor com “O” não é
necessário qualquer modificação no código

End If
ElseIf Chave = pal(2) Then
If IsNull(Casa4) Or Casa4 = "" Then
Casa4 = Replace(Chave, "'", "")„No segundo
vetor precisarei retirar o apóstrofo com a
função Replace. Por que isto? Porque não é
possível trabalhar vetores com elementos
iguais. Farei isto com todos os outros vetores.
Cada casa com exceção da Casa1 poderá receber o
valor de cada vetor aleatório, isto é, o seu
elemento modificado.

End If
ElseIf Chave = pal(3) Then
If IsNull(Casa5) Or Casa5 = "" Then
Casa5 = Replace(Chave, "*", "")

End If
ElseIf Chave = pal(4) Then
If IsNull(Casa6) Or Casa6 = "" Then

288
Casa6 = Replace(Chave, "!", "")

End If
ElseIf Chave = pal(5) Then
If IsNull(Casa7) Or Casa7 = "" Then
Casa7 = Replace(Chave, "@", "")

End If
ElseIf Chave = pal(6) Then
If IsNull(Casa9) Or Casa9 = "" Then
Casa9 = Replace(Chave, "%", "")

End If
ElseIf Chave = pal(7) Then
If IsNull(Casa8) Or Casa8 = "" Then
Casa8 = Replace(Chave, "$", "")

End If
ElseIf Chave = pal(8) Then
If IsNull(Casa3) Or Casa3 = "" Then
Casa3 = Replace(Chave, "&", "")
End If
Else
Exit Function
End If
End If

If Casa1 = "O" Then


pal(1) = "X"
pal(2) = "'X'"
pal(3) = "X*"

289
pal(4) = "X!"
pal(5) = "X@"
pal(6) = "X%"
pal(7) = "X$"
pal(8) = "X&"

Call Randomize„Gera a seleção aleatória


juntamente com Round(Rnd)

Chave = pal(Int(8 * Rnd) + 1)


If Chave = pal(1) Then
If IsNull(Casa2) Or Casa2 = "" Then
Casa2 = Chave
End If
ElseIf Chave = pal(2) Then
If IsNull(Casa4) Or Casa4 = "" Then
Casa4 = Replace(Chave, "'", "")
End If
ElseIf Chave = pal(3) Then
If IsNull(Casa5) Or Casa5 = "" Then
Casa5 = Replace(Chave, "*", "")
End If
ElseIf Chave = pal(4) Then
If IsNull(Casa6) Or Casa6 = "" Then
Casa6 = Replace(Chave, "!", "")
End If
ElseIf Chave = pal(5) Then
If IsNull(Casa7) Or Casa7 = "" Then
Casa7 = Replace(Chave, "@", "")
End If
ElseIf Chave = pal(6) Then

290
If IsNull(Casa9) Or Casa9 = "" Then
Casa9 = Replace(Chave, "%", "")
End If
ElseIf Chave = pal(7) Then
If IsNull(Casa8) Or Casa8 = "" Then
Casa8 = Replace(Chave, "$", "")

End If
ElseIf Chave = pal(8) Then
If IsNull(Casa6) Or Casa6 = "" Then
Casa6 = Replace(Chave, "&", "")
End If
Else
Exit Function
End If
End If

End Function

TRABALHANDO COM O FORM_TIMER E A FUNÇÃO


TIME

A seguinte função é um código livre na internet que


emprego para diversas finalidades para controlar a
animação de objetos como rótulos, caixas de texto etc.
Com esse código você pode criar relógios digitais,
controlar tempo de respostas do usuário, criar mensagens
com MsgBox a intervalos de tempos de exibição, controlar
a velocidade de uma animação com intervalo de
cronômetro variados. Para conhecer o intervalo de
cronômetro, entre no modo design do seu formulário, pelo

291
modo propriedades do formulário, clique na aba Eventos,
selecione intervalo de cronômetro. Geralmente para
relógios, o intervalo de cronômetro é 1000, ou se você
desejar poderá alterá-lo via código como no exemplo
abaixo.

Exemplo de um relógio:

Private Sub Form_Timer()


On Error Resume Next
Dim xHora As Integer
Dim xMinuto As Integer
Dim xSegundo As Integer

xSegundo = Second(txtTime)„txtTime é a
caixa de texto que exibe a hora, minuto e
segundos
xMinuto = Minute(txtTime)
xHora = Hour(txtTime)
Me.TimerInterval = 1000 „Altera o
intervalo de cronômetro influindo na
velocidade da animação
If xSegundo < 60 Then
xSegundo = xSegundo + 1
Else
xSegundo = 0
If xMinuto < 60 Then
xMinuto = xMinuto + 1

Else
xMinuto = 0
xHora = xHora + 1
End If

292
End If
Me.txtTime = Format(TimeSerial(xHora,
xMinuto, xSegundo), "hh:mm:ss")
End Sub

Outro exemplo mais simples de um relógio digital você


pode criar com um rótulo no formulário. Dê um nome a ele
como lblRelogio(Lembra-se prefix lbl para rótulos?) e
dimensione-o no formulário a seu bel prazer. No evento
Form_Timer coloque o seguinte código:

Private Sub Form_Timer()


Me.lblRelogio.Caption = Time() „Ou
Time$
End Sub

Lembrando que o intervalo de cronômetro no formulário


será 1000. Entre no modo design (estrutura) do
formulário, propriedades, aba evento, Intervalo de
cronômetro. Digite 1000 ao lado.

A FUNÇÃO TIME

Coloque no evento Form_Open:

txtHora= Time()„txtTime é o nome da caixa


de texto. Exibirá a hora do sistema e o dia
por extenso

TRATAMENTOS DE ERROS

293
Geralmente quando queremos assegurar que o aplicativo
rodará sem avisar sobre erros de depuração de código,
incluímos a seguinte linha de código antes do código
principal de nossa sub-rotina:

1.º CASO

Exemplo (1)
Private Sub cmdAbrir_Click()

Dim A As Integer

A = InputBox(“Qual é o seu nome?”)

MsgBox “Seu nome é “ & A

End Sub

Nota: Observe que declarei A, uma variável do tipo


Integer(Inteiro) para receber um dado do tipo String
(Texto).

294
O que acontecerá após eu dar OK?

Isso mesmo, um erro em tempo de execução de número


13. Ao depurarmos o código em busca do erro,
verificaremos que se trata do tipo de dados que minha

295
variável A recebeu, ser do tipo String, mas foi declarada
como do tipo Integer. Este é o erro.

Se eu simplesmente quiser ignorar este erro, o que devo


fazer? Inserir a expressão em grifo

1.º CASO
Option Compare Database
Option Explicit

Private Sub cmdAbrir_Click()


On Error Resume Next „Ao ocorrer um erro
execute o código a partir daqui

Dim A As Integer

A = InputBox("Qual é o seu nome?")

MsgBox "Seu nome é " & A


End Sub

Neste caso, estaremos apenas ignorando o erro sem


tratá-lo devidamente. O código da sub-rotina segue seu
curso sem interrupções, mas não assegura que se
executará o que se pretende.

296
297
Geralmente, os erros obedecem um padrão em uma
escala tabular já pré-estabelecida pela Microsoft.

Vamos tratar este erro de número 13 devidamente. Veja


como deverá ficar nosso código:

2.º CASO
Private Sub cmdAbrir_Click()
On Error GoTo TrataErro„Ao ocorrer um erro vá para
TrataErro
Dim A As Integer

A = InputBox("Qual é o seu nome?")

MsgBox "Seu nome é " & A


Exit Sub
TrataErro:
If Err.Number = 13 Then
MsgBox "Erro de Conversão de Letra para Número !"
End If

End Sub

Após digitarmos um nome em nossa InputBox, a seguinte


mensagem surgirá.

298
Nota: Observe que a mensagem “Seu Nome é ...” será
ignorada e ao invés esta mensagem personalizada
surgirá, evitando que o aplicativo seja interrompido com
uma mensagem inconveniente de depuração de código e
deixe vulnerável seu aplicativo para alterações indevidas
de seus usuários.

Agora veremos um pequeno resumo de como e quando


utilizar os comandos de tratamento de erro numa rotina:

Declaração do Tratamento de Erro

 On Error Resume Next - Se ocorrer erro, continua


executando a partir da linha sub-seqüente à linha que o
gerou (ignora o erro)
 On Error GoTo TrataErro- Se ocorrer um erro,
continua executando a partir da linha identificada pela
label
 On Errot GoTo 0 – Assegura que uma rotina de
cálculo não exibirá um cálculo errôneo.

299
Finalizando a Sub-Rotina

 Exit Sub - Finaliza a execução da sub-rotina (Sub)


 Exit Function - Finaliza a execução da função
(Function)
 Exit Property - Finaliza a execução da propriedade
da classe (Property)
 End - Finaliza a execução do programa

No Bloco de Tratamento de Erro

 Resume- Executa novamente a linha que gerou o


erro
 Resume Next - Executa a linha sub-seqüente à
linha que gerou o erro
 GoTo TrataErro- Executa a partir da linha
identificada pela label

MÓDULOS
Podemos ter módulos padrão e módulos de classe. Neste
livro, porém, vamos abordar somente módulos padrão.

Módulos Padrão:

Quando desejamos que uma determinada função ou sub-


rotina funcione em diversos formulários de um sistema,
criamos então os módulos a partir da janela da IDE de
desenvolvimento chamada Procedimento na barra de
tarefas. A Microsoft dá a seguinte definição para módulos:

300
“Um módulo é essencialmente uma coleção de
declarações, instruções e procedimentos armazenados
conjuntamente como uma unidade chamada para
organizar seu código do Microsoft Visual Basic. O
Microsoft Access possui dois tipos básicos de módulos:
módulos padrão e módulos classe.”
Módulos classe – contém procedimentos para formulários
e relatórios.
Módulos – contém procedimentos para uso geral.

Por exemplo de um módulo seria uma com função para os


botões de navegadores de registro existentes em todos os
formulários, ou para adição de registro ou exclusão.
Podemos também criar módulos com procedimentos para
mudar a cor dos formulários, ou para redimensioná-los;
módulos para verificar a ortografia de textos escritos em
caixas de textos ou memorandos, etc.
Exemplo de um módulo para alterar as propriedades dos
formulários:”

Public Function MudaPropriedades()

Dim Db As Database, doc As Document, ctl As


Control
Set Db = CurrentDb

301
On Error GoTo Err_Handler
For Each doc In
Db.Containers("Forms").Documents
DoCmd.OpenForm doc.Name, acDesign, , , ,
acHidden
For Each ctl In Forms(doc.Name)
If TypeOf ctl Is Label Then
ctl.FontName = "Arial"
ctl.FontSize = 7
ElseIf TypeOf ctl Is TextBox Then
„Alterações dos controles
ctl.FontName = "TimesNewRoman" „Define
todas os tipos de „fontes
ctl.FontSize = 10 „Define o tamanho
das fontes
ctl.BorderColor = 14727292 „Define a
cor de todas as bordas „dos controles
ctl.BackColor = 16769734 „Define a cor
de fundo de todos os controle
ctl.BackStyle = 1 „Define
se o controle será transparente ou não
ctl.BorderWidth = 2 „Define a
largura da borda de todos os controles
ctl.ForeColor = 6697728 „Define a cor
dos caracteres
ctl.SpecialEffect = 4 „Define o
efeito especial do controle, por exemplo, com
alto relevo ou baixo relevo.
ctl.BorderStyle = 1 „Define o
estilo de borda se é do tipo fino(com bordas
não acentuadas), ou caixa de diálogo etc
End If

302
Next
DoCmd.Close acForm, doc.Name, acSaveYes
Next

Exit_MudaPropriedades:
Set Db = Nothing
Exit Sub
Err_Handler:
MsgBox "Error #: " & Err.Number & vbNewLine
& Err.Description
Resume Exit_MudaPropriedades
End Function

APLICATIVOS EM REDE

Para que seus usuários possam acessar o seu banco de


dados sem bloqueio de um usuário que acessou depois,
faça o seguinte: divida o seu banco. O módulo que estiver
com as tabelas é chamado de back-end, este fica
armazenado na sua pasta da rede, ou melhor, no
servidor. O módulo com as consultas, formulários e
relatórios chama-se front-end, este pode ser copiado e
colado em cada máquina de usuário.

Uma outra opção é utilizar o recurso de Réplicas. Com


este recurso você sincroniza os dados de toda a rede
como administrador. Para utilizar este recurso você terá
que adicionar os comandos Criar Réplica e Sincronizar,
Sincronizar Agora e Sincronizar Tudo pelo botão
Opções do Access, Personalizar Faixa de Opções, Todos

303
Os Comandos e adicioná-los à sua barra de ferramentas,
Guias Principais. Após a replicação, isto é, a geração de
cópias de seu bd na rede, a cada alteração ou inclusão de
registros, clique em Sincronizar Agora.

Poderão ocorrer conflitos caso em que um mesmo campo


for preenchido por usuários diferentes, prevalescerá o
mais recente. Em dado momento surgirá a opção de você
tornar o seu bd como Design Mestre. Esta opção não
estará disponível nas outras réplicas a partir de então.
Mas você como administrador poderá também tornar uma
réplica como Design Mestre ou Administrador. Veja este
passo-a-passo da Microsoft de como resolver conflitos de
sincronização de dados na rede:

1. Inicie o Visualizador de conflitos de replicação da


Microsoft usando uma destas etapas:

Abra o banco de dados no qual você deseja


verificar os conflitos. Se houver conflitos, o
programa perguntará se você deseja resolvê-los.
Clique em Sim para continuar.

No menu Ferramentas, aponte para Replicação e,


em seguida, clique em Resolver conflitos.

2. No Visualizador de conflitos, selecione, na lista,


uma tabela que tenha conflitos e clique em Exibir.

304
3. Para cada conflito mostrado no Visualizador de
conflitos, escolha uma destas opções:

Para manter os dados na Réplica 1, clique em


Manter dados existentes.

Para modificar os dados na Réplica 1 e copiá-los


para a Réplica 2 na próxima sincronização, clique
em Manter dados revisados.

Para manter os dados na Réplica 2 e sobrescrever


os dados na Réplica 1 na próxima sincronização,
clique em Sobrescrever com dados conflitantes.

Para modificar os dados na Réplica 2 e


sobrescrever os dados na Réplica 1 na próxima
sincronização, clique em Sobrescrever com
dados revisados.

4. Clique em Resolver.
5. Repita as etapas 3 e 4 quantas vezes forem
necessárias para resolver cada conflito da tabela.

Em casos mais complexos em redes bem distribuídas por


todo um prédio por exemplo, utilize o Visual SourceSafe
com o Access 2010 com a guia Source Control (Controle
de Origem). É possível desenvolver bloqueando os
objetos, fazendo check-out e check-in, comparar versões
dos N objetos, módulos, etc.

305
Você não consegue editar o mesmo arquivo, mas
consegue fazer isso em dois locais diferentes da rede, e o
Source Safe comita as alterações em ambos os arquivos
quando você solicitar.

AVALIAÇÃO:

1 – Crie um código que filtre o nome de um bairro


utilizando uma inputBox

2 – Crie um código que filtre o nome de um bairro


utilizando uma combobox e a propriedade Column.

3 – Crie uma função para extrair a raiz quadrada de


qualquer número (variável) de uma caixa de texto do
formulário. Utilize a função sqr. Chame a
função(Raiz_Quadrada) com o código deste botão.
Private Sub cmdRaiz_Click()
Dim resposta As Integer
resposta = txtValor „Nome de sua caixa de texto
Call Raiz_Quadrada(resposta)
End Sub

4 – Crie uma função para elevar a potência de


qualquer número (variável) de uma caixa de texto do
formulário. Utilize a função (^). Chame a
função(CalculaPotenciacao) com o código deste
botão.

306
Private Sub cmdPotencial_Click()
Dim x As Integer
Dim y As Integer
Call CalculaPotenciacao(x, y)
End Sub

5 – Crie uma função para calcular o M.D.C. de


qualquer número (variável) de uma caixa de texto do
formulário. Chame a função CalculaMDC(X,Y) com o
código deste botão.
Private Sub cmdMDC_Click()
Dim x As Integer
Dim y As Integer
Call CalculaMDC(x,y)
End Sub

6 – Crie uma função para calcular o M.M.C. de


qualquer número (variável) de uma caixa de texto do
formulário. Chame a função CalculaMMC(X,Y) com o
código deste botão.
Private Sub cmdMDC_Click()
Dim x As Integer
Dim y As Integer
Call CalculaMMC(x,y)
End Sub

307
7 - Estude o seguinte código de um botão. Faça em
seguida um código semelhante que informe através
de uma MsgBox algumas informações de registros de
uma tabela Clientes, por exemplo:

Private Sub cmdUsuario_Click()


On Error Resume Next
Dim i As Integer
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strTitle As String
Dim strMsg As String
Dim intRetVal As Integer „intRetVal é uma
variável de retorno
Dim count As Integer
Dim diferenca As Integer
Dim dif As String
Dim totalOS As Integer
Dim totalCump As Integer
Dim DIFER As Integer
Dim NomeU As String

NomeU = InputBox("Digite o Nome do Usuário: ",


"Controle de Ordem de Serviço")

Set db = CurrentDb()
Set rs = db.OpenRecordset("SELECT * FROM tbl_OS
WHERE NOME = '" & NomeU & "' ORDER BY
DIASSATUALIZAÇÃO DESC")

308
For i = 1 To rs.RecordCount „Método para
contagem total de registros. Retorna o número
máximo de registros da tabela ou recordset

„Verifique se os campos DATAEXECUCAO e


EXECUTADA estão nulos ou em branco, caso
contrário execute. Sempre é bom fazer essa
verificação para se ter um retorno de dados
If Not IsNull(rs.Fields("DATAEXECUCAO")) Or
rs.Fields("EXECUTADA") = -1 Then
strTitle = "CONTROLE DE ORDENS DE SERVIÇO -
ANÁLISE CRÍTICA"

count = count + 1 „Variável Contador que


marcará a passagem de registro na navegação

DIFER = Abs(DateDiff("d",
rs.Fields("DATASOLICITACAO"),
rs.Fields("DATAEXECUCAO")))
diferenca = Abs(DateDiff("d",
rs.Fields("DIASSATUALIZAÇÃO"),
rs.Fields("PRAZO")))

„A função Abs converte um possível valor ou resultado


negativo em positivo
„vbCrLf é uma constante do Vb que junta o comando CR (
Carriage Return - chr(13)) com o LF (Line Feed - Chr(10) . Sua
função é quebrar ou pular para a outra linha.

strMsg = "O.S DE No: " & count & vbCrLf &


vbCrLf & "MATRÍCULA:" & rs.Fields("MATRÍCULA")

309
& "" & vbCrLf & "O.S." &
rs.Fields("ORDEMDESERVICO") & vbCrLf & _
"DATA DA SOLICITAÇÃO: " &
rs.Fields("DATASOLICITACAO") & vbCrLf & "DATA
DA EXECUÇÃO: " & rs.Fields("DATAEXECUCAO") & _
vbCrLf & "TIPO DE SERVIÇO: " &
rs.Fields("TIPODESERVICO") & vbCrLf & "OBS: " &
rs.Fields("OBS") & vbCrLf & "PRAZO(DIAS): " &
rs.Fields("PRAZO") & vbCrLf & _
"DIAS DECORRIDOS: " & DIFER & vbCrLf & "PRAZO
EXTRAPOLADO? " & IIf(rs.Fields("PRAZO") >=
DIFER, "NÃO", "SIM") & _
vbCrLf & vbCrLf &
"**********************************************
" & vbCrLf & IIf(rs.Fields("PRAZO") >= DIFER,
"PARABÉNS, ", "ATENÇÃO, RISCO DE MULTA ") &
rs.Fields("NOME") & " !!!" & vbCrLf & _
"**********************************************
" & vbCrLf & "RELATÓRIO GERAL: " & vbCrLf &
vbCrLf & _
"O.S. NÃO EXECUTADAS: " & dif & vbCrLf & _
"O.S. EXECUTADAS: " & totalCump & vbCrLf &
"TOTAL DE O.S.: " & totalOS & vbCrLf & _
"**********************************************
intRetVal = MsgBox(strMsg, vbOKCancel +
IIf(rs.Fields("PRAZO") >= DIFER, vbInformation,
vbCritical), strTitle)
Select Case intRetVal
Case vbOK
Case vbCancel
Exit Sub

310
End Select

Else
strTitle = "CONTROLE DE ORDENS DE SERVIÇO -
ANÁLISE CRÍTICA"
count = count + 1
diferenca = Abs(DateDiff("d",
rs.Fields("DIASSATUALIZAÇÃO"),
rs.Fields("PRAZO")))
dif = DCount("[ORDEMDESERVICO]", "tbl_OS",
"[EXECUTADA] = 0")
'dif = DCount("*", "cnsExecutada") ' Também é
válida
totalOS = DCount("*", "tbl_OS")
totalCump = totalOS - dif
strMsg = "O.S DE No: " & count & vbCrLf &
vbCrLf & _
"O.S.: " & rs.Fields("ORDEMDESERVICO") & "" &
vbCrLf & "MATRÍCULA: " & rs.Fields("MATRÍCULA")
& " " & vbCrLf & _
"DATA DA SOLICITAÇÃO: " &
rs.Fields("DATASOLICITACAO") & vbCrLf & "DATA
DA EXECUÇÃO: " & rs.Fields("DATAEXECUCAO") &
vbCrLf & _
"TIPO DE SERVIÇO: " &
rs.Fields("TIPODESERVICO") & vbCrLf &
"DAE/ÓRGÃO: " & rs.Fields("DAEORGAO") & vbCrLf
& "DIAS SEM ATUALIZAÇÃO: " &
rs.Fields("DIASSATUALIZAÇÃO") & vbCrLf & _

311
"**********************************************
" & vbCrLf & "PRAZO(DIAS): " &
rs.Fields("PRAZO") & vbCrLf & _
"DIAS ATÉ/EXCEDENTES O/AO PRAZO: " & diferenca
& vbCrLf & "PRAZO EXTRAPOLADO? " &
IIf(diferenca > rs.Fields("PRAZO"), "SIM",
"NÃO") & vbCrLf & _
IIf(diferenca > rs.Fields("PRAZO"), "ATENÇÃO,
RISCO DE MULTA ", "MUITO BEM ATÉ AGORA, FAVOR
ACOMPANHAR ") & rs.Fields("NOME") & vbCrLf & _
"**********************************************
" & vbCrLf & "RELATÓRIO GERAL: " & vbCrLf &
vbCrLf & _
"O.S. NÃO EXECUTADAS: " & dif & vbCrLf & _
"O.S. EXECUTADAS: " & totalCump & vbCrLf &
"TOTAL DE O.S.: " & totalOS & vbCrLf & _
"**********************************************
" & vbCrLf & "AVISO !!! " & vbCrLf & "USUÁRIO:
" & rs.Fields("NOME") & vbCrLf & _
"CASO ESTA O.S. AINDA NÃO TENHA SIDO EXECUTADA
" & vbCrLf & "OU JÁ TENHA SIDO BAIXADA,CONTATE
O DAE/ÓRGÃO, " & vbCrLf & _
"VERIFIQUE AS CAUSAS, ANALISE-AS COM CUIDADO "
& vbCrLf & "EM BUSCA DE UMA SOLUÇÃO E ABRA UMA
NOVA O.S. !!! " & vbCrLf & _
"ESTA O.S. PRECISA SER EXECUTADA !!!"
intRetVal = MsgBox(strMsg, vbOKCancel +
IIf(diferenca > rs.Fields("PRAZO"), vbCritical,
vbInformation), strTitle)

Select Case intRetVal

312
Case vbOK
Case vbCancel
Exit Sub
End Select
End If
rs.MoveNext
Next i
End Sub

313
CAPÍTULO 4 – DOMINANDO O ACCESS VBA II
(RELATÓRIOS)

A sequência mais prática para se criar um relatório é


utilizando o Assistente do Access.

Pelo assistente é possível selecionar-se a tabela/consulta


que vai ser a base de dados, presente na Fonte do
Registro, na aba Dados pelo modo Propriedades do
relatório após ter sido criado. Vamos seguir o passo-a-
passo da criação de um relatório com o aplicativo Clubes.
Mantenha a tecla SHIFT pressionada e abra o aplicativo.

314
(1) Na barra de ferramentas, clique na aba Criar,
Assistente de Relatório. Selecione a tabela tblAtletas e
clique no botão >>. Em seguida, clique no botão Avançar.

(2) Utilize os botões (>) para selecionar campo por


campo, respeitando a sua ordem de alinhamento ou todos
os campos de uma vez pelo botão (>>).

315
(3) Em resposta à pergunta Deseja adicionar algum
nível de agrupamento?, selecione o campo
CódigodoAtleta e clique no botão com o sinal gráfico (>).

316
A partir daí você pode determinar se seu relatório será
visualizado com destaque no código do atleta ou nome
do clube, etc.

Em um relatório você pode realizar operações


matemáticas do tipo: somar campos com valores
numéricos do tipo inteiro ou duplo com duas casas
decimais, contar campos do tipo texto, etc. otimizando o
desempenho do aplicativo e assim, evitando recorrências
desnecessárias às tabelas tornando pesado e lento o seu
desempenho.

Problema dado: Calcular o total de pontos de cada


competidor em um concurso de pesca ao final de 3 (três)
etapas e o total geral de todos os competidores.

317
Como isso foi feito?

318
Observe que as caixas de texto para os sub-totais foram
colocadas abaixo do Cabeçalho do código(MasterID)
correspondente a cada competidor que por sua vez está
um nível acima de todos os outros campos do relatório.
Como isto foi feito?

319
CRIANDO RELATÓRIOS COM NÍVEIS E
AGRUPADOS

Ao utilizar o assistente de relatório, na etapa que surge a


pergunta “Deseja adicionar algum nível de agrupamento?
Escolha o campo Código ou neste caso MasterID. Veja o
exemplo:

320
Siga o passo-a-passo do assistente selecione o nome da
escola com um nível acima. Pronto, agora vamos contar o
número de servidores da escola. Observe o modo
Estrutura do formulário acima. Coloque uma caixa de
texto no cabeçalho referente ao campo que está um nível
acima e na fonte de controle =Contar(*) , para obtermos a
contagem do número de PROFESSORES por NOME DA
ESCOLA, isto é, por grupos.

321
Simples, não? Para somar valores por grupos, coloque :

=Soma([NomedoCampo])

Na fonte de controle da sua caixa de texto disposta no


rodapé desse mesmo campo, coloque a fórmula acima.
Na aba Dados, Soma Parcial, selecione Por grupo ou
Total, para você obter resultados por página do relatório.

Não deixe de alterar o formato do campo, neste caso,


para Moeda, com 2(duas) casas decimais .

Para ordenar em ordem alfabética os items de cada


grupo, abra o relatório pelo modo Design(Estrutura),
clique com o botão direito do mouse sobre o campo e
selecione Classificar em Ordem Crescente.

322
CRIANDO RELATÓRIOS COM CAMPO
CALCULADO
Já a caixa de texto(Total) está no cabeçalho do relatório.
Como é feito o cálculo dos sub-totais? Como é feito o
cálculo do total? Isso você vai aprender após estudar as
funções DLookup(DPesquisa) e DSum(DSoma).

Caso você já saiba utilizar estas funções, veja como ficou


a sintaxe de busca e soma dos valores inerentes a esses
campos em referência para serem somados nesse
exemplo abaixo. Na fonte de controle do campo
txtTotalporNome correspondente à coluna Peso:
=DPesquisa("Nome";"Cadastro_Geral";"MasterID =
Reports!CalculaPontos!MasterID")

323
No campo txtTotalIndividual correspondente à coluna
Pontos ficou assim:
=DSoma("Pontos";"CalculaPontos";"MasterID =
Reports!CalculaPontos!MasterID")

324
No campo txtTotal ficou assim:
=DSoma("Pontos";"CalculaPontos")

325
IMPRESSÃO DE RELATÓRIOS VIA ACCESS
VBA*

Vamos nos basear no excelente tutorial de Dev Ashish.

Use o método Printout do objeto DoCmd:.

DoCmd.PrintOut [printrange][, pagefrom, pageto] _


[, printquality][, copies][, collatecopies]

Por exemplo, se eu quero imprimir duas cópias da


primeira página de um relatório, eu codificaria assim:
DoCmd.OpenReport "rptCustomers", acViewPreview
ou
DoCmd.PrintOut acPages, 1, 1, , 2

326
Ou então como colocado por Alex Dybenko, o seguinte
método que não exige que o relatório seja aberto no modo
Preview.

DoCmd.SelectObject acReport, "rptCustomers",


True

Este comando imprime duas cópias do relatório

DoCmd.PrintOut , , , , 2

No Access 2.0 o equivalente é Docmd Print

Naturalmente, surgirão ocasiões que desejaremos


imprimir uma página apenas do relatório ou registro
específico.

Vamos supor que agora você queira imprimir uma


relatório de um determinado cliente pelo seu código de
fatura.
DoCmd.OpenReport “rptFaturadoCliente”,
acViewPreview, , "codFatura = " &
Me.codFatura

DoCmd.PrintOut , , , , 1

Supõe-se que neste caso acima seu relatório se baseie


em uma tabela ou consulta que tenha um campo
chamado codFatura e que o formulário onde está o seu
botão também tenha um campo chamado codFatura.

327
Finalmente se o relatório que você deseja imprimir venha
a diferir dependendo das circunstâncias, você pode
substituir o nome do relatório com uma simples variável
como está demonstrado no código abaixo:
Private Sub btnImprimeDoc_Click()
Dim strNomeDoc as String

If Me.Comerciante = True Then


strNomeDoc = "rptFaturadoComerciante"
DoCmd.OpenReport strDocName,
acViewPreview, , "codFatura = " &
Me.codFatura
DoCmd.PrintOut , , , , 2
Exit Sub
Else
strNomeDoc = "rptFaturadoCliente"
DoCmd.OpenReport strNomeDoc,
acViewPreview, , "codFatura = " &
codFatura
DoCmd.PrintOut , , , , 2
Exit Sub
End If

End Sub

328
________

*Este excelente estudo sobre impressão foi traduzido e adaptado por


mim do site:

http://www.creativeconnections.co.uk/index.php/microsoft-access/192-
how-to-automatically-print-out-an-access-report-using-vba

CRIANDO RELATÓRIOS DO TIPO ÁLBUM


POR CATEGORIA
Primeiro, crie uma tabela exemplo com os seguintes
campos, Código(Numeração Automática), Categoria do
tipo combobox com três categorias (Ex.: cama, mesa e
banho). Para isso, você pode utilizar ou o assistente de
pesquisa ou abrir a segunda aba Pesquisa e incluir os
seus valores de categoria na origem de linha. Veja a
figura abaixo:

329
Utilize o assistente do relatório e classifique os campos
com as fotos por categoria, pela divisão por nível; em
seguida, layout por Estrutura de Tópicos e, por último,
orientação paisagem. O Access só aceita figuras com
extensão (.bmp). Daí você teria que converter todas as
fotos(.jpg, png, etc.) para esta extensão(.bmp) primeiro
antes de continuar.

330
AVALIAÇÃO:

(1) Crie um relatório com base nos dados implantados


em sua tabela que fique da seguinte forma*:

331
______
* Os dados naturalmente podem ser diferentes

(2) Crie um relatório com base nos dados implantados em


sua tabela que fique da seguinte forma*:

332
Assim, estamos concluindo este livro de fundamentos do
Access VBA para que você passe agora para o meu outro
livro Técnicas Especiais de Access VBA que abordam ou
aplicam com mais profundidade tudo o que foi estudado
neste livro e com fins mais profissionais. Para quem
deseja estudar Ciência da Computação sugiro adquirir
meu mais recente livro Engenharia de Software com
Access VBA.

Espero, com sinceridade, que você tenha gostado dos


princípios apresentados e que de alguma maneira o tenha
ajudado na sua formação ou profissão e que também,
venham a torná-lo(a) um(a) profundo(a) conhecedor(a) ou
especialista, se você se dedicar, em Access VBA.

333