Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

19
Home Vídeos-aulas Tutoriais Dicas Blog Downloads Contato Artigo SELECT Venda.codVenda, Venda.codCliente, Venda.dataVenda, DetalheVenda.codProduto, DetalheVenda.qtdProduto, Produto.descricao, Produto.unidade, Produto.valorUnitario, (Produto.valorUnitario*DetalheVenda.qtdProduto) AS SubTotal FROM Venda LEFT JOIN (Produto RIGHT JOIN DetalheVenda ON Produto.codProduto=DetalheVenda.codProduto) ON Venda.codVenda=DetalheVenda.codVenda; Option Compare Database Option Explicit 'Atributos da Classe 'Atributo de backup e atributo identificador da Classe 'PK - Código que identifica a venda. Private bkpCodVenda As Variant Private lngCodVenda As Variant 'FK - Código que indica o cliente relativo à venda. Private lngCodCliente As Variant 'Objeto da classe de Descrição de Tipo Private objetoCliente As New clsCliente 'Data de realização da venda. Private dtmDataVenda As Variant 'Métodos Get, Set e Let da Classe Property Get codVenda() As Variant codVenda = lngCodVenda End Property Property Let codVenda(argCodVenda As Variant) lngCodVenda = argCodVenda Utilizando Classe no Access - As Classes Venda e DatalheVenda Por: Plinio Mabesi Estamos chegando na reta final da criação do sistema de vendas orientado a objetos. Nesta etapa veremos a codificação das classes Venda e DetalheVenda, além da implementação de um PDV que será a nossa interface gráfica para realização das vendas. No desenrolar da criação dos códigos com certeza você encontrará rotinas repetitivas, funções não tão necessárias e instâncias em excesso. Além disso, poderá sentir falta de funcionalidades importantes em um PDV ou mesmo na totalidade do sistema de vendas. E digo mais, agora que já é praticamente um “expert” em VBA e orientação a objetos perceberá que um ou outro método poderia ser mais bem implementado de outra maneira. Mas antes de queimar neurônios tentando entender por que o trabalho está assim tão “mal projetado”, lembre-se que tudo foi feito com fins didáticos, e a repetitividade foi proposital, somente para que você fique cansado de tanto manipular objetos e realmente aprenda como utilizá-los. Não estaremos totalmente livres do aparecimento de “bugs”, pois apenas nos locais estritamente necessários foram inseridas rotinas de tratamento de erros. Estes algoritmos são cansativos de se preparar, então me dei ao luxo de não incluir em todos os procedimentos, funções e métodos do sistema. Porém nada impede que você, que já pesquisou o assunto e agora “saca” muito de programação, implemente ao seu bel prazer, corrigindo erros que porventura se apresentem. Então chega de papo e mãos à obra... A Consulta CVenda Deveremos criar uma consulta que será utilizada por um método da classe Venda. O nome da consulta será CVenda e seu código SQL será o seguinte: A Classe Venda O objetivo desta classe, conforme dito anteriormente, é oferecer funcionalidades de inclusão, consulta, atualização e exclusão dos objetos do tipo venda. 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 dos objetos da classe ConexaoBD e da classe Cliente. Código da classe: Usando Access

description

Bom

Transcript of Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

Page 1: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 1/19

Home Vídeos-aulas Tutoriais Dicas Blog Downloads Contato Artigo

SELECT Venda.codVenda, Venda.codCliente, Venda.dataVenda, DetalheVenda.codProduto, DetalheVenda.qtdProduto, Produto.descricao, Produto.unidade, Produto.valorUnitario, (Produto.valorUnitario*DetalheVenda.qtdProduto) AS SubTotalFROM Venda LEFT JOIN (Produto RIGHT JOIN DetalheVenda ON Produto.codProduto=DetalheVenda.codProduto) ON Venda.codVenda=DetalheVenda.codVenda;

Option Compare Database

Option Explicit

'Atributos da Classe

'Atributo de backup e atributo identificador da Classe

'PK - Código que identifica a venda.

Private bkpCodVenda As Variant

Private lngCodVenda As Variant

'FK - Código que indica o cliente relativo à venda.

Private lngCodCliente As Variant

'Objeto da classe de Descrição de Tipo

Private objetoCliente As New clsCliente

'Data de realização da venda.

Private dtmDataVenda As Variant

'Métodos Get, Set e Let da Classe

Property Get codVenda() As Variant

codVenda = lngCodVenda

End Property

Property Let codVenda(argCodVenda As Variant)

lngCodVenda = argCodVenda

Utilizando Classe no Access - As Classes Venda e DatalheVenda

Por: Plinio Mabesi

Estamos chegando na reta final da criação do sistema de vendas orientado a objetos.

Nesta etapa veremos a codificação das classes Venda e DetalheVenda, além da implementação de umPDV que será a nossa interface gráfica para realização das vendas.

No desenrolar da criação dos códigos com certeza você encontrará rotinas repetitivas, funções nãotão necessárias e instâncias em excesso. Além disso, poderá sentir falta de funcionalidadesimportantes em um PDV ou mesmo na totalidade do sistema de vendas. E digo mais, agora que já épraticamente um “expert” em VBA e orientação a objetos perceberá que um ou outro método poderiaser mais bem implementado de outra maneira. Mas antes de queimar neurônios tentando entender porque o trabalho está assim tão “mal projetado”, lembre-se que tudo foi feito com fins didáticos, e arepetitividade foi proposital, somente para que você fique cansado de tanto manipular objetos erealmente aprenda como utilizá-los.

Não estaremos totalmente livres do aparecimento de “bugs”, pois apenas nos locais estritamentenecessários foram inseridas rotinas de tratamento de erros. Estes algoritmos são cansativos de sepreparar, então me dei ao luxo de não incluir em todos os procedimentos, funções e métodos dosistema. Porém nada impede que você, que já pesquisou o assunto e agora “saca” muito deprogramação, implemente ao seu bel prazer, corrigindo erros que porventura se apresentem.

Então chega de papo e mãos à obra...

A Consulta CVenda

Deveremos criar uma consulta que será utilizada por um método da classe Venda. O nome daconsulta será CVenda e seu código SQL será o seguinte:

A Classe Venda

O objetivo desta classe, conforme dito anteriormente, é oferecer funcionalidades de inclusão,consulta, atualização e exclusão dos objetos do tipo venda.

Este é o código da classe, com todos os seus atributos e métodos, que se utilizam de funçõespróprias, bem como dos métodos dos objetos da classe ConexaoBD e da classe Cliente.

Código da classe:

Usando Access

Page 2: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 2/19

If IsEmpty(bkpCodVenda) Then

bkpCodVenda = lngCodVenda

End If

End Property

Property Get codCliente() As Variant

codCliente = lngCodCliente

End Property

Property Let codCliente(argCodCliente As Variant)

lngCodCliente = argCodCliente

End Property

Property Get dataVenda() As Variant

dataVenda = dtmDataVenda

End Property

Property Let dataVenda(argDataVenda As Variant)

dtmDataVenda = argDataVenda

End Property

Property Get objCliente() As Variant

If Not IsEmpty(codCliente) Then

If objetoCliente.obter(codCliente) Then

Set objCliente = objetoCliente

End If

End If

End Property

'Método Existe [Com conhecimento de SQL]

'Verifica a existência do objeto Venda na tabela

'correspondente no Banco de Dados

Function existe(argCodVenda 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 Venda " & _

"Where codVenda = " & objCon.valorSql(argCodVenda)

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 " & _

"Venda(codVenda,codCliente,dataVenda) " & _

"Values(" & objCon.valorSql(codVenda) & "," & _

objCon.valorSql(codCliente) & "," & _

objCon.valorSql(dataVenda) & ")"

incluir = (objCon.executa(strSql) > 0)

If incluir Then

'Atualiza os campos de backup

bkpCodVenda = codVenda

End If

Exit_incluir:

Page 3: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 3/19

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 Venda " & _

"Where codVenda = " & objCon.valorSql(codVenda)

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 Venda através dos argumentos informados

Function obter(argCodVenda 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 Venda " & _

"Where codVenda = " & objCon.valorSql(argCodVenda)

Set rstObter = objCon.consulta(strSql)

If rstObter.RecordCount = 0 Then

obter = False

Exit Function

End If

'Atualiza os campos de backup

'e os identificadores

codVenda = argCodVenda

bkpCodVenda = argCodVenda

'Atualiza os campos restantes

codCliente = rstObter.Fields("codCliente")

dataVenda = rstObter.Fields("dataVenda")

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(bkpCodVenda) Then

strSql = "Update Venda " & _

"Set codVenda = " & objCon.valorSql(codVenda) & _

Page 4: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 4/19

", codCliente = " & objCon.valorSql(codCliente) & _

", dataVenda = " & objCon.valorSql(dataVenda) & _

" Where codVenda = " & objCon.valorSql(bkpCodVenda)

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

bkpCodVenda = codVenda

End If

Exit_salvar:

Exit Function

Err_salvar:

salvar = False

GoTo Exit_salvar

End Function

'Método getValorTotal

'Calcula a valor total da venda atual e

'devolve o valor como resultado.

Function getValorTotal() As Currency

getValorTotal = Nz(DSum("SubTotal", "CVenda", _

"codVenda=" & Nz(lngCodVenda, -1)))

End Function

'Fim da classe...

Option Compare Database

Option Explicit

'Atributos da Classe

'Atributo de backup e atributo identificador da Classe

'PK - FK - Código que indica o produto relacionado.

Private bkpCodProduto As Variant

Private lngCodProduto As Variant

'Atributo de backup e atributo identificador da Classe

'PK - FK - Código que indica a venda relacionada.

Private bkpCodVenda As Variant

Private lngCodVenda As Variant

'Quantidade do poduto relacionado.

Private dblQtdProduto 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 codVenda() As Variant

codVenda = lngCodVenda

End Property

Property Let codVenda(argCodVenda As Variant)

lngCodVenda = argCodVenda

If IsEmpty(bkpCodVenda) Then

A Classe DetalheVenda

O objetivo desta classe, conforme dito anteriormente, é oferecer funcionalidades de consulta eatualização dos objetos de ligação entre a venda e os produtos componentes.

Este é o código da classe, com todos os seus atributos e métodos, que se utilizam de funçõespróprias, bem como dos métodos dos objetos da classe ConexaoBD e da classe Produto.

Código da classe:

Page 5: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 5/19

bkpCodVenda = lngCodVenda

End If

End Property

Property Get qtdProduto() As Variant

qtdProduto = dblQtdProduto

End Property

Property Let qtdProduto(argQtdProduto As Variant)

dblQtdProduto = argQtdProduto

End Property

'Método Existe [Com conhecimento de SQL]

'Verifica a existência do objeto DetalheVenda na

'tabela correspondente no Banco de Dados

Function existe(argCodProduto As Variant, _

argCodVenda 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 DetalheVenda " & _

"Where codProduto = " & objCon.valorSql(argCodProduto) _

And codVenda = " & objCon.valorSql(argCodVenda)"

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 " & _

"DetalheVenda(codProduto,codVenda,qtdProduto) " & _

"Values(" & objCon.valorSql(codProduto) & "," & _

objCon.valorSql(codVenda) & "," & _

objCon.valorSql(qtdProduto) & ")"

incluir = (objCon.executa(strSql) > 0)

If incluir Then

'Atualiza os campos de backup

bkpCodProduto = codProduto

bkpCodVenda = codVenda

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

Page 6: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 6/19

Dim objCon As New aclConexaoBD

Dim strSql As String

strSql = "Delete From DetalheVenda " & _

"Where codProduto = " & objCon.valorSql(codProduto) & _

" and codVenda = " & objCon.valorSql(codVenda)

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 DetalheVenda através dos argumentos informados

Function obter(argCodProduto As Variant, _

argCodVenda 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 DetalheVenda " & _

"Where codProduto = " & objCon.valorSql(argCodProduto) & _

" And codVenda = " & objCon.valorSql(argCodVenda)

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

codVenda = argCodVenda

bkpCodVenda = argCodVenda

'Atualiza os campos restantes

qtdProduto = rstObter.Fields("qtdProduto")

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, bkpCodVenda) Then

strSql = "Update DetalheVenda " & _

"Set codProduto = " & objCon.valorSql(codProduto) & _

", codVenda = " & objCon.valorSql(codVenda) & _

", qtdProduto = " & objCon.valorSql(qtdProduto) & _

" Where codProduto = " & objCon.valorSql(bkpCodProduto) & _

" and codVenda = " & objCon.valorSql(bkpCodVenda)

salvar = (objCon.executa(strSql) > 0)

Else

salvar = incluir

End If

Page 7: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 7/19

If salvar Then

'Atualiza as variáveis de backup

'com o novo valor da chave

bkpCodProduto = codProduto

bkpCodVenda = codVenda

End If

Exit_salvar:

Exit Function

Err_salvar:

salvar = False

GoTo Exit_salvar

End Function

'Método getSubTotal

'Calcula o subtotal do produto vendido para a

'venda atual e devolve o valor como resultado

Function getSubTotal() As Currency

Dim objProduto As New clsProduto

If Not IsNull(lngCodProduto) And Not IsNull(dblQtdProduto) Then

If objProduto.obter(lngCodProduto) Then

getSubTotal = objProduto.valorUnitario * dblQtdProduto

End If

End If

End Function

'Método getListaProduto(argCodVenda As Long)

'Recebe como parâmetro um código de uma venda e devolve

'um conjunto de registros contendo os códigos dos produtos,

'além de outros dados, relativos à venda informada.

Function getListaProduto(argCodVenda As Long) As Recordset

Dim strSql As String

Dim objCon As New aclConexaoBD

strSql = "SELECT Venda.codVenda, Venda.codCliente, Venda.dataVenda, " & _

"DetalheVenda.codProduto, DetalheVenda.qtdProduto, " & _

"Produto.descricao, Produto.unidade, Produto.valorUnitario, " & _

"(Produto.valorUnitario * DetalheVenda.qtdProduto) AS SubTotal " & _

"FROM Venda LEFT JOIN (Produto RIGHT JOIN DetalheVenda ON " & _

"Produto.codProduto=DetalheVenda.codProduto) " & _

"ON Venda.codVenda=DetalheVenda.codVenda " & _

"Where Venda.codVenda=" & argCodVenda

Set getListaProduto = objCon.consulta(strSql)

End Function

'Fim da classe...

Function listaProdutos(argCodVenda As Long, _

Optional ultimos As Integer = 0) As String

Dim rstLista As Recordset

Dim objDetalheVenda As New clsDetalheVenda

Dim contador

Set rstLista = objDetalheVenda.getListaProduto(argCodVenda)

If Not rstLista.EOF Then

rstLista.MoveLast

Else

listaProdutos = ""

Exit Function

End If

While Not rstLista.BOF And (contador < ultimos Or ultimos = 0)

listaProdutos = " " & FormatNumber(rstLista("qtdProduto"), 3) & _

" x " & FormatCurrency(rstLista("valorUnitario")) & _

Mais Funções Auxiliares

Para exibir os itens vendidos na tela, no formato de um cupom fiscal, necessitaremos de uma funçãoque busque os últimos itens registrados na venda para que possamos apresentá-los ao usuário.

Assim sendo deveremos incluir mais uma função no módulo Funcoes criado anteriormente, que seráchamada de listaProdutos() e receberá como parâmetros o código da venda e o número de itens, apartir do último, que devem ser retornados.

Page 8: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 8/19

" " & FormatCurrency(rstLista("SubTotal")) & _

vbCrLf & listaProdutos

listaProdutos = Format(rstLista("codProduto"), "000000") & " " & _

rstLista("unidade") & " " & rstLista("descricao") & _

vbCrLf & listaProdutos

rstLista.MovePrevious

contador = contador + 1

Wend

End Function

'Objeto da classe de Descrição de Tipo

Private objetoCliente As New clsCliente

...

Property Get objCliente() As Variant

If Not IsEmpty(codCliente) Then

If objetoCliente.obter(codCliente) Then

Set objCliente = objetoCliente

End If

End If

End Property

...

cupomVenda = cupomVenda & "CPF: " & objVenda.objCliente.cpf & vbCrLf

cupomVenda = cupomVenda & "Nome: " & objVenda.objCliente.nomeCliente & vbCrLf

Nome: FVenda

Largura: 22cm

Altura: Cabeçalho (1,6cm) / Detalhe (15cm)

Repare que a função busca os itens começando do final do conjunto de registros, inclusive montandoas linhas também do final para o início, até que seja completada a quantidade de itens solicitada, outodos os itens caso a opção não seja informada.

Ponto Importante

Desta vez, relembrando e aprimorando os conceitos da orientação a objetos, vamos destacar o pontoa seguir.

1. Atributo do tipo objeto: Nos atributos da classe Venda podemos encontrar um que faz referênciaà classe Cliente, ou seja, o atributo é um objeto da classe Cliente. Por que isto? Apenas adiantandoum pouco o assunto do próximo artigo criaremos um modelo de cupom fiscal (bem simples, lógico!!!)no qual esta opção será muito útil. Ao invés de criarmos uma variável de objeto da classe Cliente e ainstanciarmos bastará utilizarmos o atributo incluído na classe Venda depois que a mesma for obtidaatravés do código da venda. Neste caso o objeto cliente será instanciado dentro da classe Vendaautomaticamente assim que o atributo for referenciado. Com isso será possível também acessar todosos atributos e métodos do objeto cliente. Veja os trechos de código, primeiro o método de acesso aoatributo e depois a montagem do cupom fiscal:

Declaração da variável e método de acesso ao atributo:

Montagem do Cupom Fiscal:

A Interface Gráfica

Desta vez para que possamos visualizar e manipular os dados das vendas resolvi criar um interessantesistema de PDV para ser a nossa interface gráfica, já que há tanta curiosidade acerca dos mesmos.

A tela contará com exibição dos itens registrados em formato de cupom, além do cálculo e registro deprodutos utilizando o esquema de digitação do código multiplicado pela quantidade em um únicocampo. Também faremos a verificação da descrição do produto a partir do código e o cálculo detroco a partir do valor pago, além de outras pequenas funções.

Como não poderia faltar faremos o controle de estoque, tanto baixando itens vendidos como subindoprodutos devolvidos, além de verificação de estoque baixo.

A seguir serão definidas as características para o PDV. Assim como nos anteriores as especificaçõesde design também são apenas sugestões, porém as informações de origem de dados, bloqueio decampos e formatos de dados são obrigatórias, sob pena de, novamente, não obter a funcionalidadedesejada. Como de praxe as especificações estarão marcadas com um asterisco vermelho ao lado.

No formulário teremos um rótulo que exibirá os produtos vendidos, alguns campos de texto paradigitação das informações e os botões de comando para criar e cancelar vendas, excluir produtos efechar a tela do PDV.

Obs: Somente as propriedades que foram alteradas para um valor diferente do padrão serãoapresentadas. Para as demais utilize o padrão do sistema, ou o valor que desejar, desde que nãocomprometa a funcionalidade do sistema.

Formulário

Page 9: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 9/19

Cor do fundo: Cabeçalho (Vermelho) / Detalhe (Azul escuro)

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: Não

Botão Fechar: Não

Botões Min Max: Nenhum

Popup: Sim

Janela Restrita: Não

Nome: lblProdutos *

Largura: 9,7cm *

Altura: 10,4cm *

Nome: txtCodigoVenda *

Formato: 000000

Ativado: Não *

Bloqueado: Sim *

Cor do fundo: Cinza

Alinhamento: Centro

Nome: txtData *

Formato: dd/mm/yyyy *

Cor do fundo: Branco

Máscara de entrada: 00/00/00;;_

Alinhamento: Centro

Nome: txtCodCliente *

Formato: 000

Cor do fundo: Branco

Alinhamento: Centro

Nome: txtNomeCliente *

Cor do fundo: Cinza

Alinhamento: Esquerda

Ativado: Não *

Bloqueado: Sim *

Nome: txtProdutoQtd *

Cor do fundo: Amarelo

Alinhamento: Esquerda

Tamanho da Fonte: 28

Nome: txtDescricao *

Cor do fundo: Cinza

Alinhamento: Esquerda

Tamanho da Fonte: 14

Ativado: Não *

Bloqueado: Sim *

Nome: txtUnidade *

Cor do fundo: Cinza

Alinhamento: Centro

Tamanho da Fonte: 14

Ativado: Não *

Bloqueado: Sim *

Nome: txtQtd *

Cor do fundo: Cinza

Formato: Padrão

Casas decimais: 3

Alinhamento: Centro

Tamanho da Fonte: 14

Ativado: Não *

Bloqueado: Sim *

Nome: txtValorUnt *

Cor do fundo: Cinza

Formato: Unidade Monetária

Alinhamento: Direita

Tamanho da Fonte: 14

Ativado: Não *

Bloqueado: Sim *

Nome: txtSubTotal *

Cor do fundo: Cinza

Formato: Unidade Monetária

Controle Label

Controles Textbox

Page 10: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 10/19

Alinhamento: Direita

Tamanho da Fonte: 14

Ativado: Não *

Bloqueado: Sim *

Nome: txtTotal *

Cor do fundo: Laranja

Formato: Unidade Monetária

Alinhamento: Direita

Tamanho da Fonte: 24

Ativado: Não *

Bloqueado: Sim *

Nome: txtPago *

Cor do fundo: Cinza

Formato: Unidade Monetária

Alinhamento: Direita

Tamanho da Fonte: 16

Nome: txtTroco *

Cor do fundo: Cinza

Formato: Unidade Monetária

Alinhamento: Direita

Tamanho da Fonte: 16

Ativado: Não *

Bloqueado: Sim *

Nome: btnExcluirProduto *

Legenda: Excluir Produto

Cor da Fonte: Vermelho escuro

Nome: btnCancelar *

Legenda: Cancelar Venda

Cor da Fonte: Vermelho escuro

Nome: btnNovo *

Legenda: Nova Venda

Cor da Fonte: Azul escuro

Nome: btnFechar *

Legenda: Fechar

Cor da Fonte: Vermelho escuro

Botões de Comando

Como sugestão de design os campos deverão estar posicionados conforme demonstrado na figura aseguir, assim como devem ser adicionadas as legendas dos campos, as quais não foram descritasanteriormente:

Page 11: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 11/19

Private Sub limpaExibicaoProduto()

txtDescricao = Null

txtUnidade = Null

txtQtd = Null

txtValorUnt = Null

txtSubtotal = Null

End Sub

Private Sub limpaCampos()

txtCodigoVenda = Null

txtData = Null

txtCodCliente = Null

txtNomeCliente = Null

txtProdutoQtd = Null

txtTotal = Null

txtPago = Null

txtTroco = Null

Call limpaExibicaoProduto

lblProdutos.Caption = ""

txtProdutoQtd.SetFocus

End Sub

Private Sub btnNovo_Click()

Call limpaCampos

End Sub

Private Sub txtPago_AfterUpdate()

If Not IsNull(txtPago) Then

txtTroco = CDbl(txtPago) - CDbl(Nz(txtTotal))

Else

txtTroco = Null

End If

End Sub

Sub atualizaLista()

Dim objVenda As New clsVenda

If Not IsNull(txtCodigoVenda) Then

If objVenda.obter(txtCodigoVenda) Then

lblProdutos.Caption = listaProdutos(Nz(txtCodigoVenda, -1), 10)

txtTotal = objVenda.getValorTotal

Call txtPago_AfterUpdate

End If

End If

End Sub

Códigos do Formulário

Para que nosso formulário seja capaz de manipular os dados dos objetos produto deveremosimplementar as funcionalidades necessárias que permitam criar uma nova venda, calcular os valoresdos produtos vendidos, registrar as vendas, controlar estoque, devolver produtos e cancelar a venda.

Sendo assim criaremos algumas funções genéricas que sejam úteis para quantos procedimentos delasnecessitem, reaplicando o conceito da reutilização de código. Além disso, incluiremos os códigos doscampos que possuem eventos, assim como dos botões de comando.

Todos os códigos a seguir deverão ser colocados no módulo do formulário FVenda.

1. Limpeza dos campos: Para efetuar a limpeza dos campos de preenchimento utilizaremos doisprocedimentos genérico cuja função será a de atribuir o valor nulo a todos os campos de texto, deixaro rótulo de exibição do cupom em branco e enviar o foco ao campo txtProdutoQtd. Repare que umprocedimento reutiliza o código do outro, já que os dois são independentes e o primeiro é utilizadoapenas na descrição do produto e o segundo limpa todos os campos da tela.

2. Nova venda: Para a criação de uma nova venda em branco simplesmente iremos chamar oprocedimento limpaCampos() no evento Ao Clicar do botão btnNovo.

3. Cálculo do troco: Com a finalidade de informar o valor do troco a partir do valor da venda e dovalor pago utilizaremos um procedimento que será acionado no evento Após Atualizar do campotxtPago.

4. Exibição da lista de produtos registrados: Para exibir a lista de produtos registrados sempreque for incluído ou retirado algum produto utilizaremos um procedimento genérico cuja função será ade buscar o lista utilizando a função listaProdutos(), atualizar a exibição do valor total da venda nocampo txtTotal e acionar o procedimento que calcula e exibe o valor do troco.

5. Carregamento do formulário: No evento Ao Carregar do formulário implementaremos umapequena rotina que simplesmente atualizará a lista de produtos e moverá o foco para o campo

Page 12: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 12/19

Private Sub Form_Load()

Call atualizaLista

txtProdutoQtd.SetFocus

End Sub

Sub preencheVenda()

If IsNull(txtCodigoVenda) Then

txtCodigoVenda = proximoCodigo("codVenda", "Venda")

End If

If IsNull(txtData) Then

txtData = Date

End If

End Sub

Private Sub txtCodCliente_AfterUpdate()

Dim objCliente As New clsCliente

If Not IsNull(txtCodCliente) Then

If objCliente.obter(CLng(txtCodCliente)) Then

Call preencheVenda

txtNomeCliente = objCliente.nomeCliente

Else

txtNomeCliente = Null

txtCodCliente = Null

MsgBox "Código do cliente inválido!", _

vbExclamation, "Erro!"

End If

End If

End Sub

Private Sub txtProdutoQtd_Change()

Dim objProduto As New clsProduto

If txtProdutoQtd.Text <> "" Then

If InStr(txtProdutoQtd.Text, "*") = 0 Then

If IsNumeric(txtProdutoQtd.Text) Then

If objProduto.obter(CLng(txtProdutoQtd.Text)) Then

txtDescricao = objProduto.descricao

txtUnidade = objProduto.unidade

Else

txtDescricao = "Código não cadastrado..."

txtUnidade = Null

End If

txtQtd = Null

txtValorUnt = Null

txtSubtotal = Null

End If

End If

Else

txtDescricao = Null

txtUnidade = Null

End If

End Sub

txtProdutoQtd. A atualização da lista só fará sentido quando abrirmos novamente um formulário jácarregado anteriormente (por exemplo, quando abrimos o formulário, mudamos para o modo Design evoltamos para o modo Formulário).

6. Criação da venda: Ao iniciarmos uma venda deveremos gerar o código da mesma. Assim criaremosum procedimento genérico que lança mão da função proximoCodigo() para gerar o código da venda,além de atribuir a data atual caso o usuário não tenha informado alguma data específica.

7. Busca do cliente: Para que seja exibido o nome do cliente assim que o código for informadoutilizaremos esta rotina no evento Após Atualizar do campo txtCodCliente. Assim será preenchido ocampo txtNomeCliente a partir dos dados retornados pelo objeto cliente, ou então um aviso aousuário informando que o código do cliente é inválido. Ao ser informado um cliente válido a vendatambém será gerada através de uma chamada ao procedimento preencheVenda().

8. Busca do produto em tempo real: O procedimento a seguir permitirá que seja exibida a descriçãoe a unidade do produto no exato momento em que o código for digitado. Ele será incluído no eventoAo Alterar do campo txtProdutoQtd. Caso o código não corresponda a nenhum produto será exibidauma mensagem no campo txtDescricao informando que o código não está cadastrado. Veja que elesomente será executado completamente caso o valor digitado possa ser interpretado como valornumérico, ou seja, um valor compatível com o código do produto.

Page 13: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 13/19

Sub exibeProduto(argDetalhe As clsDetalheVenda)

Dim objProduto As New clsProduto

If objProduto.obter(argDetalhe.codProduto) Then

txtDescricao = objProduto.descricao

txtUnidade = objProduto.unidade

txtQtd = argDetalhe.qtdProduto

txtValorUnt = objProduto.valorUnitario

txtSubtotal = argDetalhe.getSubTotal

End If

End Sub

Private Sub txtProdutoQtd_BeforeUpdate(Cancel As Integer)

On Error GoTo Err_txtProdutoQtd_AfterUpdate

Dim codigoProduto As Long

Dim qtdProduto As Double

Dim posicao As Integer

Dim status As Integer

Dim objVenda As New clsVenda

Dim objDetalhe As New clsDetalheVenda

Dim objProduto As New clsProduto

status = 0

If Not IsNull(txtProdutoQtd) Then

Call preencheVenda

posicao = InStr(txtProdutoQtd, "*")

If posicao > 0 Then

status = 1

codigoProduto = CLng(Left(txtProdutoQtd, posicao - 1))

status = 2

qtdProduto = CDbl(Right(txtProdutoQtd, Len(txtProdutoQtd) - posicao))

Else

status = 3

codigoProduto = CLng(txtProdutoQtd)

qtdProduto = 1

End If

status = 4

objVenda.codVenda = CLng(txtCodigoVenda)

status = 5

objVenda.dataVenda = CDate(txtData)

status = 6

If Not IsNull(txtCodCliente) Then

objVenda.codCliente = CLng(txtCodCliente)

End If

If objProduto.obter(codigoProduto) Then

If objProduto.qtdEstoque < qtdProduto Then

MsgBox "O estoque existente não é suficiente!" & vbCrLf & vbLf & _

"Estoque atual: " & FormatNumber(objProduto.qtdEstoque, 3) & _

" " & objProduto.unidade, _

vbExclamation, "Estoque Baixo"

Cancel = True

Exit Sub

End If

End If

9. Exibição de produto: Para exibirmos todos os dados do produto a ser registrado em uma vendacriaremos um procedimento genérico que recebe como argumento um objeto detalhe de venda cujaspropriedades e métodos fornecerão as informações para o preenchimento dos campos. Repare que ovalor do subtotal é calculado pelo método getSubTotal() do objeto.

10. Registro do produto: Cada produto constante da venda deverá ser registrado antes dofechamento da venda. Para isto deveremos realizar várias verificações, utilizando vários objetos nesteprocedimento que será incluído no evento Antes de Atualizar do campo txtProdutoQtd para queseja capaz de cancelar o registro caso alguma informação não esteja correta. Primeiro será verificadaa validade do código do produto e a correta informação da quantidade, caso seja incluída, atribuindouma unidade em caso contrário. Em seguida será checada a validade do código da venda e tambémda data, além do código do cliente, caso seja informado (uma venda sem cliente será consideradavenda ao consumidor). Para não ocorrerem conflitos o código da venda será sempre geradoautomaticamente, não sendo permitida sua alteração posterior. O próximo passo será verificar se aquantidade solicitada existe em estoque. Caso não possa ser atendida integralmente o registro écancelado. Existindo a quantidade o produto é registrado, assim como qualquer alteração nos dadosda venda. Por último a exibição dos dados é atualizada e o estoque atualizado, informando o usuáriose o estoque ficar abaixo do mínimo. Caso ocorram erros durante o processo o esquema detratamento de erros avisa o usuário sobre qual passo gerou o problema.

Page 14: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 14/19

status = 7

If objVenda.salvar Then

objDetalhe.codVenda = objVenda.codVenda

objDetalhe.codProduto = codigoProduto

objDetalhe.qtdProduto = qtdProduto

status = 8

If objDetalhe.salvar Then

Call exibeProduto(objDetalhe)

Call atualizaLista

If objProduto.obter(codigoProduto) Then

status = 9

If objProduto.baixarEstoque(qtdProduto) Then

If objProduto.estoqueBaixo Then

MsgBox "O estoque ficou abaixo da quantidade mínima!" & _

vbCrLf & vbLf & _

"Estoque atual: " & FormatNumber(objProduto.qtdEstoque, 3) & _

" " & objProduto.unidade, vbExclamation, "Estoque Baixo"

End If

Else

MsgBox "Ocorreu um erro na atualização do estoque.", _

vbExclamation, "Erro!"

End If

End If

Else

MsgBox "Ocorreu um erro ao incluir o produto.", _

vbExclamation, "Erro!"

Cancel = True

End If

Else

MsgBox "Ocorreu um erro ao incluir a venda.", _

vbExclamation, "Erro!"

Cancel = True

End If

End If

Exit_txtProdutoQtd_AfterUpdate:

Exit Sub

Err_txtProdutoQtd_AfterUpdate:

Select Case status

Case 1, 3

MsgBox "Código do produto inválido!", vbExclamation, "Erro!"

Case 2

MsgBox "Quantidade do produto inválida!", vbExclamation, "Erro!"

Case 5

MsgBox "Data inválida!", vbExclamation, "Erro!"

Case 6

MsgBox "Código do cliente inválido!", vbExclamation, "Erro!"

Case 7

MsgBox "Ocorreu um erro ao incluir a venda!", vbExclamation, "Erro!"

Case 8

MsgBox "Ocorreu um erro ao incluir o produto!", vbExclamation, "Erro!"

Case 9

MsgBox "Ocorreu um erro ao atualizar o estoque!", vbExclamation, "Erro!"

Case Else

MsgBox "Ocorreu um erro. O sistema informou a seguinte mensagem:" & _

vbCrLf & vbLf & Err.Description, vbExclamation, "Erro!"

End Select

Cancel = True

Resume Exit_txtProdutoQtd_AfterUpdate

End Sub

Private Sub txtProdutoQtd_AfterUpdate()

btnNovo.SetFocus

txtProdutoQtd.SetFocus

txtProdutoQtd = Null

Call preencheVenda

Obs: Apenas para esclarecimento sobre o tratamento de erros lembre-se que este não é umsistema real. Sendo assim os códigos foram colocados de qualquer maneira para atingir o objetivodo curso: aprender a utilizar os objetos. Da maneira que foram implementados os registros um errono meio do processo impediria que o final do registro de uma venda ou de um produto ocorresse,deixando os dados corrompidos. Em um sistema real deveriam ser utilizadas transações paragarantir que todos os processos ocorressem integralmente, do início ao fim, ou então que todas asetapas fossem canceladas e os dados retornassem ao estado original. Não poderíamos, porexemplo, ter uma venda registrada sem que o estoque fosse atualizado. Mas isto é outra história...

11. Atualização das informações: Após o registro de um produto as informações exibidas devemser atualizadas e o foco retornar para o campo de digitação de produto e quantidade, a fim de queele esteja pronto para efetuar novo registro. Para executar esta tarefa criaremos um procedimento noevento Após Atualizar do campo txtProdutoQtd.

Page 15: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 15/19

Call atualizaLista

End Sub

Private Sub btnExcluirProduto_Click()

Dim objDetalheVenda As New clsDetalheVenda

Dim objProduto As New clsProduto

Dim codigoProduto As String

If Not IsNull(txtCodigoVenda) Then

codigoProduto = InputBox("Informe o código do produto a ser excluído:", _

"Exclusão de Produto")

Else

Exit Sub

End If

If codigoProduto <> "" Then

If IsNumeric(codigoProduto) Then

If objDetalheVenda.obter(CLng(codigoProduto), CLng(txtCodigoVenda)) Then

If objProduto.obter(CLng(codigoProduto)) Then

If objProduto.subirEstoque(objDetalheVenda.qtdProduto) Then

If objDetalheVenda.excluir Then

MsgBox "O produto foi excluído com sucesso!", _

vbInformation, "Exclusão de Produto"

Call atualizaLista

Else

MsgBox "Ocorreu um erro durante a exclusão do produto!", _

vbExclamation, "Exclusão de Produto"

End If

End If

End If

End If

Else

MsgBox "Código de produto inválido!", _

vbExclamation, "Exclusão de Produto"

End If

End If

End Sub

Private Sub btnCancelar_Click()

Dim objVenda As New clsVenda

Dim objDetalheVenda As New clsDetalheVenda

Dim objProduto As New clsProduto

Dim rstLista As Recordset

If objVenda.obter(Nz(txtCodigoVenda, -1)) Then

If MsgBox("Confirma o cancelamento da venda?", _

vbQuestion + vbYesNo, "Cancelar Venda") = vbYes Then

Set rstLista = objDetalheVenda.getListaProduto(txtCodigoVenda)

While Not rstLista.EOF

Call objProduto.obter(rstLista("codProduto"))

Call objProduto.subirEstoque(rstLista("qtdProduto"))

rstLista.MoveNext

Wend

If objVenda.excluir Then

MsgBox "A venda foi cancelada com sucesso.", _

vbInformation, "Cancelar Venda"

12. Exclusão de produto da venda: Caso tenhamos que excluir um único produto da venda, antesque ela seja fechada, deveremos desfazer os passos executados no registro do mesmo. Para istodevemos criar um procedimento no evento Ao Clicar do botão btnExcluirProduto. Ele seráencarregado de solicitar ao usuário o código do produto que deverá ser excluído, checando suavalidade, atualizando o estoque e finalmente excluindo o produto, sendo que os dados de exibiçãodevem ser novamente atualizados através de uma chamada ao procedimento genéricoatualizaLista(). Repare que não excluiremos o produto em si, mas apenas o seu registro na venda.

Obs: Veja que não incluí tratamento de erro neste procedimento. Também não incluí e nem incluireiem vários outros. Esta tarefa deverá ser executada no evento Ao Praticar do objetoLeitorAplicado.

13. Cancelamento da venda: Assim como podemos excluir um produto registrado também podemoscancelar uma venda inteira. Para executar esta tarefa deveremos desfazer todos os passosexecutados para registrar todos os produtos até o momento. O procedimento responsável seráincluído no evento Ao Clicar do botão btnCancelar. O cancelamento deverá contemplar a busca doconjunto de registros dos produtos da venda, através do método getListaProduto() do objetodetalhe de venda, que serão verificados um a um para retorno ao estoque. Em seguida a venda seráexcluída, ocasionando a exclusão dos registros associados na tabela DetalheVenda pelo mecanismodo relacionamento em cascata. Após a exclusão os campos serão limpos para iniciar nova venda.

Page 16: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 16/19

Call limpaCampos

Else

MsgBox "Ocorreu um erro durante o cancelamento.", _

vbExclamation, "Cancelar Venda"

End If

End If

End If

End Sub

Private Sub btnFechar_Click()

DoCmd.close

End Sub

Venda00.zip

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

14. Fechamento do PDV: Para encerrarmos as atividades no PDV simplesmente iremos incluir umprocedimento que fecha o formulário no evento Ao Clicar do botão btnFechar.

Sistema de Exemplo

Novamente será disponibilizado o link para download do sistema de vendas, já atualizado com todosos recursos do estado de desenvolvimento em que se encontrar o projeto.

Continua a recomendação de consultar o exemplo apenas para tirar dúvidas e verificar como foi feito,além de ver o sistema em funcionamento. Treinem bastante, digitem, testem, façam o cérebro pedirágua. Esta é a única maneira de realmente assimilar o conhecimento.

Segue o link para download:

Caso ainda não esteja com uma tela principal abra o formulário FVenda diretamente na janela Bancode Dados (Access 2003-) ou no Painel de Navegação (Access 2007+).

Conclusão

Depois desta exaustiva etapa foi possível percebermos o quanto os objetos devem interagir parachegar ao fim de uma tarefa. Funções, procedimentos, eventos, métodos e atributos trabalham emconjunto para produzir resultados que atendam as necessidades do usuário.

Este artigo foi dedicado a demonstrar de maneira maçante a criação, utilização e troca deinformações entre objetos em meio aos códigos do restante do sistema, por isso mesmo foi bem maislongo que os demais.

Além de toda a programação em si foi possível trabalharmos apresentando um sistema interessante,útil e muito comum no dia a dia, do qual muitos tinham a curiosidade de conhecer e compreender aforma de implementação: o PDV. Mas nosso sistema de vendas ultramoderno, com tecnologiaorientada a objetos, não estaria completo sem ele, não é mesmo?

Aqui praticamente encerramos a parte mais trabalhosa. De agora em diante veremos apenas afinalização do sistema, algo mais estético do que funcional, além de um pouco mais teoria nos artigosseguintes, com a apresentação do Genesis, a ferramenta case para VBA que facilitará a sua vida, e aabordagem sobre utilização de objetos no MS-Access para aprimorar seus projetos.

Conto com a presença de todos na próxima etapa, pois esta é a razão de ser desta série de artigos.

Até lá...

Page 17: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 17/19

Enoque Nunes 15/09/2010 13:25:27

E ai grande mestre Plínio, beleza meu amigo?

Cara, você está de parabens mesmo pelo artigo, baixei seu segundo exemplo e pasme, achei fantástico, sempre quis fazer algo semelhante e nãosabia nem por onde começar. rsrsrsrs

Mas, vamos lá.

Estive explorando ontem à noite seu PDV e acredito que encontrei um o erro.

Veja só.

Cadastrei um produto e dei entrada de 05 peças, fui dando baixa um a um, até ai tudo bem, o problema veio depois que as 05 peças tinhamacabado e o PDV continuou aceitando baixa e sem zerar o estoque, ele fica parado sempre com uma peça no estoque e sem abrir mensagem deestoque zero.

Assim, lancei várias saidas no PDV com uma única peça de saldo no estoque, eu tinha dado entrada apenas de 05 peças.

Dá uma checada ai amigão.

Abraços e fica com Deus.

Plinio Mabesi 17/09/2010 18:01:55

Olá Grande Enoque...

Estive aí na sua terrinha semana passada, mas foi uma passagem rápida.Vou checar o programa e assim que corrigir peço para o Avelino postar a correção.

Valeu...

Enoque Nunes 18/09/2010 09:02:47

Cara, como é que você faz uma coisa dessas, vir aqui e não me avisar? rsrsrsrs, iria lhe convidar para comer um delicioso churrasco de tambaqui.

Mas, oportunidades acredito que não irão faltar.

Abraços amigão e fica na paz do Senhor Jesus.

Até mais.

Plinio Mabesi 22/09/2010 20:02:04

O erro está no método baixarEstoque() da classe Produto. O código deve ser alterado para este:

Function baixarEstoque(argQtd As Double) As Boolean

If dblQtdEstoque - Abs(argQtd) < 0 ThenbaixarEstoque = FalseElsedblQtdEstoque = dblQtdEstoque - Abs(argQtd)baixarEstoque = salvarEnd If

End Function

Como o método considerava como falso resultados menores ou iguais a zero o estoque nunca reduzia a quantidade para abaixo de 1 unidade.Deixando falso apenas os valores menores que zero tudo corre normalmente.Mas lembrem-sem que isto não quer dizer que não haja outros erros.Agradeço por novas informações.

Valeu Enoque...

Enoque Nunes 24/09/2010 08:57:54

Valeu Grande Plínio.

Testei e está tudo certinho dessa vez.

Abraços e fica com Deus.

Enoque Nunes 27/09/2010 13:52:30

E ai Plínio, beleza?

Cara, me diz uma coisa, o problema todo estava sendo causado apenas pelo sinal de "=" na linha: If dblQtdEstoque - Abs(argQtd) <= 0 Then ?

Foi a única coisa que alterei no exemplo anterior para poder funcionar normalmente, depois disso funcionou sem problemas, até arrisquei colocarde volta o sinal de "=" para ver o que ia acontecer e para minha surpresa funcionou sem erros.

Não sei qual foi a jogada, mas funcionou.

Abraços amigão e até a próxima.

| Home | Vídeos-aulas | Tutoriais | Dicas | Blog | Downloads | Contato | Artigo |

9 comentários

Page 18: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 18/19

Wemerson Bernardo 31/01/2011 13:05:31

Olá,

Sei que já contrinbuiu demais com o bd disponibilizado (VendaOO). Confesso que segui suas dicas, estou estudando bastanteo Gênesis, e as dicas no site. Mas como não entendia muito de VBA, até assimilar tudo pode ser que demore um pouco, e ainda assim continuo comdúvida.Como vc me orientou, gerei os códigos com o gênesise não consegui ainda. Primeiro acrescentei o campo codBarra como string, coloquei como chave primária tb, o acrescentei na tab DetalheVenda, fiz as relações e nada.

Sem sucesso, tentei apenas mudar as propriedades do campo existente codProduto para texto. (Para caber a qtd de digitos)

Gerei o código com o gêneses e comparei linha por linha com o do projeto original (e não vi nada diferente).

Então. Acho que o erro está no evento AO ALTERAR do campo txtProdutoQtd

sempre que vou digitar mostra o seguinte erro:

Mesmo o produto estando cadastrado na tabela Produto informa: Código não Cadastrado e também

"Erro SQL: Select*From Produto Where codProduto=1 (= a Um ou o 1º nº digitado)

Outro caso é a linha if is numeric, acho que deveria alterar, já que o campo passou a ser texto, não?

Enfim, gostaria muito dessa ajuda.

----------------Private Sub txtProdutoQtd_Change()

Dim objProduto As New clsProduto

If txtProdutoQtd.Text <> "" ThenIf InStr(txtProdutoQtd.Text, "*") = 0 ThenIf IsNumeric(txtProdutoQtd.Text) ThenIf objProduto.obter(CLng(txtProdutoQtd.Text)) ThentxtDescricao = objProduto.descricaotxtUnidade = objProduto.unidadeElsetxtDescricao = "Código não cadastrado..."txtUnidade = NullEnd IftxtQtd = NulltxtValorUnt = NulltxtSubtotal = NullEnd IfEnd IfElsetxtDescricao = NulltxtUnidade = NullEnd If

End Sub

No evento antes de atualizarPrivate Sub txtProdutoQtd_BeforeUpdate(Cancel As Integer)On Error GoTo Err_txtProdutoQtd_AfterUpdate

Dim codigoProduto As Long não sei se continua como long ouDim codigoProduto As String

Mais uma vez, Desculpas e Grato desde já.

johann 28/05/2013 19:55:08

Boa noite plinio, meu nome é johann e eu gostei do seu resultado sobre o pdv mostrado no seu site e dei uma melhorada colocando senhas elogins, permissoes de usuarios e entre outros pra transformar em um verdadeiro sistema mais tenho uma duvida, se vc poder me ajudar eu sereimuito grato. Eu queria colocar ao inves de codproduto*qtdproduto na tela de venda codigoDeBarra*qdeProduto ou se podesse digitar codigo doproduto ou codigo de barra x a quantidade do produto e ele funcionasse. Porque aonde eu trabalho tanto eu digito o codigo do produto como ocodigo de barra. Obrigado e fico no seu aguardo.

Gil Kléber 16/04/2014 16:55:58

Olá Plínio! Parabens pela atitude de deixar seu sistema disponivel para download! Me ajudou muuito!!!No entanto, há algo (que para vc deve sem bem simples de fazer) que não consigo fazer:

Coloquei uma caixa de combinação no formulário FVenda, para selecionar 2 vendedores. Consegui fazer com que aparecesse no cupom fiscal semproblemas, mas não consigo salvar na tabela Vendas. (preciso salvar esse campo e o campo TOTAL, pq faço calculos de comissão no final do mês).Pode me ajudar?

Mais uma coisinha... não consigo adicionar 2 produtos do mesmo código e isso será recorrente aqui na minha lojinha... como posso fazer??

Grande abraço e mais uma vez, obrigado!

Envie seu comentário:

Nome:

Page 19: Curso - Utilizando Classe No Access - As Classes Venda e DatalheVenda

30/06/2015 Curso - Utilizando Classe no Access - As Classes Venda e DatalheVenda

http://www.usandoaccess.com.br/tutoriais/classe-no-access-venda.asp?id=1#inicio 19/19

Comentário:

Digite o número setecentos e onze

comentar

© 1999 Pontocom Serviços Tecnológicos