... Pague apenas R$47,00 uma única vez e tenha acesso por 1 ano aos vídeos e arquivos exemplos do site ...

Clique aqui e obtenha mais detalhes.


Utilizando Classe no Access - As Classes Auxiliares

Por: Plinio Mabesi
 

No último artigo vimos a modelagem do sistema. Agora chegou a hora de começarmos a codificar nossas primeiras classes.

As classes auxiliares serão responsáveis por realizar tarefas genéricas que atendem a solicitações de diversas outras classes ou mesmo outros módulos do sistema.

Poderíamos criar inúmeras classes auxiliares, com funções agrupadas pelo tipo de tarefa a ser realizada, assim como a classe ConexaoBD que trata de questões de conexão com banco de dados e a classe Utilitario que contempla funções de validação e conversão de dados.

A idéia principal aqui é a reutilização de código, um dos pilares da orientação a objetos.   Percebam que nós codificaremos a classe ConexaoBD apenas uma única vez em toda a nossa vida.   No próximo 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 codificação será única e praticamente eterna.

Vamos então rever a descrição de cada classe. Em seguida faremos a codificação.  O código das funções será apresentado apenas com comentários mas sem detalhamento, já que (novamente) a criação de algoritmos e a estruturação de procedimentos e funções não é o foco deste curso.

A Classe Utilitario

Objetivo: oferecer funcionalidades de validação de dados e transformação de valores, necessárias para o correto funcionamento da classe Cliente, ou qualquer outra classe ou função que venha a precisar dela, a qualquer momento.  Isto se deve ao fato da classe possuir métodos genéricos e reutilizáveis, podendo ser reaproveitados, sem nenhuma alteração, em qualquer sistema.

Método validaCpf(argCpf As String) As Boolean: recebe como argumento um texto contendo um CPF, sem pontos nem traço, e devolve um valor booleano, verdadeiro ou falso, indicando se o CPF é ou não válido;

Function validaCPF(argCpf As String) As Boolean
'Função que verifica a validade de um CPF.
   
    Dim wSomaDosProdutos
    Dim wResto
    Dim wDigitChk1
    Dim wDigitChk2
    Dim wStatus
    Dim wI
    
    'Inicia o valor da Soma
    wSomaDosProdutos = 0
    
    'Para posição I de 1 até 9
    For wI = 1 To 9
        'Soma = Soma + (valor da posição dentro do CPF x (11 - posição))
        wSomaDosProdutos = wSomaDosProdutos + Val(Mid(argCpf, wI, 1)) * (11 - wI)
    Next wI
    
    'Resto = Soma - ((parte inteira da divisão da Soma por 11) x 11)
    wResto = wSomaDosProdutos - Int(wSomaDosProdutos / 11) * 11
    'Dígito 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 posição I de 1 até 9
    For wI = 1 To 9
        'Soma = Soma + (valor da posição dentro do CPF x (12 - posição))
        wSomaDosProdutos = wSomaDosProdutos + (Val(Mid(argCpf, wI, 1)) * (12 - wI))
    Next wI
    
    'Soma = Soma (2 x dígito verificador 1)
    wSomaDosProdutos = wSomaDosProdutos + (2 * wDigitChk1)
    
    'Resto = Soma - ((parte inteira da divisão da Soma por 11) x 11)
    wResto = wSomaDosProdutos - Int(wSomaDosProdutos / 11) * 11
    'Dígito 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 dígito da posição 10 = Dígito verificador 1 E
    'dígito da posição 11 = Dígito verificador 2 Então
    If Mid(argCpf, 10, 1) = Mid(Trim(Str(wDigitChk1)), 1, 1) And _
    Mid(argCpf, 11, 1) = Mid(Trim(Str(wDigitChk2)), 1, 1) Then
        'CPF válido
        validaCPF = True
    Else
        'CPF inválido
        validaCPF = False
    End If
    
End Function

Método 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 não válido, sendo que a verificação é feita apenas no seu formato;

Function validaEmail(eMail As String) As Boolean
'Função de validação do formato de um e-mail.

    Dim posicaoA As Integer
    Dim posicaoP As Integer

    'Busca posição do caracter @
    posicaoA = InStr(eMail, "@")
    'Busca a posição do ponto a partir da posição
    'do @ ou então da primeira posição
    posicaoP = InStr(posicaoA Or 1, eMail, ".")
    
    'Se a posição do @ for menor que 2 OU
    'a posição do ponto for menor que a posição
    'do caracter @
    If posicaoA < 2 Or posicaoP < posicaoA Then
        'Formato de e-mail inválido
        validaEmail = False
    Else
        'Formato de e-mail válido
        validaEmail = True
    End If

End Function

Método nomeProprio(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com as inicias dos nomes em maiúsculas e o restante em minúsculas, levando em consideração as partículas de ligação de nomes, as quais permanecem em minúsculas;

Function nomeProprio(argNome As String) As String
'Função recursiva para converter a primeira letra
'dos nomes próprios para maiúscula, 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 função ou a recursão
    'retornando string vazia
    If lTamanho = 0 Then
        nomeProprio = ""
    Else
        'Procura a posição do primeiro espaço
        lEspaco = InStr(argNome, " ")
        'Se não tiver pega a posição da última letra
        If lEspaco = 0 Then lEspaco = lTamanho
        'Pega o primeiro nome da string
        sNome = Left(argNome, lEspaco)
        'Se não 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 através da recursão
        nomeProprio = sNome & nomeProprio(LCase(Trim(Right(argNome, lTamanho - lEspaco))))
    End If
    
End Function

Método desacentua(argTexto As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto sem acentos ou símbolos;

Function desacentua(ByVal argTexto As String) As String
'Função que retira acentos de qualquer texto.

    Dim strAcento As String
    Dim strNormal As String
    Dim strLetra As String
    Dim strNovoTexto As String
    Dim intPosicao As Integer
    Dim i As Integer

    'Informa as duas sequências de caracteres, com e sem acento
    strAcento = "ÃÁÀÂÄÉÈÊËÍÌÎÏÕÓÒÔÖÚÙÛÜÝÇÑãáàâäéèêëíìîïõóòôöúùûüýçñ"
    strNormal = "AAAAAEEEEIIIIOOOOOUUUUYCNaaaaaeeeeiiiiooooouuuuycn"
    'Retira os espaços antes e após
    argTexto = Trim(argTexto)
    
    'Para i de 1 até o tamanho do texto
    For i = 1 To Len(argTexto)
        
        'Retira a letra da posição atual
        strLetra = Mid(argTexto, i, 1)
        'Busca a posição da letra na sequência com acento
        intPosicao = InStr(1, strAcento, strLetra)
        
        'Se a posição for maior que zero
        If intPosicao > 0 Then
            'Retira a letra na mesma posição na
            'sequência 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

Método abreviaNome(argNome As String) As String: recebe como argumento um texto qualquer e devolve o mesmo texto com a penúltima parte do nome abreviada, levando em consideração as partículas de ligação de nomes, as quais permanecem inalteradas.

Function abreviaNome(argNome As String) As String
'Função que abrevia o penúltimo sobrenome, levando
'em consideração os aditivos de, da, do, dos, das, e.
    
    'Define variáveis para controle de posição e para as
    'partes do nome que serão 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 posição do último e do penúltimo
    'espaços, 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 não podemos
    'abreviar o nome
    If i = 0 Then
        abreviaNome = argNome
        Exit Function
    End If
     
    'Separação das partes do nome em três: 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
    'não é um dos nomes de ligação: de, da ou do. Caso seja usamos o método
    'recursivo para refazer os passos.
    'Caso seja necessário basta acrescentar outros nomes de ligação 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 atualização do banco de dados. Possui também métodos genéricos que podem ser reaproveitados em qualquer sistema. Uma das maiores vantagens de se utilizar uma classe de conexão é que no caso de mudança 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 comunicação dos métodos. Um exemplo seria a troca do back-end para MySql, Postgres ou Sql Server.

Declaração de Atributo de Banco de Dados a Nível de Classe

Criaremos um atributo que será responsável por receber e disponibilizar o banco de dados para ser utilizado pelos métodos da classe.

'Cria um database que será utilizado para toda a classe
Private db As Database

Função logicoSql(ByVal argValor As Boolean) As String: recebe como parâmetro um valor booleano e devolve um texto contendo os valores True ou False, necessário para códigos SQL;

Function logicoSql(ByVal argValor As Boolean) As String
'Função que troca os valores lógicos Verdadeiro/Falso
'para True/False para utilização em consultas SQL

    'Se o valor for verdadeiro
    If argValor Then
        'Troca por True
        logicoSql = "True"
    Else
        'Senão troca por False
        logicoSql = "False"
    End If

End Function

Função pontoVirgula(ByVal varValor As Variant) As String: recebe como parâmetro um valor decimal em que o padrão de separação da parte inteira e a decimal é a vírgula, e devolve um texto contendo o mesmo valor agora separado por ponto, necessário para códigos SQL;

Function pontoVirgula(ByVal varValor As Variant) As String
'Função que troca a vírgula de um valor decimal por
'um ponto para utilização em consultas SQL

    Dim strValor As String
    Dim strInteiro As String
    Dim strDecimal As String
    Dim intPosicao As Integer

    'Converte o valor em string
    strValor = CStr(varValor)
    
    'Busca a posição da vírgula
    intPosicao = InStr(strValor, ",")

    'Se há uma vírgula em alguma posição
    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 vírgula
        pontoVirgula = strInteiro & "." & strDecimal
    Else
        'Senão devolve o mesmo valor
        pontoVirgula = strValor
    End If

End Function

Função dataSql(ByVal argData As Date) As String: recebe como parâmetro uma data em qualquer formato e devolve um texto contendo a data no padrão #mm/dd/yyyy#, necessário para códigos SQL;

Function dataSql(ByVal argData As Date) As String
'Função 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, mês e ano
    strDia = Day(argData)
    strMes = Month(argData)
    strAno = Year(argData)
    
    'Remonta no formato adequado
    dataSql = "#" & strMes & "/" & strDia & "/" & strAno & "#"
    
End Function

Função valorSql(ByVal argValor As Variant) As String: recebe como parâmetro um valor qualquer, verifica o seu formato e devolve um valor no formato padrão dos códigos SQL, fazendo uso das funções anteriores, caso necessário;

Function valorSql(ByVal argValor As Variant) As String
'Função que formata valores para utilização
'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 vírgula por ponto
        Case vbSingle, vbDouble, vbDecimal, vbCurrency
            valorSql = pontoVirgula(argValor)
        'Caso seja data chama a função dataSql()
        Case vbDate
            valorSql = dataSql(argValor)
        'Caso seja string acrescenta aspas simples
        Case vbString
            valorSql = "'" & argValor & "'"
        'Caso seja lógico chama a função logicoSql()
        Case vbBoolean
            valorSql = logicoSql(argValor)
    End Select

End Function

Função executa(codigoSql As String) As Long: recebe como argumento um texto contendo um código SQL de inserção, exclusão ou alteração, executa o código e devolve o número de registros afetados na operação;

Function executa(codigoSql As String) As Long
On Error GoTo Err_executa
'Atualiza dados no Banco utilizando o código Sql passado à função,
'retornando o número de registros afetados caso a operação 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

Função consulta(codigoSql As String, Optional editavel As Boolean = False) As Recordset: recebe como argumento um texto contendo um código SQL de consulta de registros e um valor lógico que define o modo de bloqueio de execução, permitindo ou não a edição dos dados durante a operação, e devolve um recordset contendo o conjunto de registros que atenderem aos critérios;

Function consulta(codigoSql As String, Optional editavel As Boolean = False) As Recordset
On Error GoTo Err_consulta
'Consulta os dados no Banco utilizando o código Sql passado à função,
'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

Após criar os métodos salve as classes, mas não se esqueça que para salvar convencionamos que seria utilizado o prefixo acl para classes auxiliares. Então salvaremos as classes com os nomes aclUtilitario e aclConexaoBD.

Instanciação dos Objetos

Com as classes já codificadas e salvas podemos instanciá-las a partir de qualquer módulo do nosso aplicativo. Vamos fazer um teste com cada uma das classes criadas. Para isto voltaremos ao nosso módulo padrão 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 método da classe, convertendo um
    'nome em minúsculas para o padrão de nomes próprios
    'com a primeira letra maiúscula
    MsgBox objUtil.nomeProprio("plinio mabesi")

End Sub

Perceba que após digitarmos o ponto depois do nome do objeto os métodos disponíveis são listados no menu suspenso do editor do VBA.

Editor do VBA

Com isso você pode digitar o nome do método ou escolher um deles na lista suspensa. Conforme já vimos antes para executar o código basta posicionar o cursor dentro do procedimento e pressionar F5, ou F8 para acompanhar a execução passo-a-passo.

O resultado será uma caixa de mensagem exibindo o nome informado no formato de um nome próprio, com as iniciais maiúsculas:

Classe Access 2007/2010

Agora a classe ConexaoBD. Vamos criar o procedimento TesteConexao:

Sub TesteConexaoBD()

    'Declarando o objeto da classe ConexaoBD
    Dim objCon As New aclConexaoBD

    'Testando um método da classe, convertendo
    'uma data para o padrão SQL
    MsgBox objCon.dataSql("12/06/10")

End Sub

Assim como no objeto da classe Utilitario, ao digitarmos o ponto após o nome do objeto da classe ConexaoBD veremos a lista suspensa com os métodos disponíveis:

Editor do VBA

Com certeza você notou que o atributo db (Database) não foi apresentado, devido ao fato de ser um atributo privado (Private).

Perceba também que quando digitamos o primeiro parêntese após o nome do método o editor do VBA nos mostra quais são os parâmetros exigidos, o seu tipo e o tipo de dado de retorno do método.

No caso do método dataSql() deveremos informar o parâmetro argData que será passado por valor (ByVal) e é do tipo Date, e teremos como retorno uma String. Veja:

Classe Access 2007/2010

Ao executarmos este procedimento teremos como resultado uma caixa de mensagem exibindo a data informada no padrão de utilização do SQL, conforme figura abaixo.

Classe Access 2007/2010

No padrão SQL veja que o mês vem em primeiro lugar, seguido pelo dia e depois pelo ano, tudo delimitado pela cerquilha. Todos os códigos SQL devem estar com as datas neste formato, caso contrário ocorrerá um erro e o código não será executado.

Você não só pode como deve fazer testes com os outros métodos. Crie exemplos de utilização para cada um deles. Se encontrar dificuldade aguarde os próximos artigos, nos quais faremos uso intenso destas duas classes. Mesmo assim o melhor é nunca desistir...

Conclusão

Nosso sistema começa a tomar forma de um software de verdade. Nesta etapa vimos como codificar as classes auxiliares e tivemos uma noção de como instanciá-las para utilizar os métodos disponibilizados.

Apesar de não ter sido detalhada a criação da estrutura dos comandos e dos algoritmos dos métodos, os comentários o ajudarão a compreender o mínimo necessário para produzir seus próprios códigos. Caso não tenha entendido algum trecho pesquise sobre as funções, comandos e tipos utilizados.

Conforme salientado no início deste artigo, o principal conceito que deve ser lembrado no momento é o da reutilização de código.   A reutilização se refere a qualquer procedimento, função ou método que possa ser diretamente empregado em qualquer projeto imediatamente, sem necessidade de ajuste ou adaptação. Com a orientação a objetos procuramos fazer isto com classes inteiras. As classes Utilitario e ConexaoBD são dois exemplos de classes reutilizáveis que não requerem qualquer modificação para funcionarem em um projeto do Access.

Claro que alguém poderia dizer que estaria faltando um ou outro método ou atributo, ou que na verdade os métodos existentes não são os melhores, mas o importante no momento é o conceito da reutilização e não a modelagem mais eficiente e mais correta. Entenda que após projetar a classe mais perfeita possível e codificá-la, então ela poderá ser distribuída para ser importada e incorporada por qualquer projeto.

Em nossa próxima etapa poderemos enfim ver o sistema de vendas funcionando pela primeira vez, pois iremos implementar a classe Cliente, bem como a interface gráfica para cadastro e manuseio dos dados, tudo isto sem campos acoplados, apenas usando os objetos da classe.

Até lá então...


 

 


12 comentários

Márcio Melo - Rio de Janeiro/RJ   17/06/2010 22:47:45

Material nota 10, muito show, parabéns por pensar nessas funçoes, quem trabalhar com OO vai precisar muito, isso mostrar um trabalho completo e maduro, cada vez o site vai se tornando forte referência no access avançado...

Sou mais Brasil!

Américo   18/06/2010 16:42:57

Show de bola.

Tem uma aplicação feita para ilustrar um livro (Desenvolvendo Aplicativos Com Visual Basic e Uml) que usa conceitos de programação orientada a objetos, com uma GUI web. Praticamente tudo que foi implementado nesses exemplos pode ser importado e adaptado para VBA. Os fontes estão em: http://www.jacksonreed.com/VBUML.HTM.

Obs.: Para visualizar o projeto completo é necessário o VB6 instalado.

João Martins/Joinville/SC   19/06/2010 21:46:55

Parece-me que a parceria de Avelino e o Profº Plinio esta produzindo resultados positivos e quiçá seja duradoura; tenho aprendido muito. Visionários e vencedores se destacam assim: - compartilhando seus conhecimentos, pois de nada servem enclausurados nas suas cabeças.
Parabéns aos dois!
Falou Access, falou www.usandoaccess.com.br

Rodrigo Monteiro   20/06/2010 12:37:56

Caríssimo Plinio......
Meus parabéns por sua disposição em compratilhar conhecimento....
Fiquei muito interessado na função "nomeProprio"......
Mas não consegui aplicá-la numa caixa de texto..... tentei assim no evento "ao atualizar": Campo=nomeProprio(Campo)
Poderia me dizer como pode ser usada essa função?!
Desde já agradeço muito!!!

Plinio Mabesi - Anápolis-GO   20/06/2010 12:59:31

Olá Rodrigo

Obrigado a vc e a todos que nos prestigiam...

Se vc colocar esta função em um módulo padrão (que não seja de classe nem de formulário) vc poderá fazer exatamente desta maneira que fez, porém coloque no evento Após Atualizar.

Renato Novelli   23/06/2010 10:46:46

Exceleeeeente artigo! Muito obrigado por compartilhar com todos essa valiosíssima informação.
Será de muita utilidade para o desenvolvimento de minhas aplicações.
Esse tipo de material é realmente muito útil e valoriza em muito o trabalho dos desenvolvedores de aplicações em Access.
Estou ansioso para ver o próximo artigo!
Parabéns!

Gilson Gindre   24/06/2010 07:35:09

Plinio, fiquei sem palavras, não sei como agradecer seu tamanho esforço para com todos nós da area !
para se ter uma ideia eu já estou programando em Php MySql, mas a paixão pela facilidade do access fala mais alto, e agora com estes recuros todos, estou sem palavras para agradecer você e o Avelino, e parabens pelo site, que veio para ficar !

Ader Santos   06/10/2010 13:27:21

Grande Plínio, sucesso total! Só tem uma coisinha, na função nomeProprio, falta fechar um bloco com End If, senão dá "tipos incompatíveis" no Access 2007. Abração.

Plinio Mabesi   09/10/2010 16:05:37

Olá Ader

Primeiramente muito obrigado.

Sobre o erro não encontrei nenhum bloco faltando o fechamento com End If. Utilizo o Access 2007 para montar todos os exemplos, salvando em formato anterior, e até o momento não tive nenhum problema deste tipo.

Se puder verificar novamente seu código para ver se o erro está em outro local e me avisar, agradeço. Caso não encontre o problema e queira me mandar o bd com o trecho que está dando erro estarei a disposição.

Até mais...

Alex Sandro Risso   04/03/2011 14:46:11

MUITO OBRIGADO

Agradeço deveras as explicações, tornado essa fonte ama ajuda grandiosa para os iniciantes como eu

Obrigado!

Alex Sandro Risso   04/03/2011 14:46:32

MUITO OBRIGADO

Agradeço deveras as explicações, tornado essa fonte ama ajuda grandiosa para os iniciantes como eu

Obrigado!

Marcos_Novack   22/04/2011 18:54:44

Sem duvida muito bom os ensinamentos

Notei que, no testeUtilitario() foi trocado o inicio do nome da classe, de "cls" para "acl"

nos testes anteriores começava com "cls"; notei porque deu erro.

obrigado.


Envie seu comentário: