Banco de dados: Programando com Classe(s)
A utilização dos módulos de classe na programação torna o nosso código mais elegante. Ao usar a técnica de encapsular nosso código , estamos isolando código complexo do resto da aplicação e somente expondo os métodos , propriedades e eventos. Nisto está as bases da criação dos controles ActiveX e da criação dos componentes reutilizáveis.
A programação com banco de dados é grandemente afetada pela utilização dos módulos de classe. Se você já teve que escrever complexas consultas SQL para o seu banco de dados , vai perceber que usando classes vai tornar o seu código mais funcional e fácil de manter.
Vamos mostrar em um exemplo simples os fundamentos para a utilização dos módulos de classe ajudando-o assim a dar os primeiros passos nesse terreno que parece mais um campo de areia movediça.
O projeto
Vamos usar o banco de dados Nwind.mdb (esse banco de dados vem com Access) o qual contém as seguintes tabelas que interessam ao nosso objetivo.
Categorias - Categorias das
bebidas
Pedidos - Informação sobre os pedidos
Detalhes do Pedido- Detalhes dos pedidos
Produtos - Relação dos produtos
Fornecedores - Relação dos fornecedores
Obs: Exibimos aqui somentes as tabelas que iremos utilizar.
O relacionamento entre estas tabelas é mostrado a seguir:
![]() |
Nosso objetivo é extrair informações sobre os fornecedores e qual bebidas eles distribuem .Queremos exibir somente o nome do Fornecedor e o nome da bebida que é distribuida . Por exemplo queremos saber quais bebidas são distribuidos por Exotic Liquidis; no caso , fazendo um consulta iremos descobrir que este fornecedor distribui as seguintes bebidas : : "Chai", "Chang"
Você já percebeu esta informação pode ser extraida usando SQL , porém note que temos três tabelas relacionadas envolvidas na obtenção desta informação. O relacionamento das tabelas que iremos usar para criar a consulta SQL e a consulta que iremos criar no modo estrutura é exibido a seguir:
![]() |
A consulta SQL usada para o nosso caso usa dois parâmetros que devemos fornecer: o nome do fornecedor(nomedaEmpresa) e o nome da categoria(nomedaCategoria) que desejamos exibir. A seguir o código extraído da consulta montanda no Access :
| SELECT
Fornecedores.NomeDaEmpresa, Produtos.NomeDoProduto FROM Fornecedores INNER JOIN (Categorias INNER JOIN Produtos ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoria) ON Fornecedores.CódigoDoFornecedor = Produtos.CódigoDoFornecedor WHERE (((Fornecedores.NomeDaEmpresa)=[nomeEmpresa]) AND ((Categorias.NomeDaCategoria)=[nomeCategoria])); |
Você poderia fazer um programa criando uma função em um módulo que recebesse os parâmetros usados e retornasse o resultado de sua consulta ou usar módulo de classes para encapsular o seu código e torná-lo reutilizável.
Vamos lembrar as principais diferenças entre um módulo padrão e um módulo de classe:
Vamos optar por usar um módulo de classe em nosso projeto.
Escrevendo o Módulo de Classe ( Class Module )
Inicie um novo projeto no VB (stantard EXE) , referencie a Microsoft DAO 3.5/3.51 Object Library (menu: Project->References...) no seu projeto e a seguir inclua um módulo de classe (menu : Project->Add a Class Module) . Dê o nome cls_Sql para o módulo de classe e salve o seu projeto com o nome de class_SQL.
Vamos iniciar definindo duas propriedades públicas para a classe e uma váriavel pública para receber as mensagens que o objeto retornará. Insira as linhas de código como abaixo no início do módulo de classe:
![]() |
Agora vamos definir o método que irá executar a consulta , vamos chamá-lo de , Executa_SQL. Definimos um método incluindo uma procedure no módulo de classe. Veja o código da procedure a seguir:
Sub Executa_SQL()
Dim strSQL As String
Dim db As Database
Dim qdfTemp As QueryDef
Dim rsResultado As Recordset
'Constroi a consulta SQL
strSQL = "SELECT Fornecedores.NomeDaEmpresa, Produtos.NomeDoProduto "
strSQL = strSQL & " FROM Fornecedores INNER JOIN (Categorias INNER JOIN Produtos"
strSQL = strSQL & " ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoria)"
strSQL = strSQL & " ON Fornecedores.CódigoDoFornecedor = Produtos.CódigoDoFornecedor"
strSQL = strSQL & " WHERE Fornecedores.NomeDaEmpresa='" & NomedaEmpresa & "'"
strSQL = strSQL & " AND Categorias.NomeDaCategoria='" & NomedaCategoria & "'"
dbname = "c:\teste\nwind2000.mdb"
Set db = OpenDatabase(dbname)
Set qdfTemp = db.CreateQueryDef("")
qdfTemp.SQL = strSQL
Set rsResultado = qdfTemp.OpenRecordset(dbOpenSnapshot)
If rsResultado.RecordCount > 0 Then
rsResultado.MoveFirst
'Enumerando o recordset
With rsResultado
Do While Not .EOF
strmensagem = strmensagem & .Fields(1) & vbCrLf
.MoveNext
Loop
End With
Else
strmensagem = "Não há dados para estes parâmetros ! "
End If
rsResultado.Close
qdfTemp.Close
End Sub
|
Analisando o código:
-Dimensionamos as variáveis objeto para acesso aos dados - db , qdftemp , rsresultado
Dim strSQL As String
Dim db As Database
Dim qdfTemp As QueryDef
Dim rsResultado As Recordset
-Construimos a consulta SQL que irá extrair o resultado com base nos parâmetros : NomedaEmpresa, NomedaCategoria
strSQL = "SELECT Fornecedores.NomeDaEmpresa,
Produtos.NomeDoProduto "
strSQL = strSQL & " FROM Fornecedores INNER JOIN
(Categorias INNER JOIN Produtos"
strSQL = strSQL & " ON Categorias.CódigoDaCategoria =
Produtos.CódigoDaCategoria)"
strSQL = strSQL & " ON Fornecedores.CódigoDoFornecedor
= Produtos.CódigoDoFornecedor"
strSQL = strSQL & " WHERE
Fornecedores.NomeDaEmpresa='" & NomedaEmpresa &
"'"
strSQL = strSQL & " AND
Categorias.NomeDaCategoria='" & NomedaCategoria &
"'"
-Definimos o caminho do banco de dados e a seguir o abrimos:
dbname = "c:\teste\nwind2000.mdb"
Set db = OpenDatabase(dbname)
- Limpamos a querydef e a seguir atribuimos a
nossa consulta SQL para a QueryDef definida. Depois executamos a
consulta para geração de um recordset do tipo snapshot
Set qdfTemp = db.CreateQueryDef("")
qdfTemp.SQL = strSQL
Set rsResultado = qdfTemp.OpenRecordset(dbOpenSnapshot)
-Se a consulta retorna valores , estes são exibidos , caso contrário uma mensagem alerta o usuário de não há dados para os critérios adotados.
Pronto já temos uma classe definida com duas propriedades , os nossos parâmetros e um método , que executa a nossa consulta, só nos resta usá-lo na prática.
Como cada módulo de classe tem um evento Initialize o qual contém código que é executado quando um objeto baseado na classe é criado e um evento Terminate quando o objeto é destruido. O código que será executado quando nosso objeto for destruido será o seguinte:
Private Sub Class_Terminate() MsgBox strmensagem, Title:="Resultado da consulta para - " _ & UCase(NomedaEmpresa), buttons:=vbExclamation End Sub |
Ele simplesmente exibe uma caixa de mensagem com o resultado da consulta.
Pondo a classe para Trabalhar
Vamos criar um projeto no VB para usar o módulo de classe criado. Inicie o VB e crie um projeto como o da figura a seguir:
![]() |
Este projeto usa os seguintes
controles: - combo1 - cbofornecedor - combo2 - cbocategoria - commandbutton - Command1 |
A idéia é preencher as caixas de combinação , uma com o nome dos fornecedores e outra com as categorias existentes. O usuário irá selecionar o fornecedor e a categoria e clicar no botão Executa Consulta que irá chamar o método do nosso módulo de classe retornando o resultado desejado.
Para preencher as caixas de combinação usaremos a função - clssql.bas - definida em um módulo padrão. O código deste módulo é o seguinte:
Public db As Database Public area As Workspace Public Sub enchecombo(combo As Control,data As String,campo As String,Optional indice As
Variant)
'-- cria variável recordset temporária
Dim arqtemp As Recordset
'-----limpa combo
combo.Clear
'-----abre tabela como Snapshot (economiza memoria)
Set arqtemp = db.OpenRecordset(data, dbOpenSnapshot)
'--inicia loop através da tabela---
If arqtemp.RecordCount > 0 Then
Do Until arqtemp.EOF
combo.AddItem arqtemp(campo)
If Not IsMissing(indice) Then
combo.ItemData(combo.NewIndex) = arqtemp(indice)
End If
arqtemp.MoveNext
Loop
Else
MsgBox "Não há dados ..."
Exit Sub
End If
'---fecha recordset e seleciona primeiro opcao na combo
arqtemp.Close
combo.ListIndex = 0
'-----limpa memoria
Set arqtemp = Nothing
End Sub
|
O evento Load do formulário - frmclsql - tem o seguinte código:
Private Sub Form_Load()
Set area = DBEngine.Workspaces(0)
dbname = "c:\teste\nwind2000.mdb"
Set db = area.OpenDatabase(dbname)
Call enchecombo(cbofornecedor, "fornecedores", "NomedaEmpresa", "códigodofornecedor")
Call enchecombo(cbocategoria, "categorias", "NomedaCategoria", "códigodacategoria")
End Sub
|
Nele abrimos o banco de dados e chamamos a função enchecombo definida no módulo - clssql.bas . A função recebe os parâmetros para preencher cada combobox com os valores referentes a tabela dos fornecedores e a tabela das categorias. Basta o usuário selecionar o fornecedor e a categoria e clicar no botão de comando Executa Consulta.
Aqui temos a combobox com os dados dos fornecedores:
.![]() |
O resultado da consulta é exibido em uma caixa de mensagem .( ver figura abaixo):
![]() |
O código do botão Executa consulta é o seguinte:
Private Sub Command1_Click()
Dim objSQL As Cls_sql
'define a variavel objeto
Set objSQL = New Cls_sql
'define as novas propriedades do objeto
With objSQL
.NomedaEmpresa = cbofornecedor.Text
.NomedaCategoria = cbocategoria.Text
End With
'Retorna as propriedades
Debug.Print objSQL.NomedaEmpresa
Debug.Print objSQL.NomedaCategoria
'invoca o metodo do objeto
objSQL.Executa_SQL
'destroi o objeto
Set objSQL = Nothing
End Sub
|
-Iniciamos dimensionando uma váriavel objeto baseada na nossa classe Cls_sql , ou seja , instânciamos um objeto da classe Cls_sql .
Dim objSQL As Cls_sql
-A seguir determinamos os valores para as propriedades do objeto - objSQL
With objSQL .NomedaEmpresa = cbofornecedor.Text .NomedaCategoria = cbocategoria.Text End With
-Finalmente invocamos o método do objeto baseado na classe
objSQL.Executa_SQL
E acabou ! . Percebeu qual a vantagem dos módulos de classe ? Não ???
É obvio que a forma de exibir os resultados poderá ser melhorada , usando um msflexgrid por exemplo.
Este projeto completo está no Super CD VB.