Microsoft© Access Avançado
Microsoft© Access Avançado INDICE 1. INTRODUÇÃO ....................................................................................................................6 1.1. ARQUITETURA DE UMA APLICAÇÃO MS ACCESS...............................................7 EXERCÍCIOS DE FIXAÇÃO – INTRODUÇÃO ............ERRO! INDICADOR NÃO DEFINIDO. 2. PROGRAMAÇÃO NO MS ACCESS ................................................................................9 2.1. MACRO X MÓDULO ..........................................................................................................9 2.2. MÓDULOS .......................................................................................................................11 2.3. QUANDO USAR PROGRAMAÇÃO ......................................................................................12 2.4. MÓDULO PADRÃO ...........................................................................................................13 2.5. MÓDULO DE CLASSE EM FORMULÁRIOS E RELATÓRIOS ...................................................13 2.6. MÓDULO DE CLASSE .......................................................................................................14 2.7. SEÇÃO DE DECLARAÇÕES ................................................................................................15 2.8. SEÇÃO DE PROCEDIMENTOS ............................................................................................15 2.9. O EDITOR DE CÓDIGO ......................................................................................................16 2.9.1. Cores de código ......................................................................................................17 2.9.2. Opções de codificação............................................................................................17 2.9.3. Configurações da janela.........................................................................................18 2.10. JANELAS DO EDITOR DE CÓDIGO DO ACCESS .................................................................18 2.10.1. Janela de Código ..................................................................................................19 2.10.2. Janela Depurar.....................................................................................................19 2.10.3. Janela Pesquisador de Objetos ............................................................................21 PRÁTICA 2 – PROGRAMAÇÃO NO MS ACCESS ..........................................................23 EXERCÍCIO 1 – Criando um módulo padrão..................................................................23 EXERCÍCIO 2 – Criando um módulo de classe em formulário.......................................23 EXERCÍCIOS DE FIXAÇÃO – PROGRAMAÇÃO NO MS ACCESS .. ERRO! INDICADOR NÃO DEFINIDO. 3. PROCEDIMENTOS EM MÓDULO PADRÃO .............................................................24 3.1. COMPILAÇÃO DE MÓDULO ..............................................................................................26 3.2. TESTE DE EXECUÇÃO DE PROCEDIMENTO EM MÓDULO PADRÃO ......................................27 3.3. EXECUÇÃO PASSO-A-PASSO ............................................................................................27 3.4. INSPEÇÃO DE VARIÁVEIS .................................................................................................28 3.5. PONTO DE INTERRUPÇÃO ................................................................................................29 3.6. CHAMADA DE PROCEDIMENTOS ......................................................................................30 3.6.1. Passagem de Argumentos.......................................................................................31 3.6.2. Retorno de Valor ....................................................................................................31 3.6.3. Passagem de Argumentos por Valor e por Referência...........................................33 PRÁTICA 3 – CRIAÇÃO DE MÓDULO PADRÃO .......ERRO! INDICADOR NÃO DEFINIDO. EXERCÍCIO 1 – Criando um procedimento para cálculo de fatorialErro! Indicador não definido. EXERCÍCIOS DE FIXAÇÃO – CRIAÇÃO DE MÓDULO PADRÃO.... ERRO! INDICADOR NÃO DEFINIDO. 4. MÓDULO DE CLASSE EM FORMULÁRIO/RELATÓRIO ......................................35
Reprodução proibida
Microsoft© Access Avançado INDICE 4.1. COLEÇÕES E OBJETOS DE FORMULÁRIO/RELATÓRIO ......................................................36 4.2. PROPRIEDADES E MÉTODOS ............................................................................................38 4.3. COLEÇÃO PADRÃO E PROPRIEDADE PADRÃO ...................................................................39 4.4. PROPRIEDADES DE COLEÇÃO ..........................................................................................39 4.5. SEÇÕES DE FORMULÁRIO/RELATÓRIO ............................................................................40 4.6. EVENTOS DE FORMULÁRIO .............................................................................................40 EXERCÍCIOS DE FIXAÇÃO – MÓDULO DE CLASSE EM FORMULÁRIO/RELATÓRIO ........................................ERRO! INDICADOR NÃO DEFINIDO. 5. ELEMENTOS DE PROGRAMAÇÃO ............................................................................42 5.1. VARIÁVEIS..................................................................................................................42 5.1.1. Declaração .............................................................................................................42 5.1.2. Atribuição de valores à variáveis ...........................................................................44 5.2. CONSTANTES .............................................................................................................45 5.2.1. Constantes Simbólicas............................................................................................45 5.2.2. Constantes Intrínsecas............................................................................................45 5.2.3. Constantes Definidas pelo Sistema.........................................................................46 5.3. VETORES E MATRIZES .............................................................................................47 5.4. TIPOS DEFINIDOS PELO USUÁRIO .........................................................................48 5.5. ESTRUTURA DE REPETIÇÃO ...................................................................................48 5.5.1. For..Next.................................................................................................................48 5.5.2. Do..Loop .................................................................................................................49 5.5.3. While..Wend............................................................................................................50 5.5.4. For Each..Next........................................................................................................50 5.6. ESTRUTURA CONDICIONAL ...................................................................................51 5.6.1. If...Then...Else.........................................................................................................51 5.6.2. Select Case..............................................................................................................52 5.7. ENTRADA E SAÍDA DE DADOS ...............................................................................53 5.7.1. Funções do VBA para entrada e saída...................................................................54 5.7.2. Outros dispositivos de entrada e saída...................................................................55 5.8. COMENTÁRIOS...........................................................................................................56 5.9. FUNÇÕES .....................................................................................................................56 5.10. ESCOPO DE IDENTIFICADORES............................................................................57 5.11. OBJETO DOCMD .........................................................................................................58 6. LINGUAGEM SQL............................................................................................................59 6.1. EXPRESSÃO SQL ........................................................................................................60 6.2. INSTRUÇÕES BÁSICAS SQL.....................................................................................61 6.2.1. CONSULTA SELEÇÃO ...................................................................................................61 6.2.1.1. Argumento Predicado..........................................................................................63 6.2.1.2. Expressões na lista de campos ............................................................................65 6.2.1.3. Argumento Expressãodetabela ............................................................................66 6.2.1.4. Tabelas em banco de dados externos ..................................................................68 6.2.1.5. Cláusula Where ...................................................................................................68
Reprodução proibida
Microsoft© Access Avançado INDICE 7. FORMULÁRIOS AVANÇADOS .....................................................................................74 7.1. FORMULÁRIO DE MANUTENÇÃO DE TABELAS.................................................74 7.1.1. Botões de Navegação Personalizados....................................................................74 7.2. CAIXA DE DIÁLOGO..................................................................................................76 7.2.1. Passagem De Parâmetros Para Procedimento ......................................................77 7.2.2. Passagem De Parâmetros Para Consulta Parametrizada .....................................77 7.2.3. Passagem De Parâmetros Para Relatório .............................................................78 7.2.4. Passagem De Parâmetros Para Formulário..........................................................81 7.3. FORMULÁRIO DE CONSULTA.................................................................................83 7.4. CAIXA DE MENSAGEM .............................................................................................87 8. ACESSO A BANCO DE DADOS .....................................................................................89 8.1. HIERARQUIA DO OBJETOS DAO .....................................................................................89 8.2. SINTAXE PARA REFERENCIAR OBJETOS EM COLEÇÃO ....................................................90 8.3. COLEÇÃO PADRÃO..........................................................................................................91 8.4. REFERÊNCIA A OBJETOS POR MEIO DE VARIÁVEIS ..........................................................91 8.5. PROPRIEDADES E MÉTODOS ............................................................................................91 8.6. ACESSO A BANCO DE DADOS ACCESS ............................................................................93 8.7. ACESSO A BANCOS DE DADOS EXTERNOS ......................................................................96 8.7.1. Vinculação de Tabelas Externas ............................................................................96 8.7.2. Abertura Direta de Tabelas Externas...................................................................100 9. ACESSO A ARQUIVOS E IMPRESSORA ..................................................................103 10. TRATAMENTO DE ERRO ..........................................................................................105 10.1. DESVIO PARA ROTINA DE TRATAMENTO DE ERRO .......................................................106 10.1.1. Tratar o erro e terminar o programa .................................................................106 10.1.2. Tratar o erro e voltar à execução na mesma linha do erro ...............................106 10.1.3. Tratar o erro e voltar à execução na linha seguinte à linha de erro .................107 10.1.4. Tratar o erro e desviar a execução para outro rótulo. ......................................107 10.1.5. Prosseguir o programa após erro ......................................................................108 10.1.6. Evento Erro.........................................................................................................108 10.2. DEPURAÇÃO DO PROGRAMA .......................................................................................109 11. AUTOMAÇÃO ...............................................................................................................111 11.1. AUTOMAÇÃO COM O MICROSOFT WORD ...................................................................112 Hierarquia dos Objetos do Microsoft Word ..................................................................113 11.2. AUTOMAÇÃO COM O MICROSOFT EXCEL ..................................................................113 Hierarquia do Objetos do Microsoft Excel ...................................................................113 Detalhamento do Objeto Worksheets .............................................................................114 Detalhamento do Objeto Charts.....................................................................................115 Detalhamento do Objeto Chartgroups ...........................................................................115 11.3. AUTOMAÇÃO COM MICROSOFT PROJECT ...................................................................121 Hierarquia dos Objetos do Microsoft Project ...............................................................121
Reprodução proibida
Microsoft© Access Avançado INDICE 11.4. AUTOMAÇÃO COM SCHEDULE+ .................................................................................122 Hierarquia dos Objetos do Schedule..............................................................................123 11.5. REFERÊNCIA À BIBLIOTECA DE OBJETOS ......................................................123 12. CHAMADA À API DO WINDOWS 95 .......................................................................126 13. SEGURANÇA.................................................................................................................132 13.1. SENHA DE BANCO DE DADOS ............................................................................132 13.1.1. DEFININDO UMA SENHA PARA O BANCO DE DADOS .............................132 13.1.2. ABRINDO UM BANCO DE DADOS PROTEGIDO POR SENHA....................133 13.1.3. REMOVENDO SENHA DE BANCO DE DADOS .............................................133 13.1.4. DEFININDO SENHA POR CÓDIGO VBA........................................................133 13.1.5. ABRINDO UM BANCO DE DADOS PROTEGIDO VIA CÓDIGO VBA..........134 13.1.6. ALTERANDO A SENHA VIA CÓDIGO VBA.....................................................134 13.2. CRIAÇÃO DE ARQUIVO MDE ..............................................................................135 13.3. CRIPTOGRAFIA DE BANCO DE DADOS.............................................................137 13.3.1. CRIANDO UM ARQUIVO CRITPTOGRAFADO..............................................138 13.3.2. REVERTENDO A CRITPTOGRAFIA ................................................................138 13.3.2. CRIPTOGRAFIA POR CÓDIGO VBA...............................................................138 13.4. SEGURANÇA EM NÍVEL DE USUÁRIO...............................................................138 13.4.1. PROPRIEDADE SOBRE O BANCO DE DADOS E OBJETOS ........................139 13.4.2. IMPLEMENTANDO SEGURANÇA EM NÍVEL DE USUÁRIO........................139 13.4.2. LOGON POR CÓDIGO VBA .............................................................................144 13.4.3. TROCA DE SENHA VIA CÓDIGO VBA............................................................144 13.4.4. RETIRAR PEMISSÃO DE CRIAR NOVOS BANCOS DE DADOS ...................146 13.4.5. RETIRAR PEMISSÃO DE CRIAR NOVAS TABELAS E CONSULTAS.............146 ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT ..........................................................147 MICROSOFT ACCESS .....................................................................................................148 Hierarquia dos objetos do Access ..................................................................................148 Tags para objetos da janela de banco de dados do ACCESS ........................................148 Tags para objetos controles do ACCESS .......................................................................148 Tags para variáveis do ACCESS ....................................................................................149 DATA ACCESS OBJECTS - DAO....................................................................................149 Hierarquia dos objetos DAO para Microsoft Jet Workspaces.......................................149 Hierarquia dos objetos DAO para ODBCDirect Workspaces .......................................150 Tags para Data Access Objects - DAO ..........................................................................150 MICROSOFT VISUAL BASIC 5.0 ...................................................................................151 Tags para controles do Visual Basic..............................................................................151 MICROSOFT VISUAL BASIC FOR APPLICATION - VBA ..........................................151 Tags para variáveis do Visual Basic for Application.....................................................151
Reprodução proibida
Microsoft© Access Avançado
1. INTRODUÇÃO No MS Access, você armazena dados em tabelas e recupera informações por meio de consultas, de forma interativa diretamente na janela de Banco de Dados. Esta forma de trabalhar exige do usuário final um alto nível de conhecimento do MS Access. Em vez de acessar diretamente as tabelas e consultas, você pode construir uma interface com formulários e relatórios. No curso básico, você usa inicialmente os Assistentes e depois pode construir os formulários e relatórios manualmente no modo Estrutura. Esta forma de criar aplicativos atende a problemas simples de cadastramento e recuperação de dados e exige que o usuário final tenha apena um conhecimento superficial do MS Access. Com o tempo, você sente necessidade de o aplicativo dar maior controle no tratamento dos dados e que a interface seja mais segura e simples de usar, não exigindo que o usuário final tenha de saber o MS Access para operar o aplicativo. Torna-se necessário então desenvolver aplicações usando programação dentro do MS Access. Este curso ensinará a programação do MS Access , utilizando a linguagem Visual Basic for Application – VBA, para que você desenvolva aplicativos completos no MS Access. A Microsoft dispõe de três edições da linguagem Visual Basic:
Visual Basic - VB Visual Basic for Application – VBA Visual Basic Scripting – VBScript
A primeira é a linguagem completa, feita para desenvolver aplicativos profissionais. Ela gera um programa executável que pode ser instalado em qualquer PC com Windows, sem a necessidade de o Visual Basic estar instalado. Alguns dos recursos que só existem no VB é a possibilidade de desenvolver aplicativos cliente/servidor que acessa bancos de dados relacionais, como o Microsoft SQL Server ou Oracle, e a criação de componentes ActiveX, atualmente chamados de componentes COM (Component Object Model). A linguagem Visual Basic é suportada no software Microsoft Visual Basic. O VBA possui alguns recursos a menos que o VB, mas a sintaxe é idêntica. O VBA é uma linguagem embutida nos aplicativos Microsoft Office (exceto o Outlook) e no Microsoft Project 98. Não é possível gerar um programa executável. Ela é uma linguagem interpretada que depende do Microsoft Office instalado ou o Microsoft Project 98. A linguagem Visual Basic é o recurso que integra as melhores características de cada aplicativo do MS Office. Por meio de programação, VB, VBA ou VBScript, é possível construir uma interface única em um único aplicativo, como por exemplo o Access, e acessar todos os recursos especializados dos demais integrantes do pacote Office ou mesmo do Back Office. Esta técnica é conhecida como Automação, que veremos neste curso. O VBScript é a versão mais simples do Visual Basic usado principalmente na confecção de páginas WEB. Ele é suportado nos seguintes produtos:
MS Outlook MS SQL Server Windows Scripting Host MS Internet Explorer 3 ou superior
6
Microsoft© Access Avançado Vários softwares não Microsoft também suportam o VBScript para automatizar tarefas.
1.1. ARQUITETURA DE UMA APLICAÇÃO MS ACCESS Um banco de dados MS Access é um conjunto de componentes do tipo Tabela, Consulta, Formulário, Relatório, Macro e Módulo. A tendência natural ao se desenvolver uma aplicação no MS Access é criar todos os componentes em um só banco de dados, ou seja, ter um único arquivo .MDB. O fato de ter tudo em um é conveniente, pois você instala apenas um arquivo no computador e pode transportá-lo facilmente para qualquer outro computador, sem se preocupar em que disco ou pasta ele será gravado. Aplicações profissionais, entretanto, não possuem esta arquitetura tudo-em-um. Um sistema de informação é composto por dois pilares básicos: os dados e os processos. Mesmo na era do CA-Clipper havia distintamente dois tipos de arquivos: o executável (.EXE) representanto os processos e os arquivos de dados de extensão .DBF. Neste caso, ambos fazem parte de um mesmo software e atendem a um mesmo padrão, o xBase. Com a evolução da informática, processos e dados tiveram softwares e padrões distintos. Você pode escrever seus processos (programar) em um software e armazenar os dados em outro formato, gerenciado por outro software. Um exemplo disto é o MS Visual Basic e o MS SQL Server. O programa é escrito e compilado no MS Visual Basic enquanto os dados podem ficar armazenados no e ser gerenciados pelo MS SQL Server. Atualmente, você pode ter vários fornecedores diferentes para criar processos e armazenar dados. Você pode escrever programas no MS Visual Basic ou Delphi e utilizar gerenciadores de banco de dados como MS SQL Server, Oracle, Interbase ou MS Access. Apesar de o MS Access se tudo-em-um, é recomendável separar dados de processos. Você deve criar a aplicação um arquivo .MDB com consultas, formulários, relatórios, macros e módulos e ter outro (ou outros) arquivos somente com tabelas. Por que isto? Os dados são a parte mais estável de uma aplicação. Você pode ter um processo em que os descontos variem de acordo com a política da empresa ou a época do ano, mas os dados terão uma estrutura mais perene. Não é difícil encontrar empresas com cadastro de clientes de anos atrás, mas que já tiveram várias formas de processar faturas, descontos e promoções. Mudar processos não causa grande impacto na aplicação, mas quando se altera a estrutura dos dados o trabalho é colossal, porque a alteração na estrutura deve preservar os dados e há a necessidade de se revisar e alterar os programas que acessam estes dados. Um bom exemplo é o que aconteceu com o chamado Bug do Ano 2000. O problema, aparentemente simples, era acrescentar dois dígitos no ano, mas a solução demandou muito tempo e dinheiro, envolvendo o mundo inteiro e não somente sistemas de computador. Além do mais, os dados normalmente são corporativos mas ficam agrupados por área funcional. Há dados da área de pessoal, da área de transporte, da área de engenharia, etc. É comum estes dados ficarem fisicamente distribuídos vários computadores e em formatos distintos. Portanto, uma aplicação em Access deve considerar que os dados estão distribuídos e em formatos distintos. Mesmo que seja uma aplicação simples, é uma boa prática separar dados de processos. 7
Microsoft© Access Avançado O MS Access pode acessar dados em formatos dBase, texto, Excel, Paradox, FoxPro e HTML via ISAM – Indexed Sequential Access Method e bancos de dados SQL Server, Oracle e outros via ODBC – Open Database Connectivity. Para tanto, você deve ter instalado os drivers apropriados no computador onde a aplicação rodará. Como dados estão separados, o MS Access provê formas de acessá-lo:
Vinculação de tabela Consulta de passagem (pass-through) Expressão SQL com a cláusula IN. Programação com DAO Programação com ODBC-API Programação com objetos de acesso a dados, como o RDO e ADO.
No modo interativo você vincula tabelas pelo menu Arquivo|Obter dados externos|Vincular tabela…. Esta é a forma mais simples de se trabalhar, pois tudo funciona como se as tabelas estivessem no mesmo banco de dados e você pode acessar qualquer formato suportado pelos drivers ISAM ou ODBC instalados no seu computador. É possível abrir tabelas vinculadas normalmente e criar consultas, formulário e relatórios baseados em tabelas vinculadas. Você verá neste curso como vincular tabelas via programação do DAO. A consulta de passagem é usada para obter dados provenientes de bancos de dados como o SQL Server. O Access interage diretamente com o servidor SQL Server, sem utilizar ODBC nem o mecanismo Jet. Este tipo de consulta não pode ser usada como origem de registro de formulário e relatório. Expressões SQL com cláusula IN se aplica criar consultas ou expressões SQL que acessam tabelas externas em formato Access, dBase, Excel, Parados, e outros formatos ISAM. Não pode ser usada como origem de registro de formulário e relatório. O DAO – Data Access Object é um objeto de acesso a dados utilizado na programação do MS Acccess e suportado também pelo MS Visual Basic. Veremos neste curso a sua programação. A programação ODBC-API, como o nome sugere, só é possível acessar dados em servidor de banco de dados por meio de programação em módulo. Neste tipo de programação, o Access despreza o seu mecanismo de acesso a dados, o Jet Engine, e interage diretamente com o gerenciador ODBC. Este assunto não faz parte deste curso. Programar diretamente via ODBC-API é trabalhoso. O RDO – Remote Data Object é uma camada entre o Access e o ODBC-API que torna a compreensão dos comandos mais fácil. Este curso não tratará deste assunto. ODBC-API e RDO são tecnologias em desuso. A última palavra em acesso a dados é o ADO- ActiveX Data Object, da Microsoft. Ele pode acessar vários formatos de dados, desde que você tenha um OLE-DB Provider. O MS Access suporta o ADO via programação em módulo, desde que você tenha este objeto instalado no seu computador o o OLE-DB Provider apropriado para o formato desejado. A vantagem é que o ADO acessa diretamente a fonte de dados, sem passar pelo mecanismo Jet nem por gerenciador ODBC. Não veremos o ADO neste curso.
8
Microsoft© Access Avançado
2. PROGRAMAÇÃO NO MS ACCESS 2.1. Macro x Módulo No MS Access, o termo macro designa ações pré-definidas dispostas sequencialmente. Para não-programadores, as macros podem ser usadas para operações simples, como abrir um formulário ou relatório, executar uma consulta ou acionar um item de menu. A chamada de macros por botões de comando em formulários e menus fornece ao aplicativo uma interface com certo grau de controle de navegação pelas telas e automação. Isto também restringe o acesso do usuário a recursos críticos do MS Access, tal como alterar a estrutura de uma tabela, e não exige do usuário um alto nível de conhecimento sobre o MS Access. Você pode criar botões de comando em formulários e associar macros que realizam ações pré-definidas. Por exemplo, o botão de comando cuja legenda é Cadastrar Livros invoca a macro Macro1. Na Macro1 existe uma ação AbrirFormulário que abre o formulário chamado frmCadastra_Livros.
A estrutura do formulário mostra que o evento do botão cmdCadastraLivros invoca a macro Macro1 através do evento Ao clicar.
9
Microsoft© Access Avançado
A manutenção de aplicativos baseados em macros é difícil, pois existem objetos distintos: o formulário e a macro. Para cada controle que possui evento associado haveria a necessidade de uma macro. A quantidade de objetos para gerenciar tornaria difícil a compreensão do fluxo de execução. Além disso, as macros não oferecem um bom controle de fluxo, pois não possuem estruturas de controle sofisticados como If..Then..Else e estruturas de repetição como Do While. A construção de aplicativos usando programação reduz a complexidade do fluxo porque a ação é codificada na própria estrutura do formulário. Os eventos de cada controle apontam para procedimentos escritos em um linguagem de programação poderosa – o Visual Basic for Application – que permite a criação de rotinas complexas e estruturadas. No exemplo a seguir, os dois controles invocam os procedimentos de evento cmdConsultaAutores_Click e cmdCadastraLivros_Click. Estes controles são botões de comando, cujas propriedades Ao clicar apontam para o código que se encontra na própria estrutura do formulário.
10
Microsoft© Access Avançado
A programação no MS Access torna o uso de macros obsoleta, pois tudo que as macros fazem a programação consegue fazer com maior grau de controle sobre o fluxo de execução. Portanto, não faz sentido neste curso ensinar como se constrói macros.
2.2. Módulos A programação no MS Access é feita nos módulos. Um módulo é uma coleção de declarações e procedimentos armazenados conjuntamente, formando uma unidade. As declarações são instruções que direcionam o comportamento dos procedimentos em todo um módulo.Um procedimento é uma unidade de código VBA que realiza uma operação específica. Por exemplo, o cálculo dos dígito verificador do CPF é um procedimento e o cálculo do fatorial de um número é outro. Os módulos podem estar alojados em três lugares:
Na guia Módulos da janela de Banco de Dados do MS Access. Nela existem dois tipos de módulos: módulo padrão e módulo de classe. Embutido em um formulário do Access. Contém módulo de classe. Embutido em um relatório do Access. Contém módulo de classe.
Cada módulo na guia Módulos recebe um nome único dentro do aplicativo (no mesmo arquivo .mdb). O nome deve seguir uma regra de nomenclatura:
Pode conter até 64 caracteres, entre letras e números Aceita espaços e caracteres especiais, exceto ponto, exclamação, acento grave, colchetes e caracteres de controle (código ASCII de 0 a 31). Aceita letras maiúsculas e minúsculas indistintamente. Não pode conter espaços no início do nome 11
Microsoft© Access Avançado É recomendável não usar espaços nem caracteres especiais e evitar nomes muito longos. O Anexo A sugere uma convenção de nomes a ser adotada no desenvolvimento de aplicativos com produtos Microsoft. Os módulos de classe em formulários e relatórios não recebem nomes, pois são gravados juntamente com o formulário ou relatório aos quais estão relacionados. O código de um módulo é composto por:
Instruções, funções e palavras-chave do VBA Nomes de variáveis, constantes ou procedimentos fornecidos pelo desenvolvedor Instruções e cláusulas da linguagem SQL Propriedades e métodos de objetos
As instruções, funções, palavras-chave, cláusulas, propriedades e métodos são palavras reservadas, ou seja, você não as pode usar como nome de procedimento ou nome de variável ou constante.
2.3. Quando usar programação No MS Access, usa-se programação em VBA:
Para efetuar um processamento complexo, que não pode ser atendido com a utilização de consultas, nem macros. Exemplo: O cálculo de faturamento exige ler todos os serviços prestados em um período, computar para, cada fatura, os descontos, multas, juros, impostos e taxas. Para criar funções definidas pelo usuário – UDF (User Defined Functions), por exemplo, o cálculo dos dígitos verificadores do CGC. Para percorrer um registro de cada vez. As consultas de seleção e de refer6encia cruzada retornam um conjunto de registros de uma vez só, mas ás vezes é necessário processar cada registro, seja de uma tabela ou de uma consulta. Sempre que se necessitar de usar estruturas de repetição e condição complexa (do tipo Do While e If...Then...Else). Para substituir macros por código VBA equivalente. As macros ficam armazenadas em pastas de macro (a quinta guia da janela Banco de Dados), mas podem ser chamadas de qualquer parte do Access. Ás vezes pode ficar difícil entender o emaranhado de chamadas a elas. Os módulos, por formarem uma unidade, são mais compreensíveis, podendo ainda ser impressas. Assim, o aplicativo pode ser construído de forma modular e concisa, melhorando assim a sua legibilidade e documentação. Para manipular objetos de outros softwares, como o Word e Excel, através da automação. Para realizar operações de DDE (troca dinâmica de dados), como por exemplo ler uma tela do Plenus (um emulador de terminal Unisys TB-27). Para efetuar transações com COMMIT e ROLLBACK.
12
Microsoft© Access Avançado
2.4. Módulo padrão Usa-se código em módulo padrão para criar procedimentos globais, isto é, aqueles que serão usados por todo o aplicativo. Por exemplo, uma função para transformar um número em extenso pode ser chamada em qualquer do aplicativo.. Os procedimentos armazenados em Módulo Padrão são do tipo Function (aquele que retorna um valor, por exemplo o fatorial de um número) ou Sub (aquele que não retorna valor, por exemplo, uma rotina para tratar e imprimir mensagens de erro na tela). Uma janela de código em módulo padrão possui as características mostradas abaixo.
2.5. Módulo de classe em formulários e relatórios Os módulos embutidos em formulário e relatórios são do tipo Módulo de Classe. São módulos que residem na estrutura dos formulários e relatórios, assim como os objetos de controle. Por ficarem atrás dos formulários e relatórios, são também chamados de code behind form. Os módulos de classe em formulário e relatório contêm procedimentos de evento, que respondem a eventos de formulário, relatório ou controle neles inseridos. Os procedimentos de evento em módulo de formulário respondem a eventos (tais como o clicar do mouse) do próprio formulário, de suas seções (cabeçalho, detalhe, rodapé) e dos controles. Os procedimentos de evento em módulo de relatório respondem a eventos do próprio relatório e de suas seções somente. Se se deseja que um evento em um formulário ou relatório acione um procedimento Function ou Sub de um módulo padrão, é preciso que o procedimento de evento dentro do módulo de formulário/relatório faça a chamada. O código abaixo é um procedimento de evento ligado ao controle cmdOkButton que chama um procedimento Sub armazenado em módulo padrão. 13
Microsoft© Access Avançado Private Sub cmdOkButton_Click() CalculaRateio() End Sub
Uma janela de código em módulo de classe embutido em formulário/relatório tem as características mostradas abaixo.
O módulo de classe em formulário ou de relatório também pode conter procedimentos Sub ou Function.
2.6. Módulo de classe O módulo de classe criado na guia Módulos da janela de Banco de Dados do Access tem como objetivo implementar as classes de objetos definidas pelo desenvolvedor, permitindo uma certa reusabilidade de código. Os formulários e relatórios são classes de objetos pré-definidos, que possuem seus próprios métodos e propriedades. Ao construir um módulo de classe na janela de módulo, você cria uma nova classe de objetos. Os procedimentos Sub e Function tornam-se os métodos do novo objeto e os procedimentos Property Let, Property Get e Property Set tornam-se as propriedades do objeto. A programação de classes de objetos é mais efetiva no Visual Basic, pois você pode construir um objeto totalmente encapsulado em um arquivo DLL, EXE ou OCX e pode usá-lo em qualquer outra linguagem que suporte a arquitetura COM (Componente Object Model).
14
Microsoft© Access Avançado
2.7. Seção de declarações A janela de código de módulo, seja padrão ou de classe, possui a seção de declarações e a seção de procedimentos. Na seção de declarações encontram-se as instruções de escopo de módulo, ou sejam, as instruções da seção de declarações afetam todos os procedimentos daquele módulo. As variáveis declaradas nesta seção também são de nível de módulo, o que quer dizer que todos os procedimentos do módulo podem acessar e alterar o conteúdo destas variáveis. Por padrão, a seção de declaração de módulo no Access vem com as instruções Option Compare Database e Option Explicit. A instrução Option Compare define a ordem em que os caracteres são comparados. Se Option Compare não for definido, o padrão é Option Compare Binary, que define a ordem de classificação de acordo com a página de código utilizado no Windows. Tipicamente, comparação binária segue a seqüência: A
2.8. Seção de procedimentos Na seção de procedimentos você escreve seus procedimentos. Os procedimentos de um módulo padrão pode ser do tipo Sub ou Function, ou procedimentos de evento (no caso de módulo de classe de formulário e relatório) ou procedimentos Property Let, Property Get e Property Set (no caso de módulo de classe). 15
Microsoft© Access Avançado Todo procedimento deve ter um nome único em todo aplicativo e seguir as regras de nomenclatura:
Podem ter até 255 caracteres. Precisam começar com uma letra. Podem incluir letras, números ou caracteres sublinhados (_). Não podem incluir caracteres de pontuação ou espaços. Não podem ser uma palavra reservada do Visual Basic. Podem ser escritos com letras maiúsculas ou minúsculas,sem distinção.
Os procedimentos Sub começam com a instrução Sub, seguido do nome do procedimento, e terminam com End Sub. Entre Sub e End Sub fica o código que realizará a operação desejada. O procedimento Function começam com a instrução Function, seguida no nome do procedimento, e termina com End Function. Os procedimentos de um módulo de classe de formulários e relatórios podem ser do tipo Sub ou Function, mas o usual é que contenham procedimentos de evento.
2.9. O editor de código A digitação do código em VBA é feita no próprio MS Access, na janela de código de um módulo (seja módulo padrão, módulo de classe ou módulo de classe de formulário/relatório). Para facilitar a edição e visualização do código, o editor de código possui opções configuráveis, na qual pode-se escolher cores, fontes, tabulação e outros recursos.
Figura 1: Opções do editor de código do Access 16
Microsoft© Access Avançado 2.9.1. Cores de código Por padrão, todo o texto do código é escrito usando a fonte Courier New tamanho 10. A cor depende do tipo do texto. A cor é definida para o primeiro plano, para o segundo plano e para o indicador de margem. Indicador margem é um ícone que aparece na margem esquerda (margin indicator) do código, que serve para fornecer dicas visuais durante a edição ou execução do código. Os valores padrão para as opções de Caixa de texto, primeiro plano, segundo plano e indicador são: Área de texto Texto normal Texto de seleção Texto de erro de sintaxe Texto de ponto de execução Texto de ponto de interrupção Texto de comentário Texto de palavra-chave Texto de identificador Texto de indicador Texto de retorno de chamada
1o plano Preta Preta Vermelha Preta Branca Verde Azul Preta Preta Preta
2º plano Branca Azul Branca Amarela Marron Branca Branca Branca Branca Branca
Indicador
Amarela Marron
Azul claro Verde claro
Para cada valor de área de texto você pode especificar o tipo de fonte e o tamanho nas caixas Fonte e Tamanho. Os ícones de indicadores de margem são: Ícone
Nome do Indicador de margem Ponto de interrupção
Descrição
Indica que você definiu um ponto de interrupção usando o comando Ativar/desativar ponto de interrupção no menu Depurar. Você pode ativar/desativar o ponto de interrupção colocando o ponteiro do mouse na região do indicador de margem e clicando nele. Linha de execução Indica a linha de código que será executada a seguir. Você atual pode arrastar esse indicador de margem para um novo local dentro de qualquer módulo de código em execução. Caso arraste o indicador de margem da Linha de execução atual para uma linha ou região inválida, nada acontecerá e o indicador retornará para o local original. Indicador Indica o local de um indicador definido usando o comando Alternar indicador no menu Editar. Marcador de Pilha de Indica as linhas que estão atualmente na pilha de chamadas. O chamadas indicador Marcador de pilha de chamadas aparece apenas no modo de interrupção.
2.9.2. Opções de codificação Autorecuar — Permite que você tabule até a primeira linha de código; todas as linhas subseqüentes iniciarão nesse local da guia. 17
Microsoft© Access Avançado Verificação de sintaxe automática — Determina se o Visual Basic deve verificar automaticamente a sintaxe correta depois que você inserir uma linha de código. Solicitar declaração de variável — Determina se declarações de variável explícitas são exigidas nos módulos. Esta seleção adiciona a instrução Option Explicit às declarações gerais de todo módulo novo. Compilar ao ser solicitado — Determina se um projeto está totalmente compilado antes que ele seja iniciado ou se o código está compilado conforme o necessário, permitindo que o aplicativo inicie logo. Listar membros automaticamente — Exibe uma lista que contém informações que concluiriam logicamente a instrução no ponto de inserção atual. Exemplo.
Informação rápida automática — Exibe informações sobre funções e seus parâmetros à medida que você digita. Exemplo:
Dicas de dados automáticas — Exibe o valor da variável sobre a qual o seu cursor está posicionado. Disponível somente no modo de interrupção. Exemplo:
Largura da tabulação — Define a largura da guia, que pode variar de 1 a 32 espaços; o padrão é 4 espaços.
2.9.3. Configurações da janela Visualizar módulo completo — Define o estado padrão dos novos módulos para permitir que você observe os procedimentos na janela Código como uma lista rolável simples ou somente um procedimento de cada vez. Não altera o modo de exibição dos módulos atualmente abertos. Separador de procedimento — Permite que você exiba ou oculte as barras separadoras que aparecem no fim de cada procedimento na janela Código. Arrastar-e-soltar edição de texto — Permite que você arraste e solte elementos dentro do código atual e da janela Código para as janelas Imediata ou Inspeção de variáveis. Janela depurar visível — Mantém a janela Depurar aberta. Barra do indicador de margem — Exibe a margem de indicador.
2.10. Janelas do editor de código do Access A parte de programação do MS Access possui apenas três janelas:
Janela de Código Janela Depurar Janela do Pesquisador de Objetos. 18
Microsoft© Access Avançado
2.10.1. Janela de Código A janela de código contém as seções de declaração e a seção de procedimentos e é onde se digita o código.
A janela de código é aberta nas seguintes situações:
Na guia Módulos da janela de Banco de Dados clique em Novo para criar um nvo módulo ou em Estrutura para abrir um módulo existente. Na estrutura de formulário ou relatório, acione o menu Exibir|Código, ou clique no ícone da barra de ferramentas, ou acione o construtor de código nas propriedades do objeto.
2.10.2. Janela Depurar A janela Depurar consiste de três painéis: Imediato, Locais e Inspecionar. Para visualizar a janela Depurar, abra um módulo e clique no ícone na barra de ferramentas. Você também pode abrir a janela Depurar acionando o menu Exibir| Janela Depurar. Você pode também pressionar Ctrl-G a qualquer momento dentro do Access.
19
Microsoft© Access Avançado
Você pode alternar entre o painel Locais e o painel Inspecionar clicando na guia Locais ou na guia Inspecionar da janela Depurar. O painel Imediato permanece visível, independentemente de qual guia é clicada. 2.10.2.1. O Painel Locais
O painel Locais exibe uma lista de variáveis em três colunas: Expressão, Valor e Tipo. Algumas variáveis, como tipos definidos por usuários, matrizes e objetos, podem conter informações hierárquicas. Estas variáveis têm um botão para expandir/reduzir à esquerda dos nomes de variável para controlar a exibição de informações hierárquicas. Quando o painel Locais está visível, ele é atualizado automaticamente quando o modo de execução muda do modo de execução para o modo interrupção. Isto acontece quando a execução atinge um ponto de interrupção ou quando você começa a depurar o código. A primeira variável da lista é uma variável especial de módulo. Para um módulo classe, esta é a variável Me definida pelo sistema. Esta é uma referência de objeto à instância atual da classe definida pelo módulo atual. Já que esta variável é uma referência de objeto, ela pode ser expandida para mostrar todas as propriedades e os membros de dados da instância de classe atual. Para módulos padrões, a primeira variável é o nome do módulo atual e também pode ser expandida para exibir todas as variáveis no nível de módulo no módulo atual. Você pode alterar o valor de uma variável do painel Locais, mas não pode alterar suas definições de Expressão ou Tipo. 2.10.2.2. O Painel Inspecionar
O painel Inspecionar permite que você visualize o valor de uma expressão ou uma variável enquanto o código estiver em execução. Para definir uma expressão de inspeção, clique no menu Depurar|Adicionar inspeção de variáveis. O painel Inspecionar proporciona as seguintes capacidades: 20
Microsoft© Access Avançado
Expandir/reduzir informações hierárquicas. Redimensionar cabeçalhos de coluna. Editar valores in loco.
2.10.2.3. O Painel Imediato
No painel Imediato, você pode:
Executar qualquer procedimento Sub ou Function, inclusive procedimentos de evento. Executar uma expressão qualquer, inclusive usando variáveis do procedimento em execução. Visualizar a saída de valores enviados pelo método Print do objeto Debug.
Para executar um procedimento definido dentro de um módulo classe a partir do painel Imediato, você precisa qualificar o procedimento com o nome do módulo classe, a menos que você esteja no modo de interrupção dentro daquele módulo. Se você estiver no modo interrupção, não é necessário qualificar o procedimento pois esse módulo está atualmente no escopo. O exemplo seguinte, quando digitado no painel Imediato da janela Depurar, executa um procedimento ListarNomes que está definido no módulo classe associado a um formulário Funcionários: Form_Funcionários.ListarNomes
O próximo exemplo executa o procedimento do evento Click para um botão de comando chamado InformaçõesPessoais em um formulário Funcionários: Form_Funcionários.InformaçõesPessoais_Click
Para executar uma expressão, use o sinal ? seguido da expressão desejada. Por exemplo, o comando abaixo irá calcular o número inteiro de uma divisão. ? Int(345/7)
2.10.2.4. Outros Recursos da Janela Depurar
A nova janela Depurar proporciona automaticamente informações de status sobre seu código. Quando nenhum código está sendo executado, a barra de status no topo da janela Depurar mostra "". Uma vez iniciada a execução do código, a barra de status mostra o nome do banco de dados atual, o módulo no qual reside o procedimento em execução, e o nome do próprio procedimento. Você também pode visualizar a janela Chamadas a partir da janela Depurar clicando no botão Construir . 2.10.3. Janela Pesquisador de Objetos A janela Pesquisador de Objetos é aberta pelo menu Exibir|Pesquisador de Objetos ou pela tecla F2. O Pesquisador de Objetos é uma caixa de diálogo que exibe informações sobre objetos, propriedades, métodos e constantes do banco de dados atual e em bibliotecas de objetos referenciados. Você pode utilizar o Pesquisador de Objeto para pesquisar um 21
Microsoft© Access Avançado elemento específico, visualizar suas definições, obter ajuda sobre ele ou colá-lo em um módulo.
*****
22
Microsoft© Access Avançado
PRÁTICA 2 – PROGRAMAÇÃO NO MS ACCESS EXERCÍCIO 1 – Criando um módulo padrão Crie um módulo basDemonstracao contendo o procedimento Welcome. 1. 2. 3. 4. 5.
Abra o MS Access . Crie um banco de dados vazio chamado dbWelcome.mdb. Selecione a guia Módulos na janela de Banco de Dados. Clique em Novo. Digite o seguinte procedimento:
Sub Welcome() MsgBox "Bem-vindo ao curso MS Access End Sub
Avançado", vbOKOnly, "teste"
Perceba como o Access diferencia cores para instruções e texto de usuário e como o editor de código fornece dicas da sintaxe da instrução MsgBox. Clique no menu Arquivo|Salvar. Informe o nome basDemonstracao e clique OK.. Posisione o cursor em qualquer parte do código. Tecle F5. Será mostrada uma caixa de mensagem chamada Teste com o texto "Bem-vindo ao curso MS Access Avançado" 10. Clique no botão OK da caixa de mensagem. 11. Feche a janela de módulo e veja o nome do módulo basDemonstracao gravado na guia Módulos da janela de Banco de Dados.
6. 7. 8. 9.
EXERCÍCIO 2 – Criando um módulo de classe em formulário Crie um formulário chamado frmDemonstracao. 1. 2. 3. 4. 5. 6. 7.
Clique na guia Formulários da janela de Banco de Dados. Clique em Novo. Escolha Modo estrutura e clique em OK. Desligue o Assistentes de controle da barra de ferramentas Caixa de ferramentas. Crie um botão de comando. Abra as propriedades do botão de controle e selecione a guia Todas. Atribua as seguintes propriedades:
Nome: cmdOK Legenda: &Ok Ao clicar: [Procedimento de Evento] 8. Clique no botão do construtor de código aberta a janela de módulo de classe. 9. Digite o código a seguir:
em frente à propriedade Ao clicar. Será
Private Sub cmdOk_Click()
23
Microsoft© Access Avançado MsgBox "Isto é um procedimento de evento do controle cmdOk" End Sub
10. Feche a janela de módulo. 11. Salve o formulário como frmDemonstracao. 12. Alterne para o Modo Formulário. 13. Clique no controle Ok. Surgirá uma caixa de mensagem com o texto "Isto é um procedimento de evento do controle cmdOk" 14. Feche o formulário. 3. PROCEDIMENTOS EM MÓDULO PADRÃO Procedimento é uma unidade de código VBA que contém instruções e métodos sequencia e logicamente ordenados que ao final de algum tempo de execução realizará uma tarefa específica, previamente planejada no algoritmo. Por exemplo, podemos querer determinar as raízes de uma equação do segundo grau por meio de um procedimento. Ao final, podemos ter como resultado um valor, dois valores ou nenhum. A equação do 2º grau possui a forma geral: ax
2
+ bx + c = 0
A resolução do problema consiste em receber três valores da equação do 2º grau, normalmente chamados de a, b e c e determinar os valores de x. Os valores de x são determinados pela fórmula de báskara, que consiste em:
x=
b ± b 2 − 4ac 2a
O algorimo para implementar a fórmula de Báskara é: Algoritmo Baskara Declare a, b, c, Delta, x1, x2 numérico Leia a Leia b Leia c {Calcule Delta} Delta ← b2 – 4 x a x c Se Delta = 0 então x1 ← -b ÷ 2 x a Escreva x1 SenãoSe Delta > 0 então x1 ← (-b
+
x2 ← (-b Escreva x1 Escreva x2
Delta ) ÷ (2 x a) Delta ) ÷ (2 x a)
Senão Escreva "Não há solução" Fim Se Fim algoritmo
24
Microsoft© Access Avançado Este algoritmo tem uma finalidade geral e portanto é adequado usar módulo padrão. Módulos padrão são criados na guia Módulos da janela de Banco de Dados. Selecione a guia Módulos na janela de Banco de Dados e clique no botão Novo. É aberta uma janela de código para criação de procedimentos em módulo padrão. Cada módulo pode conter um ou mais procedimentos do tipo Sub (procedimento sem retorno de valor, ou simplesmente procedimento) e Function (procedimento com retorno de valor, ou simplesmente, função). Abaixo da seção de declarações, digite a palavra reservada Sub ou Function seguido do nome do procedimento. Após teclar Enter, uma seção de procedimento será criada, iniciando com a declaração do procedimento e terminando com a palavra reservada End Sub ou End Function. Option Compare Database Option Explicit Sub MeuProcedimento() [ instruções ] End Sub Function MinhaFuncao() [ instruções ] End Function
Na área entre a declaração do procedimento e o seu fim você deve digitar o seu código VBA. Comece sempre com a declaração das variáveis e constantes que serão utilizados pelo seu código. Criemos um primeiro código para implementar o algoritmo de Báskara. Sub Baskara() Dim sngA As Single Dim sngB As Single Dim sngC As Single Dim dblDelta As Double Dim sngX1 As Single Dim sngX2 As Single sngA = InputBox("Valor de A") sngB = InputBox("Valor de B") sngC = InputBox("Valor de C") ' Cálculo de Delta dblDelta = sngB ^ 2 - 4 * sngA * sngC If dblDelta = 0 Then sngX1 = -sngB / (2 * sngA) MsgBox sngX1 ElseIf dblDelta > 0 Then sngX1 = (-sngB + Sqr(dblDelta)) / (2 * sngA) sngX1 = (-sngB - Sqr(dblDelta)) / (2 * sngA) MsgBox sngX1 MsgBox sngX2 Else MsgBox "Não há solução" End If End Sub
25
Microsoft© Access Avançado Os parênteses após o nome do procedimento serve para receber argumentos (também chamado de parâmetros). Veremos a passagem e recebimento de argumentos mais adiante. Dentro do mesmo módulo, podemos ter mais de um procedimento Sub ou Function. Criaremos um procedimento para cálculo de fatorial de um número. Sub Fatorial() Dim lngNumero As Long Dim dblFatorial As Double Dim lngContador As Long lngNumero = InputBox("Entre com um número") dblFatorial = 1 lngContador = 2 If lngNumero = 0 Or lngNumero = 1 Then MsgBox "O fatorial é 1" Else Do While lngContador <= lngNumero dblFatorial = dblFatorial * lngContador lngContador = lngContador + 1 Loop MsgBox "O fatorial é " + str(dblFatorial) End If End Sub
3.1. Compilação de módulo Na maioria da linguagens de programação o termo compilação significa gerar um arquivo executável a partir do programa fonte. Compilar no MS Access significa verificar a sintaxe das instruções e a verificação de variáveis e constantes não declaradas (caso Option Explicit esteja ativado). Ao terminar a digitação do código, você deve compilar o módulo. A compilação é feita no menu Depurar|Compilar módulos carregados na janela de módulo. A compilação abrange todos os módulos abertos (seja padrão, de classe ou de formulário/relatório) e não somente o módulo que está sendo editado. Se houve erro de sintaxe ou variável não declarada, uma caixa de mensagem informará o erro e o texto onde o erro ocorreu será selecionado. Por exemplo, o código abaixo apresentará erro, pois estamos usando uma variável não declarada. Option Compare Database Option Explicit Sub Teste() Dim intNumero As Integer intNumero = intDesconto * 42 MsgBox intNumero End Sub
Ao compilar, será mostrada uma caixa de diálogo com o erro “Variável não definida”.
26
Microsoft© Access Avançado
Ao clicar OK, a janela do código onde ocorreu o erro será aberta e o local do erro ficará marcado. Caso não haja erros de sintaxe, verifique erros de lógica, para que o programa não trave o computador. Se tudo estiver correto, salve o módulo e forneça um nome. A gravação do módulo é feita pelo menu Arquivo|Salvar.
3.2. Teste de execução de procedimento em módulo padrão Os procedimentos em módulos padrão, desde que não recebam argumentos, podem ser executados, para fins de teste, a partir da janela de código do módulo que está sendo editado. Dentro de um mesmo módulo podem ser escritos vários procedimentos. Para executar um deles, você deve posicionar o cursor em qualquer parte do procedimento desejado e teclar F5 ou acionar o menu Executar|Ir para/continuar ou ainda teclar o ícone .
3.3. Execução passo-a-passo Você pode executar o procedimento passo-a-passo, uma linha de cada vez, para acompanhar o fluxo de execução, depurar eventuais erros de lógica ou visualizar o conteúdo de variáveis. A execução passo-a-passo é acionada pela tecla F8 ou pelo ícone na barra de ferramentas da janela de módulo ou pelo menu Depurar|Depuração total. Durante a execução passo-a-passo, o texto da linha de código que está sendo executada ficará na cor definida por “Texto de ponto de execução” definido nas opções do editor de código (menu Ferramentas|Opções, guia Módulo) e o indicador surgirá na barra Indicador de Margem. A qualquer momento, você pode decidir pela execução total, teclando-se F5. Durante a execução passo-a-passo você pode abortar a execução acionando o menu Executar|Fim ou clicar no ícone na barra de ferramentas. Este ícone só está ativado se algum procedimento estiver sendo executado. Ao editar o código, preste atenção neste ícone e lembre-se de terminar a execução antes de fazer qualquer alteração em seu código ou na estrutura de tabelas, consultas, formulários e relatórios.
27
Microsoft© Access Avançado
3.4. Inspeção de variáveis Durante a execução passo-a-passo você pode posicionar o mouse sobre uma variável e verificar o valor nela contida naquele momento da execução.
28
Microsoft© Access Avançado Lembre-se que este recurso de inspeção de variáveis durante a execução do procedimento só está disponível se a opção “Dicas de dados automáticas” estiver ativada nas opções do editor de código. Você pode inspecionar todas as variáveis no painel Locais da janela Depurar.
3.5. Ponto de interrupção Para depurar uma aplicação não é necessário executar passo-a-passo todos os códigos. Normalmente, você quer estudar algumas partes do código mais suceptíveis a falhas. Você pode estabelecer pontos de interrupção nas linhas em que você quer começar a execução passo-a-passo. Para isto, vá até a linha onde se deseja interromper a execução e tecle F9 ou o ícone na barra de ferramentas ou acione o menu Depurar|Ativar/Desativar pontos de interrupção. O indicador de margem apresentará o ícone e o texto da linha ficará na cor marrom em segundo plano. Ao executar o procedimento com F5, o código será executado completamente e parará no ponto de interrupção. A partir daí, pode-se prosseguir com F8 para execução passo-a-passo ou F5 para continuar a execução completa. Um novo F9 na linha do ponto de interrupção desativará o ponto de interrupção. Os pontos de interrupção servem para testar o aplicativo. Você deve lembrar de desativar todos os pontos de interrupção antes de salvar o módulo (ou formulário ou relatório) para ser distribuído. Pressionando Control+Shift+F9 desativa todos os pontos de interrupção de todos os módulos, estejam estes salvos ou não.
29
Microsoft© Access Avançado
3.6. Chamada de Procedimentos Os procedimentos anteriores são duas unidades de código independentes entre si. Cada um deles é executado ao teclar F5. Usamos a tecla F5 apenas para testar cada um dos procedimentos. Naturalmente, quando construir um aplicativo em Access, ele não funcionará à base de tecla F5. Haverá uma interface gráfica, normalmente um formulário, com opções para executar os procedimentos que você criou. Veremos em outro capítulo como chamar um procedimento a partir de um formulário. Agora, precisamos saber como um procedimento pode chamar outro e como eles se relacionam. Suponha que você escreva um procedimento para calcular a combinação de n números tomados p a p. A fórmula da combinação é: Cn, p =
n! p !(n − p)!
Note que para resolver este problema é preciso calcular três fatorias. Ora, já vimos um procedimento para calcular fatoriais. Não bastaria escrever três vezes o código dentro do procedimento de combinação? Não é nada produtivo ter que rescrever o mesmo algoritmo várias vezes. O que podemos fazer é fazer com que o procedimento de combinação chame o procedimento de fatorial todas as vezes que for necessário. Qualquer procedimento pode chamar outro procedimento apenas colocando-se o nome do procedimento como se fosse uma instrução do VBA. Sub Combinacao() . . Fatorial . End Sub
Esquematicamente, a chamada de um procedimento por outro funciona assim:
Entretanto, o procedimento Fatorial exige que um valor seja informado. No caso, informamos o valor com a função InputBox do VBA. O procedimento Fatorial também fornece a resposta por meio da função MsgBox. Da forma como o procedimento foi escrito ele é um procedimento completo e independente. 30
Microsoft© Access Avançado Para que o procedimento de combinação possa utilizar o procedimento Fatorial, de forma a ambos funcionarem em conjunto, devemos modificar o procedimento Fatorial. A primeira coisa a fazer é retirar a função InputBox do procedimento Fatorial. O número para o qual se deseja calcular o fatorial deve ser passado como um argumento. 3.6.1. Passagem de Argumentos Os parênteses à frente do nome do procedimento servem para receber argumentos vindos de outro procedimento que o chamou. Argumentos são variáveis que receberão valores, constituindo-se assim a entrada de dados para o procedimento. Sub Fatorial(lngNumero As Long) Dim dblFatorial As Double Dim lngContador As Long dblFatorial = 1 lngContador = 2 If lngNumero = 0 Or lngNumero = 1 Then MsgBox "O fatorial é 1" Else Do While lngContador <= lngNumero dblFatorial = dblFatorial * lngContador lngContador = lngContador + 1 Loop MsgBox "O fatorial é " + str(dblFatorial) End If End Sub
Para um procedimento chamar outro passando argumentos, basta escrever o seu nome e enviar a variável ou valor à frente do nome. No caso abaixo, o procedimento Combinacao irá chamar o procedimento Fatorial, passando o valor 4 como argumento. Sub Combinacao() . . Fatorial(4) . End Sub
O outro problema do procedimento Fatorial é que o resultado é escrito na tela e não pode ser usado pelo procedimento Combinacao. Devemos, portanto, transformar o procedimento Fatorial de Sub para Function, de forma que ele possa retornar o resultado para o procedimento que o chamou. 3.6.2. Retorno de Valor Somente procedimentos do tipo Function podem retornar valor para o procedimento que o chamou. Para retornar um valor, usa-se o próprio nome do procedimento para retornar o valor. Como procedimento do tipo Function retornam valor, eles precisam ter um tipo definido. 31
Microsoft© Access Avançado Function Fatorial(lngNumero As Long) As Double Dim dblFatorial As Double Dim lngContador As Long dblFatorial = 1 lngContador = 2 If lngNumero = 0 Or lngNumero = 1 Then Fatorial = 1 Else Do While lngContador <= lngNumero dblFatorial = dblFatorial * lngContador lngContador = lngContador + 1 Loop Fatorial = dblFatorial End If End Sub
Note que em Fatorial = 1, Fatorial não é uma variável e sim o nome do procedimento. 1 é o valor a ser retornado. Note também que o procedimento Fatorial, que agora é do tipo Function, tem o mesmo tipo de dado que a variável dblFatorial. Agora, o procedimento Combinacao pode chamar a function Fatorial e armazenar o valor de retorna em uma de suas variáveis. Sub Combinacao() Dim N As Integer Dim P As Integer Dim dblFatN As Double Dim dblFatP As Double Dim dblFatNP As Double Dim dblResultado As Double N = InputBox("Entre com o valor de N") P = InputBox("Entre com o valor de P") dblFatN = Fatorial(N) dblFatP = Fatorial(P) dblFatNP = Fatorial(N - P) dblResultado = dblFatN / (dblFatP * dblFatNP) MsgBox dblResultado End Sub
O procedimento Combinacao é um código completo, mas dependente da existência do procedimento Fatorial. O procedimento Combinacao pode ser executado com F5, mas o procedimento Fatorial não pode mais, por depender da passagem de um argumento. Como a combinação é um código de uso geral, podemos transformá-lo também em uma função, para que outro procedimento o chame. Neste caso, são necessários dois argumentos. Function Combinacao(intN As Integer, intP As Integer) As Double Dim dblFatN As Double Dim dblFatP As Double Dim dblFatNP As Double dblFatN = Fatorial(intN) dblFatP = Fatorial(intP)
32
Microsoft© Access Avançado dblFatNP = Fatorial(intN - intP) Combinacao = dblFatN / (dblFatP * dblFatNP) End Sub
Podemos testar a função Combinacao chamando-a de um outro procedimento, pois, agora que ela recebe argumentos, ela não pode mais ser executada com F5. Sub TestaCombinacao() Dim N As Integer, P As Integer N = 3 P = 2 MsgBox Combinacao(N,P) End Sub
3.6.3. Passagem de Argumentos por Valor e por Referência Os argumentos passados de um procedimento para outro podem ser por valor ou por referência. A passagem por valor indica que a variável enviada e a variável definida como argumento são duas posições de memória distintas. Elas podem até ter os mesmos nomes. Sub Teste1() Dim X As Integer X = 10 MsgBox X ' Será escrito 10 Teste2(X) MsgBox X ' Ainda será escrito 10 End Sub Sub Teste2(X As Integer) MsgBox X ' Será escrito 10 X = 20 MsgBox X ' Será escrito 20 End Sub
No exemplo acima, a variável X do procedimento Teste1 contém o valor 10, e é passado como argumento para o procedimento Teste2. Em Teste2, o valor é alterado para 20, mas esta variável não tem nada a ver com o X de Teste1. Apenas o valor de X em Teste1 foi passado para a variável X de Teste2. Ao retornar para Teste1, a variável X continua a ter o valor original. Em suma, a passagem de argumentos por valor equivale a copiar o valor para outra variável. Na passagem por referência, as alterações na alteração do argumento afetam o conteúdo da variável que foi passada como argumento. Na passagem por referência, o endereço de memória é que é passado para o procedimento. Assim, ambas as variáveis são na realidade a mesma variável, mesmo que tenham nomes distintos Sub Teste1() Dim X As Integer X = 10 MsgBox X ' Será escrito 10 Teste2 X MsgBox X ' Será escrito 20 End Sub
33
Microsoft© Access Avançado Sub Teste2(ByRef G As Integer) MsgBox G ' Será escrito 10 G = 20 MsgBox G ' Será escrito 20 End Sub
As palavras-chave ByRef e ByVal definem o tipo de passagem de argumento. O padrão no VBA é ByRef, ou seja, se você não especificar nada, assume a passagem por referência. Entretanto, ByVal e ByRef sozinhos não garantem que os argumentos sejam passados por valor e pro referência, respectivamente. O modo de chamada também define o tipo de passagem. Se na chamada do procedimento os argumentos forem passados entre parênteses, então a passagem é por valor, independentemente de ByRef e ByVal. Sub Teste1() Dim X As Integer X = 10 MsgBox X ' Será escrito 10 Teste2(X) ' Os parênteses definem que a passagem é por valor MsgBox X ' Será escrito 10 End Sub Sub Teste2(ByRef G As Integer) MsgBox G ' Será escrito 10 G = 20 MsgBox G ' Será escrito 20 End Sub
Se na chamada do procedimento os argumentos não forem passados entre parênteses, então o tipo de passagem será definido por ByRef e ByVal. Lembrando que ByRef é o padrão do VBA. Sub Teste1() Dim X As X = 10 MsgBox X Teste2 X MsgBox X End Sub
Integer ' Será escrito 10 ' O tipo de passagem dependerá de ByRef ou ByVal ' Será escrito 10
Sub Teste2(ByVal G As Integer) MsgBox G ' Será escrito 10 G = 20 MsgBox G ' Será escrito 20 End Sub
*****
34
Microsoft© Access Avançado
4. MÓDULO DE CLASSE EM FORMULÁRIO/RELATÓRIO Cada formulário e relatório pode conter apenas um módulo. Este módulo é do tipo módulo de classe. Este módulo não aparece como um objeto na guia de Módulos, pois fica embutido no formulário/relatório. Por isso, ele era chamado Code Behind Form. Os procedimentos estão relacionados a eventos do formulário, do relatório ou dos controles do formulário (controles de relatório não geram evento). Os procedimentos são criados no modo estrutura do formulário/relatório. No modo estrutura, com um objeto selecionado, por exemplo o botão de comando cmdOk, na guia Eventos da janela de propriedades seleciona-se o evento ao qual o procedimento estará associado. O evento pode chamar uma macro ou um procedimento em código VBA.
Escolhendo [Procedimento de evento] e clicando-se no botão do Construtor de Código, uma janela de módulo, semelhante a uma janela de módulo padrão, irá se abrir. O nome do procedimento é gerado automaticamente. Ele é formado pelo nome do objeto e pelo evento, separado por um sublinhado ( _ ). Por exemplo, para o controle cmdCancel e evento Clicar o nome do procedimento é cmdCancel_Click. Um código comum associado ao clicar sobre o botão Cancel é o do fechamento do formulário corrente. Private Sub cmdCancel_Click(Cancel As Integer)
35
Microsoft© Access Avançado DoCmd.Close End Sub
O procedimento de módulo de formulário ou de relatório só é executado quando o evento do objeto associado ao procedimento ocorrer. Como os procedimentos de evento recebem o nome do controle e do evento, é extremamente recomendável não usar os nomes padrão fornecido pelo Access (Texto1, Comando2, ect). Deve-se nomear os controles com um nome significativo na guia Outra da janela de Propriedades. Algumas das características vistas no módulo padrão se aplicam também no módulo de classe, dentre elas: Compilação, execução passo-a-passo, ponto de interrupção e inspeção de variáveis.
4.1. Coleções e Objetos de Formulário/Relatório Formulários, relatórios e controles são objetos do Access e, portanto, possuem propriedades, métodos e eventos. As propriedades e os eventos são acessíveis no modo estrutura do formulário/relatório, na janela de Propriedades. Alterando-se as propriedades no modo estrutura, os valores tornam-se estáticos. Por exemplo, se se define a Legenda do formulário como “Menu Principal”, ela só pode ser alterada novamente no modo estrutura NOTA: Controles de relatórios não possuem eventos. Via programação, podemos ter acesso às propriedades dos objetos. Os valores das propriedades podem ser alterados dinamicamente, durante a execução do código. A programação permite também que os métodos dos objetos sejam invocados, algo que não é possível no modo estrutura. Todos os formulários do banco de dados formam a coleção de formulários. Todos os relatórios do banco de dados formam a coleção de relatórios. Uma coleção é um objeto que contém objetos de um mesmo tipo. Eis as coleções do Access. Coleção Forms Reports Controls Modules
Descrição Coleção de formulários abertos Coleção de relatórios abertos Coleção de controles em formulários ou relatórios abertos Coleção de módulos padrão e módulose de classe (inclusive módulos de classe de formulário e de relatório)
A hierarquia completa dos objetos do Access é mostrada na figura abaixo:
36
Microsoft© Access Avançado
Por ser um objeto, cada coleção possui também propriedades e métodos. Para referenciar um objeto específico de uma coleção, pode-se usar quatro formas diferentes: Coleção(número do item) Coleção(“Nome do item”) Coleção![Nome do item] Coleção.Item(número do item] A primeira e a última forma têm a desvantagem de ter que saber qual o número do item dentro da coleção. Se existem vários formulários num banco de dados, cada um deles recebe um número sequencial, começando do zero (0). Na última forma, Item é uma propriedade da coleção. As duas outras formas são mais compreeensíveis e mais fáceis de usar porque já sabemos o nome do item. Por exemplo, para referir a um formulário específico chamado frmPedidos, use a expressão: Forms![frmPedidos] ou Forms(“frmPedidos”) Para referir-se a um relatórios chamado rptLista_de_Produtos, use a expressão: Reports![rptLista_de_Produtos] ou Reports(“rptLista_de_Produtos”) Para referir-se a um controle chamado txtPreçoUnitário, no formulário frmPedidos, use a expressão: Forms![frmPedidos]![txtPreçoUnitário] 37
Microsoft© Access Avançado Se o código estiver sendo escrito atrás do formulário frmPedidos, não é necessário referir-se a ele mesmo como Forms![frmPedidos], mas simplesmente como Me!. Assim, a referência ao controle txtPreçoUnitário pode ser simplificado para Me![txtPreçoUnitário]. NOTA: O objeto Form referencia formulários abertos. Formulários fechados são referenciados pelo objeto Document da hierarquia de objetos do DAO – Data Access Objects.
4.2. Propriedades e Métodos Se em vez de querer acessar um controle do formulário você quiser acessar suas propriedades ou invocar seus métodos, use a expressão: Forms![frmPedidos].Caption ou simplesmente Me.Caption Para acessar uma propriedade de um controle ou invocar um de seus métodos, use a expressão: Forms![frmPedidos]![txtPreçoUnitário].BackColor ou simplemente Me![txtPreçoUnitário].BackColor O caracter ! é usado para indicar que o próximo elemento é um item definido pelo usuário e o ponto indica que o próximo elemento é uma propriedade ou método. Você pode usar o ponto para substituir a !, se quiser. Portanto, Forms![frmPedidos] equivale a Forms.[frmPedidos]. Ao escrever um código VBA, se a opção “Listar membros automaticamente” do editor de código estivar acionada, será exibida uma lista das propriedades e métodos do objeto e os controles do objeto. Propriedade
Método
Controle
Algumas propriedades são somente para leitura, isto é, você não pode alterar o seu valor, somente recurá-lo. Por exemplo, a propriedade Name é tipicamente uma propriedade para somente leitura, já que o nome é fornecido ao salvar a estrutura de um objeto.
38
Microsoft© Access Avançado Todas as propriedades visíveis na janela de propriedades na estrutura de um formulário são acessíveis via programação. Entretanto, existem várias propriedades que são acessíveis somente no modo programado e não podem ser acessados no modo estrtutura. Por exemplo, a propriedade Hwnd de um formulário está disponível somente no modo programado.
4.3. Coleção padrão e propriedade padrão Um objeto pode conter coleções. Um objeto formulário, por exemplo, contém a coleção Controls. À rigor, a referência a um controle de um formulário deveria ser: Forms![frmPedidos].Controls![txtPreçoUnitário] Mas como a coleção Controls é a coleção padrão do objeto Form, não é necessário mencioná-lo. Os objetos possuem várias propriedades, mas uma delas é a propriedade padrão. Por exemplo, o controle caixa de texto possui a propriedade Text (o conteúdo da caixa de texto) como padrão. Assim, pode-se omitir esta propriedade. Forms![frmPedidos]![txtPreçoUnitário].Text = 3.00 equivale a Forms![frmPedidos]![txtPreçoUnitário] = 3.00
4.4. Propriedades de Coleção As coleções Forms, Reports e Controls possuem apenas propriedades, mas não métodos. As propriedades são: Application
Retorna o objeto Application, no caso, o Microsoft Access. Somente leitura. Como o retorno é um objeto, deve ser usado como Set obj = object.Application Sub ApplicationProperty( ) Dim obj As Object Set obj = Forms.Application ' Retorna o objeto Microsoft Access End Sub
Count
Retorna a quantidade de objetos da coleção. Somente leitura. Sub CountProperty( ) Dim intForms As Integer IntForms = Forms.Count End Sub
Item
Retorna o objeto em uma determinada posição ou índice dentro da coleção. Somente leitura. Sub ItemProperty( ) Dim obj As Object
39
Microsoft© Access Avançado Set obj = Forms.Item(0) ' Retorna o primeiro form aberto End Sub
Parent
objeto
Retorna o objeto superior. Somente leitura. Como o retorno é um objeto, deve ser usado como Set obj = object.Parent. Sub ApplicationProperty( ) Dim obj As Object Set obj = Me.Controls(”txtCodigo”).Parent ' Retorna o objeto form atual End Sub
4.5. Seções de Formulário/Relatório As seções dos formulários e relatórios são objetos, da mesma forma que controles. As seções possuem propriedades e eventos, mas não métodos. Deve-se tomar cuidado, pois, assim como os controles, o nome destes objetos é dado automaticamente pelo Access, entretanto, não se justifica alterá-los. Na versão em inglês, os nomes padrão são: FormHeader, FormFooter, Detail, PageHeader e PageFooter. As propriedades e métodos das seções podem ser acessadas via programação, entretanto, as seções PageHeader e PageFooter de relatórios não possuem propriedades nem eventos que possam ser acessados via programação.
4.6. Eventos de Formulário Eis alguns dos eventos de formulário para os quais pode-se definir código: Evento NoAtual (OnCurrent)
Descrição O evento NoAtual ocorre quando o foco é movido para um registro, tornando-o o registro atual, ou quando o formulário é aberto ou atualizado ou quando sua consulta é repetida. O Microsoft Access executa a macro ou procedimento de evento Current antes de o primeiro ou próximo registro ser exibido. Ao executar uma macro ou procedimento de evento quando ocorre o evento Current de um formulário, é possível exibir uma mensagem ou sincronizar registros em um outro formulário relacionado ao registro atual. Por exemplo, quando o registro de um cliente torna-se o atual, você pode exibir o pedido anterior do cliente. Quando o registro de um fornecedor torna-se o atual, é possível exibir os produtos fabricados pelo fornecedor em um formulário Fornecedores. Você também pode efetuar cálculos com base no registro atual ou alterar o formulário em resposta aos dados desse registro.
40
Microsoft© Access Avançado Se a sua macro ou procedimento de evento executar uma ação IrParaControle ou IrParaRegistro ou o método correspondente do objeto DoCmd em resposta a um evento Open, ocorrerá o evento Current. O evento Current também ocorre quando você atualiza um formulário ou repete a tabela ou consulta base do formulário — por exemplo, quando você clica em Remover Filtro/Classificação no menu Registros ou utiliza a ação RepetirConsulta em uma macro ou o método Requery em código do Visual Basic. Quando você abre um formulário pela primeira vez, os eventos ocorrem na ordem a seguir: Antes de Inserir (BeforeInsert) Após Inserir (AfterInsert) Antes de Atualizar (BeforeUpdate) Após Atualizar (AfterUpdate) Ao Excluir (OnDelete) Confirmar Antes de Excluir (BeforeDelConfirm) Após Confirmar Exclusão (AfterDelConfirm) Ao Abrir (OnOpen) Ao Carregar (OnLoad) Ao Redimensionar (OnResize) Ao Descarregar (OnUnload) Ao Fechar (OnClose) Ao Ativar (OnActivate) Ao Desativar (OnDeactivate) Ao Receber Foco (OnGotFocus) Ao Perder Foco (OnLostFocus) Ao Clicar (OnClick)
Open Load Resize Activate Current Ocorre quando o usuário digita o primeiro caractere de um novo registro, mas antes de realmente o registro ser gravado. A ordem dos eventos é: BeforeInsert BeforeUpdate AfterUpdate AfterInsert Ocorre quando o registro passa a ser um novo registro. Ocorre quando o usuário atualiza o registro Ocorre quando o registro é atualizado Ocorre quando o usuário tecla DEL em um ou mais registros. Ocorre antes de o registro ser efetivametne excluído, quando o MS Access apresenta a mensagem de confirmação da exclusão Ocorre após a confirmação da exclusão do registro. Ocorre ao abrir o formulário. A ordem dos eventos é: Open Load Resize Activate Current Ocorre após o formulário ser aberto e carregar os dados para exibição. Ocorre ao redimensionar a janela do formulário. Ocorre antes de o formulário ser fechado, mas antes de ele ser removido da tela. A ordem dos eventos é: Unload Deactivate Close Ocorre ao fechar o formulário. Ocorre quando a janela torna-se ativa, mas antes dela receber foco. Ocorre antes de a janela perder o foco. Ocorre após a janela se tornar ativa. Ocorre ao perde o foco da janela. Ocorre ao clicar o botão esquerdo do mouse sobre o formulário.
41
Microsoft© Access Avançado 5. ELEMENTOS DE PROGRAMAÇÃO Como qualquer outra linguagem de programação, o VBA implementa: • • • • • • • • •
Variáveis (simples e compostas) Constantes Vetores e matrizes Comentários Instruções de controle de estrutura de repetição Instruções de controle de estrutura condicional Instruções de entrada Instruções de saída Funções
O VBA permite ainda utilizar-se de objetos e coleções do próprio MS Access (Application, Forms/Form, Reports/Report, Controls/Control, Modules/Module, Screen e DoCmd) ou de outras aplicações que suportem a automação (como os aplicativos do MS Office) ou de controles ActiveX (atualmente chamados de COM – Component Object Model).
5.1. VARIÁVEIS Variável é um local da memória RAM do computador que armazena um valor até que um novo valor seja armazenado ou até que a rotina se encerre. A posição de memória é referida por um identificador, que nada mais é que um nome que aponta para o endereço de memória. 5.1.1. Declaração Em algoritmo, a declaração das variáveis segue a sintaxe: Declare nome_da_variável tipo Onde, declare é uma instrução, nome_da_variável é o nome que referencia a posição de memória onde será armazenada um dado e tipo é o tipo de dado, podendo ser literal, numérico ou lógico. No VBA, a principal instrução para declaração de variáveis é a Dim, seguindo a sintaxe: Dim {nome_da_variável} As {tipo} Os tipos de dados aceitos no VBA são:
42
Microsoft© Access Avançado Tipo de dados
Tamanho de Armazename nto Byte 1 byte Boolean 2 bytes Integer 2 bytes Long (inteiro longo) 4 bytes Single (vírgula flutuante de 4 bytes precisão simples) Double (vírgula flutuante de precisão dupla)
Currency
8 bytes
(inteiro escalado) 8 bytes
Decimal
14 bytes
Date
8 bytes
Object String (comprimento da variável)
4 bytes 10 bytes + comprimento da seqüência de caracteres Comprimento da seqüência de caracteres 16 bytes
String (comprimento fixo) Variant (com números) Variant (com caracteres)
Definido pelo usuário (usando Type)
22 bytes + comprimento da seqüência de caracteres Número requerido por elementos
Intervalo 0 a 255 True ou False -32.768 a 32.767 -2.147.483.648 a 2.147.483.647 -3,402823E38 a -1,401298E-45 para valores negativos; 1,401298E-45 a 3,402823E38 para valores positivos -1,769313486232E308 a 4,94065645841247E-324 para valores negativos; 4,94065645841247E-324 a 1,769313486232E308 para valores positivos -922.337.203.685.477,5808 a 922.337.203.685.477,5807 +/79.228.162.514.264.337.593.543.950.335 sem ponto decimal; +/7,9228162514264337593543950335 com 28 casas decimais à direita; o menor número diferente de zero é +/0,0000000000000000000000000001. De 1º de Janeiro de 100 até 31 de Dezembro de 9999 Qualquer referência a Object De 0 até aproximadamente 2 bilhões
De 1 até aproximadamente 65.400 Qualquer valor numérico até o intervalo de um Double O mesmo intervalo que String de comprimento variável O intervalo de cada elemento é o mesmo que o intervalo do seu tipo de dados.
43
Microsoft© Access Avançado Recomenda-se que os nomes das variáveis sigam o padrão de nomenclatura LNC (ver Apêndice A). Os nomes de variáveis, assim como o de constantes e procedimentos: • • • • •
Podem ter até 255 caracteres. Precisam começar com uma letra. Podem incluir letras, números ou caracteres sublinhados (_). Não podem incluir caracteres de pontuação ou espaços. Não podem ser uma palavra reservada do Visual Basic.
Uma palavra reservada é uma palavra que o Visual Basic utiliza como parte de sua linguagem. Isso inclui instruções (como If e Loop), funções (como Len e Abs), operadores (como Or e Mod), palavras-chave, cláusulas SQL e propriedades e métodos de objetos. Exemplos: Dim strNomeEmpregado As String Dim intIdade As Integer Dim dblValorFatura As Double
5.1.2. Atribuição de valores à variáveis Em algoritmo, a atribuição de valor a uma variável é: nome_da_variável
← {valor}
No VBA, a atribuição é feita pelo sinal =. Exemplos: strNomeEmpregado = “CARLOS KOGA” intIdade = 25 curPreco = 45.76
Se o tipo da variável for um objeto, a atribuição deve ser precedida pela instrução Set. Dim dbsBanco As Database ' Objeto Database do DAO Set dbsBanco = DBEngine.WorkSpaces(0).Databases(0)
O valor atribuído tem que ser coerente com o tipo de dado da variável. Assim, se intIdade é do tipo inteiro, ocorrerá um erro se for atribuído um valor fracionário ou um valor fora do intervalo de valores permitidos. intIdade = 25.5 intNúmeroNatural
=
' Erro! O tipo é inteiro 32768 ' Erro! O valor é maior que
44
32767
Microsoft© Access Avançado
5.2. CONSTANTES As constantes podem ser de três tipos: • • •
Constantes simbólicas, que você cria utilizando a instrução Const e utiliza em módulos. Constantes intrínsecas, que fazem parte do Microsoft Access ou de uma biblioteca referenciada. Constantes definidas pelo sistema: True, False e Null.
5.2.1. Constantes Simbólicas Freqüentemente, você terá que utilizar os mesmos valores repetidamente no seu código ou descobrirá que o código depende de certos números que não têm significado óbvio. Nesses casos, você pode tornar o código bem mais fácil de ler e de manter utilizando constantes simbólicas (também chamadas de constantes definidas pelo usuário), que permitem que você utilize um nome significativo no lugar de um número ou seqüência. Uma vez que você tenha criado uma constante utilizando a instrução Const, você não poderá modificá-la ou atribuir um novo valor a ela. Você não pode também criar uma constante que tenha o mesmo nome que uma constante intrínseca. Os exemplos a seguir mostram algumas das maneiras pelas quais você pode utilizar a instrução Const para declarar constantes numéricas e de seqüência: Const conPI = 3.14159265 Const conPI2 = conPI * 2 Const conVersão = "Versão 7.0"
' Pi é igual a este número. ' Uma constante para criar outra. ' Uma constante de seqüência.
5.2.2. Constantes Intrínsecas Além das constantes que você declara com a instrução Const, o Microsoft Access declara automaticamente várias constantes intrínsecas e oferece acesso às constantes do VBA e às constantes de objetos referenciados no código. Qualquer constante intrínseca pode ser utilizada em uma macro ou no Visual Basic. Essas constantes estão disponíveis o tempo todo. As constantes intrínsecas têm um prefixo de duas letras identificando a biblioteca de objetos que define a constante. As constantes da biblioteca Microsoft Access são iniciadas com "ac"; as constantes da biblioteca DAO são iniciadas com "db" e as constantes da biblioteca VBA são iniciadas com "vb". Por exemplo: acForm dbAppendOnly vbCurrency
45
Microsoft© Access Avançado
Observação: Como os valores representados pelas constantes intrínsecas poderão ser alterados em versões futuras do Microsoft Access, você deve utilizar as constantes em vez de seus valores reais. Você pode utilizar constantes intrínsecas sempre que puder utilizar constantes simbólicas, inclusive em expressões. O exemplo a seguir mostra como você poderia utilizar a constante intrínseca vbCurrency para determinar se varNúm é do tipo Variant para a qual a função VarType retorna 6 (tipo Currency): Dim varNúm As Variant If VarType(varNúm) = vbCurrency Then Debug.Print "varNúm contém dados do tipo Currency." Else Debug.Print "varNúm não contém dados do tipo Currency." End If
Existem várias categorias de constantes intrínsecas. Para ver uma lista de constantes intrínsecas em uma determina categoria. Consulte no Help do Access os tópicos abaixo: • • • • • • • • •
As constantes de ação (do objeto DoCmd) As constantes DAO (Data Access Object) As constantes de procedimento de evento As constantes de Código de Tecla As constantes diversas As constantes do método RunCommand (constituem um subconjunto das constantes de ação) As constantes de segurança As constantes do Visual Basic As constantes da função VarType
5.2.3. Constantes Definidas pelo Sistema As constantes definidas pelo sistema são os valores lógicos True e False e a ausência de valor Null. Assim como as constrantes intrínsecas, elas também não precisam ser declaradas com a instrução Const. Você pode usar estas constantes em qualquer lugar do Access, tais como em consultas, macros, variáveis e propriedades de objetos.
46
Microsoft© Access Avançado
5.3. VETORES E MATRIZES As matrizes suportam de 1 até 60 dimensões. A matriz de apenas uma dimensão é chamada de vetor. A declaração das dimensões e dos intervalos de cada dimensão é feita com a instrução Dim, seguindo a sintaxe: Dim nomedavariável([ [LimiteInferior To] [LimiteSuperior] [,LimiteInferior To] Limite Superior] ....] ) As tipo ' Matriz de uma dimensão (vetor) com 5 elementos Dim intMatriz1( 1 To 5) As Integer ' Matriz de duas dimensões. A primeira com 10 e a segunda com 6 elementos ' O tamanho da string de cada elemento é variável. Dim strMatriz2( 1 To 10, 1 To 6) as String ' Matriz de 3 dimensões. O número de elementos depende da instrução Option Base na seção de declarações. O tamanho da string de cada elemento é 50. Dim strMatriz3( 5, 4 , 3) As String * 50
Se o limite inferior de uma dimensão não for explicitada, assume o valor padrão declarado pela instrução Option Base. Option Base é colocada na seção de declarações do módulo. Se Option Base for omitido, o limite inferior é 0. Para iniciar em 1, declara-se Option Base 1. Para explicitar o início em 0, declara-se Option Base 0. Uma das características do VBA é a declaração de matrizes dinâmicas, ou seja, o intervalo dos subscritos e o número de dimensões podem ser alterados conforme a necessidade que surgir durante o processamento. Matriz dinâmica é declarada sem especificar as dimensões, nem limites. Dim intDinamica()
As Integer
O redimensionamento é feito instrução Redim. Redim intDinamica( 1 To 5, 1 To 10) Redim intDinamica(8, 7, 4)
Você pode também declarar uma matriz dinâmica com Redim, mas neste caso, exigese que os subscritos tenham sido definidos. Este tipo de matriz pode ter seus intervalos alterados (para maior ou menor), mas não se pode alterar o número de dimensões. Redim Redim Redim Redim Redim Redim
A( ) As Integer B(5, 2) As Integer B(3, 1) B(5, 6, 10) B(100) B(100, 100)
' ' ' ' ' '
Erro OK Ok Erro Erro Ok
47
Microsoft© Access Avançado
5.4. TIPOS DEFINIDOS PELO USUÁRIO A instrução Type define um tipo de dado a partir dos tipos básicos. Seu emprego normalmente se aplica a um registro. Veja o exemplo. Type RegistroDePessoal strMatricula As String * 8 strNome As String * 35 strCodOrgao As String * 8 strCodCargo As String * 4 dtaDataNasc As Date End Type Dim MeuRegistro As RegistroDePessoal MeuRegistro.strMatricula = “80106650” MeuRegistro.strNome = “CARLOS KOGA” MeuRegistro.dtaDataNasc = #06/10/1964#
5.5. ESTRUTURA DE REPETIÇÃO O VBA possui as seguintes instruções de repetição: For...Next Do...Loop While...Wend For Each...Next 5.5.1. For..Next A estrutura For...Next é suportada por várias linguagens, e não apresenta diferenças. A sua sintaxe é: For {contador} = {início}To {fim} [Step {passo}] [instruções] [Exit For] [instruções] Next [contador]
48
Microsoft© Access Avançado
5.5.2. Do..Loop A estrutura Do...Loop implementa uma repetição enquanto uma condição for verdadeira (while) ou até uma condição se tornar verdadeira (until). Também implementa as saídas tanto de início quanto de final. Na repetição enquanto uma condição for verdadeira, acrescenta-se a cláusula WHILE {condição} após o DO (se for saída no início) ou após o LOOP (se for saída no final). Sub WhileSaídaNoInício() contador = 0 meuNúmero = 20 Do While meuNúmero > 10 meuNúmero = meuNúmero - 1 contador = contador + 1 Loop MsgBox "O loop concluiu " & contador & " repetições." End Sub Sub WhileSaídaNoFinal() contador = 0 meuNúmero = 9 Do meuNúmero = meuNúmero - 1 contador = contador + 1 Loop While meuNúmero > 10 MsgBox "O loop concluiu " & contador & " repetições." End Sub
Na repetição até que uma condição se torne verdadeira, acrescenta-se o UNTIL {condição} após o DO (se for saída no início) ou após o LOOP (se for saída no final). Sub UntilSaídaNoInício() contador = 0 meuNúmero = 20 Do Until meuNúmero = 10 meuNúmero = meuNúmero - 1 contador = contador + 1 Loop MsgBox "O loop concluiu " & contador & " repetições." End Sub Sub UntilSaídaNoFinal() contador = 0 meuNúmero = 1 Do meuNúmero = meuNúmero + 1 contador = contador + 1 Loop Until meuNúmero = 10 MsgBox "O loop concluiu " & contador & " repetições." End Sub
49
Microsoft© Access Avançado A saída da repetição pode ser forçada com a instrução Exit Do. intContador = 0 Do While True intContador = intContador + 1 if intContador > 10 Then Exit Do Endif Loop
5.5.3. While..Wend A estrutura While...Wend implementa somente a repetição enquanto uma condição for verdadeira e não admite saída forçada. Pontanto, é melhor substituí-la pela Do...Loop. While {condição} [instruções] Wend
5.5.4. For Each..Next A instrução For Each...Next é uma variação do For..Next específica para elementos dentro de matrizes ou de coleções de objetos. Dim varNomesMeses As Variant Dim strMes As String varNomesMeses = Array("Janeiro", "Fevereiro", "Março", "Abril", _ "Maio", "Junho", "Julho", "Agosto", _ "Setembro", "Outubro", "Novembro", "Dezembro") For Each strMes In varNomesMeses Debug.Print strMes Next
Neste outro exemplo, a coleção TableDefs possui vários objetos do tipo TableDef. Cada objeto de definição de tabela possui a propriedade Name. A instrução For Each...Next pode ser usada para listar todas as tabelas do banco de dados corrente. Dim tdfsTabelas As TableDefs Dim tdfTabela As TableDef Set tbfsTabelas = CurrentDb.TableDefs For Each tdfTabela In tdfsTabelas Debug.Print tdfTabela.Name Next
50
Microsoft© Access Avançado Uma construção similar pode ser obtida com somente a instrução For...Next. Dim tdfsTabelas As TableDefs Dim tdfTabela As TableDef Dim intContador As Integer Set tbfsTabelas = CurrentDb.TableDefs For intContador = 0 To tbfsTabelas.Count Debug.Print tdfTabela(intContador).Name Next
5.6. ESTRUTURA CONDICIONAL If...Then...Else Select Case On...Goto On..GoSub As instruções On..Goto e On..GoSub não serão mostradas porque Select Case pode substituí-las, gerando um código mais estruturado e flexível.
5.6.1. If...Then...Else A estrutura condicional mais simples é: { condição } Then [ instruções] End If
If
Uma estrutura composta contém a cláusula Else: If
{ condição } Then [ instruções]
Else [ instruções] End If
A instrução IF..Then..Else admite ElseIfs aninhados. If
{ condição } Then [ instruções]
51
Microsoft© Access Avançado
Elseif [ Elseif [ Elseif [ Else [ End If
{ condição 2} Then instruções] { condição 3} Then instruções] { condição 4} Then instruções] instruções]
Dim Número, Dígitos, MinhaSeqüência Número = 53 ' Inicializa a variável. If Número < 10 Then Dígitos = 1 ElseIf Número < 100 Then ' A condição avalia como True, então a próxima instrução é executada. Dígitos = 2 Else Dígitos = 3 End If
5.6.2. Select Case O Select Case é semelhante aos ElseIfs aninhados. Select Case expressãodeteste [Case listadeexpressões-n [instruções-n]] ... [Case Else [instruçõeselse]] End Select
Dim Número As Integer Número = 8 ' Inicializa a variável. Select Case Número ' Avalia Número. Case 1 To 5 ' Número entre 1 e 5. Debug.Print "Entre 1 e 5" ' A seguinte é a única cláusula Case que avalia como True. Case 6, 7, 8 ' Número entre 6 e 8. Debug.Print "Entre 6 e 8" Case Is > 8 And Número < 11 ' Número é 9 ou 10. Debug.Print "Maior que 8" Case Else ' Outros valores. Debug.Print "Não entre 1 e 10" End Select
52
Microsoft© Access Avançado
5.7. ENTRADA E SAÍDA DE DADOS Para fazer a leitura de dados via teclado em algoritmo você usa a instrução Leia . Em Clipper usa-se o comando @..GET para a sua implementação. Para a saída, o algoritmo usa a instrução Escreva, a qual é implementada no Clipper com @..SAY. No Clipper, tanto para entrada de dados quanto para a saída, usam-se os dois comandos para construir uma tela para posicionar os campos na tela, de forma a criar uma interface agradável e compreensível. No Access, há uma maneira mais fácil de efetuar a entrada e saída de dados, sem programação: é o objeto formulário. Tomemos por exemplo a função Extenso( ), cujo código é apresentado mais adiante. A maioria das funções requer argumentos de entrada, neste caso, um valor monetário. Como toda função, esta retorna o valor por extenso do valor informado. Tanto o argumento (entrada) quanto o retorno da função (saída) podem ser colocados em um formulário. O exemplo a seguir é um formulário simples, sem nenhuma fonte de dados. Por isso, em suas propriedades estão desativados o seletor de registros, os botões de navegação e as barras de rolagem. Há dois controles caixa de texto: txtValor e txtExtenso. O primeiro é um controle não acoplado, que receberá um valor monetário, e, por isso, está formatado com o tipo Moeda. O segundo é um controle calculado que contém o dado Extenso([txtValor]). Quando este receber o foco, chamará a função, levando o argumento txtValor e retornará uma string com o valor por extenso.
53
Microsoft© Access Avançado
Este exemplo simples mostra claramente que um formulário pode ser usado como entrada e saída, substituindo com vantagens os tradicionais comando de entrada via teclado e de saída na tela.
5.7.1. Funções do VBA para entrada e saída Às vezes você não quer usar um formulário para entrada e saída de dados. Você quer usar instruções no VBA para receber um único campo e enviar uma mensagem na tela. Para isto há a função InputBox e a função/instrução MsgBox. Dim curValor As Currency curValor = InputBox("Entre com o valor", "Valor monetário") MsgBox Extenso(curValor), vbOKOnly, "Valor por Extenso"
A execução deste fragmento de código resulta em duas janelas, mostradas abaixo.
54
Microsoft© Access Avançado
Se se quer capturar a resposta do usuário, usa-se a função MsgBox em vez da instrução. A sintaxe é a mesma, somente acrescenta-se a variável que receberá a resposta. intResposta = MsgBox(Extenso(curValor), vbOKOnly, "Valor por Extenso")
InputBox e MsgBox não são sofisticados quanto um formulário. InputBox não pode consistir um dado, usando por exemplo, um código VBA em módulo de formulário, nem formatar (usando a propriedade Formato do controle Caixa de Texto).
5.7.2. Outros dispositivos de entrada e saída Nem sempre a entrada de dados é via teclado. Pode ser via leitura de arquivo. A entrada e gravação de dados em formato de tabela são tratados no tópico Acesso a Dados, mais adiante. A leitura de dados de arquivos seqüenciais, randômicos e binários será vista também em outro tópico (Acesso a Arquivos e Impressora). Da mesma forma, a saída nem sempre é a tela de vídeo. O tópico Acesso a Arquivos e Impressora mostrará como direcionar a saída para arquivos em disco ou para a impressora local. Há um outro local para onde a saída pode ser direcionada: a Janela Depurar. Esta janela recebe a saída, a qual é visualizada quando a janela é aberta. A janela depurar serve testar e depurar a lógica de um programa. A saída para a janela depurar é feita pelo objeto Debug, do VBA, utilizando-se seu único método: o Print. A janela depurar é aberta com Control-G. Dim curValor As Currency curValor = InputBox("Entre com o valor", "Valor monetário") Debug.Print Extenso(curValor)
55
Microsoft© Access Avançado
5.8. COMENTÁRIOS Um comentário são textos não executáveis, ou seja, não são entendidos como um código de programação. Comentários servem para documentar e esclarecer uma rotina complexas. Uma linha de código torna-se um comentário se ela vier precedida de uma aspa simples. Não é necessário que toda a linha seja um comentário; você acrescentar um comentário após uma instrução. ' Toda esta linha é um comentário. MsgBox "Teste" ' A partir daqui tudo que for escrito é comentário.
Todo comentário é escrito na cor verde por padrão. Você pode alterar a cor nas opções do MS Access.
5.9. FUNÇÕES O MS Access possui um rol muito grande de funções prontas. Como você já deve saber, uma função é uma rotina que retorna um valor quando é chamada. A função pode receber nenhum, um ou mais argumentos de entrada. A lista de argumentos é passada entre parênteses após o nome da função. A função retorna somente um valor de um determinado tipo, e portanto, toda chamada de função deve ser atribuída a uma variável. Exemplos: Dim dtaDataDeHoje As Date Dim intAscii As Integer dtaData = Date() intAscii = Char(“A”)
Existem funções do Visual Basic for Applications, do DAO – Data Access Object e funções agregadas SQL. Apesar de todas poderem ser usadas no código VBA de uma aplicação em MS Access, é importante saber a origem das funções, pois você não pode usálas em qualquer aplicativo. Por exemplo, se a função é do DAO, você só pode chamar a função de estiver com o objeto DAO carregado. As funções do VBA podem ser usadas em qualquer aplicação VBA, seja no MS Access, no MS Excel, MS Word, no MS PowerPoint ou no MS Project. As funções do VBA são classificadas segundo o finalidade. Os grupamentos são: • • • • •
Funções literais Funções matemáticas Funções financeiras Funções de data Funções de conversão
Você não deve confundir função com instrução. Normalmente, as instruções são da cor azul e as funções aparecem na cor preta. Funções do VBA podem ser usadas na construção de expressões SQL. Por exemplo: 56
Microsoft© Access Avançado Dim strSql As String strSql = "SELECT NúmeroDoPedido, DataDoPedido, DataDeEntrega, " strSql = strSql + "DateDiff('d', [DataDoPedido], [DataDeEntrega] As Prazo " strSql = strSql + "FROM Pedidos" Me.RecordSource = strSql
Consulte a ajuda do MS Access para saber mais sobre funções.
5.10. ESCOPO DE IDENTIFICADORES O escopo refere-se a disponibilidade dos identificadores (variáveis, constantes e procedimentos) para uso por outros procedimentos. O escopo é definido quando se declara os identificadores. Existem dois níveis de escopo e dois de visibilidade que determinam onde e quando um identificador é reconhecido (visível), Níveis de escopo • Nível de procedimento • Nivel de módulo Níveis de visibilidade • Private • Public Escopo Nível de procedimento
Private Public Não se aplica. Todas as variáveis e contantes declaradas em nível de procedimento são Private, ou seja, somente podem ser acessadas dentro do procedimento em que foram declaradas. Estas variáveis são também chamadas variáveis locais Sub Teste( ) Dim intK As Integer
Nível de módulo
Todas as variáveis e constantes declaradas na seção de Declarações podem ser acessadas por todos os procedimentos daquele módulo.
57
Todas as variáveis e constantes declaradas com a instrução Public na seção de Declarações de um módulo podem ser acessadas por qualquer procedimento do banco de dado.
Microsoft© Access Avançado Option Compare Database Option Explicit Dim intK As Integer
Option Compare Database Option Explicit Public intK As Integer
Quanto aos identificadores de procedimento, o escopo é. Tipo de módulo Módulo de formulário/relatório
Módulo padrão
Escopo Todos os procedimentos são Private, mesmo que sejam usadas as instruções Private ou Public. Isto tem lógica, já que são procedimentos de evento, os quais devem responder a somente os eventos dos objetos formulário, relatório ou controle. Todos os procedimentos são Public, a não ser que seja colocada a instrução Private antes da declaração do procedimento. Private Sub Teste()
5.11. OBJETO DoCmd O objeto DoCmd é exclusivo do MS Access , portanto, você só pode utilizá-lo em programação VBA dentro do MS Access . Este objeto não possui nenhuma propriedade nem eventos, somente métodos. Os métodos executam ações do MS Access, tais como abrir um formulário, executar uma macro, alterar o formato do cursor, etc. Muitos dos métodos do objeto DoCmd requerem argumentos, alguns obrigatórios, outros opcionais. Consulte a ajuda do MS Access para saber os mais sobre o objeto DoCmd.
58
Microsoft© Access Avançado
6. LINGUAGEM SQL As consultas criadas na guia Consultas da janela de Banco de Dados nada mais são que instruções em linguagem SQL. A SQL – Structured Query Language (Linguagem Estruturada de Consulta) foi desenvolvida pela IBM em meados da década de 10 e padronizada pela ANSI (o padrão SQL ANSI-92). Fornecedores de software de banco de dados costumam ter variações do padrão ANSI. A SQL do Microsoft SQL Server é o Transact-SQL e o da Oracle é o PL/SQL. O Access utiliza uma variação da SQL ANSI, chamada Microsoft Jet Database Engine SQL. O Microsoft Jet Database Engine SQL é suportado no Microsoft Access e no Microsoft Visual Basic. A criação de consultas no MS Access é facilitada pela existência do modo Estrutura, uma espécie de editor gráfico que torna a tarefa mais intuitiva e fácil.
Você pode criar consultas no modo SQL, escrevendo diretamente as instruções SQL. Se você não tem conhecimento da linguagem SQL, poderá se familiarizar com ela criando consultas no modo Estrutura e visualizando-a no modo SQL.
Tendo uma consulta criada na guia Consultas, você pode abrí-la interativamente pelo botão Abrir da janela de Banco de Dados. O termo executar é mais apropriado que abrir. Via programação, a consulta pode ser executada pelo método OpenQuery do objeto DoCmd. 59
Microsoft© Access Avançado A compreensão da linguagem SQL permite desenvolver aplicações sofisticadas. Na realidade, você pode construir uma aplicação inteira sem nenhuma consulta ter sido criada na guia Consultas, porque: •
•
• • •
A propriedade Origem do Registro (RecordSource) de formulários e relatórios pode ter como valor uma tabela ou uma instrução SQL (criada pelo construtor de consultas), definidos em tempo de desenvolvimento (no modo Estrutura). O valor propriedade Origem do Registro de formulários e relatórios pode ser construído em tempo de execução, passado-o na forma de uma expressão SQL para a propriedade RecordSource do formulário ou relatório. Você pode substituir consultas de ação por expressões SQL criadas em tempo de execução e executá-las pelo método RunSQL do objeto DoCmd. Você pode construir expressões SQL em tempo de execução e visualizar os dados por meio de um formulário de consulta. Você pode construir expressões SQL em tempo de execução e acessar os dados pelo método OpenRecordset do objeto Database do DAO.
Além do mais, o conhecimento da linguagem SQL é imprescindível para a criação de consultas específicas SQL (União, Passagem e Definição de dados) e útil para desenvolver programas para acessar dados em bancos de dados cliente/servidor como o MS SQL Server e Oracle.
6.1. EXPRESSÃO SQL Uma expressão SQL é uma cadeia de caracteres (string) contendo instruções SQL. Sendo uma cadeia de caracteres, você pode construí-la em tempo de desenvolvimento ou de execução e atribuí-la a uma variável do tipo String. A variável pode ser usada como argumento ou ser atribuída à propriedade RecordSource de relatório ou formulário. Veja alguns exemplos de expressão SQL. Dim strSql As String strSql = "DELET * FROM [Detalhes do Pedido]" DoCmd.RunSql strSql Dim strSql As String Dim intNumeroPedido As Integer IntNumeroPedido = InputBox("Qual o número do pedido?") strSql = "SELECT NúmeroDoPedido, CódigoDoCliente, DataDoPedido, " strSql = strSql & "DataDeEntrega, DataDeEnvio " strSql = strSql & "FROM Pedidos WHERE NúmeroDoPedido " & intNumeroPedido Me.RecordSource = strSql
No primeiro exemplo, a expressão é atribuída à variável strSql e passada como argumento do método RunSql do objeto DoCmd. Trata-se de uma consulta de ação que excluirá todos os registros da tabela Detalhes do Pedido. O nome da tabela está entre colchetes porque possui espaços em seu nome. No segundo exemplo, uma expressão é construída com o número do pedido sendo informado em tempo de execução. A expressão é então atribuída à propriedade RecordSource do formulário/relatório ao qual o módulo de classe pertence. Note os espaços no final de cada atribuição de valor à variável strSql. Isto é necessário para que a sintaxe da instrução SQL seja correta, senão ocorreria uma expressão como DataDeEntrega, DataDeEnvioFROM, o que causaria um erro em tempo de execução. 60
Microsoft© Access Avançado Apesar de mais trabalhoso, o uso de expressões SQL em programação em vez de criar consultas na guia Consultas é mais seguro. Suponha que você cie uma consulta de ação que exclua todos os registros de uma tabela. Qualquer pessoa pode abrir o banco de dados e executá-la. É claro que você poderia evitar isto definindo permissão em nível de usuário. De qualquer forma, usar expressões SQL em programação dará mais flexibilidade e segurança a sua aplicação. NOTA: Toda sintaxe das expressões SQL é em inglês, não importa o idioma que você esteja usando, inclusive nomes de funções e formato de data.
6.2. INSTRUÇÕES BÁSICAS SQL Não se pretende aqui ensinar a linguagem SQL, mas sim passar noções, restritamente do Microsoft Jet Database Engine SQL. NOTA: Se você for programar no MS Visual Basic para acessar banco de dados do MS SQL Server, deve usar a sintaxe do Transact-SQL. A maneira mais fácil de se criar expressões SQL é construir a consulta na guia Consultas, alternar para o modo SQL, selecionar todo o texto, copiar e colar no módulo para contruir a expressão. As consultas são agrupadas segundo a sua finalidade. Ao construir uma consulta pelo modo Estrutura, tem-se 4 tipos básicos: Seleção, Atualização, Exclusão, Acréscimo e Criação de tabela. O quadro a seguir mostra quais instruções SQL caracterizam cada tipo de consulta: Tipo de consulta Consulta seleção Consulta atualização Consulta de exclusão Consulta acréscimo Consulta criação de tabela
Instrução SQL característica SELECT UPDATE DELETE INSERT INTO SELECT INTO
6.2.1. Consulta Seleção A consulta seleção é a mais comum de todas. Ela retorna um conjunto de dados vindos de uma ou mais tabelas relacionadas. Quando se programa, este conjunto não é visível como no modo Folha de Dados, mas fica na memória do computador para ser acessado. Os dados também não podem ser alterados como ocorre no modo Folha de Dados, a não ser que você execute métodos de inserção, atualização ou exclusão do objeto RecordSet. A consulta seleção possui cláusulas e características específicas deste tipo de consulta e também outras comuns aos demais tipos. Veremos aqui algumas das cláusulas e características comuns mais detalhadamente para poupar mais explicações nas consultas seguintes. A sintaxe básica da consulta seleção começa com a instrução SELECT. Sua forma mais simples é: 61
Microsoft© Access Avançado SELECT {listadecampos |*} FROM {tabela} Esta instrução retorna os campos selecionados em listadecampos ou todos os campos se você utilizar o *. Todos os registros da tabela especificada por tabela são recuperados porque não há uma cláusula de critério. Os campos são recuperados na ordem em que eles foram escritos na listadecampos. Os campos são separados por vírgulas. Exemplos: SELECT * FROM Pedidos
Esta instrução retorna todos os campos e todos os registros da tabela Pedidos. SELECT CódigoDoProduto, NomeDoProduto, CódigoDoFornecedor FROM Produtos
Esta instrução retorna três campos e todos os registros da tabela Produtos. A sintaxe completa é: SELECT [predicado] { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]} FROM expressãodetabela [, ...] [IN bancodedadosexterno] [WHERE {critérioswhere} ] [GROUP BY campo1 [, campo2] [,campoN... ] ] [HAVING {critérioshaving} ] [ORDER BY campo1 [ASC|DESC] [, campo2 [ASC|DESC] ] [,campoN [ASC|DESC] ... ] ] [WITH OWNERACCESS OPTION]
A instrução SELECT extrai as colunas (campos) escolhidas, selecionando as linhas (registros) que atendam aos critérios da cláusula WHERE e classifica (ORDER BY) em orde crescente (ASC, que é o padrão) ou decrescente (DESC) ou agrupa (GROUP BY) as linhas resultantes na ordem especificada. A cláusula WITH OWNERACCS OPTION significa que o usuário que está executando a consulta possui as mesmas permissões que o criador da consulta. Isto tem sentido em um ambiente multi-usuário em que se definir segurança em nível de usuário. Os argumentos da instrução são: Argumento Predicado
* Tabela
campo1, campo2, campoN
Descrição Um dos predicados a seguir: ALL, DISTINCT, DISTINCTROW ou TOP. Você utiliza o atributo para restringir o número de registros retornados. Se nenhum for especificado, o padrão será ALL. Especifica que todos os campos da tabela ou tabelas especificadas estão selecionados. O nome da tabela contendo os campos a partir dos quais os registros são selecionados. É um argumento opcional. Você só precisa definí-lo caso suas tabelas possuam o mesmo nome de campo, como é o caso do campo PreçoUnitário, que consta das tabelas Produto e Detalhes do Pedido do banco de dados Northwind. Produto.PreçoUnitário, [Detalhes do Pedido].PreçoUnitário É a lista de campos a ser recuperada. Se você incluir mais de um campo, eles serão recuperados na ordem listada. O campo pode ser uma expressão literal, matemática ou lógica. Os nomes dos campos são usados nas cláusula ORDER BY para 62
alias1, alias2, aliasN
Expressãodetabela Bancodedadosexterno Critérioswhere Critérioshaving
Microsoft© Access Avançado definir a ordem de classificação e na cláusula GROUP BY para definir os grupamentos. Os nomes a serem utilizados como cabeçalhos de coluna em lugar dos nomes originais de coluna em tabela. Se omitido, assume o valor da propriedade Legenda na estrutura da tabela. Caso a propriedade Legenda esteja em branco, assume o nome do campo. Se um dos campos for uma expressão e não for definido um alias, é assumido Expr1, Expr2, Expr3 e assim por diante. Você não pode usar alias nas clausulas ORDER BY nem em GROUP BY. O nome da tabela ou relacionamento de tabelas contendo os dados que você deseja recuperar. O nome do banco de dados que contém as tabelas em expressãodetabela se elas não estiverem no banco de dados atual. É uma expressão lógica que filtra os registros que atendam ao critério definido na expressão. É uma expressão lógica que filtra os registros após eles terem sidos agrupados. A cláusula HAVING deve obrigatoriamente vir com a cláusula GROPU BY.
Nomes de campos ou de tabelas ou de alias que possuam espaços devem vir entre colchetes. Exemplo: SELECT CD_Matric AS Matrícula, [Nome do empregado] AS Nome FROM [Cadstro de Pessoal]
6.2.1.1. Argumento Predicado O argumento predicado assume valores que são palavras reservadas da linguagem SQL. Os predicados podem ser as seguintes palavras reservadas: PREDICADO ALL DISTINCT DISTINCTROW TOP n [PERCENT]
FINALIDADE Indica que serão selecionados todos os registros que atendam aos critérios da seleção. É assumido se nenhum predicado for utilizado. Omite registros que contêm dados duplicados em campos selecionados. Omite dados com base em registros inteiramente duplicados e não somente campos duplicados. Retorna um número fixo de registros que ficam na parte superior ou inferior de um intervalo especificado por uma cláusula ORDER BY.
Para enteder o predicado, considere as tabelas: CLIENTES ID_CLIENTE 1 2 3 4 5
NOME JOSE PAULO SIMONE CARLOS PENELOPE
SOBRENOME SANTOS VIANNA CASTRO SANTOS CHARMOSA
DT_NASC 06/07/1956 07/09/1952 10/11/1965 21/01/1960 07/09/1952
63
CARGO 001 002 001 001 002
Microsoft© Access Avançado PEDIDOS NR_PEDIDO 1 2 3 4 5 6 7
ID_CLIENTE 1 4 5 5 3 3 1
DATA 01/01/98 02/01/98 02/01/98 03/01/98 04/01/98 10/01/98 01/01/98
VALOR 500,00 100,00 30,00 15,00 60,00 90,00 120,00
PREDICADO ALL
A consulta a seguir retornará todos os registros da tabela Clientes. SELECT ALL Clientes.* FROM Clientes
é equivalente a SELECT Clientes.* FROM Clientes
PREDICADO DISTINCT
A consulta a seguir omitirá um dos registros cujo sobrenome é SANTOS. SELECT DISTINCT Clientes.SOBRENOME FROM Clientes
A consulta a seguir retornará todos os registros, pois DISTINCT não terá efeito porque há mais de um campo selecionado. SELECT DISTINCT Clientes.* FROM Clientes
PREDICADO DISTINCTROW
A consulta a seguir retornará todos os registros da tabela Clientes, exceto o cliente Paulo Vianna. SELECT DISTINCTROW Clientes.* FROM Clientes INNER JOIN Pedidos ON Clientes.ID_CLIENTE = Pedidos.ID_CLIENTE
Se o predicado DISTINCTROW não fosse usado, apareceriam múltiplas linhas para os clientes com mais de um pedido. Esta consulta a seguir não sofre o efeito de DISTINCTROW pois não existem registros repetidos, já que NR_PEDIDO tem valor distinto em cada valor. SELECT DISTINCTROW Clientes.*, Pedidos.NR_PEDIDO FROM Clientes INNER JOIN Pedidos ON Clientes.ID_CLIENTE = Pedidos.ID_CLIENTE
PREDICADO TOP
A consulta a seguir retornará os nomes dos 2 clientes mais idosos cujos cargos é 001. SELECT TOP 2 NOME FROM Clientes WHERE CARGO ="001"
64
Microsoft© Access Avançado ORDER BY DT_NASC
A consulta a seguir retornará os nomes de 2% dos clientes mais idosos, cujo cargo é 001. SELECT TOP 2 NOME FROM Clientes WHERE CARGO ="001" ORDER BY DT_NASC
O predicado TOP não distingue valores iguais. Portanto, a consulta a seguir retornará dois registros e não somente um. SELECT TOP 1 NOME FROM Clientes WHERE CARGO = "002" ORDER BY DT_NASC
6.2.1.2. Expressões na lista de campos Em qualquer dialeto da SQL é possível usar expressões literais, matemáticas ou lógicas como se fosse um campo de uma tabela. Por exemplo: SELECT CódigoDoProduto, PreçoUnitário, Quantidade, Desconto, ((PreçoUnitário * Quantidade) – (PreçoUnitário * Quantidade * Desconto)) AS Subtotal FROM [Detalhes do Pedido]
Não existe um campo subtotal na tabele Detalhes do Pedido. Ele é o alias da expressão que calcula o subtotal de um item do pedido. Quando se usa expressão nas lista de campos, ela se chama campo calculado. Linguagens SQL como o Microsoft SQL Server possui funções próprias da linguagem as quais podem ser usadas para criar campos calculados. A diferença do Microsoft Jet Database Engine SQL é que você pode usar funções do próprio Microsoft Jet Database Engine SQL, funções do VBA e funções definidas pelo usuário para criar campos calculados. O Microsoft Jet Database Engine SQL possui a função agregada Avg() para calcular a média de um valor. SELECT Avg(PreçoUnitário) AS [Média de preços] FROM Produtos
O Microsoft Jet Database Engine SQL não possui a função WeekDay(), que é do VBA. Mas você pode usá-la em expressões SQL que serão executadas no MS Access ou no MS Visual Basic. SELECT WeekDay(DataDoPedido) AS [Dia da semana] FROM Pedidos
Procedimentos do tipo Function, criadas em módulo padrão e com visibilidade Public, podem ser usadas na contrução de campos calculados. Veja este exemplo: SELECT NomeDoProduto, Fatura(Quantidade, PreçoUnitário) AS Valor FROM [Detalhes do Pedido]
O código do procedimento Fatura fica alojado no módulo padrão. Function Fatura(Qtd, PreçoUnit) As Currency
65
Microsoft© Access Avançado If Qtd < 5 Then ' Não tem desconto Fatura = Qtd * PreçoUnit Else ' Tem desconto de 10% sobre a fatura Fatura = (Qtd * PreçoUnit) * 0.90 End If End Function
6.2.1.3. Argumento Expressãodetabela O argumento de tabela pode ser apenas o nome de uma tabela, como no exemplo: SELECT * FROM Produtos
Entretanto, ela pode ser composta por mais de uma tabela, como no exemplo: SELECT NúmeroDoPedido, NomeDoProduto, [Detalhes do Pedido].PreçoUnitário, Quantidade FROM Produtos INNER JOIN [Detalhes do Pedido] ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto
No caso anterior, as tabelas Produtos e Detalhes do Pedido estão relacionadas pelo campo CódigoDoProduto, que constam nas duas tabelas. Relembrando a modelagem de dados, a cardinalidade entre Produtos e Detalhes do Pedido é uma-para-muitos. CódigoDoProduto na tabela Produtos é chave primária (primary key) enquanto CódigoDoProduto na tabela Detalhes do Pedido é chave estrangeira (foreing key). A cláusula INNER JOIN especifica que há um relacionamento entre as tabelas, do tipo de associação 1. No modo estrutura, o tipo de associação é definido na caixa de diálogo mostrada a seguir.
Os tipos de associações são: Tipo de associação 1
Cláusula SQL
Descrição
Representação do conjunto
INNER JOIN
Inclui somente os registros cujos valores dos campos relacionados são iguais. Isto quer dizer que retorna somente os dados da interseção entre as duas 66
Microsoft© Access Avançado 2
LEFT JOIN
3
RIGHT JOIN
tabelas Inclui todos os registros da tabela à esquerda e somente os registros da tabela à direita quando os valores dos campos relacionados forem iguais. Inclui todos os registros da tabela à direita e somente os registros da tabela à esquerda quando os valores dos campos relacionados forem iguais.
Dizer qual tabela está à direita e qual está à esquerda depende da ordem em que elas são escritas na expressão. Se se quiser incluir todos os registros da tabela produtos, pode se usar tanto LEFT JOIN quanto RIGHT JOIN, dependendo a ordem em que os nomes das tabelas são escritas. FROM Produtos LEFT JOIN [Detalhes do Pedido]
Isto equivale a: FROM [Detalhes do Pedido] RIGHT JOIN Produtos
Naturalmente, a ordem da escrita dos nomes das tabelas não tem efetio quando se usa INNER JOIN. INNER JON, LEFT JOIN e RIGHT JOIN simplesmente diz quais tabelas e os tipos de associações existentes entre elas, mas não define quais os campos relacionados. Após escrever os nomes das tabelas e o tipo de associação, acrescenta-se a cláusula ON seguido dos campos relacionados. No exemplo a seguir, as tabelas são relacionados pelo campo CódigoDoProduto FROM Produtos INNER JOIN [Detalhes do Pedido] ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto
Note que como os nomes dos campos são iguais nas duas tabelas, é necessário colocar o nome da tabela antes dos nomes dos campos, separados por ponto. Normalmente o operador de comparação é o =. Mas você pode usar >, >=, <., <= ou <>. Não é comum usar operadores que não seja o =, mas se você usá-los, o modo Estrutura não consegue exibir este relacionamento. Casos os relacionamento seja com dois ou mais campos, você deve usar o operador lógico AND. SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.B = Table2.B) AND (Table1.A = Table2.A)
Você pode mais de duas tabelas relacionadas. O modo de contrução é o mesmo. SELECT * FROM Produtos INNER JOIN (Pedidos INNER JOIN [Detalhes do Pedido] ON Pedidos.NúmeroDoPedido = [Detalhes do Pedido].NúmeroDoPedido) ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto
67
Microsoft© Access Avançado Note o uso de parênteses na junção entre Pedidos e Detalhes do Pedido. Somente depois desta junção é feita a junção com Produtos. 6.2.1.4. Tabelas em banco de dados externos Como você viu na introdução deste cursos, dados e processos residem em arquivos diferentes. Você pode construir uma consulta ou uma expressão SQL para acessá-los sem ter que vincular tabelas. Isto é possível com a cláusula IN do SQL. SELECT * FROM Clientes INNER JOIN Pedidos ON Clientes.CódigoDoCliente = Pedidos.CódigoDoCliente IN "D:\CursosOffice\AccessBasico\NW.mdb"
No caso, as duas tabelas devem estar no mesmo banco de dados. Você não pode recuperar dados de tabelas em bancos de dados distintos. Você pode acessar tabelas externas em formatos diferente, como Excel, Paradox ou dBase. Você coloca duas aspas seguido dos argumentos Especificador e Origem do tipo de arquivo. No capítulo sobe acesso a banco de dados há a lista completa dos argumentos para a cláusula IN. SELECT * from Customers IN "" [Excel 8.0; DATABASE=C:\Book1.xls]
Para melhor desempenho, use tabelas vinculadas em vez da cláusula IN. 6.2.1.5. Cláusula Where Enquanto o argumento listadecampos restringe quais campos devem ser recuperados, a cláusula WHERE restringue quais linhas devem ser recuperadas. A cláuslua WHERE define uma expressão lógica sob a qual cada registro é validado. Se atender à condição imposta pela expressão lógica, o registro é recuperado, caso contrário é desprezado. Operadores lógicos A expressão lógica pode conter os um ou mais dos seguintes operadores relacionais: = (igual) < (menor) <= (menor ou igual) > (maior) >= (maior ou igual) <> (diferente) Os operandos podem ser campos, campos calculados ou constantes que, se forem do mesmo tipo de dados, podem ser comparados com um dos operadores relacionais. No Microsoft Jet Database Engine SQL não se admite variáveis na expressão lógica. Se você utilizar uma variável e criar a consulta, esta será assumida como um parâmetro da consulta. Se tentar usar variável em expressão SQL, tal colocação acarretará em erro em tempo de execução. 68
Microsoft© Access Avançado Você pode usar variáveis em expressão SQL por meio de um artifício, como mostrado abaixo. Dim strSql As String Dim intNumeroPedido As Integer IntNumeroPedido = InputBox("Qual o número do pedido?") strSql = "SELECT NúmeroDoPedido, CódigoDoCliente, DataDoPedido, " strSql = strSql & "DataDeEntrega, DataDeEnvio " strSql = strSql & "FROM Pedidos WHERE NúmeroDoPedido " & intNumeroPedido
A consulta a seguir recuperará todos os campos da tabela Produtos, retornando somente os registros cujo valor unitário (campo PreçoUnitário) seja maior que 10. SELECT * FROM Produtos WHERE PreçoUnitário > 10
Note que a comparação é entre um campo e uma constante. Apesar de o campo ser do tipo moeda (currency) o valor da constante não contém o símbolo da unidade monetária R$. Operadores lógicos Se for necessário fazer mais comparações, você pode utilizar-se dos operadores lógicos AND, OR e NOT. A comparação se faz entre dois operandos de cada vez. Você não pode ter uma expressão do tipo A > B > C. Ela deve ser escrita da forma A > B AND B > C SELECT * FROM Produtos WHERE PreçoUnitário > 10 AND NOT Descontinuado
Operadores IN, BETWEEN e LIKE Além dos operadores relacionais e dos operadores lógicos, você pode operadores IN, BETWEEN e LIKE IN significa contido em um conjunto discreto de valores. Por exemplo, In (“A+”, “B+”, “O+”, “AB+”) especifica um critério que seleciona somente os de tipo sangüíneo RH positivo. Não confunda o operador IN com a instrução IN. SELECT * FROM [Detalhes do Pedido] WHERE CódigoDoProduto IN(14,24,48,55)
Between filtra os valores que estão dentro de um conjunto contínuo de valores. Por exemplo, Between 1000 AND 5000 seleciona os registros cujo valor de um campo esteja entre 1000 e 5000, inclusive. SELECT * FROM Pedidos WHERE DataDoPedido BETWEEN #01/31/95# AND #05/15/95#
Like permite um comparação parcial de string, conforme a máscara de comparação. Pode-se usara caracteres especiais na máscara. Caracter *
Função Retorna caracteres múltiplos
? # []
Retorna carater simples Retorna dígito simples Retorna intervalo de valores
Máscara o*o *ab* *ANA k* o?o MI# b[a-m] 69
Retorna ovo, Ocaso, osso, OTELO abc, Abdomem, cabeça Fabiana, cana, CABANA Katana, kibe, kamikaze Oco, ovo, OMO Mi6, mi2, MI0 Ba, bb, BC, BJ, bf
[!]
Retorna valores fora do intervalo
b[!a-m] A[!0-9]
Microsoft© Access Avançado bx, BW, BV AA, A$, ac, A+
SELECT * FROM Clientes WHERE NomeDoContato LIKE "mar*"
Outras expressões A expressão lógica da cláusula WHERE pode conter ainda as constantes definidas pelo sistema True e False, expressões (como Is Null), funções do VBA e funções definidas pelo usuário. SELECT * FROM Funcionarios WHERE False SELECT * FROM Pedidos WHERE DateDiff("d”, DataDoPedido, DataDeEntrega) > 5 SELECT NomeDaEmpresa FROM Clientes LEFT JOIN Pedidos ON Clientes.CódigoDoCliente = Pedidos.CódigoDoCliente WHERE NúmeroDoPedido Is Null
6.2.1.6. Funções agregadas SQL Funcções agregadas SQL efetuam cálculos com um conjunto de registros, retornando valores sumarizados. Por exemplo, se você quiser saber o valor total dos pedidos, terá de usar a função agregada SUM. Você não saberá o valor de cada pedido, mas sim a soma de todos os registros de pedidos. As funções agregadas são: FUNÇÃO AVG (Média) COUNT (Contar) MAX (Máx) MIN (Mín) STDEV, STDEVP (Desv) SUM (Soma) VAR, VARP (Var) FIRST (Primeiro) LAST (Último)
FINALIDADE Calcula a média aritmética de um conjunto de valores contidos em um campo especificado em uma consulta. Calcula o número de registros que retornam de uma consulta. Retorna o valor máximo de um conjunto de valores contidos em um campo especificado em uma consulta Retorna o valor mínimo de um conjunto de valores contidos em um campo especificado em uma consulta. Retorna a estimativa do desvio padrão de uma população ou de uma amostra de uma população representada como um conjunto de valores contidos em um campo especificado em uma consulta. Retorna a soma de um conjunto de valores contidos em um campo especificado em uma consulta. Retorna as estimativas da variância de uma população ou de uma amostra da população representada como um conjunto de valores contidos em um campo especificado em uma consulta. Retorna o primeiro registro de um conjunto de registros retornado por uma consulta. Retorna o primeiro registro de um conjunto de registros retornado por uma consulta.
Exemplos: SELECT COUNT(*) AS [Qtd Itens] FROM [Detalhes do Pedido]
70
Microsoft© Access Avançado SELECT MIN(DateDiff("d”, DataDoPedido, DataDeEntrega)) AS [Prazo mínimo], AVG(DateDiff("d”, DataDoPedido, DataDeEntrega)) AS [Prazo Médio], MAX(DateDiff("d”, DataDoPedido, DataDeEntrega)) AS [Prazo Máximo] FROM Pedidos
6.2.1.7. Cláusulas GROUP BY e HAVING As cláusulas GROUP BY e HAVING são usadas em conjunto com as funções agregadas SQL. GROUP BY agrupa os registros por um ou mais campos. Por exemplo, se você quiser saber o prazo médio de entrega de cada pedido, deve agrupar pelo campo do NúmeroDoPedido SELECT Pedidos.NúmeroDoPedido, Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) AS [Prazo Médio] FROM Pedidos GROUP BY Pedidos.NúmeroDoPedido
Todos os campos que aparecerem na lista de campos devem obrigatoriamente ser um campo de agrupamento ou alvo de uma função SQL. A consulta abaixo falhará porque DataDoPedido não faz parte de GROUP BY nem de uma função agregada. SELECT NúmeroDoPedido, DataDoPedido, Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) AS [Prazo Médio] FROM Pedidos GROUP BY NúmeroDoPedido
A cláusula HAVING é semelhante ao WHERE, porém atua sobre os registros retornados. O exemplo abaixo primeiramente calcula a média e depois filtra os registros cujas médias sejam maior que 20. SELECT NúmeroDoPedido, DataDoPedido, Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) AS [Prazo Médio] FROM Pedidos GROUP BY NúmeroDoPedido HAVING Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) > 20
A cláusula WHERE atua antes da agregação. No exemplo abaixo, a cláusula WHERE primeiramente filtra somente os pedidos do ano 1996, depois é calculada a média e a cláusula HAVING filtra os que ultrapassaram a média de 20 dias. SELECT NúmeroDoPedido, Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) AS [Prazo Médio] FROM Pedidos WHERE Year(DataDoPedido) = 1996 GROUP BY NúmeroDoPedido HAVING Avg(DateDiff("d",[DataDoPedido],[DataDeEntrega])) > 20
6.2.2. Consulta de atualização A consulta de atualização não retorna nenhum conjunto de registros, mas sim atualiza um ou mais campos de uma tabela ou mais tabelas. UPDATE {expressãodetabela} SET campo1 = valor1 [, campo2 = valor2] [, campoN = valorN]
71
Microsoft© Access Avançado [WHERE {condiçãoWhere}]
No exemplo abaixo, os campos Via e Quantidade são atulizados. Os campos são de tabelas distintas. A atualização afeta somente os itens de produtos descontinuados. UPDATE Produtos INNER JOIN ( Pedidos INNER JOIN [Detalhes do Pedido] ON Pedidos.NúmeroDoPedido = [Detalhes do Pedido].NúmeroDoPedido ) ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto SET Pedidos.Via = 1, [Detalhes do Pedido].Quantidade = 6 WHERE Descontinuado
6.2.3. Consulta de exclusão A consulta de exclusão elimina os registros de uma única tabela. Se você não definir uma condição na cláusula WHERE, todos os registros serão excluídos. A tabela de onde o registros forem excluídos pode estar relacionada a outras tabelas. DELETE [tabela.*] FROM {expressãodetabela} [WHERE {condiçãoWhere}]
Para excluir registros de uma única tabela, sem relacionamento, a sintaxe é: DELETE * FROM {tabela}
Caso haja tabelas relacionadas, você deve especificar o nome da tabela de onde osz registros devem ser excluídos. Exemplo: DELETE [Detalhes do Pedido].* FROM Produtos INNER JOIN [Detalhes do Pedido] ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto WHERE Descontinuado
Se a tabela possuir integridade referencial do tipo resctrict, os registros não serão excluídos. Se a integridade for do tipo cascade, os registros da tabela relacionada também serão excluídos. 6.2.4. Consulta acréscimo Você pode inserir um único registro em uma tabela ou vários registros provenientes de uma seleção em outra tabela. Para um único registro, a sintaxe é: INSERT INTO {tabela} [(campo1, campo2, campoN, ...)] VALUES (valor1, valor2, valorN, ...)
A identificação da lista de campos é opcional. Se você não a defnir, os valores serão inseridos na mesma ordem em que os campos foram criados no modo Estrutura da tabela. INSERT INTO Table1 VALUES ("0033", "PEG SUE", 2, "SP")
72
Microsoft© Access Avançado Se definir a lista de campos, cada valor estará associado ao campo na ordem em que foram digitados na instrução INSERT. INSERT INTO Table1 (EstadoCivil, UF, Nome, Matricula) VALUES ( 1, "MG", "CARLOS KOGA","0021")
Se você não especificar todos os campos da tabela, o campo omitido assumirá o valor padrão ou nulo, caso as propriedades Valor padrão e Requerido estejam configurados na estrutura da tabela. Suponha que os campos EstadoCivil possua a propriedade Requerido=Não e UF possui a propriedade Valor Padrão = “MG”. As instruções abaixo inserirão dois registros com o campo EstadoCivil como nulo e UF com “MG”. INSERT INTO Table1 (Matricula, Nome) VALUES ("0021", "CARLOS KOGA") INSERT INTO Table1 VALUES ("0033", "PEG SUE")
Você pode explicitamente inserir nulo usando a constante NULL. INSERT INTO Table1 VALUES ("0033", "PEG SUE", NULL)
A inserção deve respeitar todas as restrições da tabela, tais como unicidade de chave primária, integridade referrencial, valor requerido, regra de validação, tamanho do campo e compatibilidade de tipo de dados. Você pode inserir registros em uma tabela com registros provenientes de outras tabelas. INSERT INTO {tabela} IN bancodedadosexterno (campo1, campo2, campoN, . . .) SELECT argumentosSelect
6.2.5. Consulta de criação de tabela
73
Microsoft© Access Avançado
7. FORMULÁRIOS AVANÇADOS Os formulários podem ser usados como:
Formulário de manutenção de tabelas Caixa de diálogo Formulário de consulta Caixa de mensagem
Formulários de manutenção de tabelas podem ser criadas facilmente pelo Assistente de Formulário. Tais formulários, criados por Assistentes, são simples e carecem de aprimoramento. Via programação, podemos aperfeiçoá-las, incluindo código de validação de dados, controle de fluxo, botões de navegação personalizados, botões para inclusão de novos registros, para exclusão de registros, para alteração de dados e para pesquisa.
7.1. FORMULÁRIO DE MANUTENÇÃO DE TABELAS Um formulário simples, criado pelo Assistente de Formulário ou diretamente pelo modo estrutura, possui uma fonte de dados - a propriedade Origem do registro (RecordSource), e controles acoplados que se referem a cada um dos campos da origem do registro. Controles acoplados possuem o nome do campo na propriedade Origem do controle (ControlSource). Os controles podem ser de diversos tipos, dependendo da característica do dado que o campo contém, como por exemplo caixa de texto, caixa de combinação, caixa de verificação, caixa de grupo, etc. Você pode ter também controles calculados, cuja propriedade Origem do controle contém uma expressão. A navegação de registros, isto é, o avanço e retrocesso de registros pelo formulário, é feita pelos Botões de navegação (NavigationButtons). Os botões de navegação incluem a operação de inclusão de novos registros As operações de filtragem, exclusão e pesquisa de registros e impressão do formulário são realizadas pela barra de menus ou pela barra de ferramentas. Note que todas as operações citadas acontecem a partir de uma única tela. Não há um formulário específico para consulta, outro inclusão e outro para edição (alteração e exclusão). Isto leva à pergunta: “Qual a melhor forma de construir formulários de manutenção de tabelas?”. A resposta é sempre “Depende”. 7.1.1. Botões de Navegação Personalizados Em vez de usar os botões de navegação do formulário, você pode criar botões personalizados para navegar pelos registros. Basta criar botões de comando e vincular a código VBA. A propriedade Botões de navegação do formulário é definida como Não.
74
Microsoft© Access Avançado
Private Sub cmdFirstRecord_Click() DoCmd.RunCommand acCmdRecordsGoToFirst End Sub Private Sub cmdPreviousRecord_Click() On Error Resume Next DoCmd.RunCommand acCmdRecordsGoToPrevious End Sub Private Sub cmdNextRecord_Click() On Error Resume Next DoCmd.RunCommand acCmdRecordsGoToNext End Sub Private Sub cmdLastRecord_Click() DoCmd.RunCommand acCmdRecordsGoToLast End Sub
O botão de comando cmdPreviousRecord possui a linha On Error Resume Next para que não ocorra erro ao tentar retroceder um registro quando se está no primeiro registro. O botão de comando cmdPreviousRecord possui a linha On Error Resume Next para que não ocorra erro ao tentar avançar um registro quando se está no último registro. Há um erro de comportamento neste formulário. A navegação deveria ocorrer somente com os botões personalizados. Entretanto, a tecla Tab, além de mudar de campo, muda de registro quando se encontra no último campo. Para desabilitar esta caracterísitca, altere a propriedade de formulário Ciclo (Cycle) para Registro corrente (Current Record). Outro problema é que cmdNextRecord adiciona um registro ao tentar avançar além do último registro. Para resolver isto, altere a propriedade de formulário Permitir adição (Allow Additions) para Não.
75
Microsoft© Access Avançado
7.2. CAIXA DE DIÁLOGO Uma caixa de diálogo serve para captar dados que serão enviados como parâmetros de procedimento, consulta, relatório ou outro formulário. Antes de explicar como enviar parâmetros, você deve definir as propriedades de um formulário para desempenhar o papel de caixa de diálogo: Propriedade do formulário Guia Formato (Format) Legenda (Caption) Modo padrão (Default View) Modos permitidos (Views Allowed) Barras de rolagem (Scroll bars) Seletores de registro(Record Selectors) Botões de navegação (Navigation Buttons) Linhas divisórias (Dividing Lines) AutoCentralizar (Auto Center) Estilo da vorda (Border Style) Botões Min Max (Min Max Buttons) Guia Dados (Data) Origem do registro (RecordSource)
Valor O título da caixa de diálogo Formulário simples (Single form) Formulário (Form) Nenhuma (Neither) Não (No) Não (No) Não (No) Sim (Yes) Diálogo (Dialog) Nenhum (None) Vazio
Uma caixa de diálogo terá dois botões de comando: Um para prosseguir (Ok) e outro para fechar a caixa de diálogo (Fechar). Normalmente, as propriedades e eventos dos botões de comando são: Propriedade Legenda (Caption) Nome (Name) Padrão (Default) AoClicar (Onclick)
Valor &Ok cmdOk Sim (Yes) Chamada específica (Ver exemplos a seguir)
Propriedade Legenda (Caption) Nome (Name) Cancelar (Cancel) AoClicar (OnClick)
Valor &Fechar cmdFechar Sim (Yes) Private Sub cmdFechar_Click() DoCmd.Close End Sub
Normalmente, controles caixas de texto são não acopladas e recebem os valores que serão passados como parâmetros para proicedimentos, consultas parametrizadas, relatórios e formulários.
76
Microsoft© Access Avançado 7.2.1. Passagem De Parâmetros Para Procedimento Esta é a técnica mais simples. O procedimento chamado pelo formulário pode ser Sub ou Function definido em módulo atrás do formulário (módulo de classe de formulário) ou em módulo padrão. O evento AoClicar do botão cmdOk fará a chamada do procedimento enviando o valor do controle como argumento do procedimento. Private Sub cmdOk_Click() Dim curValor As Currency Dim strExtenso As String curValor = Me.txtValor strExtenso = Extenso(curValor) End Sub
7.2.2. Passagem De Parâmetros Para Consulta Parametrizada As consultas parametrizadas possuem critério dinânico, ou seja, o valor do critério de filtragem da consulta é informado quando da execução da consulta. Por exemplo, a consulta seleção, cujo código SQL é mostrado a seguir, pedirá o valor do parâmetro [Qual o número do pedido] por meio de uma caixa de diálogo simples. SELECT Pedidos.NúmeroDoPedido, Pedidos.CódigoDoCliente, Pedidos.DataDoPedido FROM Pedidos WHERE Pedidos.NúmeroDoPedido = [Qual o número do pedido];
Esta não é uma forma elegante de passar parâmetros para consulta, pois para cada parâmetro da consulta será aberta uma caixa de diálogo. Estas caixas de diálogo de consulta parametrizada não validam nenhum dado informado pelo usuário. A solução é criar um formulário do tipo caixa de diálogo que receberá todos os parâmetros de uma só vez e o botão Ok acionará a consulta. Os parâmetros podem ser formatados e/ou validados pelo formulário antes de ser enviado para a consulta, garantindo que o usuário informe parâmetros válidos para a consulta. Para demonstrar a solução da consulta do exemplo acima, construiremos uma caixa de diálogo chamada frmDlg_Consulta_Pedido. Ela conterá os botões cmdOk e cmdFechar, como visto anteriormente. A caixa de texto txtNumeroPedido é não acoplada e o seu valor será passado como parâmetro para a consulta qryConsulta_Pedido.
77
Microsoft© Access Avançado
O botão cmdOk conterá o seguinte código VBA associado ao evento AoClicar Private Sub cmdOk_Click() DoCmd.OpenQuery "qryConsulta_Pedido" End Sub
A consulta qryConsulta_Pedido terá o seguinte código SQL. SELECT Pedidos.NúmeroDoPedido, Pedidos.CódigoDoCliente, Pedidos.DataDoPedido FROM Pedidos WHERE Pedidos.NúmeroDoPedido = Forms![frmDlg_Consulta_Pedido].txtNumeroPedido;
A consulta funciona porque o formulário está aberto e seus controles podem ser acessados por outros objetos do Access. Esta técnica é útil para aplicativos em que a segurança não é um ponto importante. Note que a janela folha de dados da consulta, caso seja uma consulta seleção ou referência cruzada, é aberta, permitindo que o usuário possa alterar a estrutura, modificar os dados ou excluir registros. A técnica de tela de consulta, como veremos mais adiante, resolve estes problemas.
7.2.3. Passagem De Parâmetros Para Relatório Às vezes precisamos de relatórios mais flexíveis, como por exemplo, emitir os pedidos feitos entre duas datas. Precisamos passar a data inicial e a data final para a origem dos dados (normalmente uma consulta seleção). Uma alternativa de solução é criar uma consulta parametrizada, passando parâmetros pelo formulário. O relatório então se baseará nesta consulta. Por exemplo, o formulário frmDlg_Relatorio_Pedido contém as caixas de texto não acopladas txtDataInicial e txtDataFinal. Estes controles são parâmetros para a consulta qryRelatorio_Pedido.
78
Microsoft© Access Avançado
A consulta qryRelatorio_Pedido possui o código SQL. SELECT Pedidos.NúmeroDoPedido, Pedidos.CódigoDoCliente, Pedidos.DataDoPedido FROM Pedidos WHERE Pedidos.DataDoPedido BETWEEN Forms![frmDlg_Relatorio_Pedido].txtDataInicial AND Forms![frmDlg_Relatorio_Pedido].txtDataFinal;
O relatório rptRelatorio_Pedido é baseado na consulta qryRelatorio_Pedido, ou seja, a sua propriedade Origem do registro (RecordSource) é qryRelatorio_Pedido. O botão cmdOk do formulário frmDlg_Relatorio_Pedido contém o código VBA associado ao evento AoClicar. Private Sub cmdOk_Click() DoCmd.OpenReport "rptRelatorio_Pedido", acViewPreview End Sub
Esta técnica é difícil de ser administrada devido à interação de três objetos do Access (um formulário, uma consulta e um relatório). Quanto mais objetos o banco de dados possui, maior a complexidade e mais difícil é sua manutenção. Além disso, esta técnica restringe-se a filtrar a origem do registro utilizando uma consulta parametrizada. Uma outra técnica mais elaborada baseia-se na possibilidade de acessar controles de formulários que estão abertos. Controles de formulários abertos possuem visibilidade public, ou seja, eles são acessíveis em qualquer parte do Access. É por isso que consultas parametrizadas funcionam. Uma caixa de diálogo para abrir relatórios podem construir uma expressão SQL em tempo de execução, armazená-la em uma caixa de texto oculta e ser usada como parâmetro para um relatório. Desta forma, elimina-se a necessidade de se construir um objeto consulta, diminuindo-se a quantidade de objetos no banco de dados e, consequentemente, a complexidade de manutenção. Além disso, outros parâmetros podem direcionar o comportamento do relatório, tal como definir a ordem de classificação, incluir mensagem adhoc no relatório, ocultar/exibir seções do relatórios, dentre outras possibilidades. Para demonstrar esta técnica, usaremos o mesmo exemplo acima. O formulário frmDlg_Relatorio_Pedido conterá adicionalmente uma caixa de texto txtSql, com estas propriedades configuradas: Propriedade Visivel (Visible) Parada de tabulação (Tab Stop)
Valor Sim (Yes) Não (No)
79
Microsoft© Access Avançado O botão cmdOk conterá o código VBA associado ao evento AoClicar: Private Dim Dim Dim
Sub cmdOk_Click() strSql As String strDataInicial As String strDataFinal As String
strDataInicial = Me.txtDataInicial strDataFinal = Me.txtDataFinal strSql strSql strSql strSql strSql
= = = = =
"SELECT Pedidos.NúmeroDoPedido, Pedidos.CódigoDoCliente, " strSql + "Pedidos.DataDoPedido " strSql + "FROM Pedidos " strSql + "WHERE Pedidos.DataDoPedido BETWEEN #" strSql + strDataInicial + "# AND #" + strDataFinal + "#"
Me.txtSql = strSql DoCmd.OpenReport "rptRelatorio_Pedido", acViewPreview End Sub
O relatório rptRelatorio_Pedido terá a propriedade Origem do registro (RecordSource) vazia e o seguinte código associado ao evento AoAbrir. Private Sub Report_Open(Cancel As Integer) Me.RecordSource = Forms![frmDlg_Relatorio_Pedido].txtSql End Sub
Usando esta técnica, podemos modificar outras propriedades do relatório em tempo de execução, usando parâmetros da caixa de diálogo. O próximo exemplo acrescenta a opção de ordem de classificação dos dados do relatório. Uma caixa de grupo permite escolher se a ordem será por Número do pedido ou por Código do cliente. Lembre-se que a cláusula ORDER BY da origem do registro não afeta a classificação do relatório.
A propriedade que define a ordem de classificação dos dados no relatório é GroupLevel. Um relatório pode ter até 10 níveis de grupo. Assim, a propriedade GroupLevel funciona como um vetor de 10 elementos. GroupLevel(0) é o primeiro nível de grupo. GroupLevel possui as propriedades: Propriedade
Valor
80
Microsoft© Access Avançado ControlSource GroupOn GroupInterval KeepTogether SortOrder
Campo ou expressão pelo qual os dados serão classificados Agrupamento dos dados. O padrão é agrupar por cada valor. O intervalo pelo qual os dados são agrupados. O padrão é 1 (intervalo para cada valor) Mantém ou não o grupo na mesma página quando é impresso. O padrão é 0 (não mantém na mesma página) False para ascendente (padrão), True para descendente
O evento AoAbrir do relatório rptRelatorio_Pedido conterá o código: Private Sub Report_Open(Cancel As Integer) Dim bytOpcao As Byte Me.RecordSource = Forms![frmDlg_Relatorio_Pedido].txtSql bytOpcao = Forms!frmDlg_Relatorio_Pedido.grpClassificacao If bytOpcao = 1 Then Me.GroupLevel(0).ControlSource = "NúmeroDoPedido" Else Me.GroupLevel(0).ControlSource = "CódigoDoCliente" End If End Sub
7.2.4. Passagem De Parâmetros Para Formulário A passagem de parâmetros de um formulário para outro pode usar a mesma técnica de passagem de parâmetros para relatório, mostrada acima. Entretanto, formulários podem receber parâmetros de outra forma. O objeto DoCmd possui o método OpenForm, cuja sintaxe é: DoCmd.OpenForm formname[, view][, filtername][, wherecondition][, datamode][, windowmode][, openargs]
Argumento formname view
filtername wherecondition datamode
Descrição O nome do formulário a ser aberto. Uma das seguintes constantes intrínsecas: acDesign acFormDS acNormal (padrão) acPreview acNormal abre o formulário no modo formulário. Se você deixar em branco, assume o padrão. Uma expressão que é o nome de uma consulta válida no banco de dados. Pode ser também uma expressão SQL. Uma expressão de até 32768 caracteres para critério de filtragem. A sintaxe é a mesma para a cláusula WHERE da linguagem SQL, exceto que não é preciso colocar a palavra WHERE. Uma das seguintes constantes intrínsecas: acFormAdd acFormEdit acFormPropertySettings (padrão) acFormReadOnly 81
Microsoft© Access Avançado
windowmode
openargs
Se você deixar em branco, assume o padrão, que é abrir o formulário de acordo com o modos atribuído nas propriedades Permitir edição (AllowEdits), Permitir exclusão (AllowDeletions), Permitir adição (AllowAdditions) e Entrada de dados (DataEntry). Uma das seguintes constantes intrínsecas: acDialog acHidden acIcon acWindowNormal (padrão) Se você deixar em branco, assume o padrão. Uma expressão literal passada como argumento.
Os argumentos filtername e wherecondition compõem a propriedade Filtro (Filter) do formulário. Se você especificar ambas, o valor da propriedade Filtro será uma expressão lógica com as duas condições ligadas pelo operador lógico AND. Por exemplo, se filtername for definido como: "SELECT Clientes.* FROM Clientes WHERE Left([CódigoDoCliente],1)='A'"
a propriedade Filtro terá o valor: (Left([CódigoDoCliente],1)='A')
Se além de filtername for especificado wherecondition como: "Cidade = 'México D.F.'"
a propriedade Filtro terá o valor: (Cidade = 'México D.F.') AND (Left([CódigoDoCliente],1)='A')
Você pode construir um filtro em tempo de execução usando os argumentos filtername e wherecondition. Por exemplo, suponha que o formulário frmClientes apresente todos os registros da tabela Clientes do banco de dados Northwind. Você deseja consultar/editar somente os registros dos clientes de uma cidade especificada em uma caixa de diálogo frmDlg_Formulario_Clientes. O procedimento de evento AoClicar do botão cmdOk da caixa de diálogo conterá este código: Private Sub cmdOk_Click() Dim strCidade As String Dim strWhereCondition As String strCidade = Me.txtCidade ' É uma caixa de texto não acoplada strWhereCondition = "Cidade = '" + strCidade + "'" DoCmd.OpenForm "frmClientes", , , strWhereCondition End Sub
Uma outra forma de passar parâmetros de um formulário para outro é usar o argumento openargs do DoCmd. openargs é um texto que pode ser capturado no formulário especificado em formname usando a propriedade de formulário OpenArgs. Esta propriedade deve estar em um código dentro do procedimento de evento AoAbrir do formulário que será aberto por DoCmd. 82
Microsoft© Access Avançado Suponha que você tenha que abrir o formulário frmClientes e queira posicionar no registro referente ao cliente ANTON. Construa um procedimento que abra o formulário frmClientes, passando “ANTON” como argumento. Aqui, o procedimento chama-se AbreCliente. Sub AbreCliente() DoCmd.OpenForm "frmClientes", , , , , , "ANTON" End Sub
O procedimento de evento AoAbrir do formulário frmClientes conterá o código: Private Sub Form_Open(Cancel As Integer) Dim strCliente As String Dim rstCopia As Recordset If Not IsNull(Me.OpenArgs) Then strCliente = Me.OpenArgs Set rstCopia = Me.RecordsetClone rstCopia.FindFirst "CódigoDoCliente= '" + strCliente + "'" If Not rstCopia.NoMatch Then Me.Bookmark = rstCopia.Bookmark End If End If End Sub
A propriedade RecordsetClone do formulário cria uma cópia da origem do registro (propriedade RecordSource do formulário) e armazena na variável rstCopia. É usado o método FindFirst para localizar o cliente “ANTON”, valor este capturado pela propriedade OpenArgs do formulário. A propriedade NoMatch do objeto recordset (veja Acesso a Banco de Dados) indica se o registro foi localizado ou não. Caso seja localizado, a propriedade Bookmark posiciona o registro correto para ser exibido no formulário frmClientes.
7.3. FORMULÁRIO DE CONSULTA Abrir uma consulta criada na guia Consulta da janela Banco de Dados é a maneira mais simples de visualizar dados. Entretanto, o modo Folha de Dados de uma consulta possui uma apresentação é pobre. Na realidade, o modo Folha de Dados não é só para consulta, pois permite que o usuário apague ou altere dados.
83
Microsoft© Access Avançado
Usar formulário e sub-formulário é uma boa alternativa para se visualizar dados somente para leitura.
O primeiro passo é criar um subformulário para a apresentar os detalhes. As principais propriedades do subformulário são: Propriedade Nome Origem do Registro
Modo Padrão
Valor SubfrmDetalhes_Pedido SELECT [Detalhes do Pedido].NúmeroDoPedido, Produtos.NomeDoProduto, [Detalhes do Pedido].PreçoUnitário, [Detalhes do Pedido].Quantidade, [Detalhes do Pedido].Desconto, ([Detalhes do Pedido].[PreçoUnitário]-[Detalhes do Pedido].[PreçoUnitário]*[Desconto])*[Quantidade] AS SubTotal FROM Produtos INNER JOIN [Detalhes do Pedido] ON Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto; Formulários contínuos
84
Microsoft© Access Avançado Barras de Rolagem Seletor de Registros Botões de Navegação Permitir edições Permitir exclusões Permitir adições
Somente vertical Não Não Não Não Não
O formulário principal conterá o subformulário, entretanto, não haverá vínculo entre eles, ou seja, não há um campo que relacione os valores do formulário e do subformulário. A propriedade Origem do Registro (RecordSource) do subformulário será definido via programação. Pode haver um ou mais caixas de texto ou caixa de combinação não acoplados, cujos valores serão o filtro para a apresentação dos registros no subformulário. Por esta razão não é necessário haver vinculação entre formulário e subformulário. Neste exemplo, o filtro é feito pela caixa de combinação cboNumeroPedido. Este valor será usado na construção da expressão SQL que será a Origem do Registro do subformulário. A instrução SQL é criada ao abrir o formulário, ao clicar no botão Buscar e ao clicar o botão Limpar. A instrução SQL no evento AoAbrir é a mesma no evento AoClicar. Constrói-se a instrução tal qual foi feito no subformulário, mas acrescenta-se a cláusula WHERE False para não apresentar nenhum registro. Private Sub Form_Open(Cancel As Integer) Dim strSql As String strSql = "SELECT [Detalhes do Pedido].NúmeroDoPedido, Produtos.NomeDoProduto, " strSql = strSql + "[Detalhes do Pedido].PreçoUnitário , [Detalhes do Pedido].Quantidade, " strSql = strSql + "[Detalhes do Pedido].Desconto, " strSql = strSql + "([Detalhes do Pedido].[PreçoUnitário]-[Detalhes do Pedido].[PreçoUnitário]*[Desconto])*[Quantidade] AS SubTotal " strSql = strSql + "FROM Produtos INNER JOIN [Detalhes do Pedido] ON " strSql = strSql + "Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto where false" Me.subfrmDetalhes_Pedido.Form.RecordSource = strSql Me.subfrmDetalhes_Pedido.Requery Me.txtTotal = 0 Me.txtRegistros = 0 End Sub
Na linha de instrução Me.subfrmDetalhes_Pedido.Form.RecordSource = strSql é atribuído o valor da propriedade Origem do Registro do subformulário. Na linha seguinte é utilizado o método Requery para que o subformulário re-execute a instrução SQL. O evento AoClicar possui um código semelhante, apenas há o acréscimo da inibição do botão Exportar XLS e a limpeza do valor na caixa de combinação cboNumeroPedido. Private Sub cmdLimpar_Click() Dim strSql As String
85
Microsoft© Access Avançado strSql = "SELECT [Detalhes do Pedido].NúmeroDoPedido, Produtos.NomeDoProduto, " strSql = strSql + "[Detalhes do Pedido].PreçoUnitário , [Detalhes do Pedido].Quantidade, " strSql = strSql + "[Detalhes do Pedido].Desconto, " strSql = strSql + "([Detalhes do Pedido].[PreçoUnitário]-[Detalhes do Pedido].[PreçoUnitário]*[Desconto])*[Quantidade] AS SubTotal " strSql = strSql + "FROM Produtos INNER JOIN [Detalhes do Pedido] ON " strSql = strSql + "Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto WHERE False" Me.subfrmDetalhes_Pedido.Form.RecordSource = strSql Me.subfrmDetalhes_Pedido.Requery Me.txtTotal = 0 Me.txtRegistros = 0 Me.cboNumeroPedido = "" Me.cmdExportToExcel.Enabled = False End Sub
O botão Buscar é que realiza a busca dos registros a serem apresentados no subformulário. No exemplo, foram incluídas duas funcionalidades opcionais: cálcular o valor do pedido e a quantidade de itens a serem apresentados nas caixas de texto txtTotal e txtRegistros e criar uma consulta para que os dados sejam exportados para o MS Excel. Note que o botão Exportar XLS somente é habilitado (propriedade Enabled) após a criação da consulta qryExportXLSTemp Private Sub cmdBuscar_Click() Dim rst As Recordset Dim strSql As String Dim intNumPedido As Variant Dim curTotal As Currency Dim dblQtdRegistros As Double Dim qdf As QueryDef ' Cria a expressão SQL para que o subformulário apresente os dados intNumPedido = Me.cboNumeroPedido strSql = "SELECT [Detalhes do Pedido].NúmeroDoPedido, Produtos.NomeDoProduto, " strSql = strSql + "[Detalhes do Pedido].PreçoUnitário , [Detalhes do Pedido].Quantidade, " strSql = strSql + "[Detalhes do Pedido].Desconto, " strSql = strSql + "([Detalhes do Pedido].[PreçoUnitário]-[Detalhes do Pedido].[PreçoUnitário]*[Desconto])*[Quantidade] AS SubTotal " strSql = strSql + "FROM Produtos INNER JOIN [Detalhes do Pedido] ON " strSql = strSql + "Produtos.CódigoDoProduto = [Detalhes do Pedido].CódigoDoProduto " strSql = strSql + "WHERE [Detalhes do Pedido].NúmeroDoPedido = " & intNumPedido Me.subfrmDetalhes_Pedido.Form.RecordSource = strSql ' Totaliza o valor do pedido curTotal = 0 dblQtdRegistros = 0 Set rst = Me.subfrmDetalhes_Pedido.Form.RecordsetClone Do While Not rst.EOF curTotal = curTotal + rst("Subtotal") dblQtdRegistros = dblQtdRegistros + 1 rst.MoveNext Loop
86
Microsoft© Access Avançado rst.Close Me.txtTotal = curTotal Me.txtRegistros = dblQtdRegistros ' Cria uma consulta para ser exportada para o MS Excel On Error Resume Next CurrentDb.QueryDefs.Delete "qryExportXLSTemp" Set qdf = CurrentDb.CreateQueryDef("qryExportXLSTemp", strSql) Me.cmdExportToExcel.Enabled = True End Sub
Como o botão Buscar cria uma consulta, a qryExportXLSTemp, em tempo de execução, podemos aproveitá-la para exportar os dados para o Excel pelo método TransferSpreadsheet do objeto DoCmd. Existe uma função definida pelo usuário chamada CaixaDialogo_Save que será explicada mais adiante. Private Sub cmdExportToExcel_Click() Dim strFileName As String strFileName = CaixaDialogo_Save("Salvar dados para MS Excel ", CurDir, _ "Microsoft Excel" + Chr$(0) + "*.xls" + Chr$(0), _ "Pedidos", "*.xls") If strFileName = "" Then MsgBox "Informe o nome do arquivo!" Else DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel, _ "qryExportXLSTemp", strFileName End If End Sub
Finalmente, o botão Fechar possui o código mais simples. Private Sub cmdFechar_Click() DoCmd.Close End Sub
7.4. CAIXA DE MENSAGEM O modo mais simples de se ter caixas de mensagem é usar a intrução MsgBox ou a função MsgBox( ). O inconveniente disto é estas caixas de mensagem sempre acarreta uma pausa na execução do programa, pois você deve clicar em pelo menos um dos botões da caixa. Você pode usar uma formulário somente com mensagens, sem nenhum botão de comando. Isto é útil, por exemplo, para exibir uma mensagem AGUARDE enquanto um processamento longo é executado. Tipicamente um formulário para ser usado como caixa de mensagem possui as propriedades: Propriedade Modo padrão Modos permitidos Barras de rolagem
Valor Formulário simples Formulário Nenhum 87
Microsoft© Access Avançado Seletores de registro Botões de navegação Auto centralizar Estilo da borda Caixa de controle Botões Min e Max Botão fechar
Não Não Sim Fino Não Ambos desativados Não
O código para apresentar a caixa de mensagem deve ter as seguintes instruções: DoCmd.OpenForm "nome_do_formulário" DoEvents . . DoCmd.Close acForm, "nome_do_formulário"
A primeira linha do código abre o formulário no modo formulário. OpenForm é um método do objeto DoCmd. A segunda contém a função DoEvents que passa o controle para o sistema operacional, permitindo que a janela seja exibida. Se não for colocada DoEvents, a tela ficará congelada e nada será exibido. A última instrução fecha o formulário.
88
Microsoft© Access Avançado
8. ACESSO A BANCO DE DADOS O acesso a banco de dados no Access usa o modelo DAO – Data Access Object e o mecanismo Jet (Jet Engine). O DAO é um conjunto de classes de objetos que modela a estrutura de um sistema de banco de dado relacional. Eles oferecem propriedades e métodos que lhe permitem realizar todas as operações necessárias para gerenciar tal sistema, incluindo recursos para criar banco de dados, definir tabelas, campos e índices, establecer relações entre tabelas, navegar e consultar o banco de dados, e assim por diante. O Jet Engine traduz estas operações de objetos de acesso a dados em operações físicas sobre os próprios arquivos de banco de dados, tratando toda a mecânica da interface com os diferentes bancos de dados suportados. O Visual Basic, por meio do DAO e do Jet Engine reconhece três categorias de bancos de dados: Bancos de dados nativos São os bancos que utilizam o formato do Microsoft Access. Eles são criados e manipulados diretamente pelo Jet Engine, e oferecem a máxima flexibilidade e velocidade. Bancos de dados externos São os bancos ISAM (Indexed Sequential Access Method), nos quais estão incluídos os formatos dBase III, dBase IV, Btrieve, FoxPro, Paradox, arquivos texto, planilhas Excel e planilhas Lotus 1-2-3. Bancos de dados ODBC São bancos de dados cliente/servidor que atendem ao padrão ODBC, tais como o MS SQL Server e o Oracle. Existem outros métodos de acesso a banco de dados que não utilizam o Jet Engine. Somente para citar: • • • •
ODBCDirect RDO e RDC Chamada à API do OBDC ADO (ActiveX Data Objects)
8.1. Hierarquia do Objetos DAO Para usar os objetos de acesso a dados, é necessário conhecer o modelo DAO.
89
Microsoft© Access Avançado
No topo da hierarquia está o mecanismo de banco de dados do Jet Engine, representado pelo objeto DBEngine. Ele é o único objeto que não está contido em nada. Abaixo dele está uma coleção Workspaces (coleções são usadas no plural dos objetos que ela contém). A única finalidade das coleções é conter outros objetos do mesmo tipo.
8.2. Sintaxe para Referenciar Objetos em Coleção Os membros de uma coleção, isto é, os objetos, podem ser acessados por um número índice base-zero. Assim, o primeiro workspace é o Workspaces(0), que é o workspace atual (aquele que é criado quando você abre o Access). O primeiro database é o Databases(0), que é o banco de dados atual (o arquivo mdb que está aberto). Os objetos na hierarquia são identificados por um caminho completo das coleções acumuladas a que pertencem, usando o ponto (.) para separá-los. Assim, o objeto database que representa o arquivo mdb no qual você está trabalhando é referido como: DBEngine.Workspaces(0).Databases(0)
Além do número índice, usa-se uma referência explícita do nome do objeto dentro da coleção. Por exemplo, um campo CódigoDoLivro é um objeto field dentro de uma coleção Fields. Se ele for o primeiro campo, ele pode ser referenciado por: Fields(0)
Ou Fields(“CódigoDoLivro”)
90
Microsoft© Access Avançado
8.3. Coleção Padrão A maior parte dos objetos de acesso a dados possui uma coleção padrão. Por exemplo, a coleção padrão de recordset é Fields. Isto permite omitir a coleção da sintaxe. intCodigo =
rst!CódigoDoLivro ‘ Obtém o valor do campo “CódigoDoLivro”
Que é equivalente a: intCodigo =
rst.Fields!CódigoDoLivro
Ou à: intCodigo =
rst.Fields(“CódigoDoLivro”)
Ou ainda à: intCodigo =
rst.Fields(0)
Note que intCodigo é uma variável do tipo inteiro que armazena o valor do objeto e não o objeto. Valor é umas das propriedades do objeto.
8.4. Referência a Objetos por meio de Variáveis Cada objeto pode (e ás vezes deve) ser atribuído à uma variável do mesmo tipo do objeto. Dim Dim Set Set
wks dbs wks dbs
As Workspace As Database = DBEngine.Workspaces(0) = wks.Databases(0)
Se quiser, pode economizar algumas linhas de código com esta sintaxe: Dim dbs As Database Set dbs = DBEngine.Workspaces(0).Databases(0)
Neste caso específico, a economia pode ser maior se se usar a função CurrentDb para retornar o banco de dados atual. O uso de variáveis simplifica a referência a objetos nas mais baixas níveis da hierarquia do DAO.
8.5. Propriedades e Métodos
91
Microsoft© Access Avançado Um dos princípios da orientação a objeto é manter dados e procedimentos de um objeto dentro do próprio objeto. Os dados dos objetos são chamados de propriedades enquanto que os procedimentos chamam-se métodos. Usando variáveis para referenciar os objetos, torna-se prática a programação orientada a objetos. Para entender os conceitos acima, vamos usar os objetos recordset e field. Um Recordset é o conjunto de registros retornado por uma tabela, por uma consulta que retorne registros (seja esta uma consulta previamente criada na guia de Consultas da janela de Banco de Dados ou criada em tempo de execução, através de comandos SQL). Um field é o próprio campo da tabela. Para obter um objeto recordset, usa-se o método OpenRecordset do objeto database. O objeto é então atribuído à uma variável, declarada anteriormente como do tipo Recordset. Dim rst As Recordset Set rst = CurrentDb.OpenRecordset(“Tabela1”)
Abrir um recordset é semelhante ao comando USE do Clipper. Como visto, o objeto field é referido por um índice base-zero ou explicitamente pelo nome do campo. O objeto field pode ser atribuído à uma variável declarada como do tipo Field. Dim fldCampo1 As Field Set fldCampo1 = rst.Fields(“CódigoDoLivro”)
Para obter o valor deste objeto, usa-se a propriedade Value. intCampo = fldCampo1.Value
intCampo é uma variável do tipo inteiro que armazena o valor do objeto e não o objeto, o qual já é referenciado por fldCampo1. Em vez de usar a propriedade Value, pode-se simplesmente referenciar diretamente o objeto, omitindo-se a propriedade. intCampo = rst.Fields(“CódigoDoLivro”)
Para obter os valores dos campos para os demais registros, usa-se o método MoveNext do objeto recordset. Pode-se, assim, percorrer sequencialmente todo o recordset. rst.MoveNext
Este método é semelhante ao SKIP do Clipper. A leitura sequencial do recordset irá terminar quando se chegar ao seu fim. A propriedade EOF do objeto recordset. Para entender os métodos e propriedades vistos até agora, veja uma analogia com o Clipper 92
Microsoft© Access Avançado OPERAÇÃO
CLIPPER
Abrir arquivo de dados
USE {arquivo} SKIP
Recordset
MoveNext
SKIP –1
Recordset
MovePrevious
GoTop()
Recordset
MoveFirst
GoBottom() SKIP [± n]
Recordset Recordset
MoveLast Move [± n]
Eof() Bof() {nome do campo}
Recordset Recordset Fields
EOF BOF Fields({índice}) ou Fields( {nome do campo} ) ou Fields!{nome do campo})
Field Recordset Recordset
Value !{nome do campo} Close
Mover ponteiro de registro para frente Mover ponteiro de registro para trás Ir para o primeiro registro Ir para o último registro Saltar n registros para frente ou para trás Testar fim de arquivo Testar início de arquivo Obter o valor de um campo
Fechar arquivo de dados
CLOSE
VISUAL BASIC COLEÇÃO/ PROPRIEDADE/MÉTODO OBJETO Database OpenRecordset( {recordset} )
8.6. Acesso a Banco de Dados Access Vamos tomar como exemplo os conjuntos de registros abaixo para escrever um código que percorra todos os registros de um recordset e imprima o valor de seus campos . O primeiro conjunto de registro refere-se à tabela Livros, o segundo à tabela Tópicos, o terceiro à consulta seleção qryLivros_versus_Tópicos e o quarto à uma consulta gerada em tempo de execução, através da expressão SQL: SELECT Tópicos.Tópico, Count(Livros.CódigoDoLivro) AS Quantidade FROM Tópicos RIGHT JOIN Livros ON Tópicos.CódigoDoTópico = Livros.CódigoDoTópico GROUP BY Tópicos.Tópico;
Tabela: Livros Código do Livro 1 2 3 4
Título Dirk Luchte Planejando Sua Diamantes Técnicas de Tai Chi
Código do Tópico 5 1 6 4 93
Nome do Editor GGG&G Editora Jean-Paul Deloria Editora Ramona Editora Ramona
Preço de R$23,50 R$22,95 R$9,95 R$25,95
5
Minha Família
Microsoft© Access Avançado Publicações R$17,95
5
Os campos da tabela Livros são: CódigoDoLivro, Título, CódigoDoTópico, NomeDoEditor, e PreçoDoPedido
Tabela: Tópicos Código do Tópico 1 2 3 4 5 6 7
Tópico Negócios Psicologia Ciência Saúde Ficção Romance Técnico
Os campos da tabela Tópicos são: CódigoDoTópico e Tópico Consulta seleção: qryLivros_versus_Tópicos Título Tópico Planejando Sua Carreira Negócios Técnicas de Tai Chi Saúde Dirk Luchte Ficção Minha Família Ficção Diamantes Romance Consulta seleção com função agregada Tópico Quantidade Ficção 2 Negócios 1 Romance 1 1 Comecemos por fazer uma leitura sequencial de cada registro da tabela Livros, listando os conteúdos dos campos Título e NomeDoEditor. O primeiro passo, é então criar um objeto database que contenha o banco de dados atual. ' Declara um ojeto database (banco de dados) Dim dbsBancoAtual As Database ' Atribui o banco atual ao objeto database Set dbsBancoAtual = DBEngine.Workspaces(0).Databases(0)
O banco de dados atual pode ser referido simplesmente por: 94
Microsoft© Access Avançado Set dbsBancoAtual = CurrentDb
Um objeto recordset tem que ser aberto no banco de dados atual. Assim, vamos declarar um objeto recordset e usar o método OpenRecordset do objeto database. ' Declara um ojeto database (banco de dados) Dim dbsBancoAtual As Database ' Declara um ojeto recordset Dim rstTabela As Recordset ' Atribui o banco atual ao objeto database Set dbsBancoAtual = DBEngine.Workspaces(0).Databases(0) ' Abre o recordset e o atribui ao objeto recordset Set rstTabela = dbsBancoAtual.OpenRecordset(“Livros”)
Para pegar um determinado campo, poderíamos criar um objeto Field para cada o campo, uma para Título e outro para o campo NomeDoEditor, mas em vez disto vamos pegar o valor do próprio objeto Field, explicitando o nome do campo dentro da coleção Fields. rstTabela.Fields(“Título”) rstTabela.Fields(“NomeDoEditor”)
O nome do objeto Field deve ser o nome do campo e não a sua legenda. Por isso , está escrito NomeDoEditor e não Nome do Editor. Falta ainda criar uma estrutura de repetição do VBA que percorra todo o recordset. Vamos usar o Do...Loop, com a condição While (enquanto) verificando o fim do de arquivo. O fim de arquivo pode ser obtido pela propriedade EOF do objeto recordset. A navegação pelos registros é feita pelo método MoveNext do objeto recordset. ' Declara um ojeto database (banco de dados) Dim dbsBancoAtual As Database ' Declara um ojeto recordset Dim rstTabela As Recordset ' Atribui o banco atual ao objeto database Set dbsBancoAtual = DBEngine.Workspaces(0).Databases(0) ' Abre o recordset e o atribui ao objeto recordset Set rstTabela = dbsBancoAtual.OpenRecordset(“Livros”) Do While Not rstTabela.EOF Debug.Print rstTabela.Fields(“Título”) & “ - “ & rstTabela.Fields(“NomeDoEditor”) rstTabela.MoveNext Loop rst.Close
A janela depurar conterá os seguintes dados:
95
_
Microsoft© Access Avançado
8.7. Acesso a Bancos de Dados Externos No exemplo anterior a origem dos dados é uma tabela (vinculada ou não) do banco de dados corrente, ou seja, do banco de dados onde o programa está sendo executado. Em certos casos é necessário obter dados (ou objetos) que estão em outros bancos de dados Access ou de banco de dados ISAM ou ODBC.
Banco de Dados Corrente (MDB)
ARQ1.MDB
ARQ2.DBF (dBase 3 )
ARQ3.XLS (Excel 95)
ODBC (SQL Server)
Há duas maneiras de acessar os dados externos: Vinculação e Abertura direta das tabelas 8.7.1. Vinculação de Tabelas Externas Para acessar dados de banco de dados externos, via programação, a forma mais fácil é vincular as tabelas externas (através do Menu Arquivo|Obter Dados Externos|Vincular) e acessá-las normalmente pelo método OpenRecordset do Database corrente, pois elas fazem parte do banco de dados corrente. O problema da vinculação é que o Access não sabe se o arquivo de origem está onde deveria estar. Portanto, ou se faz a vinculação toda vez que o aplicativo for aberto, ou se verifica se o vinculo está ativo e o refaz se necessário. 96
Microsoft© Access Avançado Fazer a vinculação via programação exige o conhecimento de outros objetos, propriedades e métodos da DAO. Toda tabela, seja própria do banco de dados ou vinculada, é um objeto TableDef (definição de tabela). Então, fazer uma vinculação significa criar um objeto TableDef e configurar suas propriedades (Connect e TableSourceName) para apontar para o arquivo a ser vinculado. Após criada a TableDef, ela é acrescentada à coleção TableDefs do objeto Database. Sub VinculaBancosExternos() Dim dbs As Database Dim tdf As TableDef Set dbs = CurrentDb ‘ Cria o objeto TableDef Set tdf = dbs.CreateTableDef(“Clientes”) ‘ Define o tipo de banco de dados que está conectando e a localização (path) tdf.Connect = “dBASE III; DATABASE=C:\Tabelas” ‘ Define o nome da tabela (sem o sufixo, dbf, no caso) tdf.SourceTableName = “Clientes” ‘ Acrescenta o objeto TableDef à coleção TableDefs dbs.TableDefs.Append tdf End Sub
A propriedade Connect possui dois argumentos: o Especificador e a Origem (antecedido pela palavra DATABASE=), separadas por um ponto e virgula. Abaixo estão os valores para este dois argumentos para os tipos de banco de dados: Tipo de banco de dados Banco de dados Access
Especificador [banco de dados];
dBASE III dBASE IV DBASE 5 Paradox 3.x Paradox 4.x Paradox 5.x FoxPro 2.0 FoxPro 2.5 FoxPro 2.6 Excel 3.0
dBASE III; dBASE IV; dBASE 5.0; Paradox 3.x; Paradox 4.x; Paradox 5.x; FoxPro 2.0; FoxPro 2.5; FoxPro 2.6; Excel 3.0;
Excel 4.0
Excel 4.0;
97
Origem Unidade de disco:\caminho\nome do arquivo.mdb Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho Unidade de disco:\caminho\nome do arquivo.xls Unidade de disco:\caminho\nome do arquivo.xls
Microsoft© Access Avançado Excel 5.0 ou Excel 95 Excel HTML Import HTML Export Text ODBC
Exchange
Excel ;
Unidade de disco:\caminho\nome do arquivo.xls Excel 8.0; Unidade de disco:\caminho\nome do arquivo.xls HTML Import; Unidade de disco:\caminho\nome do arquivo HTML Export; Unidade de disco:\caminho Text; Unidade de disco:\caminho ODBC; DATABASE=bancode Nenhum dados; UID=usuário; PWD=senha; DSN= nomedafontededados; [LOGIN TIMEOUT=segundos;] Exchange; Unidade de disco:\caminho.mdb MAPILEVEL=caminhodapast a; [TABLETYPE={ 0 | 1 }];[PROFILE=perfil;] [PWD= senha;] [DATABASE=bancod edados;]
Quando se usa tabelas vinculadas no aplicativo, é interessante refazer os vínculos no início da da aplicação. Ora, se as tabelas já estão vinculadas, a criação de um novo TableDef vai duplicar as tabelas existentes. Além disso, a vinculação pode falhar se as tabelas não estiverem no local certo. O exemplo abaixo mostra como refazer os vínculos, reportando na tela se o processo funcionou ou não. Function VinculaTabelas() Dim tbfs As TableDefs Dim tbf As TableDef Dim strMsg As String Dim CRLF As String CRLF = Chr(13) & Chr(10) Set tbfs = CurrentDb.TableDefs
'Coleção de tabelas
On Error Resume Next tbfs.Delete "Pessoal" tbfs.Delete "Cargo" tbfs.Delete "Funcao" Err.Clear
'Limpa o erro anterior, se houver
DoCmd.OpenForm "Histórico de Eventos" Err.Clear Set tbf = CurrentDb.CreateTableDef("Pessoal") tbf.Connect = "dBASE III; DATABASE=C:\Tabelas\" tbf.SourceTableName = "Pessoal" If Err.Number <> 0 Then Forms![Histórico de Eventos].txtMsg = _
98
Microsoft© Access Avançado Forms![Histórico de Eventos].txtMsg & "Erro ao vincular Pessoal" & CRLF Else Forms![Histórico de Eventos].txtMsg = _ Forms![Histórico de Eventos].txtMsg & "Vinculou Pessoal" & CRLF tbfs.Append tbf End If Err.Clear Set tbf = CurrentDb.CreateTableDef("Cargo") tbf.Connect = "dBASE III; DATABASE=C:\Tabelas\" tbf.SourceTableName = "Cargo" If Err.Number <> 0 Then Forms![Histórico de Eventos].txtMsg = _ Forms![Histórico de Eventos].txtMsg & "Erro ao vincular Cargo" & CRLF Else Forms![Histórico de Eventos].txtMsg = _ Forms![Histórico de Eventos].txtMsg & "Vinculou Cargo" & CRLF tbfs.Append tbf End If Err.Clear Set tbf = CurrentDb.CreateTableDef("Funcao") tbf.Connect = "dBASE III; DATABASE=C:\Tabelas\" tbf.SourceTableName = "Funcao" If Err.Number <> 0 Then Forms![Histórico de Eventos].txtMsg = _ Forms![Histórico de Eventos].txtMsg & "Erro ao vincular Funcao" & CRLF Else Forms![Histórico de Eventos].txtMsg = _ Forms![Histórico de Eventos].txtMsg & "Vinculou Funcao" & CRLF tbfs.Append tbf End If Err.Clear Forms![Histórico Forms![Histórico Forms![Histórico Forms![Histórico
de de de de
Eventos].txtMsg = _ Eventos].txtMsg & "--------------------------" & CRLF Eventos].txtMsg = _ Eventos].txtMsgtrMsg & "Fim da vinculação"
End Function
A execução desta função vinvula as tabelas e mostra o formulário Histórico de Eventos com o resultado do processamento, como mostra a figura a seguir.
99
Microsoft© Access Avançado
8.7.2. Abertura Direta de Tabelas Externas Com uma tabela vinculada, além de poder abrir um recordset via programa, você pode abrí-la normalmente no modo folha de dados ou ainda criar consultas, formulários e relatórios com base na tabela. Se o seu caso é simplesmente abrir uma tabela externa via programação, não há motivo para vinculá-la. Basta abrí-la diretamente. Para abrir diretamente as tabelas, sem vinculação, lembre-se que cada arquivo externo é um objeto Database. Portanto, basta declarar as variáveis deste tipo, na quantidade necessária. Vamos supor que além do banco corrente, queira-se objetos de outros três bancos Access. Dim Dim Dim Dim
dbsCorrente As Database dbsArq1 As Database dbsArq2 As Database dbsArq3 As Database
Para abrir o banco corrente pode-se usar a função CurrentDb ou toda a referência de seus objetos pais DBEngine.Workspaces(0).Database(0). Para abrir bancos de dados externos, usa-se o método OpenDatabase do objeto Workspace, cuja sintaxe é: Set bancodedados = [workspace.]OpenDatabase(Banco[, Exclusivo[, ReadOnly[, Origem]]]) Banco Exclusivo ReadOnly Origem
é o nome do banco de dados a ser aberto, incluindo o seu path. é um valor lógico (True ou False que indica se o banco será aberto em modo exclusivo. é um valor lógico (True ou False) que indica se o banco será aberto somente para leitura. é um string de parâmetros para abrir o banco de dados. 100
Microsoft© Access Avançado
Set Set Set Set
dbsCorrente = CurrentDb dbsArq1 = DBEngine.Workspaces(0).OpenDatabase(“C:\Tabelas\Arq1.mdb”) dbsArq2 = DBEngine.Workspaces(0).OpenDatabase(“C:\Sistemas\Arq2.mdb”) dbsArq3 = DBEngine.Workspaces(0).OpenDatabase(“C:\Arq3.mdb”)
Com a abertura de vários objetos Database, você tem acesso a todos os dados destes bancos de dados (e a objetos, se for banco Access). Os argumentos Banco e Origem, do método OpenDatabase, e Recordset, do método OpenRecordset, têm valores específicos para cada tipo de banco de dados. Abaixo estão os valores para alguns dos mais comuns tipos de banco de dados: Tipo Access
Banco Path e nome do banco de dados. Ex.: “C:\Tabelas\TB_Org.mdb”
DBase III
Path Ex.: “\\SMG0002\Sistemas” “D:\Dados” Path e nome do arquivo. Ex.: “C:\Temp\Clientes.xls”
Excel
Fox Pro
Path Ex.: “\\SMG0003\Arqs”
Origem Usuário e senha (se necessários). Ex.: “UID=Admin;PWD=senha ” Tipo do banco de dados. “dBASE III;”
Recordset Nome da tabela. Ex.: “Cidades”
Versão do Excel. “Excel 4.0;” “Excel 5.0;” “Excel 8.0;”
Intervalo das células ou nome do intervalo. Ex.: “Plan1$A1:B5” “Custos” Nome do arquivo sem o sufixo. Ex.: “Carros”
Versão do Fox Pro. “FoxPro 2.0;” “FoxPro 2.6;” “FoxPro 3.0;”
Nome do arquivo, sem o sufixo .dbf. Ex.: “Cliente”
1) Exemplo de acesso direto a arquivo dBase III, situado em um recurso de rede. Set dbsDBase = DBEngine.Workspaces(0).OpenDatabase(“\\SMG0006\Tabelas”, _ False, False, “dBASE III;”) Set rst = dbsDBase.OpenRecordset(“Orgao”)
2) Exemplo de acesso direto a arquivo FoxPro 2.0 Set dbsFoxPro2 = DBEngine.Workspaces(0).OpenDatabase(“C:\”, _ False, False, “FoxPro 2.0;”) Set rst = dbsFoxPro2.OpenRecordset(“Clientes”)
3) Exemplo de acesso direto a arquivo Excel 101
Microsoft© Access Avançado Set dbsExcel = DBEngine.Workspaces(0).OpenDatabase(“C:\Sheets\Venda.xls”, _ False, False, “Excel 8.0;”) Set rst = dbsExcel.OpenRecordset(“Plan3$A1:F7”)
102
Microsoft© Access Avançado
9. ACESSO A ARQUIVOS E IMPRESSORA O acesso a banco de dados Access, ISAM ou ODBC, via DAO e Jet Engine, substitui o tradicional acesso a arquivos seqüenciais e randômicos. Apesar disso, o Access não eliminou este tipo de acesso. Não tem muito sentido apresentar o acesso a dados em arquivos, uma vez que a maioria das necessidades é atendida por banco de dados. Porém pode-se usar o acesso a arquivos para outros fins, tal como direcionar a saída para disco ou diretamente para a porta da impressora local. Uma utilidade para a gravação da saída em disco é a monitoração, através de log em arquivo texto, de alguns acontecimentos importantes que ocorreu no aplicativo, tal como um erro fatal. Por exemplo, o aplicativo falhou ao tentar abrir um banco de dados .mdb que não se encontrava mais no disco. Com certeza, este erro será tratado por uma rotina de erro (ver tópico Tratamento de Erro) que gerará uma caixa de mensagem na tela. Porém a mensagem é apresentada ao operador, que esqueceu-se de anotá-la. Se esta mensagem for também gravada para o disco , o programador pode posteriormente abrir o arquivo e identificar o erro e em que linha de programa ele ocorreu. Para mostrar o acesso a arquivo, mostrarei um exemplo que gerará um relatório para disco, em formato ASCII, para ser impresso em uma impressora matricial em modo texto. Dim rst As Recordset Dim strNome As String * 35 Set rst = CurrentDb.OpenRecordset("Pessoal") Open "C:\SAIDA.TXT" For Output As #1 Do While Not rst.EOF LSet strNome = rst.Fields("NM_EMPREG") Print #1, rst.Fields("CD_MATRIC") & " "; Print #1, strNome; Print #1, rst.Fields("CD_CARGO") & " "; Print #1, rst.Fields("CD_ORGAO") rst.MoveNext Loop Close #1 rst.Close
O resultado deste código, o arquivo SAIDA.TXT, pode ser aberto no Notepad. Numa sessão DOS, este arquivo pode ser enviado para uma impressora matricial em modo texto (type saida.txt > prn: ). Isto significa que a impressão será rápida, pois não usa as fontes do Windows.
103
Microsoft© Access Avançado
Em vez de direcionar a saída para um arquivo ASCII, pode-se enviar a saída diretamente para a porta da impressora local. Isto equivale no Clipper a Set Print On e o comando ?. Dim rst As Recordset Dim strNome As String * 35 Set rst = CurrentDb.OpenRecordset("Pessoal") Open "Lpt1:" For Output As #1 ' Liga o modo condensado em impressoras padrão Epson Print #1, Chr(15) Do While Not rst.EOF LSet strNome = rst.Fields("NM_EMPREG") Print #1, rst.Fields("CD_MATRIC") & " "; Print #1, strNome; Print #1, rst.Fields("CD_CARGO") & " "; Print #1, rst.Fields("CD_ORGAO") rst.MoveNext Loop Close #1 rst.Close
104
Microsoft© Access Avançado
10. TRATAMENTO DE ERRO Há três tipos de erros. • • •
Erro lógico Erro em tempo de compilação Erro em tempo de execução
Erro lógico é quando o aplicativo não funciona como se esperava. Por exemplo, esquecer-se de zerar um contador leva a um erro lógico. Este tipo de erro só pode ser corrigido pelo próprio programador. Erros em tempo de compilação ocorrem como resultado da construção incorreta de código. Você pode ter esquecido de balancear pares de instruções (como If e End If ou For e Next) ou pode ter cometido um erro de programação que viola as regras do Visual Basic (como um erro de ortografia, omissão de um separador ou um erro de digitação). Erros em tempo de compilação também incluem erros de sintaxe, que são erros de gramática ou pontuação. Isso inclui parênteses mal emparelhados ou um número incorreto de argumentos passados para uma função. Erro em tempo de compilação ocorre também quando se usam funções definidas pelo usuário que não existem ou estão fora do escopo, quando se usam objetos de uma biblioteca não referenciada (ver Referência a Biblioteca de Objetos mais adiante) e quando de usa variáveis não declaradas (desde que Option Explicit esteja ativada). O erro por falta de referência a objetos nem sempre pode ser verificado antes de executar o programa, pois um objeto pode ser criado em tempo de execução (ver Automação mais adiante) e não há como o Access verificar se as propriedades e métodos são suportados pelo objeto. Neste caso, é um erro em tempo de execução. Para verificar a existência de erro de compilação, execute Compilar módulos carregados no menu Depurar de uma janela de módulo. Erro em tempo de execução é algo inesperado que ocorre quando o programa está sendo executado. Por exemplo, tentar abrir um banco de dados em modo exclusivo quando um outro usuário já o fez ou dividir um número por uma variável que contém zero. Normalmente, um erro em tempo de execução suspende o programa. Na suspensão, a janela de módulo é a aberta, a linha onde ocorreu o erro fica iluminada e mensagem de erro aparece para se optar por depurar o programa ou encerrá-lo.
105
Microsoft© Access Avançado Esta situação não é boa, não só porque o programa falha, mas porque o usuário tem acesso ao código fonte do programa (lembre-se que o Access não é um compilador que gera um programa executável). O erro em tempo de execução pode ser tratado dentro do próprio programa, melhorando a forma como o programa seja abortado, ou, conforme a gravidade do erro, até mesmo corrigindo o erro e impedindo que o programa seja interrompido. O tratamento de erro em tempo de execução é implementado com a instrução On Error. Esta instrução permite duas formas de tratamento: • •
Desviar o programa para uma rotina de tratamento de erro Prosseguir a execução na linha posterior ao do erro
10.1. Desvio para rotina de tratamento de erro Para o primeiro caso usa-se On Error GoTo rótulo, onde rótulo é uma marca para fragmento de código dentro do próprio procedimento. Este código pode: • • • •
Tratar o erro e terminar o programa Tratar o erro e voltar à execução na mesma linha do erro Tratar o erro e voltar à execução na linha seguinte à linha de erro Tratar o erro e desviar a execução para outro rótulo.
A rotina de tratamento de erro faz uso do objeto Err, que tem duas propriedades importantes> o número do erro (Number) e a sua descrição (Description).
10.1.1. Tratar o erro e terminar o programa Sub MostraErro() On Error GoTo Trata_Erro Open “c:\teste.txt” For Input As #1 Close #1 Exit Sub Trata_Erro: ‘ Erro 53 File not found MsgBox Err.Number & “- “ & Err.Description End Sub
Note que foi preciso colocar Exit Sub para que o código de tratamento de erro, no rótulo Trata_Erro, não seja executado em situação sem erro. Note também, que após reportar o erro, o programa segue o fluxo normal e pára, já que encontra End Sub.
10.1.2. Tratar o erro e voltar à execução na mesma linha do erro Sub VoltaNaLinhaDoErro() On Error GoTo Corrige_Erro
106
Microsoft© Access Avançado Open “c:\teste.txt” For Output As #1 Kill “c:\teste.txt” Exit Sub Corrige_Erro: If Err.Number = 55 Close #1 Resume End If
‘ File alredy open
End Sub
Neste caso o erro ocorre porque tenta-se apagar um arquivo que ainda está aberto. A rotina de tratamento de erro pode corrigir a situação de erro e retornar o fluxo de programa na mesma linha onde o erro ocorreu.
10.1.3. Tratar o erro e voltar à execução na linha seguinte à linha de erro Sub VoltaNaProximaLinha() Dim blnArquivoExiste As Boolean On Error GoTo Corrige_Erro blnArquivoExiste = True Open “c:\teste.txt” For Input As #1 If blnArquivoExiste MsgBox “Preparando para ler arquivo C:\teste.txt” Else MsgBox “O arquivo C:\teste.txt não existe!” End If Exit Sub Corrige_Erro: If Err.Number = 53 Resume Next End If
‘ File not found
End Sub
10.1.4. Tratar o erro e desviar a execução para outro rótulo. Sub DesviaParaUmRotulo() On Error GoTo Corrige_Erro Open “c:\teste.txt” For Input As #1 Exit Sub Fim: MsgBox “O arquivo C:\teste.txt não existe. ” & _ “Irei criá-lo vazio para as próximas execuções!” Open “c:\teste.txt” For Output As #1 Close #1 Exit Sub
107
Microsoft© Access Avançado Corrige_Erro: If Err.Number = 53 Resume Fim End If
'
File not found
End Sub
10.1.5. Prosseguir o programa após erro Para prosseguir o programa normalmente após a ocorrência de um erro usa-se On Error Resume Next. Isto é útil quando o erro não compromete a lógica do programa e pode ser ignorado. Por exemplo, quando for apagar tabela vinculada (significa desfazer o vínculo), a falta dela já estiver apagada não é um erro grave e pode ser ignorado. Sub DesvinculaTabelas() On Error Resume Next CurrentDb.TableDefs(“Pessoal”).Delete CurrentDb.TableDefs(“Cargo”).Delete CurrentDb.TableDefs(“Funcao”).Delete End Sub
On Error Resume Next pode ser usado para tratar o erro imediatamente após a sua ocorrência, sem desviar para um rótulo. Sub TrataErroImediatamente() Dim obj As Object On Error Resume Next Set obj = CreateObject("Outlook.Application") If Err.Number <> 0 Then ' Err.Number é 429 ' Err.Description é ActiveX component can’t create object MsgBox "Não foi possível criar o objeto Outlook" Else . . End If End Sub
10.1.6. Evento Erro A instrução On Error pode ser usada em módulo padrão e módulo de classe. Em módulo de classe há uma outra maneira de interceptar error: é o evento On Error (Ao Ocorrer Erro, em português) dos objetos formulário e relatório. O evento On Error detecta somente os erros do Jet Engine e não erros do VBA. Se um campo que não aceita nulo receber um nulo será gerado um evento de erro, porque é um erro do Jet Engine. Se o código tentar uma divisão por zero, o erro não é interceptado pelo evento On Erro, porque é um erro do VBA. Neste caso, tem que se usar a instrução On Error. 108
Microsoft© Access Avançado
10.2. Depuração do Programa À vezes ocorre um erro persistente, difícil de ser solucionado, para o qual são necessários executar o programa passo-a-passo, interromper o programa para verificar o conteúdo das variáveis e prosseguir o programa a partir da interrupção. Para parar o programa em pontos críticos, podem ser colocados um ou mais Pontos de Interrupção (tecla F9 põe e tira pontos de interrupção). Nestes pontos o programa é interrompido e a janela do módulo é aberta. Pode-se então prosseguir com a tecla F8, para executar o programa passo-a-passo ou F5 para continuar normalmente até outro ponto de interrupção ou até o fim do programa. Durante a interrupção, pode-se abrir a janela Depurar (Control G) e verificar o valor das variáveis ou executar um comando interativamente, inclusive alterando o valor de algumas variáveis.
Na figura acima, a linha marcada com um círculo é um ponto de interrupção e a linha marcada com seta é a linha atualmente executada. Na janela Depurar (Debug Windows, em inglês) foi dado o comando ? xlsSheet.Application, o qual retornou Microsoft Excel (que é o nome do objeto pai). Após depurar o programa, não se esqueça de limpar todos os pontos de interrupção. 109
Microsoft© Access Avançado
110
Microsoft© Access Avançado
11. AUTOMAÇÃO A automação (antigamente chamada de Automação OLE) é um recurso do COM (Component Object Model), um padrão da indústria de informática utilizado pelos aplicativos para expor os seus objetos a ferramentas de desenvolvimento, linguagens de macro e a outros aplicativos que suportam automação. Por exemplo, um aplicativo de planilha pode expor uma planilha, gráfico, célula ou intervalo de células— como diferentes tipos de objetos. Um processador de textos pode expor objetos como um aplicativo, um documento, um parágrafo, uma frase, um indicador ou uma seleção. Quando um aplicativo suporta automação, os objetos expostos por ele podem ser acessados pelo Visual Basic. Para manipular esses objetos no Visual Basic, execute métodos sobre o objeto ou obtenha e defina as propriedades do objeto. Por exemplo, você pode criar um objeto de automação nomeado MyObj e gravar o código apresentado a seguir para acessálo: MyObj.Insert "Oi, mundo." ' Insere um texto. MyObj.Bold = True ' Formata o texto. MyObj.SaveAs "C:\PROCTXT\DOCS\OBJTEST.DOC" ' Grava o objeto.
Os objetos que que expõem suas funcionalidades é chamado pela Microsoft de ActiveX. O termo ActiveX engloba também os controles OLE, antigamente chamados de componentes OCX (isto porque os arquivos têm a terminação .ocx). Atualmente, o termo ActiveX tem sido substituído por COM – Component Object Model. Há dois tipos de elementos na automação:
Os servidores de automação, que podem ser controlados porque suas funcionalidades são expostas e podem ser acessadas por outras aplicações. Exemplos de servidores de automação: todos os softwares do Microsoft Office, Schedule+ e o Project. Os controladores de automação, que podem controlar servidores de automação através de código de programação, acessando a funcionalidade exposta pelos servidores de automação. Exemplos de controladores: MS Visual Basic, MS Visual C++, MS FoxPro e o VBA (que está embutido no Access, Excel, Word e Project).
A automação permite extrair o que há de melhor dos softwares especialistas e integrálos. Por exemplo, pode-se usar o Access, especializado em banco de dados, para processar dados de vendas e exportá-los para uma planilha do Excel. O Excel, especializado em gráfico, pode gerar um gráfico de barras, mostrando a evolução das vendas. Este gráfico pode ser exportado para um relatório trimestral de vendas, que está digitado no Word. Todo este processo poderia ser manual, usando-se os recursos de copiar e colar. A automação faz tudo isto com um simples disparo de um código em VBA. Para usar a automação, no entanto, é necessário conhecer os objetos, propriedades e métodos de cada um dos aplicativos envolvidos, sem contar com o conhecimento da linguagem de programação Visual Basic. No VBA existem duas funções chaves para realizar a automação. GetObject() e CreateObject(). GetObjetc() obtém um objeto ActiveX de uma determinada classe de objetos. Sua sintaxe e argumentos são: 111
Microsoft© Access Avançado GetObject([pathname] [, class]) Pathname class
Opcional; Variant (String). Indica o caminho completo e nome do arquivo que contém o objeto a ser recuperado. Se pathname for omitido, class passa a ser obrigatório. Opcional; Variant (String). Uma seqüência de caracteres que representa a classe do objeto.
O argumento class utiliza a sintaxe nomedoaplic.tipodeobjeto e possui partes a seguir: Parte Descrição nomedoaplic Obrigatória; Variant (String). Nome do aplicativo que fornece o objeto. tipodeobjeto Obrigatória; Variant (String). Tipo ou classe do objeto a ser criado. O objeto retornado por GetObject é atribuído a uma variável do mesmo tipo, possibilitando invocar seus métodos e acessar suas propriedades. O exemplo abaixo obtém um objeto Application do Word. A propriedade Visible é setada para que a janela do aplicativo aparece na tela. É usado o método Open, da coleção Documents, para abrir um documento existente. Dim wrd As Object Set wrd = GetObject(, "Word.Application") wrd.Visible = True wrd.Documents.Open "C:\Meus Documentos\Temp.doc" Set wrd = Nothing
CreateObject() cria e retorna a referência de um objeto ActiveX da classe especificada em seu argumento. O argumento é obrigatório e é o mesmo argumento [class] da função GetObject().
11.1. Automação com o Microsoft Word
112
Microsoft© Access Avançado Hierarquia dos Objetos do Microsoft Word
O exemplo abaixo cria um novo objeto Application do Word. É usado o método TypeText, do objeto Selection, para inserir um texto. O documento é salvo e o aplicativo é encerrado. A referência ao objeto é encerrada atribuindo-se Nothing à variável. Dim objWord As Object Set objWord = CreateObject("Word.Application") objWord.Visible = True objWord.Documents.Add objWord.Selection.TypeText Text:="Carlos Koga" objWord.ActiveDocument.SaveAs FileName:="C:\Koga.doc" objWord.Quit Set objWord = Nothing
11.2. Automação com o Microsoft Excel Hierarquia do Objetos do Microsoft Excel
113
Microsoft© Access Avançado
Detalhamento do Objeto Worksheets
114
Microsoft© Access Avançado
Detalhamento do Objeto Charts
Detalhamento do Objeto Chartgroups
115
Microsoft© Access Avançado
Normalmente, ao abrir o Excel no Windows, abre-se automaticamente um novo Workbook (Pasta de Trabalho, em português) chamado Book1 (Pasta1, em português) com três Worksheets (planilhas) denominados Sheet1, Sheet2, Sheet3 (em português, são Plan1, Plan2 e Plan3, respectivamente). Cada Worksheet possui várias células, referenciadas por coordenadas de colunas de A a IV e linhas de 1 a 65536. Este são os principais objetos do Excel. O próprio Excel, o Workbook, o Worksheet e o Range (que são as células), nesta ordem de hierarquia. O objeto de mais alto nível é o Application. Ele representa o próprio programa Excel. No modo programado, o objeto Application não possui de imediato nenhum Workbook (Pasta de Trabalho, em português) e, consequentemente, nenhum Worksheet (planilha) e nenhum Range. O Excel pode abrir um ou mais workbooks. Workbooks (no plural) é uma coleção de objetos Workbook (no singular). Um objeto workbook é um arquivo .XLS. Note que na hierarquia de objetos, Workbooks está abaixo do objeto Application. Note também que a legenda do modelo está errada, pois indica que Workbook é apenas objeto. Na realidade é coleção e objeto. Um workbook possui um ou mais Worksheets. Worksheets (no plural) é uma coleção de objetos Worksheet (no singular). Note que no modelo de objetos Worksheet está abaixo de Workbook. Cada worksheet (planilha) contém células, que são os objetos Range (intervalo). A célula A1 é referenciada por Range(“A1”). As células de A1 a C5 são referenciadas por Range(“A1:C5”).
116
Microsoft© Access Avançado
Para criar uma instância do objeto Excel, usa-se a função CreateObject() do VBA. Exemplo: Sub InstanciaExcel() Dim xls As Excel.Application ' Cria uma instância do objeto Excel Set xls = CreateObject(“Excel.Application”) ' Propriedade para tornar o objeto visível xls.Visible = True MsgBox “Clique em OK para fechar o Excel” ' Método para fechar o Excel xls.Quit Set xls = Nothing End Sub
' Libera memória
O procedimento acima abre o Excel e o fecha ao clicar OK na caixa de mensagem. A figura abaixo é a repersentação visual do objeto Excel.Application. Perceba que ele não contém nenhum objeto Workbook ainda. 117
Microsoft© Access Avançado
Para termos uma janela do Excel com um workbook, temos que acrescentar uma linha de código, invocando o método Add da coleção Workbooks. Sub InstanciaExcel() Dim xls As Excel.Application ' Cria uma instância do objeto Excel Set xls = CreateObject(“Excel.Application”) ' Propriedade para tornar o objeto visível xls.Visible = True ' Cria um workbook novo. ' Por default, ele se chama Book1 e possui três worksheets xls.WorkBooks.Add MsgBox “Clique em OK para fechar o Excel” ' Método para fechar o Excel xls.Quit Set xls = Nothing End Sub
' Libera memória
O objeto Excel.Application tem agora um objeto Workbook. Logo a sua coleção Workbooks contém apenas um objeto Workbook, chamado Book1. Para referenciar um objeto Workbook dentro da coleção, usa-se um índice ou o seu nome dentro de parênteses. xls.Workbooks(1)
ou
xls.Workbooks(“Book1”)
118
Microsoft© Access Avançado Note que a referência deve seguir a hierarquia dos objetos. Primeiro Application, seguida de Workbooks. Sub InstanciaExcel() Dim xls As Excel.Application ' Cria uma instância do objeto Excel Set xls = CreateObject("Excel.Application") ' Propriedade para tornar o objeto visível xls.Visible = True ' Cria um workbook novo. ' Por default, ele se chama Book1 e possui três worksheets xls.Workbooks.Add xls.Workbooks(1).Worksheets(1).Range("A1") = 4 xls.Workbooks(1).Worksheets(1).Range("B1") = 6 xls.Workbooks(1).Worksheets(1).Range("C1") = "=A1 + B1" MsgBox "Clique em OK para fechar o Excel" ' Salva o workbook como Teste.xls xls.Workbooks(1).SaveAs "C:\Teste.xls" ' Método para fechar o Excel xls.Quit Set xls = Nothing End Sub
O exemplo a seguir mostra como ler cada registro de um recordset do Access, gravando cada campo em uma célula. Dim xlsPlan As Object Dim rstPessoal As Recordset Din lngLine As Long Set xlsPlan = CreateObject("Excel.Sheet") Set rstPessoal = CurrentDb.OpenRecordset("qryRelacaoDePessoal") lngLine = 1 Do While Not rstPessoal.EOF xlsPlan.Application.Cells(lngLine, xlsPlan.Application.Cells(lngLine, xlsPlan.Application.Cells(lngLine, xlsPlan.Application.Cells(lngLine, xlsPlan.Application.Cells(lngLine, rstPessoal.MoveNext lngLine = lngLine + 1 Loop
1) 2) 3) 4) 5)
xlsPlan.SaveAs ("C:\Pessoal.xls") rstPessoal.Close Set xlsPlan = Nothing
119
= = = = =
rstPessoal.Fields(“Matricula”) rstPessoal.Fields(“Nome”) rstPessoal.Fields(“CodOrgao”) rstPessoal.Fields(“CodCargo”) rstPessoal.Fields(“CodFuncao”)
Microsoft© Access Avançado xlsPlan é um objeto Workbook. A propriedade Application retorna o objeto Application, que possui a propriedade Cells. Outro exemplo mais sofisticado é gerar e imprimir um gráfico de barras tridimensional do Excel a partir de uma consulta referência cruzada do Access. REGIAO LESTE NORTE OESTE SUL
PROD A 111 245 99 210
PROD B 54 200 34 348
PROD C 78 114 48 442
Dim xls As Object Dim rst As Recordset Dim intLinha As Integer, intColuna As Integer Set rst = CurrentDb.OpenRecordset(“qryConsumo por Produto e Por Regiao”) Set xls = CreateObject("Excel.application") xls.Workbooks.Add ' Insere na linha 1 os cabeçalhos de cada coluna For intColuna = 1 to rst.Fields.Count xls.Cells(1, intColuna) = rst.Fields(intColuna – 1).Name Next intLinha = 2 Do While Not rst.EOF ' Insere os valores de cada coluna For intColuna = 1 to rst.Fields.Count xls.Cells(intLinha,intColuna) = rst.Fields(intColuna – 1) Next intLinha = intLinha + 1 rst.MoveNext Loop xls.Range("A1:D5").Select xls.Charts.Add xls.ActiveChart.ChartType = -4100 xls.ActiveChart.SetSourceData xls.Worksheets("Plan1").range("A1:D5"), 2 xls.ActiveChart.Location 1 With xls.ActiveChart .HasTitle = True .ChartTitle.Characters.Text = "Consumo por Regiao" .Axes(1).HasTitle = True .Axes(1).AxisTitle.Characters.Text = "Produtos" .Axes(3).HasTitle = True .Axes(3).AxisTitle.Characters.Text = "Regiao" .Axes(2).HasTitle = False End With xls.ActiveWindow.SelectedSheets.PrintOut Copies:=1
Neste exemplo, xls é um objeto Application, que possui as propriedades Cells, Range (retorna o objeto Range), ActiveChart (que retorna o objeto Chart atual) e ActiveWindow (que retorna o objeto Window atual) e as coleções Workbooks e Charts. 120
Microsoft© Access Avançado
11.3. Automação com Microsoft Project 95 Hierarquia dos Objetos do Microsoft Project 95 (versão 4.1)
A utilidade da automação com o Microsoft Project é mostrada no exemplo a seguir. Uma tabela do Access contém os eventos de cursos a serem realizados. Cada evento tem as datas de início e de término, o que não permite uma visualização fácil de todos os eventos programados num período de tempo. O Project possui o gráfico de Gantt, como mostrado abaixo, que torna a grade de eventos.
O código a seguir possibilita inserir os dados dos eventos de cursos em um arquivo do Project e imprimir o gráfico de Gantt, automaticamente. Dim prjApp As Object Dim prjProj As Object
121
Microsoft© Access Avançado Dim rst As Recordset Dim intI As Integer Set rst = CurrentDb.OpenRecordset("Cursos") Set prjApp = CreateObject("MSProject.Application") prjApp.filenew Set prjProj = prjApp.projects(1) intI = 1 Do While Not rst.EOF prjProj.tasks.Add rst.Fields("Evento") prjProj.tasks(intI).start = rst.Fields("DataInicio") prjProj.tasks(intI).finish = rst.Fields("DataTermino") rst.MoveNext intI = intI + 1 Loop prjApp.FileSaveas "C:\Temp\cursos.mpp" prjApp.fileprint 1, 1, False, False, 1, Null, Null, True, False, False prjApp.Quit
11.4. Automação com Schedule+ 7.0
122
Microsoft© Access Avançado Hierarquia dos Objetos do Schedule+ 7.0
O exemplo a seguir mostra como criar um novo compromisso (Almoço), que iniciarse-á na data/hora do sistema operacional e durará 1 hora. Este exemplo pode ser aperfeiçoado, integrando a automação com o Project, para criar compromissos para o instrutor do curso. Dim objSch As Object Dim objApontamento As Object Set objSch = CreateObject(“SchedulePlus.Application”) objSch.Logon objSch.ScheduleSelected.Activate Set objApontamento = objSch.ScheduleSelected.SingleAppointments.New objApontamento.SetProperties Text:= “Almoço”, _ Start:=Now(), End:= Now() + Format(“01:00”) objSch.Logoff
11.5. REFERÊNCIA À BIBLIOTECA DE OBJETOS Para acessar objetos, propriedades, métodos e constantes intrínsecas de outros softwares, é preciso que as referências aos arquivos de acesso a objetos estejam estabelecidas. Uma aplicação Access típica faz referência a três bibliotecas de objetos: • • •
Arquivo de acesso a objetos do Access (tais como formulários e relatórios) e constantes do Access (referência obrigatória). Arquivo de acesso a objetos (todos os comandos e constantes) do VBA (referência obrigatória). Arquivo de acesso a objetos de dados - DAO (referência necessária apenas se for acessar dados). 123
Microsoft© Access Avançado Os arquivos que permitem o acesso a objetos do Access são: Arquivo Nome Descrição Msaccess.tlb Microsoft Access for Windows 95 Para o Access 95 (versão 7.0), em português Msacc8.olb Microsoft Access 8.0 Object Library Para o Access (versão 8.0) em inglês Msacc8.tlb Microsoft Access 8.0 Object Library Para o Access (versão 8.0) em português O arquivo que permite o acesso a objetos do VBA é: Arquivo Ven2232.olb
Nome Visual Basic for Applications
Descrição Para a versão 2.2, em inglês
Os arquivos que permitem o acesso a objetos da DAO são: Arquivo Dao350.dll Dao3021.dll Dao2532.tlb Dao2535
Nome Microsoft DAO 3.5 Object Library Microsoft DAO 3.0 Object Library Microsoft DAO 2.5/3.0 Compatibility Library Microsoft DAO 2.5/3.5 Compatibility Library
Descrição Para a versão 3.5 Para a versão 3.0 Para compatibilidade das versões 2.5 e 3.0 Para compatibilidade das versões 2.5 e 3.5
Os arquivos que permitem acesso a objetos dos aplicativos Microsoft são: Arquivo Sp7en32.olb Xl5en32.olb Xl5pt32.olb Excel8.olb Pj4en32.olb Msword8.olb Graph8.olb Grptb50.olb
Nome Microsoft Schedule+ 7.0 Object Library Biblioteca de objetos do Microsoft Excel 5.0
Descrição Para a versão em inglês Para a versão 5.0 em português, com sintaxe de comandos em inglês Biblioteca de objetos do Microsoft Excel Para a versão 5.0 em português, 5.0 com sintaxe de comandos em português Microsoft Excel 8.0 Object Library Para a versão em inglês Microsoft Project 4.1Object Library Para a versão 95 em inglês Microsoft Word 8.0 Object Library Para a versão em português, com sintaxe de comandos em inglês Microsoft Graph 8.0 Object Library Para a versão em inglês Biblioteca de objetos do Microsoft Para a versão em português Graph 5.0
As referências são estabelecidas no menu Ferramentas|Referências..., a partir de uma janela de módulo aberta.
124
Microsoft© Access Avançado
Se estiver faltando alguma referência na lista de bibliotecas disponíveis, acione o botão Procurar e localize o arquivo necessário. É importante saber qual as versões dos objetos você está referenciando, pois em cada uma há mudanças de sintaxes e até objetos, propriedades e métodos novos ou de comportamento diferente. Por isto, um aplicativo que funciona perfeitamente em um computador pode não funcionar em outro. A referência às bibliotecas de objetos ajuda no tempo de codificação do programa, pois os objetos, propriedades e métodos ficam visíveis na janela Object Browser (acionada pela tecla F2). Veja na figura a seguir as propriedades e métodos do objeto ÁreaPlotagem da biblioteca do Excel 5.0 com a sintaxe em português.
125
Microsoft© Access Avançado
12. CHAMADA À API DO WINDOWS 95 A API (Application Programming Interface) do Windows consiste de um conjunto de bibliotecas de vínculo dinâmico (DLLs) ou arquivo de recursos (EXEs) contendo procedimentos relacionados ao sistema operacional que incluem funções, mensagens, estruturas de dados, tipos de dados e instruções que você pode usar na criação de aplicativos a serem executados sob o Windows 95. Para chamar esses procedimentos a partir do Visual Basic, você precisa primeiro declará-los usando uma instrução Declare. Você pode então chamá-los como faria com qualquer outro procedimento. A instrução Declare possui a seguinte sintaxe: [Public | Private ] Declare Function|Sub nome Lib "nomedabibliot" [Alias "nomedoalias" ] [([listadeargumento])][As tipo] A sintaxe da instrução Declare tem estas partes: Parte Public Private Sub Function nome Lib nomedabibliot Alias
nomedoalias listadeargumento tipo
Descrição Usada para declarar procedimentos que estão disponíveis em todos os outros procedimentos em todos os módulos. Usada para declarar procedimentos que estão disponíveis apenas dentro do módulo onde a declaração é feita. Indica que o procedimento não retorna um valor. Indica que o procedimento retorna um valor que pode ser usado numa expressão. Qualquer nome de procedimento válido. Indica que uma DLL ou recurso de código contém o procedimento que está sendo declarado. A cláusula Lib é obrigatória para todas as declarações. Nome da DLL ou do recurso de código que contém o procedimento declarado. Indica que o procedimento que está sendo chamado tem um outro nome na DLL ou está num recurso de código do Macintosh. É útil quando o nome do procedimento externo é igual ao da palavra-chave. Alias também pode ser usado quando um procedimento DLL tem o mesmo nome de uma variável ou constante pública ou qualquer outro procedimento no mesmo escopo. Alias também é útil se a convenção de nomenclatura da DLL não permitir algum caractere no nome do procedimento. Nome do procedimento na DLL ou recurso do código. Lista de variáveis que representam argumentos que são passados ao procedimento quando ela é chamada. Tipo de dados do valor retornado por um procedimento Function; pode ser Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (apenas de tamanho flexível), Object, Variant, um tipo definido pelo usuário ou um tipo de objeto.
O argumento listadeargumento tem a sintaxe e partes abaixo: 126
Microsoft© Access Avançado [Optional][ByVal | ByRef][ParamArray] nomedavariáv[( )][As tipo] Parte Optional
ByVal ByRef ParamArray
nomedavariáv tipo
Descrição Indica que um argumento não é obrigatório. Se usada, todos os argumentos subseqüentes na listadeargumento devem ser opcionais e declarados pelo uso da palavra-chave Optional. Todos os argumentos Optional devem ser Variant. Optional não poderá ser usada por nenhum argumento se ParamArray for usada. Indica que o argumento é passado por valor. Indica que o argumento é passado por referência. Usada apenas pelo último argumento em listadeargumento para indicar que o argumento final é uma matriz Optional de elementos Variant. A palavra-chave ParamArray permite fornecer um número arbitrário de argumentos. Não pode ser usada com ByVal, ByRef ou Optional. Nome da variável que representa o argumento que está sendo passado ao procedimento; segue convenções de nomenclatura padrão de variável. Tipo de dados do argumento passado ao procedimento; pode ser Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (apenas de comprimento flexível), Object, Variant, um tipo definido pelo usuário ou um tipo de objeto.
Para usar a API, simplesmente saber a sintaxe não significa muito. É preciso saber: • • • •
os nomes dos procedimentos embutidos em quais arquivos de biblioteca os procedimentos se encontram quais os argumentos devem ser passados quais os valores que os argumentos devem receber
Quanto aos itens 1 a 3, há uma relação gravada em um banco de dados (Win32API.mdb) que contém as funções do WinAPI. Eis algumas delas: Função Beep CharLower GetOpenFileN ame GetSaveFileN ame
Declaração Declare Function Beep Lib "kernel32" Alias "Beep" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long Declare Function CharLower Lib "user32" Alias "CharLowerA" (ByVal lpsz As String) As String Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Long
Observação importante: As declarações das funções devem ser escritas seguindo fielmente a tabela acima. Os nomes são sensíveis à caixa.
127
Microsoft© Access Avançado As funções Beep e CharLower não apresentam problema para identificar os valores que os argumentos devem receber. Os exemplos abaixo demonstram isto. Option Explicit Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, _ ByVal dwDuration As Long) As Long Declare Function CharLower Lib "user32" Alias "CharLowerA" _ (ByVal lpsz As String) As String Function Som() Dim lngSom As Long lngSom = Beep(500, 200) lngSom = Beep(370, 100) End Function Function CaixaBaixa() Dim str as String str = CharLower(“CAIXA ALTA”) MsgBox str End Function
Entretanto, as funções GetOpenFileName e GetSaveFileName, assim como a maioria das funções API, necessitam de documentação quanto à estrutura e os valores dos argumentos. Por exemplo, OPENFILENAME é uma estrutura de dados definida pelo usuário que contém os seguintes elementos. lStructSize As Long hwndOwner As Long hInstance As Long lpstrFilter As String lpstrCustomFilter As nMaxCustFilter As Long nFilterIndex As Long lpstrFile As String nMaxFile As Long lpstrFileTitle As String nMaxFileTitle As Long lpstrInitialDir As String lpstrTitle As String flags As Long nFileOffset As Integer nFileExtension As lpstrDefExt As String lCustData As Long lpfnHook As Long lpTemplateName As
128
Microsoft© Access Avançado Os exemplos dessas duas funções, apresentados adiante, só foram possíveis graças ao aplicativo Solutions, que acompanha o Access . A função GetOpenFileName abre uma caixa de diálogo do tipo “Abrir”, retornando um valor lógico que indica se o usuário clicou no botão Abrir (true) ou no Cancelar (false). O nome do arquivo é armazenado no elemento lpstrFile de OPENFILENAME. Option Compare Database Option Explicit Declare Function GetOpenFileName Alias "GetOpenFileNameA" Declare Function GetSaveFileName Alias "GetSaveFileNameA" Type OPENFILENAME lStructSize As Long hwndOwner As Long hInstance As Long lpstrFilter As String lpstrCustomFilter As Long nMaxCustrFilter As Long nFilterIndex As Long lpstrFile As String nMaxFile As Long lpstrFileTitle As String nMaxFileTitle As Long lpstrInitialDir As String lpstrTitle As String flags As Long nFileOffset As Integer nFileExtension As Integer lpstrDefExt As String lCustrData As Long lpfnHook As Long lpTemplateName As Long End Type
Lib "comdlg32.dll" _ (pOpenfilename As OPENFILENAME) As Boolean Lib "comdlg32.dll" _ (pOpenfilename As OPENFILENAME) As Boolean
Function CaixaDialogo_Open( ) Dim of As OPENFILENAME Dim blnAbriu As Boolean ' Verifica se o usuário abriu ou cancelou. ' Poderia ser o retorno da função. Dim strTitulo as String ' Título da caixa de diálog. Poderia ser um ' argumento Dim strFiltro As String ' Filtro para o tipo de arquivo. Também ' poderia ser um argumento Dim strDirInicial As String ´Diretório inicial. Idem strTitulo = “Abrir banco de dados” strFiltro = “Banco de dados Access” & Chr(0) & “*.mdb” & Chr(0) & Chr(0) strDirInicial = “C:\” of.hwndOwner = Application.hWndAccessApp of.hInstance = 0 of.lpstrCustomFilter = 0 of.nMaxCustrFilter = 0 of.lpfnHook = 0 of.lpTemplateName = 0
129
_
Microsoft© Access Avançado of.lCustrData = 0 of.lpstrFilter = strFiltro of.nFilterIndex = 0 of.lpstrFile = String$(512, 0) of.nMaxFile = 511 of.lpstrFileTitle = String$(512, 0) of.nMaxFileTitle = 511 of.lpstrTitle = "Teste" of.lpstrInitialDir = strDirInicial of.lpstrDefExt = "" of.flags = 0 of.lStructSize = Len(of) blnAbriu = GetOpenFileName(of) MsgBox blnAbriu ´True se clicou em Abrir. False se clicou em Cancelar If blnAbriu Then MsgBox of.lpstrFile ´ Nome do arquivo escolhido End If End Function Function CaixaDialogo_Save( ) Dim of As OPENFILENAME Dim blnSalvou As Boolean ' Verifica se o usuário salvou ou cancelou. ' Poderia ser o retorno da função. Dim strTitulo As String ' Título da caixa de diálog. Poderia ser um ' argumento Dim strFiltro As String ' Filtro para o tipo de arquivo. Também ' poderia ser um argumento Dim strDirInicial As String 'Diretório inicial. Idem Dim strNomeArq As String 'Nome sugerido para salvar. Idem Dim strExtensaoDefault As String ' Extensão default. Idem strTitulo = "Salvar banco de dados" strFiltro = "Text files " & Chr(0) & "*.txt" & Chr(0) & Chr(0) strDirInicial = "C:\" strNomeArq = "Teste2" strExtensaoDefault = "txt" of.hwndOwner = Application.hWndAccessApp of.hInstance = 0 of.lpstrCustomFilter = 0 of.nMaxCustrFilter = 0 of.lpfnHook = 0 of.lpTemplateName = 0 of.lCustrData = 0 of.lpstrFilter = strFiltro of.nFilterIndex = 0 of.lpstrFile = strNomeArq & String$(512 - Len(strNomeArq), 0) of.nMaxFile = 511 of.lpstrFileTitle = String$(512, 0) of.nMaxFileTitle = 511 of.lpstrTitle = strTitulo of.lpstrInitialDir = strDirInicial of.lpstrDefExt = "txt" of.flags = 0 of.lStructSize = Len(of) blnSalvou = GetSaveFileName(of)
130
Microsoft© Access Avançado MsgBox blnSalvou 'True se clicou em Salvar. False se clicou em Cancelar If blnSalvou Then MsgBox of.lpstrFile ' Nome do arquivo escolhido End If End Function
Estas funções não realizam operações de abertura/salvamento de arquivo, mas simplesmente abrem caixas de diálogo para se selecionar os arquivos.
131
Microsoft© Access Avançado
13. SEGURANÇA Antes de construir um aplicativo Access, você deve ter em mente que níveis de segurança que o aplicativo deve atender. É mais construir um aplicativo com a segurança já definida desde o início que definí-la após o aplicativo estiver pronto. A segurança visa proteger os dados contra leitura de informações confidenciais, alteração indevida, inclusão e exclusão de registros por pessoa não autorizada. A segurança protege também a estrutura dos objetos e o acesso ao código-fonte dos módulos. Existem várias formas de segurança:
Senha de banco de dados: É a forma mais simples de proteger um banco de dados. Uma vez definida a senha, uma caixa de diálogo solicita a entrada da senha. Todos os dados e estruturas são acessíveis por quem informar a senha correta. Criação de arquivo MDE: Cria uma cópia do banco de dados, com extensão .MDE, o que torna impossível visualizar, criar ou alterar código VBA. Impede também a criação e alteração de formulários e relatórios. Criptografia: Torna a leitura dos dados impossível através de um processador de texto ou outra ferramenta de acesso a disco. Abrindo o banco de dados no próprio Access, a criptografia é imperceptível, a não ser a perda de desempenho de 10 a 15%. Segurança em nível de usuário: Define permissões de leitura, gravação e alteração de estrutura por objeto e usuário (ou grupo de usuários). É a forma mais completa de segurança. Você pode combinar utilizar todas as formas de segurança em um mesmo aplicativo.
13.1. SENHA DE BANCO DE DADOS 13.1.1. DEFININDO UMA SENHA PARA O BANCO DE DADOS Para definir uma senha para o banco de dados, o arquivo MDB que você quer proteger deve estar em uso. 1) Antes de definir uma senha, faça uma cópia de segurança do banco de dados que você quer proteger. 2) Se você trabalha em rede, assegure-se que ninguém mais esteja com o banco de dados em uso. 3) Abra o banco de dados no modo exclusivo. Na caixa de diálogo Abrir, acionada pelo menu Arquivo|Abrir banco de dados…, há uma caixa de verificação Exclusivo. 4) A senha para um banco de dados é feita pelo menu Ferramentas|Segurança|Definir senha do banco de dados…. Ao acionar o menu, será aberta a seguinte caixa de diálogo. Digite a senha, confirme e clique Ok
132
Microsoft© Access Avançado
Observações: Você pode definir uma senha de até 14 caracteres, entre letras, números e caracteres especiais. A senha é sensível a letras maiúsculas e minúsculas. Guarde a senha e a cópia de segurança do banco de dados em lugar seguro, pois em caso de esquecimento, é impossível descobrí-la. Se você pretende replicar seu banco de dados, não configure senha de banco de dados, pois a replicação não funciona em banco de dados protegidos por senha. 13.1.2. ABRINDO UM BANCO DE DADOS PROTEGIDO POR SENHA Ao abrir um banco de dados protegido por senha, uma caixa de diálogo solicitará a senha.
Caso a senha esteja correta, o banco de dados é aberto normalmente, com acesso a todos os dados e objetos.
13.1.3. REMOVENDO SENHA DE BANCO DE DADOS Após ter aberto o banco de dados com a senha correta e no modo exclusivo, você pode remover a senha e voltar o banco de dados à situação normal. Num banco de dados protegido por senha, o menu Ferramentas|Segurança|Definir senha do banco de dados… passa a ser Ferramentas|Segurança|Desproteger senha do banco de dados…. Ao acionar este menu, será pedida novamente a senha e o banco de dados é então desprotegido.
13.1.4. DEFININDO SENHA POR CÓDIGO VBA
133
Microsoft© Access Avançado Você pode definir uma senha do banco de dados por código VBA, utilizando os objetos do DAO. O método para definir a senha é NewPassword do objeto Database. O código não pode ser escrito no mesmo banco de dados o qual se deseja proteger. Sub SetDBPassword() ' Declara a variável do objeto database. Dim dbs As Database ' Abre o banco de dados em modo exclusivo. Set dbs = OpenDatabase("C:\bd1.mdb", True) ' Define a senha e fecha o banco de dados. dbs.NewPassword "","topsecret" dbs.Close End Sub
13.1.5. ABRINDO UM BANCO DE DADOS PROTEGIDO VIA CÓDIGO VBA Para abrir um banco de dados protegido via código VBA, utilize o método OpenDatabase. Sub OpenProtectedDB() ' Declara a variável do objeto database. Dim dbs As Database ' Abre o banco de dados protegido em modo compartilhado. Set dbs = OpenDatabase("C:\bd1.mdb", False, False, ";pwd=topsecret") End Sub
13.1.6. ALTERANDO A SENHA VIA CÓDIGO VBA Você pode também alterar a senha via código usando o método NewPassword do objeto Database. O código não pode ser escrito no mesmo banco de dados o qual se deseja trocar a senha. Sub ChangeDBPassword() ' Declara a variável do objeto database. Dim dbs As Database ' Abre o banco de dados em modo exclusivo. Set dbs = OpenDatabase("C:\bd1.mdb", True, False, ";pwd=topsecret")) ' Define a senha e fecha o banco de dados. dbs.NewPassword "topsecret", "novasenha" dbs.Close End Sub
134
Microsoft© Access Avançado
13.2. CRIAÇÃO DE ARQUIVO MDE Você pode criar um arquivo de extensão .MDE a partir de um arquivo .MDB. Não é preciso que o banco de dados .MDB esteja em uso. Num arquivo MDE todas as estruturas de formulários, relatórios e módulos ficam ocultas e inacessíveis. Você não pode criar novos formulários, relatórios e módulos, nem exportar estes objetos, nem importar estes objetos de outros banco de dados .MDE. Entretanto, tabelas, consultas e macros permanecem acessíveis e podem ser importados e exportados. Se você alterar seu banco de dados original, deve criar novamente um arquivo .MDE. Mantenha sempre uma cópia de segurança do banco de dados original, pois não é possível desfazer um arquivo .MDE. Arquivos MDE são ideais para a distribuição da sua aplicação front-end, isto é, um banco de dados de extensão MDE possui as consultas, formulários, relatórios, macros e módulos que acessam outros bancos de dados que contêm as tabelas. Arquivos .MDB Arquivo .MDE
Aplicativo
Tabelas
Tabelas Tabelas
Para criar um arquivo MDE, siga os passos: 1) Antes de criar um arquivo .MDE, faça uma cópia de segurança do banco de dados original. 2) Se você trabalha em rede, assegure-se que ninguém mais esteja com o banco de dados em uso. 3) Acione o menu Ferramentas|Utilitários de banco de dados|Criar arquivo MDE … 4) Na caixa de diálogo “Salvar banco de dados como MDE”, escolha o banco de dados original e clique no botão Criar MDE. 5) Na caixa de diálogo “Salvar como MDE”, escolha o nome do novo arquivo e clique no botão Criar. Se o banco de dados original fizer referência a outros bancos de dados MDB ou banco de dados de suplemento (.MDA), estes devem também ser convertidos para MDE, na ordem em que eles são referenciados. Por exemplo, se o seu banco de dados db3.mdb referencia db2.mdb que por sua vez referencia db1.mda, a ordem deve ser db1.dba, db2.mdb e db3.mdb. 135
Microsoft© Access Avançado Para um bom nível de segurança, defina senhas para o banco de dados do aplicativo (extensão MDE) e para cada banco de dados de tabelas (extensão MDB). Dentro do código do aplicativo, vincule as tabelas necessárias via código VBA, passando a senha. Como o código do aplicativo ficará inacessível, a senha ficará a salvo no código. Desta forma, as tabelas também ficam protegidas contra alteração de estrutura, já que tabelas vinculadas não podem ter suas estruturas alteradas. Eis um código VBA para vincular uma tabela de uma banco de dados protegido por senha. Sub LinkTable() Dim dbs As Database Dim tdfs As TableDefs Dim tdf As TableDef Set dbs = CurrentDb Set tdfs = dbs.TableDefs Set tdf = dbs.CreateTableDef("Order Linked") tdf.Connect = ";database=c:\bd1.mdb; pwd=topsecret" tdf.SourceTableName = "Order" tdfs.Append tdf End Sub
Nesta configuração, os dados das tabelas ainda ficam vulneráveis à alteração, assim como as estruturas das consultas. Os dados somente podem ser protegidos com a segurança em nível de usuário. Quanto as consultas, você pode minimizar o problema com as seguintes recomendações: 1) Define a propriedade Origem do Registro de formulários e relatórios como uma tabela ou uma consulta SQL (chamando o Construtor de Consulta ou passando a expressão SQL diretamente). 2) Defina consultas de ação em código VBA, construindo consultas com expressões em SQL e utilizando o método RunSQL objeto DoCmd. 3) Abra consultas que retorna folha de dados em sub-formulários. Defina consultas seleção ou referência cruzada em código VBA, construindo consultas com expressões em SQL e passando a expressão como propriedade RecordSource do subformulário. Eis um exemplo de consulta de ação definida em código VBA. Sub DeleteCliente() Dim strSql As String strSql = "DELETE * FROM Clientes" DoCmd.RunSQL (strSql) End Sub
Eis um exemplo de como passar uma consulta de ação para um subformulário. Private Sub cmdAbrir_Click( )
136
Microsoft© Access Avançado Dim strSql as String strSql = "SELECT * FROM [Detalhes do Pedido]" Me![subfrmDetalhe].Form.RecordSource = strSql Me![subfrmDetalhe].Requery End Sub
13.3. CRIPTOGRAFIA DE BANCO DE DADOS A criptografia protege o banco de dados contra acesso a seus dados via um editor de texto ou outra ferramenta de acesso a disco. Ela deve ser usada juntamente com a senha de banco de dados, pois se alguém abrir um banco de dados diretamente pelo Access, a criptografia não tem efeito nenhum. Note a ao abrir o banco de dados Northwind.mdb, pelo Wordpad, dados podem ser lidos.
No arquivo criptografado, todos os dados ficam ilegíveis.
137
Microsoft© Access Avançado A criptografia é um processo reversível. Você pode criptografar um banco de dados e depois decriptografá-lo.
13.3.1. CRIANDO UM ARQUIVO CRITPTOGRAFADO 1) Abra o MS Access. 2) Certifique-se que o arquivo a ser criptografado não esteja em uso. 3) No menu Ferramentas|Seguraça escolha Criptografar/decriptografar banco de dados.. 4) Na caixa de diálogo “Criptografar/Decriptografar banco de dados”, selecione um arquivo não criptografado e clique Ok. 5) Na caixa de diálogo “Criptografar banco de dados”, informe o novo nome do arquivo e clique Salvar. 13.3.2. REVERTENDO A CRITPTOGRAFIA 1) Abra o MS Access. 2) Certifique-se que o arquivo a ser decriptografado não esteja em uso. 3) No menu Ferramentas|Seguraça escolha Criptografar/decriptografar banco de dados.. 4) Na caixa de diálogo “Criptografar/Decriptografar banco de dados”, selecione um arquivo criptografado e clique Ok. 5) Na caixa de diálogo “Descriptografar banco de dados”, informe o novo nome do arquivo e clique Salvar.
13.3.2. CRIPTOGRAFIA POR CÓDIGO VBA Use o médodo CompactDatabase do objeto DBEngine para criptografar outro banco de dados. Sub EncryptDb() DBEngine.CompactDatabase "C:\bd1.mdb", "C:\db1Cripto.mdb", _ dbLangGeneral, dbEncrypt End Sub
13.4. SEGURANÇA EM NÍVEL DE USUÁRIO A segurança em nível de usuário é o modo mais flexível e seguro de proteger um banco de dados. Com ele, para cada objeto, pode-se definir permissões de:
abrir/executar (para formulário, relatório e macro) leitura de dados (para tabela e consulta), inserção de dados (para tabela e consulta), exclusão de dados (para tabela e consulta), alteração de dados (para tabela e consulta), visualização de estrutura, 138
Microsoft© Access Avançado
alteração de estrutura e administração. Ainda pode-se definir permissões para o banco de dados:
Abrir/executar, Abrir exclusivo e Administração
As permissões são definidas para cada usuário (chamada permissão explícita) ou para grupo de usuários (chamada permissão implícita). Neste último caso, os usuários membros do grupo herdam as permisssões do grupo. As definições das permissões ficam armazenadas em um arquivo de informação de grupo de trabalho, de extensão .MDW. Por padrão, o arquivo de informação de grupo de trabalho é o SYSTEM.MDW e existem dois grupos pré-definidos:
Administradores (Admins, na versão em inglês) Usuarios (Users, na versão em inglês)
Existe ainda um usuário pré-definido, o Adminsitrador (Admin, na versão em inglês) que pertence a ambos os grupos pré-definidos. O arquivo de informação de grupo de trabalho pode ser associado a todos os bancos de dados ou a apenas um especificamente. O segundo método é o mais adequado, pois você define segurança por aplicativo. Ao definir segurança em nível de usuário, ao abrir o banco de dados será apresentada uma caixa de diálogo de Logon para que seja informado o nome do usuário e a senha. Se o usuário e a senha estiverem corretos, o banco de dados é aberto e permitirá que o usuário execute somente as tarefas definidas nas permissões. As permissões sobre os objetos podem ser alteradas:
Por membros do grupo Administradores. Pelo proprietário do objeto. Por usuários que tenha permissão Administração sobre o objeto.
13.4.1. PROPRIEDADE SOBRE O BANCO DE DADOS E OBJETOS
Por padrão, o usuário Administrador é o proprietário do banco de dados e de todos os objetos nele contidos. Proprietário é o usuário que criou o objeto. Na segurança em nível de usuário não é possível retirar a permissão de usuários criarem objetos. Criando-se um arquivo MDE, pode-se evitar que novos formulários, relatórios e módulos sejam criados. Via programação, pode-se retirar permissões de usuários de criarem novas tabelas e consultas e novos banco de dados, mas não se pode retirar permissão de criar formulários, relatórios, macros e módulos.
13.4.2. IMPLEMENTANDO SEGURANÇA EM NÍVEL DE USUÁRIO
139
Microsoft© Access Avançado Crie um novo arquivo de informação de grupo de trabalho. 1) Clique no atalho para o “Administrador de grupo de trabalho do MS Access”. Surgirá a caixa de diálogo a seguir:
2) O arquivo SYSTEM.MDW é o arquivo padrão de informação de grupo de trabalho. Clique no botão Criar. 3) Surgirá uma caixa de diálogo para definir o proprietário do grupo de trabalho. Guarde bem as informações, incluindo se as letras estão em maiúsculas ou minúsculas.
4) Ao clicar OK, surgirá uma caixa de diálogo para o nome e localização do novo arquivo de informação de grupo de trabalho.
140
Microsoft© Access Avançado
5) Ao clicar OK, uma caixa de diálog surgirá confirmando o novo arquivo de informação de grupo de trabalho. Ao abrir o Access, todos os bancos de dados utilizarão o novo arquivo para a segurança em nível de usuário.
Observação: Você pode pensar em simplesmente criar um arquivo MDW a partir de uma cópia do system.mdw. Este método não funciona, pois cada arquivo tem uma identificação única, formada pelo Nome, Empresa e Código do grupo de trabalho. Crie um usuário proprietário e administrador 1) Inicie o Access, sem abrir ou criar nenhum banco de dados. Acione o menu Ferramentas|Segurança|Contas de usuário e grupo… 2) Na caixa de diálogo Contas de usuário e grupo, crie um novo usuário que será o proprietário e administrador do banco de dados de seu aplicativo e inclua-o no grupo Administradores. Usaremos para exemplo o usuário Master.
141
Microsoft© Access Avançado
3) Na caixa de combinação Nome, selecione o usuário Administrador e retire-o do grupo Administradores. 4) Na guia Alterar senha de logon, informe uma senha para o usuário Administrador. Isto fará com que uma caixa de diálogo de logon apareça ao abrir o Access. 5) Clique no botão OK e saia do Access. 6) Abra novamente o Access. Surgirá a caixa de logon. Informe o novo usuário, no caso Master. A senha não foi definida ainda e portanto, pode clicar OK. 7) Acione o menu Ferramentas|Segurança|Contas de usuário e grupo…, selecione a guia Alterar senha de logon, informe uma senha para o usuário Master. Clique Ok. Observação: Se você não retirar o usuário Administrador do grupo Administradores, qualquer um poderá acessar seu banco de dados usando o arquivo padrão system.mdw. O usuário Administrador permanece no grupo Usuários e não pode ser retirado desde grupo. Criar um banco de dados novo sem permissões de usuário 1) Crie um banco de dados novo. O usuário Master será o proprietário do banco de dados. O grupo Administradores e Usuarios terão todas as permissões sobre todos os objetos e sobre o banco de dados novo. 2) Acione o menu Ferramentas|Segurança|Permissões para usuário e grupo…. 142
Microsoft© Access Avançado 3) Mude para listar Grupos e selecione o grupo Usuários. Na caixa de combinação Tipo de objeto, altere para “banco de dados”, retire todas as pemissões e clique no botão Aplicar. 4) Na caixa de combinação Tipo de objeto, altere para cada tipo de objeto e retire todas as pemissões. Clique no botão Aplicar antes de mudar de tipo de objeto. 5) Clique Ok. Observação: Se você não retirar as permissões do grupo Usuários, qualquer um poderá acessar seu banco de dados usando o arquivo padrão system.mdw e o usuário Administrador, pois ele ainda permanece ao grupo Usuários. Defina um grupo de usuários para seu aplicativo 1) Acione o menu Ferramentas|Segurança|Contas de usuário e grupo… 2) Na guia Grupos, crie um novo grupo de usuário do seu aplicativo, por exemplo Usuarios do sistema. Clique Ok. 3) Acione o menu Ferramentas|Segurança|Permissões para usuário e grupo…. 4) Mude para listar Grupos e selecione o grupo Usuarios do sistema . Na caixa de combinação Tipo de objeto, altere para “banco de dados”, marque somente a permissão Abrir/Executar e clique no botão Aplicar. 5) Na caixa de combinação Tipo de objeto, altere para cada tipo de objeto e escolha as permissões desejadas. De um modo geral, os usuários não devem ter permissão de Modificar estrutura e Administrador. Clique no botão Aplicar antes de mudar de tipo de objeto. 6) Clique Ok. 7) Se alguns usuário tiverem níveis de permissão diferentes, crie novos grupos de usuários e marque as pemissões desejadas. Crie usuários e associe aos grupos 1) Acione o menu Ferramentas|Segurança|Contas de usuário e grupo… 2) Crie novos usuários e adicione ao grupo Usuarios do sistema. Todo novo usuário automaticamente faz parte do grupo Usuários e não pode ser removido dele. Os usuários herdarão as permissões do grupo ao qual pertencem. 3) Se outro usuário precisar ter o poder de administrar o banco de dados, inclua-o no grupo Administradores. 4) Todos os usuários não terão senha. Você deve abrir o Access e efetuar o logon com cada usuário e definir uma senha. Acione o menu Ferramentas|Segurança|Contas de usuário e grupo…, selecione a guia Alterar senha de logon, informe uma senha para o usuário atual. Eliminado a caixa de logon 1) Efetue o logon como Administrador. 2) Acione o menu Ferramentas|Segurança|Contas de usuário e grupo…, selecione a guia Alterar senha de logon, informe a senha atual e mantenha a caixa Nova senha e Confirmar em branco. Clique OK. Observação: Ao retirar a senha do usuário Administrador, o Access não mais pedirá senha de logon, e todos os usuários se logarão como Administrador. Como este usuário não tem 143
Microsoft© Access Avançado nenhuma permissão, ele nada poderá fazer, a não ser que o grupo Usuários tenha alguma permissão. Você pode definir algumas permissões básicas para o usuário Administrador. Não é aconselhável eliminar a senha do usuário Administrador.
Definindo um arquivo de informação de grupo de trabalho para um aplicativo 1) Acione o Administrador de grupo de trabalho e associe o arquivo original (SYSTEM.MDW). Isto fará com que o Access use o arquivo original mas não permitirá o acesso aos bancos de dados protegidos. 2) Crie um atalho que chame o Access e passe os parâmetros de linha de comando. “C:\Arquivos de programas\Microsoft Office\Office\MSAccess.exe” C:\bd1.mdb /wrkgrp C:\sistemax.mdw
13.4.2. LOGON POR CÓDIGO VBA
Ao definir segurança em nível de usuário, você pode ter uma complicação com códigos escritos sem levar em conta esta segurança. Uma operação que normalmente funcionava antes pode não funcionar mais depois de configurada a segurança. Um caso típico é a abertura De uma tabela pelo método OpenRecordset do objeto Database. Normalmente o código é: Sub AbreTabela() Dim dbs As Database Dim rst As Recordset Set dbs = CurrentDb Set rst = dbs.OpenRecordset("Categorias") End Sub
Caso o usuário atual não tenha permissão sobre a tabela Categorias, o código falhará. Se você não quer dar permissão ao usuário para acessar a tabela, é preciso abrir o banco de dados, via código, com uma conta de um usuário que tenha as permissões necessárias. Sub AbreTabela() Dim wks As Workspace Dim dbs As Database Dim rst As Recordset Set wks = DBEngine.CreateWorkspace("NewWork", "master", "topsecret") Set dbs = wks.OpenDatabase(CurrentDb.Name) Set rst = dbs.OpenRecordset("Categorias") End Sub
Observação: No modo programado, os grupos Administradores e Usuários são referidos como Admins e Users, respectivamente, e o usuário Administrador é Admin, independentemente se o Access é em português ou inglês.
144
Microsoft© Access Avançado 13.4.3. TROCA DE SENHA VIA CÓDIGO VBA
Para os usuários mudarem a sua senha, precisam ter acesso ao menu Ferramentas|Segurança|Contas de usuário e grupo…Entretanto, em uma aplicação não é interessante que os usuários tenham acesso a menus. Para resolvere esta situação, pode-se criar um código VBA para eles mesmos alterem suas senhas, sem ter acesso ao menu. Sub ChangePassword() Dim wks As Workspace Set wks = DBEngine.Workspaces(0) wks.Users("Teste").NewPassword "senhaantiga", "novasenha" End Sub
O usuário não precisa ser administrador para alterar sua própria senha. Porém, eles não conseguem alterar senha de usuários do grupo Administradores, nem conseguem alterar sus própria senha caso esqueçam a senha atual. No exemplo acima, foi alterada a senha do usuário Teste. Uma melhoria do código seria criar uma caixa de diálogo que obtivesse o nome do usuário atual. O nome do usuário atual pode ser obtido pela função CurrentUser().
Private Sub cmdFechar_Click() DoCmd.Close End Sub Private Sub cmdOk_Click() Dim wks As Workspace Set wks = DBEngine.Workspaces(0) If Me.txtNovaSenha <> Me.txtConfirmar Then MsgBox "Nova senha não confere!" Exit Sub End If On Error Resume Next wks.Users(CurrentUser()).NewPassword Me.txtSenhaAtual, Me.txtNovaSenha If Err.Number <> 0 Then MsgBox "Não foi possível alterar a senha. Confira a sua senha atual!"
145
Microsoft© Access Avançado End If End Sub Private Sub Form_Open(Cancel As Integer) Me.txtUsuario = CurrentUser() Me.txtSenhaAtual.SetFocus End Sub
13.4.4. RETIRAR PEMISSÃO DE CRIAR NOVOS BANCOS DE DADOS
Quando um usuário efetua o logon no Access, é possível ele fechar o database do aplicativo e criar um novo banco de dados. Via programação é possível retirar esta permissão. A permissão de criar banco de dados está no objeto Container, especificamente o container Databases, do arquivo de informação de grupo de trabalho. Deve-se portanto abrir este arquivo e configurar a propriedade Permissions do container Databases. Para acrescentar uma permissão às já existentes, faz-se uma operação Or. Para remover permissão, faz-se uma operação And Not. As operações são feitas com as permissões atuais e uma constante intríseca das Constantes de Segurança. No caso de criação de banco de dados, a constante é a dbSecDBCreate. Sub Deny_DBCreate() Dim dbs As Database, ctr As Container, strMDW ' Recupera o caminho e o nome do arquivo de grupo de trabalho strMDW = DBEngine.SystemDB Set dbs = DBEngine(0).OpenDatabase(strMDW) Set ctr = dbs.Containers!Databases ctr.Username = "Users" ' Grupo Usuários ctr.Permissions = ctr.Permissions And Not dbSecDbCreate End Sub
13.4.5. RETIRAR PEMISSÃO DE CRIAR NOVAS TABELAS E CONSULTAS
As permissões para criar tabelas e consultas ficam são definidas no objeto Container, especificamente no container Tables, do banco de dados protegido (.MDB). A propriedade Permissions deste container deve sofrer a operação And Not dbSecCreate. Sub Deny_Create_TableQuery() Dim dbs As Database, ctr As Container Set dbs = CurrentDb() Set ctr = dbs.Containers!Tables ctr.Username = "Users" ' Grupo Usuários ctr.Permissions = ctr.Permissions And Not dbSecCreate End Sub
146
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT A Microsoft adota a Leszynski Naming Conventions - LNC, também conhecida como notação húngara, para nomear objetos dos produtos MS Office (Access, Excel, Word, Outlook e PowerPoint), MS Project, MS BackOffice (SQL Server, Exchange Server, System Management Server, Internet Information Server e SNA Server) e MS Visual Studio (Visual Basic, Visual FoxPro, Visual C++ e Visual InterDev). Estes objetos englobam: • Class modules (módulos de classe do Visual Basic) • Constants (constantes) • Form controls (controles de formulários do Visual Basic e do Access) • Forms (formulários do VB e do Access) • Modules (módulos do VB e Access) • Procedures (procedimentos do VB e Access) • Queries and views (consultas do Access e SQL) • Report controls (controles de relatório do Access) • Reports (relatórios do Access) • Security objects (objetos de segurança do Access) • Stored procedures (procedimentos armazenados do SQL) • Table fields (campos de tabelas do Access) • Tables (tabelas do Access) • Triggers (gatilhos do SQL) • User-defined types (tipos definidos pelo usuário do VB e Access) • Variables (variáveis) A estrutura da LNC baseia-se em uma tag (etiqueta) antes do nome do objeto (por exemplo, frmLogin). A sintaxe é: [prefixo(s)] {tag} {Nome} [Qualificador] [Sufixo] Os elementos entre colchetes são opcionais. O prefixo e a tag são escritos sempre em letras minúsculas. O nome e o qualificador são escritos em letras maiúsculas e minúsculas. O sufixo pode ser escrito tanto em letras maiúsculas quanto minúsculas. Exemplos: Nome do objeto Prefixo qryVendasReopABR frmSobre sdtmVigCtr s plngAcumulado p
Tag qry frm dtm lng
Nome Vendas Sobre Vig Acumulado
147
Qualificador Reop Ctr
Sufixo ABR
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT
MICROSOFT ACCESS Hierarquia dos objetos do Access
Tags para objetos da janela de banco de dados do ACCESS Objeto Formulário (form) Macro Módulo (module) Consulta (query) Relatório (report) Tabela (table) (*)
Tag frm mcr bas qry rpt tbl
(*) As tabelas não usarão prefixo nem tags, somente o Nome. Tags para objetos controles do ACCESS Controle Bound object frame (moldura de objeto acoplado) Chart Check box (caixa de verificação) Combo box (caixa de combinação) Command button (botão de comando) Custom control (controle personalizado) Image (imagem) Label (rótulo) Line (linha) List box (caixa de listagem) Option button (botão de opção) Option group (grupo de opção) Page break (quebra de página) Rectangle (retângulo) Section (seção) Subform/Subreport (subformulário/subrelatório) Text box (caixa de texto) Toggle button (botão alternar) Unbound object frame (moldura de objeto não acoplado)
148
Tag frb cht chk cbo cmd ocx img lbl lin lst opt grp brk shp sec sub txt tgl fru
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT
Tags para variáveis do ACCESS Objeto Application Collection Control Controls CustomControl CustomControlinReport Debug DoCmd Err Form Forms GroupLevel Report Reports Screen Section
Tag app col ctl ctls ocx ocx n/a doo n/a frm frms lvl rpt rpts scn sec
DATA ACCESS OBJECTS - DAO Hierarquia dos objetos DAO para Microsoft Jet Workspaces
149
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT
Hierarquia dos objetos DAO para ODBCDirect Workspaces
Tags para Data Access Objects - DAO Objeto Connection Connections Conteiner Conteiners Database Databases DBEngine Document Documents Error Errors Field Fields Group Groups Index Indexes Parameter Parameters Properties Property QueryDef QueryDefs RecordSet RecordSets Relation Relations TableDef TableDefs User Users Workspace Workspaces
Tag (ACCESS) con cons ctr ctrs dbs dbss dbe doc docs err errs fld flds grp grps idx idxs prm prms prps prp qdf qdfs rst rsts rel rels tdf tdfs usr usrs wrk wrks
150
Tag (VB)
db
qry rec
tbd
wsp
ANEXO A - CONVENÇÃO DE NOMES PARA DESENVOLVIMENTO DE APLICAÇÕES COM PRODUTOS MICROSOFT
MICROSOFT VISUAL BASIC 5.0 Tags para controles do Visual Basic Controle 3D Panel Animated button Check box Combo box, drop-down list box Command button Common dialog Communications Control (usado em procedures quando o tipo é indefinido) Data control Data-bound combo box Data-bound grid Data-bound list box Directory list box Drive list box File list box Form Frame Gauge Graph Grid Horizontal scroll bar Image Key status Label Line List box MAPI message
Tag pnl ani chk cbo cmd dlg com ctr
MAPI session MCI MDI child form Menu MS Flex grid MS Tab OLE Outline Pen BEdit Pen HEdit Pen ink Picture Picture clip Report Shape Spin Text box Timer UpDown Vertical scroll bar Slider ImageList TreeView Toolbar TabStrip StatusBar ListView ProgressBar RichTextBox
dat dbcbo dbgrd dblst dir drv fil frm fra gau gra grd hsb img key lbl lin lst mpm
mps mci mdi mnu msg mst ole out bed hed ink pic clp rpt shp spn txt tmr upd vsb sld ils tre tlb tab sta lvw prg rtf
MICROSOFT VISUAL BASIC FOR APPLICATION - VBA Tags para variáveis do Visual Basic for Application Tipo de variável
Tag (VBA) bln byt ccc cur dtm dbl err int lng obj sng str typ var
Boolean (lógico) Byte Collection object Conditional Compilation Constant Currency (moeda) Date (data) Double (dupla precisão) Error Integer (inteiro) Long (inteiro longo) Object Single (inteiro simples) String (caracter) User-Define Type Variant
151
Tag (VB) col -
udt vnt