Utilizando Classe no Access - A Classe Produto
Nota importante: para ter acesso aos vídeos e arquivos exemplos deste site, adquira um dos planos apresentados abaixo. Você pode comprar em até 5x no Cartão de Crédito, através do Paypal.
Veja como comprar e saiba mais sobre o material oferecido, clicando aqui.
Por: Plinio Mabesi
Continuando a inclusão de funcionalidade em nosso sistema vamos agora ao próximo passo.
A próxima classe a ser codificada será a classe Produto. Após apresentar a estrutura da classe faremos a implementação da interface gráfica que manipulará os dados dos objetos.
Mais uma vez, caso necessário, relembre os conceitos anteriores sobre atributos, métodos, acesso às propriedades do objeto, instâncias e demais ensinamentos sobre a programação orientada a objetos, vistos nos primeiros artigos.
A Classe Produto
O objetivo desta classe, conforme dito anteriormente, é oferecer funcionalidades de inclusão, consulta, atualização e exclusão dos objetos do tipo produto.
Este é o código da classe, com todos os seus atributos e métodos, que se utilizam de funções próprias, bem como dos métodos do objeto da classe ConexaoBD.
Código da classe:
Option Compare Database Option Explicit 'Atributos da Classe 'Atributo de backup e atributo identificador da Classe 'PK - Código que identifica o produto. Private bkpCodProduto As Variant Private lngCodProduto As Variant 'Descrição do produto. Private strDescricao As Variant 'Quantidade mínima desejada no estoque. Private dblEstoqueMinimo As Variant 'Quantidade atual do estoque. Private dblQtdEstoque As Variant 'Unidade de comercialização do produto. Private strUnidade As Variant 'Valor unitário do produto. Private curValorUnitario As Variant 'Métodos Get, Set e Let da Classe Property Get codProduto() As Variant codProduto = lngCodProduto End Property Property Let codProduto(argCodProduto As Variant) lngCodProduto = argCodProduto If IsEmpty(bkpCodProduto) Then bkpCodProduto = lngCodProduto End If End Property Property Get descricao() As Variant descricao = strDescricao End Property Property Let descricao(argDescricao As Variant) strDescricao = argDescricao End Property Property Get estoqueMinimo() As Variant estoqueMinimo = dblEstoqueMinimo End Property Property Let estoqueMinimo(argEstoqueMinimo As Variant) dblEstoqueMinimo = argEstoqueMinimo End Property Property Get qtdEstoque() As Variant qtdEstoque = dblQtdEstoque End Property Property Let qtdEstoque(argQtdEstoque As Variant) dblQtdEstoque = argQtdEstoque End Property Property Get unidade() As Variant unidade = strUnidade End Property Property Let unidade(argUnidade As Variant) strUnidade = Ucase(argUnidade) End Property Property Get valorUnitario() As Variant valorUnitario = curValorUnitario End Property Property Let valorUnitario(argValorUnitario As Variant) curValorUnitario = argValorUnitario End Property 'Método Existe [Com conhecimento de SQL] 'Verifica a existência do objeto Produto na tabela
'correspondente no Banco de Dados. Function existe(argCodProduto As Variant) As Boolean On Error GoTo Err_existe Dim objCon As New aclConexaoBD Dim rstExiste As Recordset Dim strSql As String existe = False strSql = "Select * " & _ "From Produto " & _ "Where codProduto = " & objCon.valorSql(argCodProduto) Set rstExiste = objCon.consulta(strSql) If rstExiste.RecordCount > 0 Then existe = True End If 'Fecha o Recordset existe rstExiste.close Exit_existe: Set rstExiste = Nothing Exit Function Err_existe: existe = False GoTo Exit_existe End Function 'Método Incluir [Com conhecimento de SQL] 'Inclui um novo objeto na tabela correspondente dentro do Banco de dados Function incluir() As Boolean On Error GoTo Err_incluir Dim objCon As New aclConexaoBD Dim strSql As String strSql = "Insert Into " & _ "Produto(codProduto,descricao,estoqueMinimo,qtdEstoque, _
unidade,valorUnitario) " & _ "Values(" & objCon.valorSql(codProduto) & "," & _
objCon.valorSql(descricao) & "," & _ objCon.valorSql(estoqueMinimo) & "," & _
objCon.valorSql(qtdEstoque) & "," & _ objCon.valorSql(unidade) & "," & _
objCon.valorSql(valorUnitario) & ")" incluir = (objCon.executa(strSql) > 0) If incluir Then 'Atualiza os campos de backup bkpCodProduto = codProduto End If Exit_incluir: Exit Function Err_incluir: incluir = False GoTo Exit_incluir End Function 'Método Excluir [Com conhecimento de SQL] 'Exclui o objeto atual na tabela correspondente dentro do Banco de dados Function excluir() As Boolean On Error GoTo Err_excluir Dim objCon As New aclConexaoBD Dim strSql As String strSql = "Delete From Produto " & _ "Where codProduto = " & objCon.valorSql(codProduto) excluir = (objCon.executa(strSql) > 0) Exit_excluir: Exit Function Err_excluir: excluir = False GoTo Exit_excluir End Function 'Método Obter [Com conhecimento de SQL] 'Recupera o objeto Produto através dos argumentos informados Function obter(argCodProduto As Variant) As Boolean On Error GoTo Err_obter Dim objCon As New aclConexaoBD Dim rstObter As Recordset Dim strSql As String strSql = "Select * " & _ "From Produto " & _ "Where codProduto = " & objCon.valorSql(argCodProduto) Set rstObter = objCon.consulta(strSql) If rstObter.RecordCount = 0 Then obter = False Exit Function End If 'Atualiza os campos de backup e os identificadores codProduto = argCodProduto bkpCodProduto = argCodProduto 'Atualiza os campos restantes descricao = rstObter.Fields("descricao") estoqueMinimo = rstObter.Fields("estoqueMinimo") qtdEstoque = rstObter.Fields("qtdEstoque") unidade = rstObter.Fields("unidade") valorUnitario = rstObter.Fields("valorUnitario") obter = True 'Fecha o Recordset obter rstObter.close Exit_obter: Set rstObter = Nothing Exit Function Err_obter: obter = False GoTo Exit_obter End Function 'Método Salvar [Com conhecimento de SQL] 'Salva o objeto atual na tabela correspondente dentro do Banco de dados Function salvar() As Boolean On Error GoTo Err_salvar Dim objCon As New aclConexaoBD Dim strSql As String If existe(bkpCodProduto) Then strSql = "Update Produto " & _ "Set codProduto = " & objCon.valorSql(codProduto) & _ ", descricao = " & objCon.valorSql(descricao) & _ ", estoqueMinimo = " & objCon.valorSql(estoqueMinimo) & _ ", qtdEstoque = " & objCon.valorSql(qtdEstoque) & _ ", unidade = " & objCon.valorSql(unidade) & _ ", valorUnitario = " & objCon.valorSql(valorUnitario) & _ " Where codProduto = " & objCon.valorSql(bkpCodProduto) salvar = (objCon.executa(strSql) > 0) Else salvar = incluir End If If salvar Then 'Atualiza as variáveis de backup com o novo valor da chave bkpCodProduto = codProduto End If Exit_salvar: Exit Function Err_salvar: salvar = False GoTo Exit_salvar End Function 'Método baixarEstoque() 'Atualiza o estoque diminuindo a quantidade informada como parâmetro 'e devolve um valor booleano que indica o sucesso da operação; Function baixarEstoque(argQtd As Double) As Boolean If dblQtdEstoque - Abs(argQtd) < 0 Then baixarEstoque = False Else dblQtdEstoque = dblQtdEstoque - Abs(argQtd) baixarEstoque = salvar End If End Function 'Método subirEstoque() 'Atualiza o estoque acrescentando a quantidade informada como 'parâmetro e devolve um valor booleano que indica o sucesso 'da operação; Function subirEstoque(argQtd As Double) As Boolean dblQtdEstoque = dblQtdEstoque + Abs(argQtd) subirEstoque = salvar End Function 'Método estoqueBaixo 'Verifica o estoque atual e compara com o valor de estoque mínimo 'cadastrado para produto e devolve um valor booleano que indica 'se o valor atual está abaixo do previsto. Function estoqueBaixo() As Boolean If dblQtdEstoque < dblEstoqueMinimo Then estoqueBaixo = True End If End Function 'Fim da classe...
Pontos Importantes
Desta vez, complementando os itens tratados no artigo anterior, vamos destacar o pontos a seguir.
1. Controle do estoque: Ao baixarmos o estoque de um produto, devemos verificar se é possível diminuir a quantidade informada, pois seria impossível retirar mais do que a quantidade existente em estoque. Além disso, não podemos baixar quantidades negativas de produto, pois isto significa que estaríamos aumentando a quantidade ao invés de diminuir. O método somente retornará True se for possível realizar a operação.
Function baixarEstoque(argQtd As Double) As Boolean If dblQtdEstoque - Abs(argQtd) <= 0 Then baixarEstoque = False Else dblQtdEstoque = dblQtdEstoque - Abs(argQtd) baixarEstoque = salvar End If End Function
2. Conversão de dados no momento da atribuição do valor: Para a atribuição de algumas propriedades será realizada uma conversão dos dados. No caso da unidade o valor será convertido em letras maiúsculas para que fique padronizado. Para os atributos que armazenas a quantidade de produto em estoque e estoque mínimo não serão aceitos valores negativos, sendo assim todas as quantidades serão convertidas para seus respectivos valores absolutos.
Property Let estoqueMinimo(argEstoqueMinimo As Variant) dblEstoqueMinimo = Abs(argEstoqueMinimo) End Property Property Let qtdEstoque(argQtdEstoque As Variant) dblQtdEstoque = Abs(argQtdEstoque) End Property Property Let unidade(argUnidade As Variant) strUnidade = UCase(argUnidade) End Property
A Interface Gráfica
Assim como no artigo anterior, para que possamos visualizar e manipular os dados dos produtos devemos criar um formulário com campos para preenchimento e botões de comando que coordenem as ações sobre os dados.
A seguir serão definidas as características para o formulário no qual iremos trabalhar com os dados dos objetos relativos aos produtos. Neste caso as especificações de design também são apenas sugestões, porém as informações de origem de dados, bloqueio de campos e formatos de dados são obrigatórias, sob pena de não obter a funcionalidade desejada. Estas especificações estarão marcadas com um asterisco vermelho ao lado.
No formulário teremos uma lista contendo os produtos cadastrados, um campo de texto para realizar buscas, alguns campos de texto para digitação das informações e os botões de comando para criar, salvar e excluir registros.
Obs: Somente as propriedades que foram alteradas para um valor diferente do padrão serão apresentadas. Para as demais utilize o padrão do sistema ou o valor que desejar, desde que não comprometa a funcionalidade do sistema.
Formulário
Nome: FProduto Largura: 19cm Altura: Cabeçalho (1cm) / Detalhe (10cm) Legenda: Sistema de Vendas Estilo da borda: fino Seletores de registro: Não Botões de navegação: Não Linhas divisórias: Não Barras de rolagem: Nenhuma Caixa de controle: Sim Botão Fechar: Sim Botões Min Max: Nenhum Popup: Sim Janela Restrita: Não
Controle Listbox
Nome: lstProduto * Origem da linha: SELECT Produto.codProduto, Produto.descricao,
Produto.unidade, Produto.valorUnitario, Produto.estoqueMinimo,
Produto.qtdEstoque FROM Produto ORDER BY Produto.descricao; * Tipo de Origem da Linha: Tabela/Consulta * Coluna acoplada: 1 * Número de colunas: 6 * Largura das colunas: 0cm;5cm;1cm;2cm;1cm;1cm * Largura: 10cm Cor do fundo: Cinza claro
Controles Textbox
Nome: txtPesquisa * Cor do fundo: Amarelo Alinhamento: Esquerda Nome: txtCodigo * Ativado: Não * Bloqueado: Sim * Cor do fundo: Cinza Alinhamento: Centro Nome: txtDescricao * Cor do fundo: Azul claro Alinhamento: Esquerda Nome: txtUnidade * Cor do fundo: Azul claro Alinhamento: Esquerda Nome: txtValorUnitario * Cor do fundo: Azul claro Alinhamento: Direita Formato: Unidade Monetária Nome: txtQtdEstoque * Cor do fundo: Azul claro Alinhamento: Centro Formato: 00 Nome: txtEstoqueMinimo * Cor do fundo: Cinza Alinhamento: Centro Formato: 00
Botões de Comando
Nome: btnNovo * Legenda: Novo Cor da Fonte: Azul escuro Nome: btnSalvar * Legenda: Salvar Cor da Fonte: Azul escuro Nome: btnExcluir * Legenda: Excluir Cor da Fonte: Vermelho escuro
Como sugestão de design os campos deverão estar posicionados conforme demonstrado na figura a seguir, assim como devem ser adicionadas as legendas dos campos, as quais não foram descritas anteriormente:
Códigos do Formulário
Para que nosso formulário seja capaz de manipular os dados dos objetos produto deveremos implementar as funcionalidades necessárias que permitam criar um novo produto, buscar um produto já cadastrado, editar seus dados, salvá-lo ou excluí-lo.
Sendo assim criaremos algumas funções genéricas que sejam úteis para quantos procedimentos delas necessitem, reaplicando o conceito da reutilização de código. Além disso incluiremos os códigos dos campos que possuem eventos, além dos botões de comando.
Todos os códigos a seguir deverão ser colocados no módulo do formulário FProduto.
1. Pesquisa de produtos: Para facilitar a busca de produtos por qualquer parte do nome utilizaremos um campo de texto cujo valor será o elemento condicional para o código SQL que será atribuído ao controle lstProduto, atualizando sua propriedade Origem da Linha após cada alteração realizada no campo de pesquisa. Para isto devemos colocar o código no evento Ao Alterar do campo txtPesquisa.
Private Sub txtPesquisa_Change() lstProduto.RowSource = "SELECT codProduto, descricao, " & _ "unidade, valorUnitario, estoqueMinimo, qtdEstoque " & _ "FROM Produto " & _ "WHERE descricao Like '*" & txtPesquisa.Text & "*' " & _ "ORDER BY Produto.descricao;" lstProduto.Requery End Sub
2. Limpeza dos campos: Para efetuar a limpeza dos campos de preenchimento utilizaremos um procedimento genérico cuja função será a de atribuir o valor nulo a todos os campos de texto e enviar o foco ao campo txtDescricao.
Private Sub limpaCampos() txtCodigo = Null txtDescricao = Null txtUnidade = Null txtValorUnitario = Null txtQtdEstoque = Null txtEstoqueMinimo = Null txtDescricao.SetFocus End Sub
3. Novo registro: Para a criação de um novo registro em branco simplesmente iremos chamar o procedimento limpaCampos() no evento Ao Clicar do botão btnNovo.
Private Sub btnNovo_Click() Call limpaCampos End Sub
4. Atualização de campos: Assim como fizemos um procedimento genérico que limpa os campos para a criação de um novo registro teremos também um que preencha os campos com as informações de um objeto produto passadas como parâmetro, ou seja, o procedimento recebe um objeto completo e lança os valores de seus atributos nos campos do formulário.
Private Sub atualizaCampos(argProduto As clsProduto) txtCodigo = argProduto.codProduto txtDescricao = argProduto.descricao txtUnidade = argProduto.unidade txtValorUnitario = argProduto.valorUnitario txtQtdEstoque = argProduto.qtdEstoque txtEstoqueMinimo = argProduto.estoqueMinimo End Sub
5. Escolha de produto: Já que teremos também que trabalhar com produtos já cadastrados, devemos implementar alguma maneira de recuperar suas informações. Faremos isto utilizando a Listbox lstProduto, que utilizará o procedimento atualizaCampos() para preencher os campos com as informações do objeto do produto que foi clicado.
Private Sub lstProduto_Click() Dim objProduto As New clsProduto Dim codigoProduto As Long codigoProduto = lstProduto.Value If objProduto.obter(codigoProduto) Then Call atualizaCampos(objProduto) End If End Sub
6. Montagem de um objeto: Esta também é uma função genérica que será utilizada por outros procedimentos ou funções. Seu objetivo é criar um novo objeto produto, coletar os dados digitados nos campos, atribuir ao objeto criado, e devolvê-lo para quem chamou a função.
Private Function buscaCampos() As clsProduto Set buscaCampos = New clsProduto If IsNull(txtCodigo) Then txtCodigo = proximoCodigo("codProduto", "Produto") End If buscaCampos.codProduto = txtCodigo buscaCampos.descricao = txtDescricao buscaCampos.unidade = txtUnidade buscaCampos.valorUnitario = txtValorUnitario buscaCampos.qtdEstoque = txtQtdEstoque buscaCampos.estoqueMinimo = txtEstoqueMinimo End Function
7. Salvando um produto: Depois de informados os dados de um novo produto, ou alterados os dados de um produto já cadastrado, necessitaremos de um procedimento que efetue a gravação destes dados. Para isto o botão btnSalvar conterá o código necessário no evento Ao Clicar. Ele fará uso da função buscaCampos(), a qual montará o objeto a ser salvo, e também o método salvar() do objeto, apresentando uma mensagem ao usuário com o resultado da operação. Após salvar os dados de um produto também deveremos atualizar a Listbox para que apresente estes dados, sejam eles novos ou apenas alterados.
Private Sub btnSalvar_Click() Dim objProduto As clsProduto If Not IsNull(txtDescricao) And Not IsNull(txtUnidade) And _
Not IsNull(txtValorUnitario) Then Set objProduto = buscaCampos If objProduto.salvar Then MsgBox "O produto foi salvo com sucesso.",vbInformation,"Salvar produto" lstProduto.Requery Call atualizaCampos(objProduto) Else MsgBox "Ocorreu um erro durante o salvamento.", vbExclamation, _
"Salvar produto" End If Else MsgBox "Informe os dados do produto.", vbExclamation, "Salvar produto" End If End Sub
8. Excluindo um produto: Além de criar e alterar os dados de um produto, é importante que também possamos excluí-lo definitivamente de nosso cadastro. Logo devemos também implementar a funcionalidade para o botão btnExcluir, que conterá o código necessário também no evento Ao Clicar. Ele também deverá fazer uso da função buscaCampos() para a montagem do objeto a ser excluído, pois caso contrário a classe não saberá que objeto deve ser excluído. Em seguida utilizaremos o método excluir() do objeto, apresentando uma mensagem ao usuário com o resultado da operação. É claro que após excluir um produto também deveremos atualizar a Listbox para que a mesma reflita as alterações realizadas.
Private Sub btnExcluir_Click() Dim objProduto As clsProduto If Not IsNull(txtCodigo) Then If MsgBox("Confirma a exclusão do registro?", vbQuestion + vbYesNo, _
"Excluir produto") = vbYes Then Set objProduto = buscaCampos If objProduto.excluir Then MsgBox "O registro foi excluído com sucesso.", vbInformation, _
"Excluir produto" lstProduto.Requery Call limpaCampos Else MsgBox "Ocorreu um erro durante a exclusão.", vbExclamation, _
"Excluir produto" End If End If End If End Sub
Sistema de Exemplo
Novamente será disponibilizado o link para download do sistema de vendas, já atualizado com todos os recursos do estado de desenvolvimento em que se encontrar o projeto.
Mais uma vez recomendo aos desenvolvedores que o consultem apenas para tirar dúvidas e realizar comparações. Aqueles que realmente quiserem aprender façam toda a codificação e a montagem das telas manualmente. Somente assim a sua mente irá se defrontar com as dificuldades do processo e assimilará os passos necessários para a resolução dos problemas e a conclusão dos objetivos.
Segue o link para download:
Caso ainda não esteja com uma tela principal abra o formulário FProduto diretamente na janela Banco de Dados (Access 2003-) ou no Painel de Navegação (Access 2007+).
Conclusão
Nesta fase não encontramos praticamente nada de novo, mas tivemos a chance de relembrar a maioria dos procedimentos vistos até o momento. A codificação das funcionalidades da classe Produto são muito semelhantes à codificação da classe Cliente. Porém este era o nosso objetivo: relembrar o passo-a-passo necessário para utilizar objetos em sistemas informatizados no MS-Access/VBA.
Com relação à parte realmente prática da série de artigos estamos chegando na reta final. No próximo artigo, que será o último em que trabalharemos com a programação de classes, poderemos perceber um pouco mais da dinâmica de troca de informações entre os objetos de um sistema. Ao realizarmos vendas de produtos para clientes estaremos englobando a utilização de todas as nossas classes de uma só vez, trabalhando com vários objetos instanciados simultaneamente para a conclusão das tarefas.
Com toda certeza você, caro leitor que nos acompanha, já deve estar imaginando os objetos se interagindo, os métodos realizando tarefas e retornando valores, os atributos recebendo e fornecendo valores, os objetos sendo enviados inteiramente para métodos de outros objetos, e assim sucessivamente.
É isto aí, orgulhe-se de dizer: Agora estou quase dominando essa tal de OO!
Encontro vocês no próximo então...
Artigos Relacionados
Utilizando Classe no Access - Introdução
Utilizando Classe no Access - Parte 1 - Orientação a Objetos
Utilizando Classe no Access - Parte 2 - Programação OO no Access/Vba
Utilizando Classe no Access - Parte 4 - As Classes Auxiliares
Utilizando Classe no Access - Parte 5 - A Classe Cliente
Utilizando Classe no Access - Parte 6 - A Classe Produto
Utilizando Classe no Access - Parte 7 - As Classes Venda e Detalhe de Venda
Utilizando Classe no Access - Parte 8 - Finalização do Sistema
Utilizando Classe no Access - Parte 9 - Genesis: A Ferramenta Case
Utilizando Classe no Access - Parte 10 - Conclusão
Como estudar com o Pesquisador de Objetos
4 comentários Adelmo 10/08/2023 05:23:22 Bom dia! Você tem a planilha pronta, eu sou leigo no assunto mais tenho alguns conhecimento achei muito interessante suas informações. obrigado. meu e-mail nab875@hotmail.com Lázaro Kiosa 29/06/2021 07:46:31 ainda não explorei o site porque so descobri agora, mais ja da para ti parabenizar pelo site Sr Plinio Plinio Mabesi 09/02/2021 11:27:15 Obrigado Luis... Eu é que agradeço a sua visita no site do amigo Avelino. Visite também meu site: www.mabesi.com Luis Eugenio Riquelme Pino 09/02/2021 02:08:07 Este é um dos melhores sites sobre MS Access, muito bom e profundo, bem explicado, Obrigado Sr Plinio |