ADO - Básico e Prático I 


I - Introdução

Nosso objetivo neste artigo é ajudar quem esta iniciando agora com a linguagem Visual Basic , quer trabalhar com banco de dados  ,  pegou a migração DAO -> ADO -> VB.Net  , e esta confuso quanto a por onde começar.

Vamos mostrar os conceitos básico para acessar um banco de dados Access com ADO usando os controles vinculados  ADO data Control, DataList , DataCombo, DataGrid, etc.... Ao trabalho...

II - Criando um Banco de Dados com ADO

Para criar um banco de dados você vai ter que usar a ADOX ( leia : ADOX - Gerenciando seu banco de dados ). A primeira coisa a fazer é referenciar no seu projeto a biblioteca : Microsoft ADO Ext. 2.X for DDL and Security além  de referenciar a biblioteca : Microsoft ActiveX Data Objects 2.X Library.

Abaixo temos o código que cria o banco de dados DbAdo1.mdb e a tabela TblAdoIni com os seguintes campos:

Dim dbNome As String
Dim tbnome As String

dbNome = "c:\teste\DbAdo1.mdb"
tbnome = "TblAdoIni"

If Dir(dbNome) = "" Then
  Dim cn$
  Dim cat As New ADOX.Catalog
  Dim tbl As New ADOX.Table

  Novo = True

  cn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = " & dbNome & ";"
  cat.Create cn

  With tbl
      .Name = tbnome
      'Campo tipo texto
      .Columns.Append "Nome", adVarWChar
      .Columns!Nome.Attributes = adColNullable
      'campo tipo data
      .Columns.Append "Nascimento", adDate
      .Columns!Nascimento.Attributes = adColNullable
      'Campo tipo texto
      .Columns.Append "Telefone", adVarWChar
      .Columns!Telefone.Attributes = adColNullable
   End With

   cat.Tables.Append tbl
   Set tbl = Nothing
   Set cat = Nothing
End If

With Data1
   .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dbNome & ";Persist Security Info=False"
   .RecordSource = "SELECT * FROM " & tbnome
   .Refresh
End With

Text1.DataField = "Name"         'define o campo vinculado

With MaskEdBox1
   .DataField = "Nascimento"        'define o campo vinculado
   .Format = "mm/dd/yy"
   .Mask = "##/##/##"
   .MaxLength = 8
End With

With MaskEdBox2
   .DataField = "Telefone"        'define o campo vinculado
   .Mask = "(###) ###-####"
   .MaxLength = 14
End With

Primeiro verificamos se o arquivo "c:\teste\DbAdo1.mdb" existe. Se o arquivo não existir criamos o banco e dados e a tabela com os campos já comentados.

A seguir criamos uma string de conexão para o banco de dados criado selecionado todos os registros da tabela.

Para exibir os dados em um formulário optamos por usar o controle ADO Data Control ( Data1 ) e usamos uma caixa de texto (Text1) para exibir o nome , uma maskEdBox para exibir a data de nascimento e outra para exibir o telefone.

Observe que configuramos as propriedades dos controles via código, definindo o campo vinculado (DataField) e no caso das MaskEdBox as máscaras para exibir os dados.

O resultado final seria o seguinte formulário sendo exibido:

Aqui apenas mostrei o código para criar o banco de dados e para exibir o formulário com o controle ADO Data Control.

 

III -  Usando DataCombo e DataList - Exibindo dados de tabelas relacionadas

Os controles vinculados sempre foram olhados com desconfiança quando do desenvolvimento de aplicações comerciais devido a suas limitações e a sua performance. Com o advento da ADO  chegaram também os novos controles vinculados , que , se não beiram a perfeição melhoraram muito em relação aos utilizados com a ADO.

Eu não estou fazendo apologia dos controles vinculados , apenas digo que , dependendo da ocasião , por que não usá-los ? Se isto for facilitar nosso trabalho...

Os controles DataCombo e DataList estão presentes na ocx MsDatlst.ocx(232.640 Kb). Quando usamos estes controles trabalhamos basicamente com as propriedades DataSource/DataField   e  RowSource/ListField onde: 

DataSource e DataField governam o valor ativo do controle de dados vinculados  e RowSource e ListField permitem exibir os dados do registro atual.

Neste exemplo estaremos usando estes dois controles vinculados - DataCombo e DataList , além do ADO Data Control. Vamos exibir em um DataList os nomes dos produtos relacionados com a categoria selecionada em um controle DataCombo.  Vamos ao problema:

a-) Temos a tabela Categorias do banco de dados Northwind com a seguinte estrutura:

b-) Temos também a tabela Produtos do banco de dados Northwind com a seguinte estrutura:

3-) O relacionamento entre as duas tabelas é o seguinte:

Queremos então exibir o nome das categorias em um DataCombo e conforme selecionarmos uma categoria , os produtos a ela relacionados  deverão ser exibidos em um DataList.

Isto vai ser possível graças ao relacionamento entre as duas tabelas ter sido feito pelo campo  CódigoDaCategoria. Percebeu então que muitas vezes não só o código que torna possível realizar certas tarefas mas , no caso de aplicações para banco de dados , uma definição e normalização adequada das tabelas de dados envolvidos no processo. Ninguém faz milagre... Agora siga o roteiro passo a passo:

- O controle Adodc1 será vinculado ao controle DataCombo1

- O controle Adodc2 será vinculado ao controle DataList1

- adodc1 e adodc2 estarão conectados com o banco de dados Northwind

Agora vamos configurar os controles :

1-) Precisamos conectar o controle adodc1 ao banco de dados Northwind e a tabela Categorias , pois desejamos exibir no controle DataCombo1 o nome das categorias existentes na tabela categorias. Vejamos como fazer isto:

a- Selecione o controle adodc1 e clique com o botão direto do mouse ou na janela Properties clique em Custom

b- Na janela Property Pages clique no botão Build e na janela Data Link Properties selecione o provedor para acessar o banco de dados - Microsoft Jet 4.0 OLE DB Provider. Ver abaixo:

c- A seguir clique no botão Next>> ,e , na aba Connection , selecione o banco de dados , no nosso caso : Northwind.mdb :

d- Após isto clique no botão OK e , na janela Properties Pages , clique no botão Aplicar e selecione a aba Recordsource. Em Command Type selecione : 2- adCmdTable  e em Table or Stored Procedures Name selecione a tabela categorias. (Veja abaixo)

e-  Pronto , clique em OK  e seu controle adodc1 já esta configurado para acessar o banco de dados Northwind e a tabela Categorias usando o provedor OLE DB 4.0.

Vamos agora vincular o controle adodc1 ao controle DataCombo1 para pode exibir o nome das categorias neste controle: Faça assim:

Vinculando o DataList ao controle adodc1 

- Defina a propriedade RowSource = Data1 

- Defina a propriedade ListField = NomedaCategoria

- Limpe a propriedade Text do controle DataList

Pronto , se você executar o projeto agora verá que o controle DataCombo1 irá exibir o nome das categorias existentes na tabela Categorias

Falta configurar o controle DataList1 para que conforme selecionarmos uma categoria em DataCombo1 os nomes dos produtos desta categoria sejam exibidos. Vamos lá:

2-) Primeiro vamos configurar o controle adodc2 para se conectar ao banco de dados Northwind. Basta repetir os mesmos procedimentos adotados para o controle adodc1 até o passo c. 

A única diferença estará no passo d , onde informamos a tabela a qual o controle estará vinculado. Para adodc2 não iremos vincular tabela alguma , apenas iremos definir um recordset que NÃO retorne nenhum registro através da instrução SQL  - Select * From Produtos Where NomedoProduto="" . (Ver figura abaixo)

- Configuração do controle adodc2

- Não vinculamos nenhuma tabela ao controle , apenas definimos um recordset que não retorna registro algum.

Agora basta vincular o controle adodc2 ao controle DataList. Assim:

Vinculando o controle DataList ao controle adodc2:

- Defina a propriedade RowSource = adodc2

- Defina a propriedade ListField = NomedoProduto

 

Para terminar devemos incluir algumas linhas de código para que quando uma categoria for selecionada em DataCombo1 os nomes dos produtos relacionados sejam exibidos em DataList1. 

Vamos usar o evento Change do controle DataCombo1 , de forma que , toda vez que o houve uma mudança em DataCombo1, isto se reflita em DataList1.

Ora para fazer isto basta que a cada alteração a propriedade Recordsource do controle adodc2 seja alterada através de uma instrução SQL que selecione da tabela Produtos os nomes do produtos para a categoria selecionada em DataCombo1. A propriedade Text do controle DataCombo1, será então usada para informar o nome da categoria selecionada e assim montar a instrução SQL . Veja a seguir o código:

Private Sub Datacombo1_Change()
Dim sql As String

sql = "SELECT * FROM Produtos WHERE CódigodaCategoria = " & _
                      "(SELECT CódigodaCategoria FROM Categorias " & _
                      "WHERE NomedaCategoria = '" & DataCombo1.Text & "')"

Adodc2.RecordSource = sql
Adodc2.Refresh
End Sub

Agora é só executar e ver o resultado :

Deu para perceber as possibilidades de uso destes controles ???? Você pode exibir dados de várias tabelas relacionadas sem usar qualquer linha de código apenas vinculados os controles , se as tabelas estiverem corretamente normalizadas , é claro...

 Com prática dá  fazer tudo isto em uns 4 minutos...

IV -  Usando DataGrid

O controle DataGrid permite exibir várias linhas e colunas de dados , como uma planilha eletrônica , dando assim uma visão geral das informações. Para preencher um DataGrid basta definir a sua propriedade DataSource para a fonte de dados que desejar exibir ; além disto o DataGrid permite alterar, excluir e incluir colunas. As mudanças na exibição dos dado podem se conseguidas alterando a propriedade DataSource usando uma instrução SQL.

O controle DataGrid esta presente na ocx  MsdatGrd.ocx. ( 262.328 Kb ). 

Geralmente o controle DataGrid esta vinculado a um controle Ado Data control . Vamos mostrar a utilização do controle DataGrid para exibir os dados da tabela Produtos do banco de dados NorthWind.  Para isto iremos fazer a conexão do controle adodc1 ao banco de dados Northwind e definir sua propriedade RecordSource usando a instrução SQL para selecionar todos os registros da tabela produtos - Select * from produtos. Depois basta vincular o controle DataGrid1 ao controle adodc1 através da propriedade DataSource=adodc1.  

Obs: O DataGrid apresentava alguns bugs que foram resolvidos a partir do serviço SP3.

1-)  Inicie um novo projeto no Visual Basic e inclua os componentes, abaixo , através do menu Project|Components... 

2-) Agora vamos conectar o controle adodc1 ao banco de dados Northwind e definir o Recordset:

3-) Vamos agora vincular o controle DataGrid1 ao controle adodc1 . Para isto basta definir a propriedade DataSource = adodc1.

Se você rodar o projeto agora irá obter o seguinte:

 

Muito bem ! O Grid esta exibindo todos os registros da tabela Produtos. Mas , e se você não quiser exibir todas as colunas ?  Vai ter que configurar o controle . Vamos supor que você queira exibir somente as colunas : CódigodoProduto , NomedoProduto e PreçoUnitário. Como vai fazer isto ? Ora , siga-me...:

  1. Clique com o botão direito do mouse sobre o controle DataGrid1 e no menu suspenso selecione a opção : Retrieve Fields
  2. Na janela com a mensagem : Replace existing grid layout with new field definitions ? - clique me SIM.
  3. O seu grid vai exibir o nome de todas as colunas da tabela
  4. Clique agora com o botão direito do mouse sobre o datagrid1 e selecione a opção : Edit.
  5. Para remover colunas clique sobre elas com o botão direito do mouse e selecione : Delete
  6. Você pode também ajustar as colunas e incluir novas colunas ( Insert )
  7. Para alterar o nome do titulo de uma coluna clique sobre o Grid e selecione a opção Properties. A seguir selecione a aba Columns . Agora é só alterar a propriedade Caption da coluna. Ver figura. 

Veja como ficou o nosso projeto após as mudanças:

Muito bem !!! E se agora você quiser formatar os dados exibidos ? Vamos supor que você queira formatar a exibição do campo Código de forma a exibir o código do produto no formato - P00X e o Preço do produto no formato R$ 99,99

Para formatar a coluna Preço basta clicar com o botão direito do mouse sobre o Grid e na janela Property Pages selecionar a aba Format. Selecione a coluna que deseja formatar e escolha a formatação. Veja figura abaixo:

Vamos mostrar agora como formatar a coluna Código via código. Para isto usamos a propriedade NumberFormat do DataGrid. A formatação somente altera a exibição dos dados na coluna não afetando os dados em si.  Veja o código abaixo:

Private Sub Form_Load()
  DataGrid1.Columns("Código").NumberFormat = "P-000"
  DataGrid1.Columns("Preço").Alignment = dbgRight
End Sub

Note que também alinhamos a coluna Preço a direita usando a propriedade Alignment. Veja o resultado abaixo:

Se você quiser obter os valores da coluna onde o usuário clicar basta usar o evento RowColChange . Abaixo temos o código que exibe o texto da coluna , o número da linha e da coluna clicada pelo usuário:

Private Sub DataGrid1_RowColChange(LastRow As Variant, ByVal LastCol As Integer)
   MsgBox DataGrid1.Text & " - " & DataGrid1.Row & " - " & DataGrid1.Col
End Sub

Para obter os valores formatados pela propriedade FormatNumber  você pode usar o métodos CellText ( o mesmo resultado é obtido usando a propriedade Text . Ex: DataGrid1.Text). Assim para obter o valor formatado da coluna Preço temos:

DataGrid1.Columns("Preço").CellText(DataGrid1.Bookmark)

Observe que usamos , neste caso , a propriedade BooKmark.

Já se você quiser retornar o valor que esta no banco de dados , independente da formatação , deve usar o método CellValue. Assim :

DataGrid1.Columns("Preço").CellValue(DataGrid1.Bookmark)

Ambos deverão ser usados no evento RowColChange.

Novamente eu repito as possibilidades são imensas... Cabe a você se aprofundar...e batalhar...  

V - ADO -  Trabalhando com Imagens

Como tratar imagens em banco de dados com ADO ? Vamos mostrar como fazer isto usando o ADO Data Control.

Existem duas maneiras básicas de trabalhar com imagens em banco de dados :

  1. Você salva no arquivo a localização da imagem e a carrega toda vez que quer exibí-la.
  2. Você salva a imagem diretamente no seu banco de dados. 

Já vou adiantar que você não pode salvar um arquivo imagem apenas atribuindo o nome da imagem  ao campo e usando o comando Update.  Um arquivo imagem geralmente é um arquivo do tipo binário que precisa ser tratado antes de ser gravado. Para fazer isto usamos o método AppendChunck() da ADO. Vejamos como fazer:

1-) Inicie um novo projeto no Visual Basic e insira no formulário os seguintes controles :

  1. Uma referência a livraria : Microsoft ADO Ext. 2.X for DDL and Security
  2. Um controle Image - Image1
  3. Um controle ADO Data Control ( faça a referência ao componente  antes )
  4. Um botão de comando
  5. Um controle CommonDialog - Microsoft Common Dialog Control 6.0. Veja abaixo o formulário:

Agora vamos definir a propriedade DataSource do controle image1 e do controle text1 como sendo igual ao controle Adodc1.

Após isto insira o seguinte código no formulário:

1- Código do evento Load do formulário :

Private Sub Form_Load()
Dim dbNome$, tbNome$

dbNome = "c:\teste\DBImg.mdb"
tbNome = "Imagens"

If Dir(dbNome) = "" Then
  Dim cn$
  Dim cat As New ADOX.Catalog
  Dim tImagens As New ADOX.Table

  cn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = " & dbNome & ";"
  cat.Create cn

 With tImagens
     .Name = tbNome
     .Columns.Append "Nome", adVarWChar
     .Columns!Nome.Attributes = adColNullable
     .Columns.Append "Imagem", adLongVarBinary
  End With

  cat.Tables.Append tImagens
  Set tImagens = Nothing
  Set cat = Nothing
End If

 With Adodc1
  .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dbNome & ";Persist Security Info=False"
  .RecordSource = "SELECT * FROM " & tbNome
  .Refresh
 End With

'vinculando os controles text1 e image1 ao adodc1
Text1.DataField = "Nome"
Command1.Caption = "&Incluir Imagem"
Image1.DataField = "Imagem"

End Sub

Neste código estamos criando o banco de dados - DBImg.mdb , se o mesmo ainda não existir, e a tabela Imagens com a seguinte estrutura:

  1. Nome        - Tipo Texto
  2. Imagem    - Tipo Binário Longo

Após criar o banco de dados e a tabela , criamos uma conexão com o banco de dados  e definimos o recordset atual como sendo igual a todos os registros da tabela. ("SELECT * FROM " & tbNome )

2-) Código do evento Click do botão de comando - command1:

Private Sub Command1_Click()
Dim f as String

Dim L as String

dim  Imagem as String

On Error GoTo trata_erro

With CommonDialog1
   .CancelError = True
   .Filter = FLTR
   .ShowOpen
   Imagem$ = .FileName
End With

f = FreeFile
Open Imagem For Binary Access Read As f

L = LOF(f)
ReDim B(L) As Byte
Get f, , B()
Close f

'inclui o registro no banco de dados
With Adodc1.Recordset
  .AddNew
  !Imagem.AppendChunk B()
  !Nome = Imagem
  .Update
End With

'mostra imagem no controle image1

Image1.Picture = LoadPicture(Imagem)
Exit Sub

trata_erro:
MsgBox Err.Description

End Sub

Aqui ativamos o controle CommonDialog com a janela Abrir , já filtrando somente arquivos imagens , graças a constantel: Const FILTRO = "Imagens|*.jpg*;*.gif*;*.bmp;*.ico|All Files|*.*"

Quando o usuário selecionar uma imagem ativamos a rotina que guarda a imagem no vetor B() ,e , em seguida gravamos o banco de dados o nome da imagem e a imagem , usando o método AppenChunck() A imagem é a seguir exibida usando o comando LoadPicture.

Veja a seguir o resultado obtido:


Bem , se você pretende tratar imagens sem usar um ADO Data control , vai precisar da rotina para ler a imagem do banco de dados e exibí-la . Abaixo temos o código que lê a imagem do banco de dados para estes casos:

Private Sub LeImagem_Click()
Dim L as string

Dim t as string

dim f as string

L = Adodc1.Recordset!Imagem.ActualSize
ReDim B(L) As Byte
B = Adodc1.Recordset!Imagem.GetChunk(L)

t = "tmp"
f = FreeFile
Open t For Binary Access Write As f
Put f, , B()
Close f

Set Image2.Picture = LoadPicture(t)
End Sub

Obs: Você deve substituir o nome do campo Imagem na rotina quando for adaptar o código ao seu caso.

Por hoje é só ... Veja continuação no próximo artigo...  


José Carlos Macoratti