Entidades:
Livros(cota,titulo,autor,situação)
Leitores(bilhete_identidade,Nome,Morada)
Requisições(nr, bilhete_identidade,data)
Requisicao_livros(nr,cota,data_devolucao)
Modelo de dados:

As entidades "Leitores" e "Livros" são as entidades primárias nas relações. Estas entidades existem de forma independente. Isto é, uma biblioteca pode ter leitores e livros mesmo que não tenha requisições, no entanto não pode haver requisições se não houver livros ou leitores.
Usualmente, a manutenção das tabelas que envolvem entidades primárias requer:
- Consultar registos que satisfazem determinadas condições;
- Inserir novos registos;
- Corrigir dados em registos existentes;
- Eliminar registos-
A entidade "requisições" reflete as transacções entre "leitores" e "livros". A manutenção desta entidade requer:
- Efectuar requisições;
- Consultar requisições;
- Efectuar devoluções.
A entidade de ligação "Req_livros", surge por necessidade do modelo: deverá ser transparente para o utilizador.
O formulário "Biblioteca" é um "BlankForm" com botões de comando para aceder ás diferentes operações. Á propriedade "OnClick" dos botões estão associadas macros que abrem os formulários respectivos.
|
|
Na base de dados, existe uma macro chamada "Autoexec". Porque se chama "Autoexec", é executada automaticamente quando a Base de Dados é aberta. Esta macro abre o formulário "Biblioteca".
A manutenção (inserir, editar, consultar ou eliminar registos) da tabela "Leitores" é feita através do formulário "Leitores" (um "Tabular Form" em que a fonte de registos é a tabela "Leitores"):

|
Control |
Tipo Control |
Propriedade |
Macro /Função |
|
|
TextBox |
AfterUpdate |
localiza |
|
|
CommandButton |
OnClick |
primeiro, novo, ultimo, fechar |
|
|
CommandButton |
OnClick |
anterior(), seguinte(), elimina() |
Todas as operações para deslocar pelos registos poderiam ser efectuadas a partir de macros. No entanto, situações de erro (Ex: posicionar no registo anterior quando está no 1º registo) não são tratáveis por macros, por esse motivo as operações de: posicionar no registo anterior, posicionar no registo seguinte e eliminar registos, são implementadas utilizando funções.
Macros associadas aos controlos:

Funções para as operações: posiciona no registo anterior, posiciona no registo seguinte, elimina registo:
|
Function anterior () On Error GoTo anterior_erro DoCmd GoToRecord , , A_PREVIOUS anterior_exit: Exit Function anterior_erro: MsgBox("Inicio da Fonte de Registos!") Resume anterior_exit End Function |
Function seguinte () On Error GoTo seguinte_erro DoCmd GoToRecord , , A_Next seguinte_exit: Exit Function seguinte_erro: MsgBox ("Fim dos Registos !") Resume seguinte_exit End Function |
Function elimina ()
On Error GoTo elimina_erro
DoCmd DoMenuItem A_FORMBAR, A_EDITMENU, A_SELECTRECORD_V2, , A_MENU_VER20
DoCmd DoMenuItem A_FORMBAR, A_EDITMENU, A_DELETE_V2, , A_MENU_VER20
elimina_exit:
Exit Function
elimina_erro:
MsgBox ("Não pode eliminar registo corrente !")
Resume elimina_exit
End Function
A fonte de registos do formulário é uma "query" que ordena os livros por ordem alfabética do "Titulo":

Os botões ("A" a "Z") permitem filtrar os registos que são apresentados, selecionando os registos para os quais o campo selecionado na "ComboBox" começa pela letra indicada. A "Combo Box" "procura por" possibilita estabelecer o campo ("Titulo", "Autor" ou "Editor") sobre o qual é estabelecido o filtro:
|
"Combo Box" "Procura por" |
Botões de comando (A a Z) |
|
|
|
A função "Localiza" está definida no Módulo "Biblioteca":
Function Localiza (Letra As String)
Select Case Forms![Livros]![procura]
Case "Titulo":
DoCmd ApplyFilter , "[titulo] Like ""[" & Letra & "]*"""
Case "Autor":
DoCmd ApplyFilter , "[autor] Like ""[" & Letra & "]*"""
Case "Editor":
DoCmd ApplyFilter , "[editor] Like ""[" & Letra & "]*"""
End Select
End Function
O botão de comando "TODOS" tem associada a macro:
![]()
A informação necessária está distribuída por 4 tabelas.
Um formulário Main/Subform tem duas fontes de informação. Uma solução é a seguinte:
|
"Query" |
Objectivo |
|
leitor requisicao |
|
|
livros requisitados |
|
Formulário Main/SubForm que integra a informação das duas "queries".
Query "Leitor requisição":

Query "Livros requisitados":

Formulário de Requisições:
|
|
|

Os controlos com fundo branco, são os que recebem "Input" do utilizador. Os controlos de fundo cinzento, têm as propriedades "Enabled" e "Locked" respectivamente "No" e "Yes" de forma a não possibilitar alterar o seu valor (nem receber "Foco").
O botão "Requisição" é utilizado para criar uma nova requisição (em branco). Tem associada uma macro que posiciona num novo registo.
O botão "Fechar" tem uma macro associada que fecha o formulário. No subformulário existe uma "Text Box" que conta o número de livros requisitados. É um controlo calculado que tem a expressão =COUNT([ cota] ), associada á propriedade "Control Source".
Digitando um Bilhete de Identidade não existente na tabela "Leitores" a operação de "JOIN" na "Query" "Requisição leitores" (a mesma situação para "Cota"), não satisfaz as restrições de integridade, pelo que aparece a mensagem de erro:

Uma forma de ultrapassar este problema consiste em definir uma função para validar a informação digitada pelo utilizador.

|
Macro |
Control |
Propriedade |
Objectivo |
|
nova |
Botão "Requisição" |
OnClick |
Iniciar uma nova requisição |
|
leitor |
"TextBox" Leitor |
BeforeUpdate |
Verifica se o leitor está registado na tabela "Leitores" |
|
livro |
"TextBox" Cota |
AfterUpdate |
Verifica se está identificado o leitor Verifica se a cota digitada corresponde a um livro na tabela "Livros" |
|
fechar |
Botão "Fechar" |
OnClick |
Fecha o formulário |
Modulo "Biblioteca"
Variáveis Globais para o módulo:
Dim db As Database, leitor As Recordset, livros As Recordset
|
Function abrir () Set db = DBEngine.Workspaces(0).Databases(0) Set leitor = db.OpenRecordset("Leitores") leitor.index = "PrimaryKey"
Set livros = db.OpenRecordset("Livros") livros.index = "PrimaryKey" End Function |
Associada á propriedade "OnOpen" do formulário. Tem como objectivo inicializar as variáveis tipo "RecordSet" |
|
Function fechar () livros.Close leitor.Close db.Close End Function |
Associada á propriedade "OnClose" do formulário. |
|
Function procura_leitor (cod As Control) leitor.Seek "=", cod If leitor.NoMatch Then MsgBox ("Leitor não existe !") procura_leitor = 0 Else procura_leitor = -1 End If End Function |
Executada a partir da macro "Leitor". Verifica se um leitor existe na tabela "Leitores". O parametro "cod" é o código do leitor, a função retorna "True"(-1) se o leitor existe "False" (0) caso contrário. |
Para o control "Cota" a situação é mais complexa, pois alem de validar o valor introduzido é necessário o efeito "lateral" de atribuir ao campo "situação" o valor FALSE.
|
Function valida_livro (cod As Control) livros.Seek "=", cod If livros.NoMatch Then MsgBox ("O Livro não existe !") valida_livro = 0 Else If livros.[situação] Then valida_livro = -1 Else MsgBox ("O Livro está requisitado!") valida_livro = 0 End If End If End Function |
Executada a partir da macro "livro". Verifica se um dado livro existe na tabela "Livros". A função tem um parametro "cod" - a cota do livro - e retorna "True" (-1) se o livro existe ou "False" (0) se o livro não existe. |
|
Function reset_livro (cod As Control) If Not IsNull(cod) Then livros.Seek "=", cod If livros.NoMatch Then MsgBox ("Livro não existe !") reset_livro = 0 Else livros.Edit livros.[situação] = -1 livros.Update End If End If End Function |
Associado á propriedade "OnEnter" do control "cota" e "OnDelete" do formulário. Marca o campo "situação" da tabela "Livros" como disponível. |
|
Function set_livro (cota As Control) On Error GoTo set_livro_erro If Not IsNull(cota) And Not livros.NoMatch Then livros.Edit livros.[situação] = 0 livros.Update End If set_livro_exit: Exit Function set_livro_erro: Resume set_livro_exit End Function |
Associado á propriedade "OnExit" do control "cota". Marca o campo"situação" da tabela "Livros" como indisponível. |
Devolver um livro requer: localizar a requisição onde esse livro foi requisitado, preencher o campo data de devolução e marcar o livro como disponível (campo situação da tabela "Livros"). O formulário que se apresenta, identifica o leitor, e mostra, no subformulário, todos os livros ainda não devolvidos, requisitados pelo leitor. Prenchendo o campo devolução, é executada a função "devol()" que marca o livro com disponível.

A fonte de registos para o formulário principal é a tabela "Leitores". A fonte para o subformulário é a "query":

A query seleciona os livros da tabela "Req_livros" com o campo "devolucao" não preenchido (Criteria: IsNull).
O formulário "Devoluções" só possibilita preencher o control "Localiza" para encontrar uma dada requisição e o controlo "devolução", todos os outros têm as propriedades:
![]()
A macro "invalida" associada ás propriedades "On Insert" e "On Delete" do subformulário, cancela os eventos de inserir ou eliminar registos:
|
|
|
O controlo "Devolução" tem associada á propriedade "AfterUpdate" a função:
![]()
Funções Definidas:
Option Compare Database 'Use database order for string comparisons
Dim db As Database, livros As Table
|
Function abrir_livros () Set db = CurrentDB() Set livros = db.OpenTable("livros") livros.index = "PrimaryKey" End Function |
Function fecher_livros () livros.Close End Function |
Function devol (cota As Control, data_devol As Control)
livros.Seek "=", cota
If Not livros.nomatch Then
livros.Edit
If IsNull(data_devol) Then
livros![situacao] = 0
Else
livros![situacao] = -1
End If
livros.Update
End If