Utilizando Classe No Access

Embed Size (px)

Citation preview

Utilizando Classe no Access - IntroduoPor: Plnio Mabesi [email protected] Maio / 2010 Esta srie de artigos tem o objetivo de apresentar o uso de classes e disseminar a utilizao da orientao a objetos dentro de sistemas desenvolvidos em Access / Visual Basic for Applications. A programao orientada a objetos vem se difundindo com grande vulto no mundo todo, resolvendo problemas e causando revoluo no desenvolvimento de sistemas. Ganho de produtividade e qualidade nos produtos so apenas algumas das principais caractersticas deste novo paradigma. Logo no seria muito inteligente da nossa parte, amantes do Access/VBA, nos mantermos distantes desta onda de tecnologia apenas por desconhecimento da ferramenta. Para que todos possam tirar proveito da OO (orientao a objetos) foi que nasceu a idia de ensinar e demonstrar como criar programas com a utilizao de classes no Visual Basic for Applications, a linguagem fornecida pelo MS-Access. O trabalho no ser dirigido para uma verso especfica do Access, mas ser direcionado a todas as verses existentes, atravs da apresentao de conceitos e ferramentas genricos, para que todos tenham condies de se aproveitarem dos conhecimentos aqui transmitidos. No sero descritos nem implementados os padres de projetos que so padres de fato, amplamente utilizados em linguagens especficas e voltadas POO, como Java e PHP, por exemplo. Ao contrrio, ser utilizado um padro prprio para fins didticos, tambm direcionados para a utilizao da ferramenta case Genesis, que ser tema de um dos artigos. Ao final dos artigos teremos um exemplo prtico, pronto para utilizao e visualizao da metodologia empregada. O exemplo ser um banco de dados com um pequeno sistema de vendas feito em Access com as funes totalmente implementadas utilizando classes e objetos. Alm do objetivo principal dos artigos tambm ser apresentada a utilizao de uma ferramenta case, o Genesis, um sotware capaz de auxiliar na construo de um banco de dados funcional, desde a sua documentao at a criao das classes que sero utilizadas pelo sistema. O trabalho contar com 10 artigos, assim divididos: I - ORIENTAO A OBJETOS: Histrico dos paradigmas de linguagens de programao e apresentao de conceitos relativos programao orientada a objetos;

II PROGRAMAO OO NO ACCESS/VBA: Apresentao dos recursos de orientao a objetos presentes no Visual Basic for Applications, com a forma de utilizao e as restries existentes; III MODELAGEM DO SISTEMA DE VENDAS: Definio e modelagem de um pequeno sistema de vendas de alimentos, bastantes simples, com o desenho das classes e suas ligaes para posterior implementao; IV AS CLASSES AUXILIARES: Implementao das classes auxiliares, as quais contm funes que sero necessrias para o bom funcionamento das classes principais; V A CLASSE CLIENTE: Definidos os itens da classe ser o momento da implementao da classe Cliente, com a codificao de todos os atributos e mtodos necessrios, alm da interface grfica para manipulao dos dados; VI A CLASSE PRODUTO: Implementao dos atributos e mtodos da classe Produto, alm da interface grfica para manipulao dos dados; VII AS CLASSES VENDA E DETALHE DE VENDA: Implementao dos atributos e mtodos da classe Venda e de sua classe de ligao DetalheVenda, que ser responsvel pelo controle de quais produtos fazem parte de uma venda, alm da interface grfica para manipulao dos dados; VIII FINALIZAO DO SISTEMA: Finalizao do sistema de vendas, com a criao do formulrio principal e dos relatrios para apresentao dos dados; IX GENESIS: A FERRAMENTA CASE: Apresentao do Genesis, um aplicativo capaz de agilizar a criao de um software em Access/VBA que utiliza classes em sua estrutura, alm de produzir elementos para a documentao do sistema. X CONCLUSO: Ao final concluiremos a srie de artigos apresentando alguns apanhados sobre o uso das classes nas diferentes verses do Access e as possibilidades de utilizao da orientao a objetos para melhorar o desempenho dos sistemas desenvolvidos. Vamos ento dar incio a esta jornada de programao imergindo no mundo dos objetos e do nosso querido Access.

Utilizando Classe no Access Orientao a ObjetosPor: Plinio Mabesi [email protected] Maio / 2010 Desde o surgimento da computao, as tcnicas de programao e desenvolvimento de sistemas sofrem modificaes, geralmente para melhor, a cada perodo de tempo. No incio os computadores eram programados diretamente no hardware, atravs de fios e interruptores, que eram conectados de acordo com a ocasio. Com a evoluo dos equipamentos, e o conseqente aumento das necessidades de processamento, surgiram

as primeiras linguagens de programao, ainda de baixo nvel, como o Assembly, de difcil compreenso, por ser muito prximo da linguagem do computador. Para vencer esta dificuldade comearam a ser desenvolvidas as linguagens de alto nvel, mais prximas da linguagem humana, cuja sintaxe de comandos so palavras, inteiras ou abreviadas, em ingls. At a os programas eram desenvolvidos de forma linear, um comando depois do outro, e assim eram executados. Era a programao linear. Com o aumento da complexidade dos softwares, pesquisadores comearam a se preocupar com a estrutura dos programas, de forma que ficasse mais fcil criar programas ainda mais complexos, pois a programao linear era muito difcil de ser corrigida, j que o programador freqentemente se perdia em meio aos desvios e loops existentes. A partir do aperfeioamento e adequao das linguagens de alto nvel, tornou-se possvel desenvolver programas baseados em funes agrupadas em mdulos, onde cada mdulo era responsvel por determinadas funes, e o conjunto de mdulos formava o sistema completo. Eis que surge a programao estruturada. Este tipo de abordagem seguiu dois caminhos principais, a programao orientada a funes, onde a base do projeto do software eram os processos necessrios execuo das tarefas, e a programao orientada a dados, no qual o projeto do sistema era baseado no modelo de dados. Alguns autores acreditam que a abordagem nos dados melhor, pois funes so baseadas nas regras do negcio, e regras mudam constantemente, j os dados sofrem muito menos alteraes no mesmo perodo de tempo, por isso apresentam maior consistncia. O paradigma estruturado resolveu grande parte dos problemas por um bom perodo. As crticas apareceram quando desenvolvedores do mundo todo perceberam que ainda era muito difcil realizar manuteno ou extenso dos softwares estruturados. No se chega a um consenso sobre o motivo, alguns afirmam que isto se deve falta de documentao, outros alegam falta de preocupao com a anlise e o projeto. Contudo, todos concordam que ele no conseguia atender crescente demanda por sistemas de grande complexidade, e que exigiam prazos reduzidos para concluso, alm de possibilitar a manuteno e a extenso de pontos especficos do sistema sem que isto afetasse tanto os outros componentes. Em grande parte dos sistemas estruturados, seria mais fcil recomear do zero do que realizar uma alterao bem sucedida. A proposta que alcanou o nvel mais prximo do ideal foi a de tratar os sistemas como eles realmente so. Qualquer software , na verdade, uma representao da realidade, e o mundo real composto de objetos independentes que se relacionam. Os objetos possuem caractersticas e realizam aes prprias, que os diferenciam dos demais. Alguns objetos possuem caractersticas e realizam aes similares, por isso podem ser facilmente agrupados em um tipo de objeto, um modelo que serve de referncia para qualquer objeto deste tipo. A partir do estudo dos objetos surge a programao orientada a objetos, um novo paradigma cuja idia principal a de modelar os sistemas considerando que cada classe de objetos possui caractersticas (dados) e realizam aes (funes) prprias.

O sucesso da POO se deve ao fato de que representando o problema como objetos fica bem mais fcil analisar e compreender a complexidade de qualquer sistema, tanto os mais simples quanto os mais complexos, os quais a PE no conseguia representar com a fidelidade e a simplicidade desejadas. Na POO uma alterao realizada em uma classe geralmente no afeta o restante do software, ento a manuteno ou a extenso se resume a alterar o ponto desejado. Conceitos Bsicos A POO introduziu vrios conceitos novos, alm de utilizar alguns j existentes, mas que ganharam um novo sentido. Para compreender melhor um sistema OO importante conhecer pelo menos alguns deles. Objeto => qualquer indivduo, lugar, evento, coisa ou conceito aplicvel ao sistema, sobre o qual se deseja armazenar informaes, ou que seja necessrio ao desenvolvimento do software Ex: Um gato um objeto, uma televiso um objeto, um carro um objeto, um cliente um objeto, um relatrio um objeto, um documento de texto um objeto, etc. Classe => grupo de objetos similares, utilizada para definir um objeto apenas uma vez. Imagine uma empresa com 1.000 clientes, tendo que modelar um objeto para cada cliente. Ao invs disso modelamos uma classe Cliente, que a base para a criao de um objeto. A classe contm todas as informaes que precisamos para construir um objeto. Ex: Todas as caractersticas que um gato possui, e aes que ele executa so modeladas na classe. Quando criarmos o objeto gato usaremos as informaes da classe para isto. Normalmente modelamos graficamente uma classe como um retngulo dividido em trs partes. A primeira contm o nome da classe, a do meio os atributos, e a inferior os mtodos.

Interface => Modelo contendo os mtodos obrigatrios que devero ser implementados em uma classe. A interface no implementa nenhum dos mtodos, mas contem a assinatura de cada um deles, ou seja, define os nomes, os parmetros de entrada e os tipos de dados de retorno dos mtodos que a classe dever obrigatoriamente implementar. Instncia => o objeto criado a partir da classe. Cada objeto criado uma instncia da classe

Abstrao => Quando modelamos a classe no utilizamos, na verdade, todas as caractersticas do objeto, e sim apenas aquelas que tem alguma relao com o sistema a

ser desenvolvido, ou seja, apenas aquilo que interessa. Quando escolhemos as caractersticas e aes que so importantes estamos abstraindo as informaes do objeto a ser modelado. Ex: Quando modelamos uma classe Cliente para uma farmcia no precisamos saber, por exemplo, o nmero do sapato ou do manequim do cliente. J em uma loja de moda estas informaes j seriam relevantes. Para decidir quais aes ou caractersticas so relevantes devemos fazer a abstrao do objeto dentro daquele determinado propsito. Atributo => So as caractersticas que o objeto possui. Para um objeto Cliente teramos como atributos o nome, o CPF, o endereo, etc. Atributo tudo aquilo que deva ser lembrado sobre o objeto. Mtodo => tudo aquilo que o objeto capaz de fazer. Um objeto Aluno pode, por exemplo, solicitar matrcula, realizar exame, ser reprovado, etc. Persistncia => a capacidade de um objeto manter suas informaes por tempo indeterminado. Em outras palavras um objeto persistente quando ele foi salvo, ou gravado, em um meio fsico, para que possa ser recuperado posteriormente. Mensagem => Como no mundo real os objetos precisam da ajuda de outros objetos para realizarem suas funes. Um objeto Aluno, quando solicita trancamento de matrcula, precisa da ajuda do objeto Coordenao para realizar esta tarefa. Para que isto ocorra ele deve enviar uma mensagem ao objeto Coordenao informando seu desejo de trancar a matrcula. Na prtica, a troca de mensagens se d pelas chamadas de funes (mtodos) das classes dentro do sistema. Encapsulamento => Um dos maiores benefcios da OO a possibilidade de escondermos do mundo externo o modo como so implementados os atributos e os mtodos de uma classe. Para que um objeto solicite uma informao de outro, ou solicite a execuo de uma ao, ele no precisa saber como ela se dar realmente, pois apenas o resultado interessa. Ex: Como ilustrao podemos citar o sistema de frenagem dos carros. Para que um objeto Carro freie ns sabemos que basta pisar no pedal de freio. Como esto organizadas as engrenagens, mangueiras, pastilhas e discos no interessa. O sistema de freio de um carro popular diferente do sistema de um carro de luxo com ABS, por exemplo, mas nos dois casos o motorista no precisa saber disso para frear, basta pisar no pedal e a ao frenagem ser executada, resultando na parada do carro. Herana => Um objeto pode herdar caractersticas ou funes de outro. Em um sistema escolar encontramos a necessidade de modelar duas classes distintas, Aluno e Professor, pois cada um deles possui informaes e executam aes diferentes um do outro, mas tambm possuem similaridades, como nome, endereo, entre outras. Para evitarmos que uma eventual alterao neste tipo de dado seja feita em mais de um local, podemos modelar uma classe chamada Pessoa, que contenha os atributos comuns a Aluno e Professor, em seguida fazemos com que Aluno e Professor herdem estas caractersticas de Pessoa. A regra tambm vale para quando temos uma classe que possui os mesmos atributos e executa as mesmas aes de outra, mas de uma maneira diferente. Para isto utilizamos a herana em conjunto com o polimorfismo.

Polimorfismo => Capacidade que as classes tem de possuir atributos ou mtodos iguais, mas que executam suas aes de maneiras distintas, devendo ser implementadas separadamente. Conforme descrito no caso anterior, a segunda classe herda todos os atributos e mtodos da primeira, e redefine os atributos e mtodos prprios, mantendo o mesmo nome. Quando um objeto externo enviar uma mensagem a ao executada ser aquela correspondente classe para a qual a mensagem foi enviada. Em resumo, polimorfismo ocorre quando aes diferentes podem ser executadas a partir do mesmo comando, ou seja, quando da chamada de um mesmo mtodo cada objeto responde a sua maneira. Ex: Imagine os objetos piano e flauta. Os dois teriam o mtodo tocar(), mas cada um executaria o mtodo de maneira diferente. Vantagens da POO Uma das principais vantagens da programao orientada a objetos , com certeza, a possibilidade de reutilizao de cdigos em vrios sistemas distintos. Assim como j de praxe em outras reas do conhecimento a padronizao permite que componentes genricos de software sejam construdos e possam ser utilizados diretamente em uma infinidade de outros sistemas. Algumas vezes a utilizao direta no possvel, mas nestes casos em geral basta uma pequena adaptao. Para isto j existem solues prontas como o conhecido padro de projeto Adapter, que tem por finalidade acoplar dois ou mais diferentes objetos de software. Alm do padro de adaptao existem diversos outros que atendem s mais diversas finalidades dentro da modelagem e programao de objetos. Com a criao de padres internacionais, como no caso da OO, ocorre uma maior facilidade de envolvimento entre desenvolvedores do mundo todo, acelerando tanto o desenvolvimento de sistemas complexos quanto a disseminao de novas tcnicas para soluo de problemas at ento obscuros. Uma outra vantagem dos sistemas OO que, em geral, possuem uma diviso de cdigo um pouco mais lgica e melhor encapsulada do que a empregada nos sistemas no orientados a objetos, o que torna a manuteno e extenso do cdigo mais fcil e

com menos riscos de insero de bugs. Tambm mais fcil reaproveitar o cdigo. (David, 2007) Ainda segundo David (2007), mais fcil gerenciar o desenvolvimento deste tipo de software quando temos uma equipe grande. Podemos fazer uma especificao UML antes de iniciar o desenvolvimento do software em si, e em seguida dividirmos o sistema em classes e pacotes, e cada membro da equipe pode ficar responsvel por desenvolver uma parte do sistema. Com isto o software ganha uma sobrevida maior que os sistemas estruturados, pois a sua manuteno e at mesmo a sua extenso tornam-se mais fceis de se implementar. Desvantagens da POO O maior dos entraves para a adoo da OO nos sistemas atuais est no aprendizado dos conceitos referentes metodologia, que so complexos e requerem maturidade e massificao de conhecimento do indivduo. A correta aplicao dos conceitos requer bastante prtica e esforo mental para assimilao e abstrao das caractersticas do mundo real, o que muitos no esto dispostos a enfrentar. Ao contrrio da programao procedural tradicional, na qual basta decorar meia dzia de comandos e voc j consegue fazer um programa simples, de acordo com David (2007). Na OO conceitos como herana e polimorfismo, entre outros, geralmente causam um n na cabea dos iniciantes. Alm do problema do aprendizado, a programao orientada a objetos exige mais do hardware, como capacidade de processamento e memria. claro que a programao orientada a objetos no pode se comparar, em desempenho, com outros tipos de linguagens procedurais ou lineares. Porm com o avano da tecnologia de hardware esta perda de desempenho facilmente compensada pela velocidade e capacidade dos atuais processadores e outros dispositivos de hardware. Devido a sua complexidade a metodologia orientada a objetos no indicada para a produo de pequenos sistemas, pois a quantidade de trabalho inicial necessria no compensa o esforo. Porm na medida em que o software cresce as vantagens comeam a aparecer. Quanto maior fica o sistema, mais a metodologia se paga, em todos os aspectos.

Utilizando Classe no Access - Modelagem do Sistema de VendasPor: Plinio Mabesi [email protected] Maio / 2010 Nesta etapa da srie definiremos o modelo de classes do nosso sistema de vendas de alimentos. Consequentemente, faremos tambm o mapeamento das classes para o modelo de banco de dados relacional, o qual utilizaremos para persistir os objetos criados. Conforme foi dito anteriormente no sero abordados tpicos aprofundados sobre o assunto. A modelagem utiliza alguns diagramas da Linguagem de Modelagem

Unificada (UML), mas no segue plenamente o padro proposto nem contempla todas as fases da modelagem. Para maiores informaes sobre a UML consulte um manual especializado ou sites de referncia na Internet. Alm disso o modelo adotado tem carter didtico e no pretende servir como um padro para aplicaes reais. As relaes criadas, as funes definidas e os atributos escolhidos tero como objetivo maior demonstrar como funciona a aplicao da orientao a objetos no Access / VBA, mesmo no sendo a forma mais correta e eficiente de modelagem de classes ou de banco de dados. Portanto preocupe-se em visualizar e compreender bem as tcnicas utilizadas nas chamadas de mtodos, criao de atributos, passagem de parmetros, enfim esteja focado em aprender como se d a interao entre os objetos dentro do sistema. Padro de Nomenclatura O padro que ser utilizado neste trabalho obedecer s seguintes definies: > No sero usados acentos, smbolos ou espaos nos nomes, j que isto uma prtica que causa problemas na maioria das linguagens de programao existentes, no sendo nem mesmo aceita em vrias delas. > Nomes de classes comeando em maisculas, com o restante em minsculas. Quando o nome da classe for formado por mais de uma palavra elas sero separadas por maiscula. Ex: Cliente, Venda, DetalheVenda; > Nomes de atributos em minsculas. Quando o nome do atributo for formado por mais de uma palavra elas sero separadas por maiscula. Ex: cpf, nomeCliente, descricao; > Nomes de mtodos em minsculas seguidos por parnteses. Quando o nome do atributo for formado por mais de uma palavra elas sero separadas por maiscula. Ex: obter(), salvar(), consulta(), calculaClasse(); > Nomes de tabelas comeando em maisculas, com o restante em minsculas. Quando o nome da tabela for formado por mais de uma palavra elas sero separadas por maiscula. Ex: Cliente, Venda, DetalheVenda; > Nomes de campos de tabelas em minsculas. Quando o nome do campo for formado por mais de uma palavra elas sero separadas por maiscula. Ex: cpf, nomeCliente, descricao; > Nomes de consultas comeando em maisculas, precedidos pela letra C, com o

restante em minsculas. Quando o nome da consulta for formado por mais de uma palavra elas sero separadas por maiscula. Ex: CCliente, CVenda, CDetalheVenda; > Nomes de formulrios comeando em maisculas, precedidos pela letra F, com o restante em minsculas. Quando o nome do formulrio for formado por mais de uma palavra elas sero separadas por maiscula. Ex: FCliente, FVenda, FDetalheVenda; > Nomes de relatrios comeando em maisculas, precedidos pela letra R, com o restante em minsculas. Quando o nome o relatrio for formado por mais de uma palavra elas sero separadas por maiscula. Ex: RCliente, RVenda, RDetalheVenda; Obs: No momento da implementao das classes ser adicionado o prefixo cls ao nome daquelas que dizem respeito a objetos persistentes e acl ao nome das que so auxiliares. O motivo desta escolha ser explicado no artigo sobre o Genesis, a ferramenta case para o Access. Modelo de Classes Para criarmos um sistema de vendas necessitaremos dos seguintes itens bsicos: 1- Os PRODUTOS que sero vendidos; 2- Os CLIENTES que iro comprar os PRODUTOS; 3- Cada grupo de PRODUTOS vendido a um CLIENTE ir gerar uma VENDA. Ento inicialmente podemos dizer que nosso sistema dever ser capaz de manipular os objetos Cliente, Produto e Venda. Sendo assim estas sero as classes que deveremos modelar. Obs: Consideraremos que j foi feito um prvio levantamento de requisitos e que j foram definidos quais atributos e mtodos as classes devem ter. Nas interaes entre os objetos poderemos perceber que: 1- Um cliente pode ser cadastrado mesmo que no tenha comprado ainda; 2- Ento um cliente cadastrado pode comprar zero ou mais vezes, por isso podero ser realizadas zero ou mais vendas para cada cliente; 3- Cada venda realizada deve ser feita, obrigatoriamente, a um determinado cliente; 4- Cada produto cadastrado pode estar presente ou no em uma ou mais vendas;

5- Cada venda realizada deve conter, obrigatoriamente, um ou mais produtos.

A figura abaixo ilustra ento o modelo de classes referente descrio anterior:

Para executar funes genricas e comuns a vrias classes do sistema criaremos ainda mais duas classes, uma para realizar a conexo com banco de dados e persistir ou buscar os objetos e outra para realizar tarefas de validao e transformao de valores, as quais sero utilizadas pela classe Cliente. Estas sero chamadas de ConexaoBD e Utilitario. Mas antes de definirmos o esquema bsico de nossas classes temos que ajustar a relao entre Venda e Produto. Como todos j perceberam esta uma relao muitos-paramuitos, ento as regras de modelagem nos mandam criar uma classe de associao para gerenciar a ligao entre elas. Portanto teremos tambm a classe DetalheVenda. Estas sero as outras classes criadas para completar nosso modelo:

Descrio das Classes A seguir sero descritas as estruturas bsicas de cada uma das classes. Porm neste artigo ainda no sero detalhadas as formas de implementao das funcionalidades de cada mtodo definido no modelo. Apenas a assinatura de cada mtodo ser informada, contendo seu objetivo, seus parmetros de entrada e seu tipo de retorno. Os mtodos Let, Get e Set tambm no sero abordados por enquanto. Classe Utilitrio Objetivo: oferecer funcionalidades de validao de dados e transformao de valores, necessrias para o correto funcionamento da classe Cliente, ou qualquer outra classe ou funo que venha a precisar dela, a qualquer momento. Isto se deve ao fato da classe possuir mtodos genricos e reutilizveis, podendo ser reaproveitados, sem nenhuma alterao, em qualquer sistema.

Funes: validaCpf(argCpf As String) As Boolean: recebe como argumento um texto contendo um CPF, sem pontos nem trao, e devolve um valor booleano, verdadeiro ou falso, indicando se o CPF ou no vlido; validaEmail(argEmail As String) As Boolean: recebe como argumento um texto contendo um e-mail e devolve um valor booleano, verdadeiro ou falso, indicando se o email ou no vlido, sendo que a verificao feita apenas no seu formato; nomeProprio(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com as iniciais dos nomes em maisculas e o restante em minsculas, levando em considerao as partculas de ligao de nomes, as quais permanecem em minsculas; desacentua(argTexto As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto sem acentos; abreviaNome(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com a penltima parte do nome abreviada, levando em considerao as partculas de ligao de nomes, as quais permanecem inalteradas. Classe ConexaoBD Objetivo: oferecer funcionalidades de consulta e atualizao do banco de dados. Possui tambm mtodos genricos que podem ser reaproveitados em qualquer sistema. Uma das maiores vantagens de se utilizar uma classe de conexo que no caso de mudana do tipo de Sistema Gerenciador de Banco de Dados (SGBD) somente ela dever ser alterada, permanecendo todas as outras intocadas, desde que seja mantida a interface de comunicao dos mtodos. Um exemplo seria a troca do back-end para MySql, Postgres ou Sql Server. Funes: executa(codigoSql As String) As Long: recebe como argumento um texto contendo um cdigo SQL de insero, excluso ou alterao, executa o cdigo e devolve o nmero de registros afetados na operao; consulta(codigoSql As String, Optional editavel As Boolean = False) As Recordset: recebe como argumento um texto contendo um cdigo SQL de consulta de registros e um valor lgico que define o modo de bloqueio de execuo, permitindo ou no a edio dos dados durante a operao, e devolve um recordset contendo o conjunto de registros que atenderem aos critrios; logicoSql(ByVal argValor As Boolean) As String: recebe como parmetro um valor booleano e devolve um texto contendo os valores True ou False, necessrio para cdigos SQL; pontoVirgula(varValor As Variant) As String: recebe como parmetro um valor decimal em que o padro de separao da parte inteira e a decimal a vrgula, e devolve um

texto contendo o mesmo valor agora separado por ponto, necessrio para cdigos SQL; dataSql(ByVal argData As Date) As String: recebe como parmetro uma data em qualquer formato e devolve um texto contendo a data no padro #mm/dd/yyyy#, necessrio para cdigos SQL; valorSql(ByVal argValor As Variant) As String: recebe como parmetro um valor qualquer, verifica o seu formato e devolve um valor no formato padro dos cdigos SQL, fazendo uso das funes anteriores, caso necessrio. Classe Cliente Objetivo: oferecer funcionalidades de consulta e atualizao dos objetos do tipo cliente. Atributos: codCliente (Long); cpf (String); nomeCliente (String); email (String); renda (Currency); classe (String). Funes: existe(argCodCliente As Long) As Boolean: recebe como argumento um cdigo de um cliente, utiliza a classe de conexo para consultar e devolve um valor booleano que indica se o cliente existe ou no no banco de dados; incluir() As Boolean: persiste o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este um mtodo privado, somente sendo acessvel pelos mtodos internos da classe; obter(argCodCliente As Long) As Boolean: recebe como argumento um cdigo de um cliente, utiliza a classe de conexo para consultar, atualiza o objeto com os dados e devolve um valor booleano que indica se o cliente foi buscado com sucesso; salvar() As Boolean: salva objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este mtodo atualiza o objeto atual caso ele j exista ou ento o inclui no banco de dados caso seja um novo objeto; excluir() As Boolean: exclui o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso; calculaClasse() As String: calcula a classe social do objeto atual baseado na renda informada e devolve uma letra correspondente sua classificao dentro das faixas salariais.

Classe Produto Objetivo: oferecer funcionalidades de consulta e atualizao dos objetos do tipo produto. Atributos: codProduto (Long); unidade (String); descricao (String); valorUnitario (Currency); estoqueMinimo (Double); qtdEstoque (Double). Funes: existe(argCodProduto As Long) As Boolean: recebe como argumento um cdigo de um produto, utiliza a classe de conexo para consultar e devolve um valor booleano que indica se o produto existe ou no no banco de dados; incluir() As Boolean: persiste o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este um mtodo privado, somente sendo acessvel pelos mtodos internos da classe; obter(argCodProduto As Long) As Boolean: recebe como argumento um cdigo de um produto, utiliza a classe de conexo para consultar, atualiza o objeto com os dados e devolve um valor booleano que indica se o produto foi buscado com sucesso; salvar() As Boolean: salva objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este mtodo atualiza o objeto atual caso ele j exista ou ento o inclui no banco de dados caso seja um novo objeto; excluir() As Boolean: exclui o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso; baixarEstoque(argQtd As Double) As Boolean: atualiza o estoque diminuindo a quantidade informada como parmetro e devolve um valor booleano que indica o sucesso da operao; subirEstoque(argQtd As Double) As Boolean: atualiza o estoque acrescentando a quantidade informada como parmetro e devolve um valor booleano que indica o sucesso da operao; estoqueBaixo() As Boolean: verifica o estoque atual e compara com o valor de estoque mnimo cadastrado para produto e devolve um valor booleano que indica se o valor atual est abaixo do previsto.

Classe Venda Objetivo: oferecer funcionalidades de consulta e atualizao dos objetos do tipo venda. Atributos: codVenda (Long); codCliente (Long); dataVenda (Date); Funes: existe(argCodVenda As Long) As Boolean: recebe como argumento um cdigo de uma venda, utiliza a classe de conexo para consultar e devolve um valor booleano que indica se o venda existe ou no no banco de dados; incluir() As Boolean: persiste o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este um mtodo privado, somente sendo acessvel pelos mtodos internos da classe; obter(argCodVenda As Long) As Boolean: recebe como argumento um cdigo de uma venda, utiliza a classe de conexo para consultar, atualiza o objeto com os dados e devolve um valor booleano que indica se o venda foi buscada com sucesso; salvar() As Boolean: salva objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este mtodo atualiza o objeto atual caso ele j exista ou ento o inclui no banco de dados caso seja um novo objeto; excluir() As Boolean: exclui o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso; getValorTotal() As Currency: Calcula o valor total da venda atual e devolve o valor como resultado. Classe DetalheVenda Objetivo: oferecer funcionalidades de consulta e atualizao dos objetos de ligao entre a venda e os produtos componentes. Atributos: codVenda (Long); codProduto (Long); qtdProduto (Double); Funes: existe(argCodVenda As Long, argCodProduto As Long) As Boolean: recebe como argumento um cdigo de uma venda e de um produto, utiliza a classe de conexo para

consultar e devolve um valor booleano que indica se objeto existe ou no no banco de dados; incluir() As Boolean: persiste o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este um mtodo privado, somente sendo acessvel pelos mtodos internos da classe; obter(argCodVenda As Long, argCodProduto As Long) As Boolean: recebe como argumento um cdigo de uma venda e de um produto, utiliza a classe de conexo para consultar, atualiza o objeto com os dados e devolve um valor booleano que indica se o objeto foi buscado com sucesso; salvar() As Boolean: salva objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso. Este mtodo atualiza o objeto atual caso ele j exista ou ento o inclui no banco de dados caso seja um novo objeto; excluir() As Boolean: exclui o objeto atual no banco de dados, utilizando a classe de conexo, e devolve um valor booleano que indica se a operao ocorreu com sucesso; getSubTotal() As Currency: Calcula o subtotal do produto vendido para a venda atual e devolve o valor como resultado; getListaProduto(argCodVenda As Long) As Recordset: recebe como parmetro um cdigo de uma venda e devolve um conjunto de registros contendo os cdigos dos produtos relativos venda informada. Diagrama de Alto Nvel Organizando as relaes entre todas as classes do sistema chegamos a este modelo de alto nvel, ainda sem informaes de atributos e mtodos, para melhor visualizao do contexto do sistema:

Diagrama de Classes Detalhado Incluindo agora o restante das informaes de atributos e mtodos chegamos a este diagrama detalhado:

A fim de evitar sobrecarregar o modelo com informaes foram omitidos os mtodos de acesso aos atributos, os Get / Let / Set, que sero includos apenas na implementao das classes, nos prximos artigos. Alm disso atributos auxiliares tambm no foram descritos nesta etapa, mas sero includos no momento da implementao das classes. Modelo de Dados Para que um objeto seja persistente, ou seja, possa ser recuperado posteriormente, ele dever ser gravado em algum meio permanente. Neste caso vamos persistir nossos objetos em um gerenciador de banco de dados bastante conhecido de todos: o prprio Access. Realizando o mapeamento das classes para o formato de banco dados do Access temos ento o dicionrio de dados, com as informaes sobre cada tabela e seus campos, alm dos relacionamentos entre elas, necessrios para manter a integridade dos dados. Temos tambm o diagrama de entidade-relacionamento, que a apresentao grfica do dicionrio. Ressalto que do nosso DER foram suprimidas as informaes detalhadas dos campos para evitar sobrecarregar o modelo, j que este tambm no o foco do presente trabalho. Dicionrio de Dados No dicionrio de dados de um modelo de dados esto descritas as informaes detalhadas sobre as tabelas, seus campos, tipos de dados, tamanho dos campos, chaves primrias e estrangeiras, alm das respectivas referncias estrangeiras. Em nosso sistema teremos as seguintes tabelas mapeadas e seus campos: Cliente Armazena os dados cadastrais dos clientes.Campo Descrio Tipo

codCliente cpf email renda classe

PK - Cdigo que identifica o cliente CPF do cliente E-mail do cliente Renda mensal do cliente, em Reais Classe social do cliente, calculada de acordo com arenda

Long(campo chave) String(11) String(50) String(50) Currency String(1)

nomeCliente Nome completo do cliente

Produto Armazena as informaes sobre os produtos.

Campo

Descrio

Tipo

codProduto descricao unidade valorUnitario estoqueMinimo qtdEstoque

PK - Cdigo que identifica o produto Descrio do produto Unidade de comercializao do produto Valor unitrio do produto, em Reais Quantidade mnima desejada no estoque Quantidade atual do estoque

Long(campo chave) String(30) String(5) Currency Double Double

Venda Armazena informaes sobre as vendas realizadas.Campo Descrio Tipo

codVenda

PK - Cdigo que identifica a venda

Long(campo chave) Long Date/Time

codCliente FK - Cdigo que indica o cliente relativo venda dataVenda Data de realizao da venda

DetalheVenda Armazena informao de ligao entre a Venda e os seus Produtos integrantes.Campo Descrio Tipo

PK - FK - Cdigo que indica o produto codProduto relacionado codVenda PK - FK - Cdigo que indica a venda relacionada qtdProduto Quantidade do produto relacionado

Long(campo chave) FK: Produto(codPoduto) Long(campo chave) FK: Venda(codvenda) Double

Obs: PK: Primary Key (chave primria) / FK: Foreign Key (chave estrangeira)

Diagrama de Entidade-Relacionamento Para facilitar a visualizao e permitir que o modelo de dados seja melhor compreendido o dicionrio de dados convertido em um desenho que apresenta as tabelas e seus campos de forma grfica. Desta maneira a percepo das relaes fica bem mais simples.

Este o Diagrama de Entidade-Relacionamento (DER) do nosso sistema de vendas:

Assim como a modelagem de classes utilizando a UML, a modelagem do diagrama de entidade-relacionamento no ser abordado em detalhes neste curso. Ento mais uma vez para se aprofundar no assunto procure material especializado em livros ou na Internet, ou aguarde outro artigo em um futuro prximo. Concluso Este artigo teve o objetivo de iniciar realmente a construo do sistema que ser objeto de estudo desta srie, atravs da definio de quais sero as partes componentes do projeto. Apesar de no nos aprofundarmos no assunto foi possvel termos uma noo de utilizao de padres de nomenclatura e da modelagem com a UML, conhecendo o diagrama de classes e percebendo a diferena entre os nveis de visualizao do sistema pelo detalhamento das informaes nos modelos. Alm disso conhecemos um pouco sobre o mapeamento das classes para o modelo relacional, utilizando o dicionrio de dados e o diagrama de entidade-relacionamento como ferramentas. Mesmo no abrangendo todas as etapas do desenvolvimento de um software ficou clara a importncia de se planejar bem o que dever ser construdo, atravs da modelagem e da descrio dos itens, tarefa esta que faz parte da fase de anlise do sistema. Bem, como tudo j est definido a nossa etapa seguinte ser colocar a mo na massa, iniciando pela codificao das classes auxiliares, que sero teis para o funcionamento das restantes. Encontro voc no prximo artigo...

Utilizando Classe no Access - As Classes AuxiliaresPor: Plinio Mabesi [email protected] Jun / 2010 No ltimo artigo vimos a modelagem do sistema. Agora chegou a hora de comearmos a codificar nossas primeiras classes.

As classes auxiliares sero responsveis por realizar tarefas genricas que atendem a solicitaes de diversas outras classes ou mesmo outros mdulos do sistema. Poderamos criar inmeras classes auxiliares, com funes agrupadas pelo tipo de tarefa a ser realizada, assim como a classe ConexaoBD que trata de questes de conexo com banco de dados e a classe Utilitario que contempla funes de validao e converso de dados. A idia principal aqui a reutilizao de cdigo, um dos pilares da orientao a objetos. Percebam que ns codificaremos a classe ConexaoBD apenas uma nica vez em toda a nossa vida. No prximo sistema que montarmos simplesmente a importaremos para o novo software, e a classe j dever estar pronta para ser usada. Pode ser que a codifiquemos para outro tipo de banco de dados, por exemplo uma ConexaoBDMySql ou uma ConexaoBDSqlServer, mas cada codificao ser nica e praticamente eterna. Vamos ento rever a descrio de cada classe. Em seguida faremos a codificao. O cdigo das funes ser apresentado apenas com comentrios mas sem detalhamento, j que (novamente) a criao de algoritmos e a estruturao de procedimentos e funes no o foco deste curso. A Classe Utilitario Objetivo: oferecer funcionalidades de validao de dados e transformao de valores, necessrias para o correto funcionamento da classe Cliente, ou qualquer outra classe ou funo que venha a precisar dela, a qualquer momento. Isto se deve ao fato da classe possuir mtodos genricos e reutilizveis, podendo ser reaproveitados, sem nenhuma alterao, em qualquer sistema. Mtodo validaCpf(argCpf As String) As Boolean: recebe como argumento um texto contendo um CPF, sem pontos nem trao, e devolve um valor booleano, verdadeiro ou falso, indicando se o CPF ou no vlido;Function validaCPF(argCpf As String) As Boolean 'Funo que verifica a validade de um CPF. Dim Dim Dim Dim Dim Dim wSomaDosProdutos wResto wDigitChk1 wDigitChk2 wStatus wI

'Inicia o valor da Soma wSomaDosProdutos = 0 'Para posio I de 1 at 9 For wI = 1 To 9 'Soma = Soma + (valor da posio dentro do CPF x (11 - posio)) wSomaDosProdutos = wSomaDosProdutos + Val(Mid(argCpf, wI, 1)) * (11 wI) Next wI

'Resto = Soma - ((parte inteira da diviso da Soma por 11) x 11) wResto = wSomaDosProdutos - Int(wSomaDosProdutos / 11) * 11 'Dgito verificador 1 = 0 (se Resto=0 ou 1 ) ou 11 - Resto (nos casos restantes) wDigitChk1 = IIf(wResto = 0 Or wResto = 1, 0, 11 - wResto) 'Reinicia o valor da Soma wSomaDosProdutos = 0 'Para posio I de 1 at 9 For wI = 1 To 9 'Soma = Soma + (valor da posio dentro do CPF x (12 - posio)) wSomaDosProdutos = wSomaDosProdutos + (Val(Mid(argCpf, wI, 1)) * (12 wI)) Next wI 'Soma = Soma (2 x dgito verificador 1) wSomaDosProdutos = wSomaDosProdutos + (2 * wDigitChk1) 'Resto = Soma - ((parte inteira da diviso da Soma por 11) x 11) wResto = wSomaDosProdutos - Int(wSomaDosProdutos / 11) * 11 'Dgito verificador 2 = 0 (se Resto=0 ou 1 ) ou 11 - Resto (nos casos restantes) wDigitChk2 = IIf(wResto = 0 Or wResto = 1, 0, 11 - wResto) 'Se o dgito da posio 10 = Dgito verificador 1 E 'dgito da posio 11 = Dgito verificador 2 Ento If Mid(argCpf, 10, 1) = Mid(Trim(Str(wDigitChk1)), 1, 1) And _ Mid(argCpf, 11, 1) = Mid(Trim(Str(wDigitChk2)), 1, 1) Then 'CPF vlido validaCPF = True Else 'CPF invlido validaCPF = False End If End Function

Mtodo validaEmail(argEmail As String) As Boolean: recebe como argumento um texto contendo um e-mail e devolve um valor booleano, verdadeiro ou falso, indicando se o e-mail ou no vlido, sendo que a verificao feita apenas no seu formato;Function validaEmail(eMail As String) As Boolean 'Funo de validao do formato de um e-mail. Dim posicaoA As Integer Dim posicaoP As Integer 'Busca posio do caracter @ posicaoA = InStr(eMail, "@") 'Busca a posio do ponto a partir da posio 'do @ ou ento da primeira posio posicaoP = InStr(posicaoA Or 1, eMail, ".") 'Se a posio do @ for menor que 2 OU 'a posio do ponto for menor que a posio 'do caracter @ If posicaoA < 2 Or posicaoP < posicaoA Then

'Formato de e-mail invlido validaEmail = False Else 'Formato de e-mail vlido validaEmail = True End If End Function

Mtodo nomeProprio(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com as inicias dos nomes em maisculas e o restante em minsculas, levando em considerao as partculas de ligao de nomes, as quais permanecem em minsculas;Function nomeProprio(argNome As String) As String 'Funo recursiva para converter a primeira letra 'dos nomes prprios para maiscula, mantendo os 'aditivos em caixa baixa. Dim sNome As String Dim lEspaco As Long Dim lTamanho As Long 'Pega o tamanho do nome lTamanho = Len(argNome) 'Passa tudo para caixa baixa argNome = LCase(argNome) 'Se o nome passado vazio 'acaba a funo ou a recurso 'retornando string vazia If lTamanho = 0 Then nomeProprio = "" Else 'Procura a posio do primeiro espao lEspaco = InStr(argNome, " ") 'Se no tiver pega a posio da ltima letra If lEspaco = 0 Then lEspaco = lTamanho 'Pega o primeiro nome da string sNome = Left(argNome, lEspaco) 'Se no for aditivo converte a primeira letra If Not InStr("e da das de do dos ", sNome) > 0 Then sNome = UCase(Left(sNome, 1)) & LCase(Right(sNome, Len(sNome) - 1)) End If 'Monta o nome convertendo o restante atravs da recurso nomeProprio = sNome & nomeProprio(LCase(Trim(Right(argNome, lTamanho - lEspaco)))) End If End Function

Mtodo desacentua(argTexto As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto sem acentos ou smbolos;

Function desacentua(ByVal argTexto As String) As String 'Funo que retira acentos de qualquer texto. Dim Dim Dim Dim Dim Dim strAcento As String strNormal As String strLetra As String strNovoTexto As String intPosicao As Integer i As Integer

'Informa as duas sequncias de caracteres, com e sem acento strAcento = "" strNormal = "AAAAAEEEEIIIIOOOOOUUUUYCNaaaaaeeeeiiiiooooouuuuycn" 'Retira os espaos antes e aps argTexto = Trim(argTexto) 'Para i de 1 at o tamanho do texto For i = 1 To Len(argTexto) 'Retira a letra da posio atual strLetra = Mid(argTexto, i, 1) 'Busca a posio da letra na sequncia com acento intPosicao = InStr(1, strAcento, strLetra) 'Se a posio for maior que zero If intPosicao > 0 Then 'Retira a letra na mesma posio na 'sequncia sem acentos. strLetra = Mid(strNormal, intPosicao, 1) End If 'Remonta o novo texto, sem acento strNovoTexto = strNovoTexto & strLetra Next 'Devolve o resultado desacentua = strNovoTexto End Function

Mtodo abreviaNome(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com a penltima parte do nome abreviada, levando em considerao as partculas de ligao de nomes, as quais permanecem inalteradas.Function abreviaNome(argNome As String) As String 'Funo que abrevia o penltimo sobrenome, levando 'em considerao os aditivos de, da, do, dos, das, e. 'Define variveis para controle de posio e para as 'partes do nome que sero separadas e depois unidas 'novamente. Dim ultimoEspaco As Integer, penultimoEspaco As Integer Dim primeiraParte As String, ultimaParte As String Dim parteNome As String

Dim tamanho As Integer, i As Integer 'Tamanho do nome passado 'no argumento tamanho = Len(argNome) 'Loop que verifica a posio do ltimo e do penltimo 'espaos, utilizando apenas um loop. For i = tamanho To 1 Step -1 If Mid(argNome, i, 1) = " " And ultimoEspaco 0 Then penultimoEspaco = i Exit For End If If Mid(argNome, i, 1) = " " And penultimoEspaco = 0 Then ultimoEspaco = i End If Next i 'Caso i chegue a zero no podemos 'abreviar o nome If i = 0 Then abreviaNome = argNome Exit Function End If 'Separao das partes do nome em trs: primeira, meio e ltima primeiraParte = Left(argNome, penultimoEspaco - 1) parteNome = Mid(argNome, penultimoEspaco + 1, ultimoEspaco penultimoEspaco - 1) ultimaParte = Right(argNome, tamanho - ultimoEspaco) 'Para a montagem do nome j abreviado verificamos se a parte retirada 'no um dos nomes de ligao: de, da ou do. Caso seja usamos o mtodo 'recursivo para refazer os passos. 'Caso seja necessrio basta acrescentar outros nomes de ligao para serem 'verificados. If parteNome = "da" Or parteNome = "de" Or parteNome = "do" Or _ parteNome = "dos" Or parteNome = "das" Or parteNome = "e" Then abreviaNome = abreviaNome(primeiraParte & " " & parteNome) & " " & ultimaParte Else abreviaNome = primeiraParte & " " & Left(parteNome, 1) & ". " & ultimaParte End If End Function

A Classe ConexaoBD Objetivo: oferecer funcionalidades de consulta e atualizao do banco de dados. Possui tambm mtodos genricos que podem ser reaproveitados em qualquer sistema. Uma das maiores vantagens de se utilizar uma classe de conexo que no caso de mudana do tipo de Sistema Gerenciador de Banco de Dados (SGBD) somente ela dever ser alterada, permanecendo todas as outras intocadas, desde que seja mantida a interface de comunicao dos mtodos. Um exemplo seria a troca do back-end para MySql, Postgres ou Sql Server.

Declarao de Atributo de Banco de Dados a Nvel de Classe Criaremos um atributo que ser responsvel por receber e disponibilizar o banco de dados para ser utilizado pelos mtodos da classe.'Cria um database que ser utilizado para toda a classe Private db As Database

Funo logicoSql(ByVal argValor As Boolean) As String: recebe como parmetro um valor booleano e devolve um texto contendo os valores True ou False, necessrio para cdigos SQL;Function logicoSql(ByVal argValor As Boolean) As String 'Funo que troca os valores lgicos Verdadeiro/Falso 'para True/False para utilizao em consultas SQL 'Se o valor for verdadeiro If argValor Then 'Troca por True logicoSql = "True" Else 'Seno troca por False logicoSql = "False" End If End Function

Funo pontoVirgula(ByVal varValor As Variant) As String: recebe como parmetro um valor decimal em que o padro de separao da parte inteira e a decimal a vrgula, e devolve um texto contendo o mesmo valor agora separado por ponto, necessrio para cdigos SQL;Function pontoVirgula(ByVal varValor As Variant) As String 'Funo que troca a vrgula de um valor decimal por 'um ponto para utilizao em consultas SQL Dim Dim Dim Dim strValor As String strInteiro As String strDecimal As String intPosicao As Integer

'Converte o valor em string strValor = CStr(varValor) 'Busca a posio da vrgula intPosicao = InStr(strValor, ",") 'Se h uma vrgula em alguma posio If intPosicao > 0 Then 'Retira a parte inteira strInteiro = Left(strValor, intPosicao - 1) 'Retira a parte decimal strDecimal = Right(strValor, Len(strValor) - intPosicao) 'Junta os dois novamente incluindo 'agora o ponto no lugar da vrgula

pontoVirgula = strInteiro & "." & strDecimal Else 'Seno devolve o mesmo valor pontoVirgula = strValor End If End Function

Funo dataSql(ByVal argData As Date) As String: recebe como parmetro uma data em qualquer formato e devolve um texto contendo a data no padro #mm/dd/yyyy#, necessrio para cdigos SQL;Function dataSql(ByVal argData As Date) As String 'Funo que formata uma data para o modo SQL 'com a cerquilha: #mm/dd/yyyy# Dim strDia As String, strMes As String, strAno As String 'Retira dia, ms e ano strDia = Day(argData) strMes = Month(argData) strAno = Year(argData) 'Remonta no formato adequado dataSql = "#" & strMes & "/" & strDia & "/" & strAno & "#" End Function

Funo valorSql(ByVal argValor As Variant) As String: recebe como parmetro um valor qualquer, verifica o seu formato e devolve um valor no formato padro dos cdigos SQL, fazendo uso das funes anteriores, caso necessrio;Function valorSql(ByVal argValor As Variant) As String 'Funo que formata valores para utilizao 'em consultas SQL 'Seleciona o tipo de valor informado Select Case VarType(argValor) 'Caso seja vazio ou nulo apenas 'devolve a string Null Case vbEmpty, vbNull valorSql = "Null" 'Caso seja inteiro ou longo apenas 'converte em string Case vbInteger, vbLong valorSql = CStr(argValor) 'Caso seja simples, duplo, decimal ou moeda 'substitui a vrgula por ponto Case vbSingle, vbDouble, vbDecimal, vbCurrency valorSql = pontoVirgula(argValor) 'Caso seja data chama a funo dataSql() Case vbDate valorSql = dataSql(argValor) 'Caso seja string acrescenta aspas simples Case vbString valorSql = "'" & argValor & "'"

'Caso seja lgico chama a funo logicoSql() Case vbBoolean valorSql = logicoSql(argValor) End Select End Function

Funo executa(codigoSql As String) As Long: recebe como argumento um texto contendo um cdigo SQL de insero, excluso ou alterao, executa o cdigo e devolve o nmero de registros afetados na operao;Function executa(codigoSql As String) As Long On Error GoTo Err_executa 'Atualiza dados no Banco utilizando o cdigo Sql passado funo, 'retornando o nmero de registros afetados caso a operao ocorra 'com sucesso ou 0 caso ocorra algum problema Set db = Currentdb db.Execute codigoSql executa = db.RecordsAffected Exit_executa: Set db = Nothing Exit Function Err_ executa: executa = 0 Resume Exit_executa End Function

Funo consulta(codigoSql As String, Optional editavel As Boolean = False) As Recordset: recebe como argumento um texto contendo um cdigo SQL de consulta de registros e um valor lgico que define o modo de bloqueio de execuo, permitindo ou no a edio dos dados durante a operao, e devolve um recordset contendo o conjunto de registros que atenderem aos critrios;Function consulta(codigoSql As String, Optional editavel As Boolean = False) As Recordset On Error GoTo Err_consulta 'Consulta os dados no Banco utilizando o cdigo Sql passado funo, 'retornando um recordset com o resultado da consulta Set db = Currentdb If editavel Then Set consulta = db.OpenRecordset(codigoSql, , dbInconsistent, dbOptimistic) Else Set consulta = db.OpenRecordset(codigoSql, dbOpenSnapshot, dbReadOnly) End If Exit_consulta: Set db = Nothing Exit Function

Err_consulta: MsgBox "Erro SQL: " & codigoSql Set consulta = Nothing Resume Exit_consulta End Function

Aps criar os mtodos salve as classes, mas no se esquea que para salvar convencionamos que seria utilizado o prefixo acl para classes auxiliares. Ento salvaremos as classes com os nomes aclUtilitario e aclConexaoBD. Instanciao dos Objetos Com as classes j codificadas e salvas podemos instanci-las a partir de qualquer mdulo do nosso aplicativo. Vamos fazer um teste com cada uma das classes criadas. Para isto voltaremos ao nosso mdulo padro TesteClasse. Primeiro a classe Utilitario. Vamos criar o procedimento TesteUtilitario:Sub TesteUtilitario() 'Declarando o objeto da classe Utilitario Dim objUtil As New aclUtilitario 'Testando um mtodo da classe, convertendo um 'nome em minsculas para o padro de nomes prprios 'com a primeira letra maiscula MsgBox objUtil.nomeProprio("plinio mabesi") End Sub

Perceba que aps digitarmos o ponto depois do nome do objeto os mtodos disponveis so listados no menu suspenso do editor do VBA.

Com isso voc pode digitar o nome do mtodo ou escolher um deles na lista suspensa. Conforme j vimos antes para executar o cdigo basta posicionar o cursor dentro do procedimento e pressionar F5, ou F8 para acompanhar a execuo passo-a-passo. O resultado ser uma caixa de mensagem exibindo o nome informado no formato de um nome prprio, com as iniciais maisculas:

Agora a classe ConexaoBD. Vamos criar o procedimento TesteConexao:Sub TesteConexaoBD() 'Declarando o objeto da classe ConexaoBD Dim objCon As New aclConexaoBD 'Testando um mtodo da classe, convertendo 'uma data para o padro SQL MsgBox objCon.dataSql("12/06/10") End Sub

Assim como no objeto da classe Utilitario, ao digitarmos o ponto aps o nome do objeto da classe ConexaoBD veremos a lista suspensa com os mtodos disponveis:

Com certeza voc notou que o atributo db (Database) no foi apresentado, devido ao fato de ser um atributo privado (Private). Perceba tambm que quando digitamos o primeiro parntese aps o nome do mtodo o editor do VBA nos mostra quais so os parmetros exigidos, o seu tipo e o tipo de dado de retorno do mtodo. No caso do mtodo dataSql() deveremos informar o parmetro argData que ser passado por valor (ByVal) e do tipo Date, e teremos como retorno uma String. Veja:

Ao executarmos este procedimento teremos como resultado uma caixa de mensagem exibindo a data informada no padro de utilizao do SQL, conforme figura abaixo.

No padro SQL veja que o ms vem em primeiro lugar, seguido pelo dia e depois pelo ano, tudo delimitado pela cerquilha. Todos os cdigos SQL devem estar com as datas neste formato, caso contrrio ocorrer um erro e o cdigo no ser executado. Voc no s pode como deve fazer testes com os outros mtodos. Crie exemplos de utilizao para cada um deles. Se encontrar dificuldade aguarde os prximos artigos, nos quais faremos uso intenso destas duas classes. Mesmo assim o melhor nunca desistir... Concluso

Nosso sistema comea a tomar forma de um software de verdade. Nesta etapa vimos como codificar as classes auxiliares e tivemos uma noo de como instanci-las para utilizar os mtodos disponibilizados. Apesar de no ter sido detalhada a criao da estrutura dos comandos e dos algoritmos dos mtodos, os comentrios o ajudaro a compreender o mnimo necessrio para produzir seus prprios cdigos. Caso no tenha entendido algum trecho pesquise sobre as funes, comandos e tipos utilizados. Conforme salientado no incio deste artigo, o principal conceito que deve ser lembrado no momento o da reutilizao de cdigo. A reutilizao se refere a qualquer procedimento, funo ou mtodo que possa ser diretamente empregado em qualquer projeto imediatamente, sem necessidade de ajuste ou adaptao. Com a orientao a objetos procuramos fazer isto com classes inteiras. As classes Utilitario e ConexaoBD so dois exemplos de classes reutilizveis que no requerem qualquer modificao para funcionarem em um projeto do Access. Claro que algum poderia dizer que estaria faltando um ou outro mtodo ou atributo, ou que na verdade os mtodos existentes no so os melhores, mas o importante no momento o conceito da reutilizao e no a modelagem mais eficiente e mais correta. Entenda que aps projetar a classe mais perfeita possvel e codific-la, ento ela poder ser distribuda para ser importada e incorporada por qualquer projeto. Em nossa prxima etapa poderemos enfim ver o sistema de vendas funcionando pela primeira vez, pois iremos implementar a classe Cliente, bem como a interface grfica para cadastro e manuseio dos dados, tudo isto sem campos acoplados, apenas usando os objetos da classe. At l ento...

Utilizando Classe no Access - A Classe ClientePor: Plinio Mabesi [email protected] Jul / 2010 Chegou enfim a hora de criarmos a primeira parte funcional do nosso sistema. Depois de todo o sistema estar modelado e tambm estarem codificadas as classes auxiliares, vamos ento dar vida ao programa. A primeira classe a ser codificada ser a classe Cliente. Aps apresentar a estrutura da classe faremos a implementao da interface grfica que manipular os dados dos objetos. Caso necessrio relembre os conceitos anteriores sobre atributos, mtodos, acesso s propriedades do objeto, instncias e demais ensinamentos sobre a programao orientada a objetos, vistos nos primeiros artigos. A Classe Cliente

O objetivo desta classe, conforme dito anteriormente, oferecer funcionalidades de incluso, consulta, atualizao e excluso dos objetos do tipo cliente. Este o cdigo da classe, com todos os seus atributos e mtodos, que se utilizam de funes prprias, bem como dos mtodos dos objetos das classes Utilitario e ConexaoBD. Cdigo da classe:Option Compare Database Option Explicit 'Objeto da classe Utilitario Private objUtil As New aclUtilitario 'Atributos da Classe 'Atributo de backup e atributo identificador da Classe 'PK - Cdigo que identifica o cliente. Private bkpCodCliente As Variant Private lngCodCliente As Variant 'Classe social do cliente, calculada de acordo com a renda. Private strClasse As Variant 'CPF do cliente. Private strCpf As Variant 'E-mail do cliente. Private strEmail As Variant 'Nome completo do cliente. Private strNomeCliente As Variant 'Renda mensal do cliente, em reais. Private curRenda As Variant 'Mtodos Get, Set e Let da Classe Property Get codCliente() As Variant codCliente = lngCodCliente End Property Property Let codCliente(argCodCliente As Variant) lngCodCliente = argCodCliente If IsEmpty(bkpCodCliente) Then bkpCodCliente = lngCodCliente End If End Property Property Get classe() As Variant classe = strClasse

End Property Property Get cpf() As Variant cpf = strCpf End Property Property Let cpf(argCpf As Variant) If Not IsNull(argCpf) Then If Not objUtil.validaCPF(argCpf) Then MsgBox "O CPF no vlido.", vbExclamation, "CPF Invlido" strCpf = Null Else strCpf = argCpf End If Else strCpf = argCpf End If End Property Property Get email() As Variant email = strEmail End Property Property Let email(argEmail As Variant) If Not IsNull(argEmail) Then If Not objUtil.validaEmail(argEmail) Then If MsgBox("O E-mail no possui um formato vlido." _ & vbCrLf & "Deseja incluir este e-mail?", vbQuestion + vbYesNo, _ "E-mail Invlido") = vbYes Then strEmail = argEmail End If Else strEmail = argEmail End If Else strEmail = argEmail End If End Property Property Get nomeCliente() As Variant nomeCliente = strNomeCliente End Property Property Let nomeCliente(argNomeCliente As Variant) If Not IsNull(argNomeCliente) Then strNomeCliente = objUtil.nomeProprio(argNomeCliente)

Else strNomeCliente = argNomeCliente End If End Property Property Get renda() As Variant renda = curRenda End Property Property Let renda(argRenda As Variant) curRenda = argRenda 'Alterar classe quando o valor da 'renda for alterado strClasse = calculaClasse() End Property 'Mtodo Existe [Com conhecimento de SQL] 'Verifica a existncia do objeto Cliente na tabela correspondente 'no Banco de Dados Function existe(argCodCliente 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 Cliente " & _ "Where codCliente = " & objCon.valorSql(argCodCliente) 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 'Mtodo Incluir [Com conhecimento de SQL] 'Inclui um novo objeto na tabela correspondente dentro do Banco de dados Private Function incluir() As Boolean On Error GoTo Err_incluir

Dim objCon As New aclConexaoBD Dim strSql As String strSql = "Insert Into " & _ "Cliente(codCliente,classe,cpf,email,nomeCliente,renda) " & _ "Values(" & objCon.valorSql(codCliente) & "," _ & objCon.valorSql(classe) & "," & objCon.valorSql(cpf) _ & "," & objCon.valorSql(email) & "," & objCon.valorSql(nomeCliente) _ & "," & objCon.valorSql(renda) & ")" incluir = (objCon.executa(strSql) > 0) If incluir Then 'Atualiza os campos de backup bkpCodCliente = codCliente End If Exit_incluir: Exit Function Err_incluir: incluir = False GoTo Exit_incluir End Function 'Mtodo 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 Cliente " & _ "Where codCliente = " & objCon.valorSql(codCliente) excluir = (objCon.executa(strSql) > 0) Exit_excluir: Exit Function Err_excluir: excluir = False GoTo Exit_excluir End Function 'Mtodo Obter [Com conhecimento de SQL] 'Recupera o objeto Cliente atravs dos argumentos informados Function obter(argCodCliente 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 Cliente " & _ "Where codCliente = " & objCon.valorSql(argCodCliente) Set rstObter = objCon.consulta(strSql) If rstObter.RecordCount = 0 Then obter = False Exit Function End If 'Atualiza os campos de backup e os identificadores codCliente = argCodCliente bkpCodCliente = argCodCliente 'Atualiza os campos restantes strClasse = rstObter.Fields("classe") cpf = rstObter.Fields("cpf") strEmail = rstObter.Fields("email") nomeCliente = rstObter.Fields("nomeCliente") renda = rstObter.Fields("renda") obter = True 'Fecha o Recordset obter rstObter.Close Exit_obter: Set rstObter = Nothing Exit Function Err_obter: obter = False MsgBox Err.Description GoTo Exit_obter End Function 'Mtodo 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(bkpCodCliente) Then strSql = "Update Cliente " & _ "Set codCliente = " & objCon.valorSql(codCliente) _ & ", classe = " & objCon.valorSql(classe) _ & ", cpf = " & objCon.valorSql(cpf) & ", email = " _ & objCon.valorSql(email) & ", nomeCliente = " _ & objCon.valorSql(nomeCliente) & ", renda = " _ & objCon.valorSql(renda) _ & " Where codCliente = " & objCon.valorSql(bkpCodCliente) salvar = (objCon.executa(strSql) > 0) Else salvar = incluir End If

If salvar Then 'Atualiza as variveis de backup com o novo valor da chave bkpCodCliente = codCliente End If Exit_salvar: Exit Function Err_salvar: salvar = False GoTo Exit_salvar End Function 'Mtodo calculaClasse 'Calcula a classe social do objeto atual baseado na 'renda informada e devolve uma letra correspondente ' sua classificao dentro das faixas salariais. Private Function calculaClasse() As String If renda >= 15300 Then calculaClasse = "A" ElseIf renda >= 7650 Then calculaClasse = "B" ElseIf renda >= 3060 Then calculaClasse = "C" ElseIf renda >= 1020 Then calculaClasse = "D" ElseIf renda > 0 Then calculaClasse = "E" Else calculaClasse = "" End If End Function 'Fim da classe...

Pontos Importantes Nesta primeira classe referente a um objeto atualizvel, com atributos modificveis, passveis de serem persistidos, podemos notar alguns pontos de interesse para o aprendizado da metodologia, conforme a seguir. 1. Atributos do tipo Variant: Como podemos encontrar objetos cujos campos no so de preenchimento obrigatrio devemos manter a possibilidade de atribuir valores nulos aos atributos dos objetos, os quais sero reconhecidos pelo mtodo valorSql(), da classe ConexaoBD, e convertidos da maneira correta para armazenagem na tabela. Caso utilizssemos atributos com os tipos pr-definidos no teramos como reconhecer um atributo nulo de maneira to fcil. Neste caso teramos que procurar mtodos alternativos de conveno e tratamento de valores que representariam a nulidade de atributos, como por exemplo uma seqncia de comprimento zero em uma string, ou um valor negativo que provavelmente nunca seria atribudo a um campo de cdigo para chave primria, entre outros. Contudo, para o nosso projeto, contando com a facilidade

da atribuio de valores e seus tipos s variveis do tipo Variant, e a funcionalidade do mtodo valorSql() esta ser a forma que adotaremos.'Nome completo do cliente. Private strNomeCliente As Variant

2. Criao do atributo de backup do objeto: Apesar de no ser necessrio quando se usa atributos identificadores do tipo auto-numerao, esta uma tcnica que possibilita a alterao do cdigo identificador do objeto permitindo salvar as modificaes posteriormente, j que o antigo valor, que continua armazenado no banco de dados, ainda estar disponvel no atributo de backup. Quando se usa qualquer tipo de cdigo personalizado como a chave primria este recurso torna-se indispensvel.'Atributo de backup e atributo identificador da Classe 'PK - Cdigo que identifica o cliente. Private bkpCodCliente As Variant Private lngCodCliente As Variant

3. Validao de dados no momento da atribuio do valor: Neste caso podemos visualizar na prtica como validar um dado antes de atribu-lo ao objeto. Como exemplo verificamos a validade de um CPF fornecido pelo usurio, permitindo ou no a sua utilizao. Esta uma tarefa que evita falhas de digitao e incorrees nos dados armazenados.Property Let cpf(argCpf As Variant) If Not IsNull(argCpf) Then If Not objUtil.validaCPF(argCpf) Then MsgBox "O CPF no vlido.", vbExclamation, "CPF Invlido" strCpf = Null Else strCpf = argCpf End If Else strCpf = argCpf End If End Property

4. Converso de dados no momento da atribuio do valor: Neste caso podemos visualizar na prtica como alterar um dado fornecido pelo usurio antes de atribu-lo ao objeto. Esta tarefa til na padronizao das informaes armazenadas. Como exemplo armazenamos todos os nomes dos clientes no padro de nomes prprios, com a primeira letra de cada parte do nome em maisculas e o restante em minsculas. Esta funcionalidade oferecida pelo mtodo nomeProprio() da classe Utilitario, representada pelo objeto objUtil.Property Let nomeCliente(argNomeCliente As Variant) If Not IsNull(argNomeCliente) Then strNomeCliente = objUtil.nomeProprio(argNomeCliente) Else strNomeCliente = argNomeCliente End If

End Property

5. Determinao de uma propriedade baseada em outra: Apesar de no ser uma boa prtica e estar diretamente contra as Formas Normais, esta funcionalidade foi colocada apenas para servir de exemplo. Aqui determinamos a classe social a que o cliente pertence a partir da sua renda informada. Para isto utilizamos o mtodo calculaClasse() da prpria classe Cliente. A informao atribuda propriedade classe e armazenada no banco de dados, lembrando mais uma vez que esta no uma prtica recomendada em sistemas profissionais.Property Let renda(argRenda As Variant) curRenda = argRenda 'Alterar classe quando o valor da 'renda for alterado strClasse = calculaClasse() End Property

6. Ajuste de cdigo SQL: Para que possamos montar nossas classes sem nos preocupar com o formato SQL dos dados, utilizamos a classe ConexaoBD e seus mtodos para fazer todos os ajustes e nos deixar resolver os problemas mais srios, que requerem nossa ateno. Veja que para ns no ser necessrio descobrir se o atributo e do tipo texto, data ou numrico. O mtodo valorSql() se encarrega disto. Aqui a classe est representada pelo objeto objCon.strSql = "Select * " & _ "From Cliente " & _ "Where codCliente = " & objCon.valorSql(argCodCliente)

7. Atributo classe: Para o clculo da classe social a partir da renda foi utilizada uma tabela fictcia de exemplo, a qual no representa fielmente os valores publicados pelos rgos competentes. Outra funcionalidade importante que podemos encontrar nos cdigos o tratamento de erros com a instruo On Error. Apesar de no ser detalhado neste curso altamente recomendado que o leitor pesquise e compreenda a sua utilizao. Foram colocados exemplos simples nos mtodos, porm o correto entendimento deste recurso possibilita alta capacidade de resoluo de problemas na programao, evitando que possveis e provveis erros no projeto ou na implementao sejam visveis para o usurio final de maneira inadequada. Mais Funes Auxiliares Neste projeto no utilizaremos cdigos com auto-numerao diretamente nas tabelas. Sendo assim necessitaremos de uma funo que realize esta tarefa. Criaremos ento um mdulo padro que conter todas as funes auxiliares que necessitarmos durante o curso. Ele se chamar Funcoes e nossa primeira funo ser chamada proximoCodigo().

Este ser o cdigo da funo:Function proximoCodigo(argCampo As String, argTabela As String, _ Optional criterio As String = "") As Long proximoCodigo = Nz(DMax(argCampo, argTabela, criterio), 0) + 1 End Function

Ela receber como parmetros o nome do campo, o nome da tabela e um critrio de busca opcional, devolvendo um nmero que ser o prximo cdigo livre daquele campo numrico da tabela informada. Desta maneira a funo ser genrica e servir para qualquer tabela que contenha um campo chave de cdigo numrico ordenado. A Interface Grfica Para que possamos visualizar e manipular os dados dos clientes devemos criar um formulrio com campos para preenchimento e botes de comando que coordenem as aes sobre os dados. A seguir sero definidas as caractersticas para o formulrio no qual iremos trabalhar com os dados dos objetos relativos aos clientes. As especificaes de design so apenas sugestes, porm as informaes de origem de dados, bloqueio de campos e formatos de dados so obrigatrias, sob pena de no obter a funcionalidade desejada. Estas especificaes estaro marcadas com um asterisco vermelho ao lado. No formulrio teremos uma lista contendo os clientes cadastrados, um campo de texto para realizar buscas, alguns campos de texto para digitao das informaes e os botes de comando para criar, salvar e excluir registros. Obs: Somente as propriedades que foram alteradas para um valor diferente do padro sero apresentadas. Para as demais utilize o padro do sistema ou o valor que desejar, desde que no comprometa a funcionalidade do sistema. FormulrioNome: FCliente Largura: 20cm Altura: Cabealho (1cm) / Detalhe (10cm) Legenda: Sistema de Vendas Estilo da borda: fino Seletores de registro: No Botes de navegao: No Linhas divisrias: No Barras de rolagem: Nenhuma Caixa de controle: Sim Boto Fechar: Sim Botes Min Max: Nenhum Popup: Sim Janela Restrita: No

Controle Listbox

Nome: lstCliente * Origem da linha: SELECT Cliente.codCliente, Cliente.nomeCliente, Format(Cliente.cpf,"000\.000\.000-00") AS cpf FROM Cliente ORDER BY Cliente.nomeCliente; * Tipo de Origem da Linha: Tabela/Consulta * Coluna acoplada: 1 * Nmero de colunas: 3 * Largura das colunas: 0cm;5cm;3cm * Largura: 8cm Cor do fundo: Cinza claro

Controles TextboxNome: txtPesquisa * Cor do fundo: Amarelo Alinhamento: Esquerda Nome: txtCodigo * Ativado: No * Bloqueado: Sim * Cor do fundo: Cinza Alinhamento: Centro Nome: txtCpf * Cor do fundo: Azul claro Mscara de entrada: 000.000.000\-00;;_ * Alinhamento: Centro Nome: txtNome * Cor do fundo: Azul claro Alinhamento: Esquerda Nome: txtEmail * Cor do fundo: Azul claro Alinhamento: Esquerda Nome: txtRenda * Cor do fundo: Azul claro Alinhamento: Direita Formato: Unidade Monetria Nome: txtClasse * Ativado: No * Bloqueado: Sim * Cor do fundo: Cinza Alinhamento: Centro

Botes de ComandoNome: 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 sugesto de design os campos devero estar posicionados conforme demonstrado na figura a seguir, assim como devem ser adicionadas as legendas dos campos, as quais no foram descritas anteriormente:

Cdigos do Formulrio Para que nosso formulrio seja capaz de manipular os dados dos objetos cliente deveremos implementar as funcionalidades necessrias que permitam criar um novo cliente, buscar um cliente j cadastrado, editar seus dados, salv-lo ou exclu-lo. Sendo assim criaremos algumas funes genricas que sejam teis para quantos procedimentos delas necessitem, reaplicando o conceito da reutilizao de cdigo. Alm disso incluiremos os cdigos dos campos que possuem eventos, alm dos botes de comando.Todos os cdigos a seguir devero ser colocados no mdulo do formulrio FCliente.

1. Pesquisa de clientes: Para facilitar a busca de clientes por qualquer parte do nome utilizaremos um campo de texto cujo valor ser o elemento condicional para o cdigo SQL que ser atribudo ao controle lstCliente, atualizando sua propriedade Origem da Linha aps cada alterao realizada no campo de pesquisa. Para isto devemos colocar o cdigo no evento Ao Alterar do campo txtPesquisa.Private Sub txtPesquisa_Change()

lstCliente.RowSource = "SELECT Cliente.codCliente, Cliente.nomeCliente, " & _ "Format(Cliente.cpf,'000\.000\.000-00') AS cpf " & _ "FROM Cliente " & _ "WHERE nomeCliente Like '*" & txtPesquisa.Text & "*' " & _ "ORDER BY Cliente.nomeCliente;" lstCliente.Requery End Sub

2. Limpeza dos campos: Para efetuar a limpeza dos campos de preenchimento utilizaremos um procedimento genrico cuja funo ser a de atribuir o valor nulo a todos os campos de texto e enviar o foco ao campo txtCpf.Private Sub limpaCampos() txtCodigo = Null txtCpf = Null txtNome = Null txtEmail = Null txtRenda = Null txtClasse = Null txtCpf.SetFocus End Sub

3. Novo registro: Para a criao de um novo registro em branco simplesmente iremos chamar o procedimento limpaCampos() no evento Ao Clicar do boto btnNovo.Private Sub btnNovo_Click() Call limpaCampos End Sub

4. Atualizao de campos: Assim como fizemos um procedimento genrico que limpa os campos para a criao de um novo registro teremos tambm um que preencha os campos com as informaes de um objeto cliente passadas como parmetro, ou seja, o procedimento recebe um objeto completo e lana os valores de seus atributos nos campos do formulrio.Private Sub atualizaCampos(argCliente As clsCliente) txtCodigo = argCliente.codCliente txtCpf = argCliente.cpf txtNome = argCliente.nomeCliente txtEmail = argCliente.email txtRenda = argCliente.renda txtClasse = argCliente.classe End Sub

5. Escolha de cliente: J que teremos tambm que trabalhar com clientes j cadastrados, devemos implementar alguma maneira de recuperar suas informaes. Faremos isto utilizando a Listbox lstCliente, que utilizar o procedimento

atualizaCampos() para preencher os campos com as informaes do objeto do cliente que foi clicado.Private Sub lstCliente_Click() Dim objCliente As New clsCliente Dim codigoCliente As Long codigoCliente = lstCliente.Value If objCliente.obter(codigoCliente) Then Call atualizaCampos(objCliente) End If End Sub

6. Montagem de um objeto: Esta tambm uma funo genrica que ser utilizada por outros procedimentos ou funes. Seu objetivo criar um novo objeto cliente, coletar os dados digitados nos campos, atribuir ao objeto criado, e devolv-lo para quem chamou a funo.Private Function buscaCampos() As clsCliente Set buscaCampos = New clsCliente If IsNull(txtCodigo) Then txtCodigo = proximoCodigo("codCliente", "Cliente") End If buscaCampos.codCliente = txtCodigo buscaCampos.cpf = txtCpf buscaCampos.nomeCliente = txtNome buscaCampos.email = txtEmail buscaCampos.renda = txtRenda End Function

7. Salvando um cliente: Depois de informados os dados de um novo cliente, ou alterados os dados de um cliente j cadastrado, necessitaremos de um procedimento que efetue a gravao destes dados. Para isto o boto btnSalvar conter o cdigo necessrio no evento Ao Clicar. Ele far uso da funo buscaCampos(), a qual montar o objeto a ser salvo, e tambm o mtodo salvar() do objeto, apresentando uma mensagem ao usurio com o resultado da operao. Aps salvar os dados de um cliente tambm deveremos atualizar a Listbox para que apresente estes dados, sejam eles novos ou apenas alterados.Private Sub btnSalvar_Click() Dim objCliente As clsCliente If Not IsNull(txtCpf) And Not IsNull(txtNome) Then Set objCliente = buscaCampos If objCliente.salvar Then MsgBox "O cliente foi salvo com sucesso.", vbInformation, _ "Salvar Cliente" lstCliente.Requery

Call atualizaCampos(objCliente) Else MsgBox "Ocorreu um erro durante o salvamento.", vbExclamation, _ "Salvar Cliente" End If Else MsgBox "Informe os dados do cliente.", vbExclamation, "Salvar Cliente" End If End Sub

8. Excluindo um cliente: Alm de criar e alterar os dados de um cliente, importante que tambm possamos exclu-lo definitivamente de nosso cadastro. Logo devemos tambm implementar a funcionalidade para o boto btnExcluir, que conter o cdigo necessrio tambm no evento Ao Clicar. Ele tambm dever fazer uso da funo buscaCampos() para a montagem do objeto a ser excludo, pois caso contrrio a classe no saber que objeto deve ser excludo. Em seguida utilizaremos o mtodo excluir() do objeto, apresentando uma mensagem ao usurio com o resultado da operao. claro que aps excluir um cliente tambm deveremos atualizar a Listbox para que a mesma reflita as alteraes realizadas.Private Sub btnExcluir_Click() Dim objCliente As clsCliente If Not IsNull(txtCodigo) Then If MsgBox("Confirma a excluso do registro?", vbQuestion + vbYesNo, _ "Excluir Cliente") = vbYes Then Set objCliente = buscaCampos If objCliente.excluir Then MsgBox "O registro foi excludo com sucesso.", vbInformation, _ "Excluir Cliente" lstCliente.Requery Call limpaCampos Else MsgBox "Ocorreu um erro durante a excluso.", vbExclamation, _ "Excluir Cliente" End If End If End If End Sub

Estes so os procedimentos e funes bsicas para que a interface possa manipular os objetos. No se esquea de que para efetuar os testes deveremos utilizar um CPF vlido devido verificao realizada. Sistema de Exemplo

A partir deste artigo ser disponibilizado o link para download do sistema de vendas no estado de desenvolvimento em que se encontrar o projeto. Recomendo aos estudiosos desenvolvedores que o consultem apenas para tirar dvidas e realizar comparaes. Aqueles que realmente quiserem aprender faam toda a codificao e a montagem das telas manualmente. Somente assim a sua mente ir se defrontar com as dificuldades do processo e assimilar os passos necessrios para a resoluo dos problemas e a concluso dos objetivos. Segue o link para download:Venda00.zip

Como ainda no h uma tela principal abra o formulrio FCliente diretamente na janela Banco de Dados (Access 2003-) ou no Painel de Navegao (Access 2007+). Concluso Enfim demos incio parte mais empolgante do curso, na qual podemos ver o sistema realmente operando, manipulando os objetos. Pudemos ver como se d a interao entre objetos, a verificao de atributos, a montagem de cdigos SQL para busca, alterao, insero e excluso de dados, alm de visualizar procedimentos simples de tratamento de erros. Nunca demais relembrar que o objetivo maior de todas as etapas do curso apresentar de forma didtica, da maneira mais simples possvel, a utilizao de objetos em projetos do Access/VBA. Sendo assim no considere as implementaes apresentadas como o padro de fato da programao. Muita coisa foi simplesmente omitida ou modificada, mesmo partindo dos prprios padres que utilizo em meus projetos reais para que fosse alcanada a objetividade necessria ao entendimento por parte de usurios iniciantes ou com pouca experincia na POO. A lio mais importante deste artigo foi realmente a visualizao da dinmica da utilizao dos objetos na manipulao de informaes, tanto na sua apresentao quanto na sua persistncia. A partir deste momento, creio, ficar cada vez mais fcil a percepo da operao com objetos, desde que o leitor compreenda bem o que foi visto at agora, pois estes conceitos iniciais so a base da orientao a objetos. Apesar de no contarmos com as outras faces da OO, como a herana por exemplo, com certeza a mente do leitor j comear a visualizar melhor as infinitas possibilidades que a metodologia fornece. Porm relembro que para conseguir dominar a tcnica imprescindvel continuar treinando, criando seus prprios cdigos, fazendo experincias, resolvendo problemas com a aplicao do paradigma, lendo outros materiais e compartilhando conhecimento, seja com colegas de trabalho, amigos ou em fruns sobre o assunto. No prximo artigo, que ser muito parecido com este, faremos a implementao da classe Produto, com sua respectiva interface grfica. Isto ajudar a massificar os conhecimentos adquiridos nesta etapa, pois tudo ser relembrado.

At o prximo...

Utilizando Classe no Access - A Classe ProdutoPor: Plinio Mabesi [email protected] Ago / 2010 Continuando a incluso de funcionalidade em nosso sistema vamos agora ao prximo passo. A prxima classe a ser codificada ser a classe Produto. Aps apresentar a estrutura da classe faremos a implementao da interface grfica que manipular os dados dos objetos. Mais uma vez, caso necessrio, relembre os conceitos anteriores sobre atributos, mtodos, acesso s propriedades do objeto, instncias e demais ensinamentos sobre a programao orientada a objetos, vistos nos primeiros artigos. A Classe Produto O objetivo desta classe, conforme dito anteriormente, oferecer funcionalidades de incluso, consulta, atualizao e excluso dos objetos do tipo produto. Este o cdigo da classe, com todos os seus atributos e mtodos, que se utilizam de funes prprias, bem como dos mtodos do objeto da classe ConexaoBD. Cdigo da classe:Option Compare Database Option Explicit 'Atributos da Classe 'Atributo de backup e atributo identificador da Classe 'PK - Cdigo que identifica o produto. Private bkpCodProduto As Variant Private lngCodProduto As Variant 'Descrio do produto. Private strDescricao As Variant 'Quantidade mnima desejada no estoque. Private dblEstoqueMinimo As Variant 'Quantidade atual do estoque. Private dblQtdEstoque As Variant 'Unidade de comercializao do produto. Private strUnidade As Variant 'Valor unitrio do produto. Private curValorUnitario As Variant

'Mtodos 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 'Mtodo Existe [Com conhecimento de SQL] 'Verifica a existncia 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 'Mtodo 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 'Mtodo 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 'Mtodo Obter [Com conhecimento de SQL] 'Recupera o objeto Produto atravs 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 'Mtodo 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 variveis 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 'Mtodo baixarEstoque() 'Atualiza o estoque diminuindo a quantidade informada como parmetro 'e devolve um valor booleano que indica o sucesso da operao; 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 'Mtodo subirEstoque() 'Atualiza o estoque acrescentando a quantidade informada como 'parmetro e devolve um valor booleano que indica o sucesso 'da operao; Function subirEstoque(argQtd As Double) As Boolean dblQtdEstoque = dblQtdEstoque + Abs(argQtd) subirEstoque = salvar End Function 'Mtodo estoqueBaixo 'Verifica o estoque atual e compara com o valor de estoque mnimo '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 possvel diminuir a quantidade informada, pois seria impossvel retirar mais do que a

quantidade existente em estoque. Alm disso, no podemos baixar quantidades negativas de produto, pois isto significa que estaramos aumentando a quantidade ao invs de diminuir. O mtodo somente retornar True se for possvel realizar a operao.Function baixarEstoque(argQtd As Double) As Boolean If dblQtdEstoque - Abs(argQtd) 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 'Mtodo Incluir [Com conhecime