VBBBR - Visual Basic Bem Básico Revisitado


Que tal rever alguns conceitos bem básicos de aplicações para banco de dados usando VB ? Dê uma olhada na relação de funcionalidades , quem sabe você não aprende algo novo...

Neste artigo irei rever alguns conceitos básicos utilizados em uma aplicação para banco de dados que usa um banco de dados Access e usa a técnica de Recordset Desconectado da ADO. Acompanhando este artigo você vai aprender a  :

O projeto é uma agenda de contatos e possui somente dois formulários , que estão exibidos a seguir, e , um modulo bas.

Vamos começar espiando o módulo .bas:

1- A seção de declarações gerais do módulo possui as seguintes declarações:

Perceba que você deve incluir referências as bibliotecas de acesso aos dados e também a ADOX para poder criar o banco de dados e as tabelas.

Microsoft Scripting Runtime - FileSystemObject
Microsoft ADO Ext. for DDL and Security - ADOX
Microsoft ActiveX Data Object 2.x Library - ADO
 
Option Explicit

'Incluir as seguintes referencias no seu projeto
'*********************************************************
'Microsoft Scripting Runtime
'Microsoft ADO Ext. for DDL and Security
'Microsoft ActiveX Data Object 2.x Library
'Microsoft DataBinding collection
'*********************************************************
'ADOX para criar o banco de dados
'Vinculação de dados usando ADO e recordset desconectados
'*********************************************************
'Define uma estrutura de dados referente as informações dos contatos
Public Type UserDefContatos
    strNome As String
    strEmpresa As String
    strEndereco As String
    strCidade As String
    strEstado As String
    strCep As String
End Type
Public Clientes As ADOX.Catalog
Public strArquivo As String
Public strConn As String
Aqui estou definindo uma estrutura chamada UserDefContatos que representa a estrutura da tabela Contatos

Estou definindo a variável Clientes como do tipo Catalog. Esta variável será usada para criar o banco de dados Clientes.mdb

Defini também as variáveis :

strArquivo que irá representa o caminho do banco de dados

strConn que representa a string de conexão com o banco de dados

O módulo .bas possui a rotina CriaDB que irá criar um novo banco de dados chamado clientes.mdb

'Se o banco de dados não existir cria um banco de dados Access 2000 chamado Clientes.mdb
Public Sub CriaDB()
    Set Clientes = New ADOX.Catalog
    Clientes.Create strConn
End Sub

Outra rotina importante do módulo .bas e a rotina CriaTabela que cria a tabela contatos com a seguinte estrutura :

Na rotina CriaTabela abaixo estamos definindo a estrutura da tabela criada e a chave primária também. Note que ao final da definição eu estou anexando a tabela Contatos a coleção de tabelas do banco de dados via comando:     Clientes.Tables.Append tbl

Todas estas operações são feitas usando a ADOX.

'Cria a tabela
Public Sub CriaTabela()
    Dim tbl As ADOX.Table
    Dim key As ADOX.key

    Set tbl = New ADOX.Table
    'TableName.Columns.Append "ColumnName" é um método ADOX
    'para criar colunas na tabela
    With tbl
        Set .ParentCatalog = Clientes
        .Name = "Contatos"
        .Columns.Append "Nome", adVarWChar, 50
        .Columns.Append "Empresa", adVarWChar, 50
        .Columns("Empresa").Attributes = adColNullable
        .Columns.Append "Endereco", adVarWChar, 50
        .Columns("Endereco").Attributes = adColNullable
        .Columns.Append "Cidade", adVarWChar, 50
        .Columns("Cidade").Attributes = adColNullable
        .Columns.Append "Estado", adVarWChar, 20
        .Columns("Estado").Attributes = adColNullable
        .Columns.Append "Cep", adVarWChar, 12
        .Columns("Cep").Attributes = adColNullable
        'para o exemplo vou usar o nome como chave , mas o correto é usar um valor numerico (Codigo)
        .Keys.Append "PrimaryKey", adKeyPrimary, "Nome"
    End With
    'inclui a tabela no banco de dados .mdb
    Clientes.Tables.Append tbl
End Sub

A última rotina do módulo é a função existeDB que verifica se a pasta Dados existe . Se a pasta não existir o programa cria a pasta. Estas operações são feitas pelo FileSystemObject do VB

'Verifica se o arquivo de banco de dados existe em App.Path & "\Dados\"
'Retorna True o arquivo existir
Public Function existeDB() As Boolean
    
    Dim fso As FileSystemObject
    Dim pasta As String   
    'cria o objeto fso do tipo FileSystemObject
    Set fso = CreateObject("Scripting.FileSystemObject")    
    'define o caminho da pasta
    pasta = App.Path & "\Dados"

    'verifica se a pasta \Dados existe , senão existir entao cria
    If Not (fso.FolderExists(pasta)) Then
        fso.CreateFolder (pasta)
    End If    
    existeDB = fso.FileExists(strArquivo)
End Function

É importante saber a sequência de eventos que irão ocorrer quando a aplicação for executada. O que vai ser executado primeiro ?

No menu Project|Project Properties , olhando na guia General , vemos que Startup Object esta definido como frmcontatos. Logo este formulário será carregado primeiro quando da execução da aplicação.

E o acontece depois ?

Quando o formulário frmcontatos for carregado o evento Load será o primeiro que será executado no código usado. Então acontece o seguinte :

  1. Verificamos se o banco de dados existe usando a rotina existeDB

  2. Se o banco de dados não existir iremos chamar as rotinas : CriaDB e CriaTabela

O código do evento Load do formulário frmcontatos é mostrado a seguir com comentários :

O recordset desconectado é criado pelo código:

    'Cria um recordset desconectado
    'depois pega os registros

    Set rsContatos.ActiveConnection = Nothing
     cnContatos.Close

Private Sub Form_Load()
    Dim blnArquivoExiste As Boolean
    Dim strNomeDB As String    
    strNomeDB = "Clientes.mdb"      'nome do banco de dados a ser usado    
    'strArquivo e strConn são declaradas no modulo modCriaDatabase.bas
    'em um ambiente cliente/servidor, o caminho do bd estara no servidor
    'neste exemplo modifiquei para rodar na maquina local    
    strArquivo = App.Path & "\Dados\" & strNomeDB
    strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strArquivo & ";"    
    blnArquivoExiste = existeDB()        'verifica se o banco de dadaos Contatos.mdb existe    
    If blnArquivoExiste = False Then
        intResposta = MsgBox(strArquivo & " não existe e será criado.", vbInformation + vbOKCancel)
        If intResposta = vbCancel Then Unload Me
        Call CriaDB                         'se o arquivo nao existe cria (.mdb)
        Call CriaTabela                    'cria tabela Contatos
    End If    
    Set cnContatos = New ADODB.Connection       'usa conexao ADO
    Set rsContatos = New ADODB.Recordset         'e recordset ADO    
    If cnContatos.State = adStateClosed Then    'o arquivo recém criado deve ser aberto
        cnContatos.CursorLocation = adUseClient  'cria o cursor do lado do cliente
        cnContatos.Open strConn                       'verifica antes de abrir
    End If    
    rsContatos.Open "SELECT * FROM Contatos ORDER BY Nome", cnContatos, adOpenStatic,_
 adLockBatchOptimistic, adCmdText        
    'preenche a combobox com nomes
    Do Until rsContatos.EOF
        If Not IsNull(rsContatos!Nome) Then cboNome.AddItem rsContatos!Nome
        rsContatos.MoveNext
    Loop    
    'data binding - na vincula cboNome para habilitar a procura
    Set txtEmpresa.DataSource = rsContatos
    txtEmpresa.DataField = "Empresa"
    Set txtEndereco.DataSource = rsContatos
    txtEndereco.DataField = "Endereco"
    Set txtCidade.DataSource = rsContatos
    txtCidade.DataField = "Cidade"
    Set txtEstado.DataSource = rsContatos
    txtEstado.DataField = "Estado"
    Set txtCep.DataSource = rsContatos
    txtCep.DataField = "Cep"    
    If cboNome.ListCount > 0 Then
        rsContatos.MoveFirst
        cboNome.Text = rsContatos!Nome
    End If  
    DoEvents
    'Cria um recordset desconectado
    'depois pega os registros
    Set rsContatos.ActiveConnection = Nothing
    cnContatos.Close
    
    blnUpdated = True
End Sub

Vejamos a seção General Declarations do formulário :

Option Explicit
'Incluir as seguinets referencias no projeto
'Microsoft Scripting Runtime
'Microsoft ADO Ext. for DDL and Security
'Microsoft ActiveX Data Object 2.x Library
'Microsoft DataBinding collection
'define o objeto connection e recordset
Dim cnContatos As ADODB.Connection
Dim rsContatos As ADODB.Recordset
Dim umRegistro As UserDefContatos
Dim blnAdd As Boolean           'define como true se esta incluindo
Dim blnEdit As Boolean          'define como true se esta editando
Dim blnUpdated As Boolean       'define como true se as mudanças foram escritas no banco de dados
Dim blnExiting As Boolean       'define como true se estive encerrando aplicação
Dim strProcura As String
Dim strEditaReg As String
Dim vntBookMark As Variant
Dim intResposta As Integer
'define uma enumeração para cada acão dos botões
'os botões são um array de controle assim temos o mesmo nome para cada botão com indice iniciando em zero
'cmdbutton(0)=Botao Excluir cmdbutton(1)=botão cancelar e assim por diante...
Private Enum cmdButtons
    DeleteButton = 0
    CancelButton = 1
    EditButton = 2
    SaveButton = 3
    AddNewButton = 4
    ExitButton = 5
    MoveFirstButton = 6
    MovePreviousButton = 7
    MoveNextButton = 8
    MoveLastButton = 9
End Enum

 

definimos as variáveis que irão controlar as operações feitas no banco de dados :

Dim blnAdd As Boolean             'define como true se esta incluindo
Dim blnEdit As Boolean             'define como true se esta editando
Dim blnUpdated As Boolean       'define como true se as mudanças foram escritas no banco de dados
Dim blnExiting As Boolean         'de
fine como true se estive encerrando aplicação

definimos as enumerações de forma a tornar o código mais claro quando usamos o SELECT/CASE para quando o usuário clicar nos botões de comando:

'define uma enumeração para cada acão dos botões
'os botões são um array de controle assim temos o mesmo nome para cada botão com indice iniciando em zero
'cmdbutton(0)=Botao Excluir cmdbutton(1)=botão cancelar e assim por diante...
Private Enum cmdButtons
    DeleteButton = 0
    CancelButton = 1
    EditButton = 2
    SaveButton = 3
    AddNewButton = 4
    ExitButton = 5
    MoveFirstButton = 6
    MovePreviousButton = 7
    MoveNextButton = 8
    MoveLastButton = 9
End Enum

A reabertura da conexão e a atualização dos dados no banco de dados é feita quando o usuário clicar o botão - cmdAtualizaEmLote - o trecho de código que faz isto é :

cnContatos.Open                                                           're-abre a conexao
Set rsContatos.ActiveConnection = cnContatos     're-conecta com o recordset
rsContatos.UpdateBatch

A combobox é carregada com o nome do contato usando o código abaixo:

'preenche a combobox com nomes
Do Until rsContatos.EOF
   If Not IsNull(rsContatos!Nome) Then cboNome.AddItem rsContatos!Nome
   rsContatos.MoveNext
Loop

o texto das caixas de texto e da combobox é limpo usando o seguinte código :

Public Sub limpaTexto()
   'limpa o texto dos controles vinculados
    Dim i As Integer    
   'percorre a coleção com os controles do formulario
    For i = 1 To Me.Controls.Count - 1
        'se o controle for do tipo texbox então limpa
        If (TypeOf Me.Controls(i) Is TextBox) Then
            Me.Controls(i).Text = ""
        'se o controle for do tipo combo tb limpa
        ElseIf (TypeOf Me.Controls(i) Is ComboBox) Then
            Me.Controls(i).Text = ""
        End If
    Next i
    cboNome.SetFocus
End Sub

Os botões são habilitados usando a seguinte rotina :

Note que quando chamamos esta rotina devemos passar uma string Y ou N tantas vezes quantos forem os botões que desejamos habilitar/desabilitar. Assim  Call habilitaBotes("YYYYYYYYYY") ira habilitar todos os botões.

Public Sub habilitaBotes(strYN As String)

    Dim intIndex As Integer
    Dim intTodosBotoes As Integer    
    strYN = Trim$(strYN)
    intTodosBotoes = Len(strYN)    
    For intIndex = 1 To intTodosBotoes
        cmdButton(intIndex - 1).Enabled = True      'padrao é enabled
        If (Mid$(strYN, intIndex, 1) = "N") Then cmdButton(intIndex - 1).Enabled = False
    Next intIndex    
End Sub

O evento QueryUnload sempre será executado quando o seu formulário for descarregado (mesmo se você fechar o form clicando no X da barra de titulo). Neste evento eu verifico se há atualizações pendentes e chamo a rotina para atualizar em lote do programa.

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

    If blnUpdated = False Then
        intResposta = MsgBox("Deseja enviar as modificações para o banco de dados ? ", vbQuestion + vbYesNoCancel)

        If intResposta = vbYes Then
            blnExiting = True
            Call cmdAtualizaEmLote_Click
        ElseIf intResposta = vbNo Then
            Exit Sub
        ElseIf intResposta = vbCancel Then
            Cancel = True
        End If

    End If
End Sub

Outra característica é que ao selecionar um nome da combobox os dados serão exibidos nas caixas de texto. Isto é feito no evento Click da combo. Primeiro eu verifico se estou incluindo (blnAdd) se eu não estiver incluindo então chamo a rotina procuraRegistro()

Private Sub cboNome_Click()
    
    If blnAdd = False Then                      'AddNew nao foi clicado entao vou procurar
        Dim blnFound As Boolean
        strProcura = CStr(cboNome.Text)
        blnFound = procuraRegistro()        'procura o registro e retorna um booelan       
        If blnFound = True Then             'exibe nome do contato se achou o registro
            cboNome.SetFocus
            Exit Sub
        End If
    End If    
    txtEmpresa.SetFocus   
End Sub

O código do formulário frmAbout foi encontrado na web como esta , eu , apenas usei no projeto para enfeitar...

Existem outras cositas mas en el código que usted puede estudar ...  (eta portunhol brabo...)

Pegue o código completo e incremente-o com novas funcionalidades. contatos.zip

Nota: Se você incluir registros e não fazer a atualização do banco de dados eles serão perdidos pois o recordset esta desconectado.

referências:

VB - ADO Total - Uma livraria de funções para acesso a dados
ADOX - Gerenciando o seu banco de dados.
ADO , ADOX - Manual de sobrevivência...
Verificando se uma tabela existe com ADO e ADOX
Criando uma Consulta com ADOX

VB - Usando o objeto FileSystemObject
Exportando um Recordset como Texto ( ADO e FileSystemObject)
Lendo e escrevendo em arquivos usando TextStream do FileSystemObject
Usando Enumeração no Visual Basic
ADO - Trabalhando com Recordsets sem uma base de dados.
Migração ADO/DAO - Retornando e Alterando dados - Trabalhando com Recordsets
Otimizando o seu Recordset ADO

Hasta la vista ...