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 :
Utilizar estruturas
Utilizar Enumerações
Criar o banco de dados e tabela em tempo de execução se eles não exisitirem
Verificar se um arquivo existe e criar uma pasta usando o FileSystemObject
Incluir , excluir , editar , Procurar e Salvar registros em um banco de dados usando recordsets desconectados
usar ADOX
usar ADO
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 :
Verificamos se o banco de dados existe usando a rotina existeDB
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
'define 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 ...