Os conteúdos aqui podem ser aplicados ao Northwind 2.0 Developer Edition e ao Starter Edition.
Referência do VBA do Access
O VBA (Visual Basic for Applications) é a linguagem de programação utilizada em todos os Produtos do Office. A aprendizagem do VBA permite-lhe trabalhar com todos os produtos do Office (e não apenas com o Access).
Ao procurar "procedimentos", certifique-se de que procura exemplos específicos do Access e inclui o Microsoft Access na pesquisa. Muitas vezes, as soluções para outros produtos do Office funcionam, mas não há garantias. O Microsoft Access é um produto maduro; isto significa que existem muitos exemplos lá fora; o que é ótimo para si!
Também significa que os livros mais antigos sobre programação do Access ainda são viáveis para que possa ver. Muitos dos livros mais antigos ainda estão disponíveis em sites de livros usados a uma fração do seu custo original. Consulte o site da Microsoft para determinar que versões do Access ainda estão a ser suportadas e siga-as.
Fim dos recursos de suporte do Office – Implementar o Office | Microsoft Learn
Seguem-se algumas ligações para a documentação do Access na Microsoft.
- Referência do Access Visual Basic for Applications (VBA) | Microsoft Learn
- Glossário do VBA | Microsoft Learn
- Tópicos conceptuais do Visual Basic | Microsoft Learn
- Visual Basic for Applications - Wikipédia
- VBA-Docs/API no principal · MicrosoftDocs/VBA-Docs · GitHub
Localizações Fidedignas e Conteúdo Ativado
Os ficheiros do Microsoft Access são ficheiros do Office. Os ficheiros do Office têm de estar numa "Localização Fidedigna" ou ter o "conteúdo ativado". Estes itens são considerados "seguros" porque os criou ou são provenientes de uma origem fidedigna. Verifique se existem Localizações Fidedignas sempre que abre qualquer Ficheiro do Office. Vamos referir-nos a isto como Fidedigno/Ativado a partir de agora. NOTA: se uma nova versão da aplicação for lançada e aberta a partir de uma localização não fidedigna, o processo de ativação do conteúdo será repetido.
Saiba mais sobre localizações fidedignas.:
- Localizações Fidedignas para ficheiros do Office – Implementar o Office | Microsoft Learn
- Decidir se pretende confiar numa base de dados (Suporte da Microsoft)
- Adicionar, remover ou alterar uma localização fidedigna (Suporte da Microsoft)
Macros, Funções e Subs
Macros, Funções e Subs são a forma como implementa a lógica de negócio na sua base de dados do Access. É importante que compreenda o Âmbito e a Visibilidade antes de começar.
- Ação de macro RunCode | Microsoft Learn
- Introdução às macros | Suporte da Microsoft
- Instrução de função (VBA) | Microsoft Learn
- Sub-instrução (VBA) | Microsoft Learn
Os eventos (como clicar num controlo) em Controlos num formulário (por exemplo, botões, caixas de texto, etiquetas, etc.) acionam outros processos, como adicionar, eliminar registos ou abrir formulários. Estes processos podem ser implementados com macros ou VBA. O Northwind Starter Edition utiliza principalmente macros e alguns VBA onde as macros não conseguem executar as funções necessárias. A Northwind Developer Edition utiliza principalmente o VBA.
Alguns tipos de controlo têm assistentes incorporados para criar automaticamente uma macro. Por exemplo, adicionar um botão de comando a um formulário abre um assistente que oferece várias opções de funcionalidade para o botão. Adicionar uma caixa de combinação abre um assistente que pode ser configurado para localizar um registo específico no formulário.
Painel de Navegação
O Painel de Navegação é a principal forma de ver e aceder a todos os objetos da base de dados e é apresentado no lado esquerdo da janela do Access por predefinição.
O Painel de Navegação da Northwind foi personalizado. Criámos uma categoria personalizada denominada Northwind Starter 2.0. Isto permite-nos organizar os objetos por área funcional.
- Utilizar o Painel de Navegação | Suporte da Microsoft
- Personalizar o Painel de Navegação | Suporte da Microsoft
Âmbito e Visibilidade das Variáveis no VBA
É importante saber mais sobre o Âmbito e a Visibilidade no Access/Office. Pode começar aqui:
- Compreender o âmbito e a visibilidade (VBA) | Microsoft Learn
- Declaração pública (VBA) | Microsoft Learn
- Instrução privada (VBA) | Microsoft Learn
- Instrução estática (VBA) | Microsoft Learn
- Compreender a duração das variáveis (VBA) | Microsoft Learn
Variáveis Persistentes
Por vezes, é necessário que exista uma variável após o objeto que o criou ficar fora do âmbito. Veja Âmbito e Visibilidade acima. Existem três formas principais de o fazer: Variáveis Públicas, TempVars e Armazenar os valores numa tabela local. Muitos programadores utilizam uma combinação destes. Cada um tem os seus prós e contras. Mais informações sobre cada um aqui:
Variável Pública do Módulo VBA:
TempVars:
- Objeto TempVars (Access) | Microsoft Learn
- Sugestão de Energia: Maximizar a utilização de TempVars no Access 2007 e 2010 | Blogue do Microsoft 365
Armazenar os valores na tabela local
- As variáveis públicas e as TempVars existem para a sessão atual e ficam fora do âmbito quando a aplicação é fechada. Mas e se quiser manter variáveis específicas do utilizador entre sessões? Pode armazenar estes tipos de valores numa tabela local. Em Northwind 2.0, uma dessas variáveis é guardada numa tabela denominada SystemSettings. O valor na tabela é ShowWelcome. Este valor indica ao Access se pretende ver o ecrã de Boas-vindas sempre que iniciar sessão ou não.
OpenArgs e StringFormat()
Muitas vezes, os programadores precisam de transmitir parâmetros de um formulário para outro ou de um formulário para um relatório. Estes parâmetros transmitem informações importantes, que a função denominada utilizará para se configurar. Existem várias formas de o segundo formulário ou relatório obter informações do primeiro formulário. Eis algumas dessas formas:
- O segundo formulário pode "olhar para trás" para o primeiro formulário para recolher alguns valores, possivelmente num controlo visível ou invisível. Por exemplo:
lngCustomerID = Forms!FirstForm!cboCustomerID - O primeiro formulário pode guardar valores em variáveis globais ou em TempVars. Por exemplo:
g_lngUserID = Me.cboUserID
TempVars.Add "UserID", Me.cboUserID
O método que é frequentemente utilizado na Northwind Developer Edition, bem como na nossa vida profissional, está a utilizar o argumento OpenArgs do DoCmd.OpenForm ou OpenReport. Por exemplo:
DoCmd.OpenForm "frmCompanyDetail", OpenArgs:=StringFormat("CompanyID={0} &CompanyTypeID={1}", Me.VendorID, ctVendor)
Estamos a combinar duas técnicas aqui: (1) a utilização de OpenArgs para transmitir o VendorID e VendorType e (2) a utilização da função StringFormat() para criar, por exemplo, esta cadeia:
CompanyID=5&CompanyTypeID=2
Esta cadeia é muito semelhante a uma cadeia de consulta, tal como é utilizada num browser. Contém um ou mais "pares nome/valor" separados pelo caráter de e comercial:
name1=value1&name2=value2
A vantagem de tal cadeia é que cada valor tem um nome. Compare esta opção com uma abordagem mais simples, na qual definiria OpenArgs apenas como "5,2". Nesse caso, seria necessário um esforço para descobrir o que cada valor significa. Atribuir um nome a cada valor torna a cadeia de consulta "autodescritiva", o que é uma boa prática de programação.
Na extremidade receção do DoCmd.OpenForm , normalmente estamos no evento Form_Open ou Form_Load e queremos analisar a cadeia OpenArgs nos respetivos componentes.
Em Northwind, pode fazê-lo com a função StringToDictionary . Ele usa uma função semelhante a querystring e a analisa em seus componentes. Esses componentes são armazenados em um objeto Scripting.Dictionary . Observe que isso exige que você use Referências de Ferramentas > e defina uma referência ao Microsoft Scripting Runtime (scrrun.dll).
Os recursos e os benefícios do objeto Dictionary incluem estes:
- A ordem dos elementos não é importante
- Funções simples para adicionar e remover elementos da coleção
- Funções para fazer loop sobre a coleção, para que você possa saber o que está nela
- Uma função Existe para que você possa testar se um determinado elemento estiver disponível
O uso do objeto dicionário é exibido em todo o Northwind. Por exemplo, o evento Form_Load no frmGenericDialog.
Tratamento de Erro
As macros criadas com assistentes de controle no Access raramente incluem o tratamento de erros; O VBA criado com assistentes de controle pode ser limitado a um MsgBox Err.Description genérico.
No Northwind 2.0, mostramos como fazer melhor ao usar o código VBA. Implementamos o que é chamado de Manipulador Global de Erros. Erros que ocorrem em qualquer procedimento chamam uma função no nível global para mostrar o erro. A grande vantagem aqui é que o tratamento de erros é consistente. E se a mensagem precisar ser alterada (por exemplo, para mostrar adicionalmente o número de erro ou registrar o erro em um arquivo), ela precisa ser feita somente em um só lugar.
clsErrorHandler é o Módulo de Classe que implementa o código de tratamento de erros. Um módulo de classe mantém todas as suas funções principais e auxiliares juntas em uma unidade, encapsulando o código.
A macro AutoExec chama a função Inicialização no modStartup. No Starter Edition, a função cria uma instância do clsErrorHandler e a salva como uma variável global disponível para uso em todo o aplicativo. Na edição Dev, uma classe estática é usada – confira os comentários na parte superior do módulo de classe.
Na verdade, o código de tratamento de erros em procedimentos é tão consistente que fomos capazes de criar tudo isso em menos de cinco minutos usando código VBA específico que equipava cada procedimento com o manipulador de erros adequado. (Código não incluído no modelo). As edições de modelo do Northwind 2.0 Starter e do Desenvolvedor foram inicialmente equipadas com essa abordagem de tratamento de erros.
'
MANIPULAÇÃO DE ERROS APRIMORADA
Começando com a versão 2.2 do Northwind Developer Edition, o manipulador de erros foi aprimorado, graças aos comentários da comunidade do Access. A edição inicial não foi alterada.
Em essência, o manipulador de erros na versão anterior (2.0 – lançada em abril de 2023) é:
Public Sub HandleError(…)
MsgBox Err.Description
End Sub
Na versão 2.2, ele é atualizado para:
Public Sub HandleError (…, Optional ByVal IsEventProcedure As Boolean = False)
If Not IsEventProcedure Then
Err.Raise lngError, strErrSource
End If
MsgBox Err.Description
End Sub
Para entender por que essa alteração foi feita, vamos primeiro entender o que faz o código ser executado:
- A macro AutoExec chama o procedimento Inicialização, que executa algumas inicializações antes de abrir o primeiro formulário.
- O usuário interage com o aplicativo, como abrir um formulário ou clicar em um botão, fazendo com que procedimentos de evento disparem, como Form_Load e cmdPrintInvoice_Click.
'
Além dos procedimentos de evento, os aplicativos têm sub-rotinas e funções , principalmente em módulos, e esse código é chamado dos procedimentos de evento. Estes são chamados de procedimentos "padrão".
Na versão 2.0 do Northwind, os procedimentos padrão tratariam seus próprios erros com mensagens, mas não notificariam de alguma forma o procedimento de evento de chamada de que havia ocorrido um erro. Isso pode ser ruim se o procedimento de evento tiver um código subsequente que deve ser executado independentemente do erro anterior tratado pelo procedimento chamado. Claro, poderíamos substituir a sub-rotina por uma função que retorna êxito ou falha e codificar o procedimento de evento de acordo, mas isso nem sempre é uma opção.
No Northwind versão 2.2, os procedimentos padrão não lidam com mensagens de erro, mas sim, usando Err.Raise, denuncie-os de volta ao procedimento de evento de chamada. Em seguida, o procedimento de evento de chamada exibe o erro gerado e é retomado em Exit_Handler. Isso é melhor, pois permite que o procedimento de chamada seja concluído normalmente.
Para usar o código Northwind versão 2.2, os procedimentos de evento devem passar para o HandleError um terceiro argumento indicando que o chamador é um procedimento de evento. O Northwind Dev Edition foi atualizado para fazer isso.
Um módulo ainda mais poderoso do manipulador de erros teria suporte para procedimentos de "push e popping" em uma "pilha" (matriz). O primeiro elemento sempre seria o procedimento de evento, portanto, o argumento extra não é necessário. Essa implementação está além das metas da Northwind Dev Edition.
Lista MRU
MRU ou Mais Recentemente Usado é uma lista de pedidos e pedidos de compra usados recentemente. Talvez você queira voltar a estes com frequência para colocá-los no próximo Status. As listas de MRU geralmente são vistas em produtos do Office como uma lista de arquivos usados recentemente que talvez você queira reabrir novamente.
na edição Northwind Dev, para implementar o recurso MRU (que não existe na edição Starter), primeiro você deve estabelecer os seguintes itens:
- Uma tabela para armazenar informações de MRU.
- Código para atualizar a tabela quando uma PO (ordem de compra ou pedido) for aberta.
- Código para atualizar a lista suspensa MRU na faixa de opções.
- Código para carregar o item quando um item mru é selecionado na faixa de opções.
Vamos examinar cada uma delas com mais detalhes.
1. Tabela para armazenar informações de MRU.
Vale a pena examinar o design da MRU da tabela, especialmente seus índices. Observe que há um SortIdx de índice duplicado para ajudar na classificação rápida dos itens mru na lista suspensa da faixa de opções, bem como um índice exclusivo para impor a regra de negócios que para cada usuário um item pode ocorrer apenas uma vez. Por exemplo, abrir a mesma ordem duas vezes não cria dois registros na tabela MRU.
A tabela aproveita o fato de que todos os campos PK (chave primária) relacionados à MRU no banco de dados são AutoNumber, de modo que o tipo de dados Long Integer pode ser usado para PKValue.
2. Código para atualizar a tabela quando um pedido ou P.O. é aberto.
No NW2, optamos por adicionar à lista de MRU somente quando um novo registro foi criado, não quando um existente foi atualizado novamente. Certamente poderíamos mover a chamada AddToMRU de Form_AfterInsert para Form_AfterUpdate para dar suporte a isso.
Os procedimentos AddToMRU e DeleteFromMRU são implementados no modGlobal, que é um módulo Standard cujos procedimentos públicos estão visíveis de qualquer formulário.
AddToMRU (como o nome sugere) adiciona o novo item à tabela MRU e, opcionalmente, o corta de volta, excluindo o registro mais antigo, se ele tiver crescido além do tamanho máximo (MAX_MRU_COUNT). A última etapa provavelmente é a menos conhecida para os desenvolvedores do Access: a lista suspensa da faixa de opções precisa ser atualizada e isso é realizado chamando InvalidateControl. Este é um sinal para a faixa de opções para executar novamente seu processo de inicialização.
3. Código para atualizar a lista suspensa mru na faixa de opções.
No momento da inicialização e, depois que InvalidateControl for chamado, um conjunto complexo de funções é executado para preencher a faixa de opções. Esses procedimentos são chamados pelo Ribbon XML na tabela uSysRibbons que diz em parte:
<group id="gCurrentStatus" label="MRU">
<box id="bxMRU" boxStyle="vertical">
<dropDown id="ddMRU"
getItemCount="ddMRU_GetItemCount"
getItemLabel="ddMRU_GetItemLabel"
getSelectedItemIndex="ddMRU_GetSelectedItemIndex"
getItemID="ddMRU_GetItemID"
onAction="ddMRU_OnAction"
screentip="Most Recently Used Objects">
</dropDown>
</box>
</group>
Essas quatro funções de retorno de chamada preenchem a lista suspensa. Observe que essa é a mesma ideia descrita aqui para caixas de combinação padrão.
Se você descompactar as linhas Debug.Print no modRibbonCallback e reiniciar o aplicativo, a Janela Imediata apresentará uma sequência como esta:
ddMRU_GetItemCount ddMRU 6
ddMRU_GetItemLabel ddMRU 0 Order 60, Proseware, Inc.
ddMRU_GetItemID ddMRU 0 2
ddMRU_GetItemLabel ddMRU 1 Order 62, Best For You Organics Company
ddMRU_GetItemID ddMRU 1 4
ddMRU_GetItemLabel ddMRU 2 Order 63, Wide World Importers
ddMRU_GetItemID ddMRU 2 5
ddMRU_GetItemLabel ddMRU 3 Order 66, Proseware, Inc.
ddMRU_GetItemID ddMRU 3 8
ddMRU_GetItemLabel ddMRU 4 Order 67, Best For You Organics Company
ddMRU_GetItemID ddMRU 4 9
ddMRU_GetItemLabel ddMRU 5 Order 68, Adatum Corporation
ddMRU_GetItemID ddMRU 5 10
ddMRU_GetSelectedItemIndex ddMRU 0
Podemos ver aqui que o Access está chamando primeiro um procedimento que retorna o número de itens a serem carregados no argumento ByRef de ddMRU_GetItemCount. Essa também é a hora em que abrimos a consulta na tabela MRU e a armazenamos em cache porque ela está prestes a ser usada várias vezes.
Em seguida, a faixa de opções chama repetidamente dois procedimentos para obter os valores ID e Label para a lista suspensa de duas colunas.
Por fim, ele chama um procedimento para desabilitar qual item deve ser selecionado. (No nosso caso, é o primeiro.)
4. Código para carregar um item quando o item MRU é selecionado na faixa de opções.
Como acontece com qualquer outro item de faixa de opções, a propriedade OnAction no Ribbon XML especifica uma função de retorno de chamada a ser usada para executar a ação:
onAction="ddMRU_OnAction"
Esse procedimento é implementado no modRibbonCallback. Ele reutiliza o conjunto de registros já aberto para localizar o registro com o item selecionado e, dependendo do TableName necessário, abre o formulário correspondente, passando o valor PK a ser carregado.
Saiba mais
- Northwind 2.0 Developer Edition: Template-Tutorial
- Northwind 2.0 Developer Edition: todos os tópicos