ADO -  Filtrando e Classificando dados em um Recordset


Aqui estamos em mais um artigo falando sobre ADO - ActiveX Data Objects , agora iremos ver como filtrar e classificar dados em um recordset usando ADO.

Temos escritos diversos artigos sobre ADO , se você esta começando agora a usar ADO talvez fosse melhor dar uma olhada nos artigos anteriores. Vamos relacioná-los para facilitar a sua busca :

  1. Migrando da DAO para a ADO

  2. ASP e ADO - Colocando o seu banco de dados na Web

  3. ADO - Active Data Objects

  4. Desenvolvendo Aplicações em VB 6.0 com o mouse e o dicionário

  5. VB6 - Usando os Controles Vinculados - ADODC, DataGrid, DataList, DataCombo

  6. Acesso a banco de dados

  7. ADO , ADOX - Manual de sobrevivência...

  8. Relação de Strings para Conexões ADO

  9. ADO - Localizando informações

  10. Usando ADO na prática - Adodc, DataGrid , DataCombo e MsChart.

  11. Criando sua Loja Virtual - ASP e ADO - Banco de dados na WEB. - Curso em 15 artigos

  12. MsFlexGrid e ADO

  13. ADO - Connection

  14. ADO e fonte de dados - Schemas

  15. Migração DAO/ADO - Quando?

Creio que estes são os principais artigos que podem lhe dar um bom embasamento sobre a tecnologia ADO.

Continuando nossa série de artigos sobre ADO vamos tratar agora em como filtrar e classificar Recordsets usando ADO.

Filtrando dados em um Recordset

Para começar você pode usar a propriedade Filter para filtrar os registros de um recordset. O recordset que for filtrado se tornará o recordset atual e suas propriedades serão pertinentes ao recordset filtrado.

Podemos definir a propriedade Filter de um recordset para os seguintes valores:

Constante Descrição
adFilterNone Remove o filtro atual e restaura todos os registros para exibição.
adFilterPendingRecords Permite visualizar somente os registros que foram alterados mas que ainda não foram enviados para o servidor. Aplicável somente ao modo  de atualização em lote.
adFilterAffectedRecords Permite visualizar somente os registros que foram afetados pela última chamada dos comandos : Delete, Resync, UpdateBatch, ou CancelBatch
adFilterFetchedRecords Permite visualizar os registros no cache atual, ou seja ,  o resultado do último recordset filtrado.
adFilterConflictingRecords Filtra registros que falharam na última atualização
tabela 1.0

Após aplicar a propriedade Filter o cursor do recordset é definido para o primeiro registro no recordset , ou , para EOF caso nenhum registro atenda ao critério de filtragem.

Vejamos a seguir como utilizar cada uma das três opções :

1-) Aplicando um critério para filtrar um recordset

Podemos aplicar um critério a propriedade Filter , da mesma forma que utilizamos a expressão WHERE em uma instrução SELECT na SQL , a sintaxe é a seguinte:

rs.Filter = "criterio"   onde criterio é uma expressão na forma =>  "NomeCampo Operador Valor"

  1. NomeCampo - deve ser um campo válido contido no Recordset , e , se o nome do campo contiver espaços ele deverá ser colocado entre chaves.

  2. Operador - Um operador válido . Os permitidos são :  = , < , > , <=, >= , LIKE

  3. Valor - indica o valor que será comparado com o campo. De forma geral os valores válidos podem ser: 

(Nome = 'Jose' OR Nome = 'Carlos') AND Sobrenome = 'Silva'

Deverá ser substituida por

(Sobrenome = 'Silva' AND Nome = 'Jose') OR (Sobrenome = 'Silva' AND Nome = 'Silva')

Agora vejamos um exemplo prático: Vamos mostrar como filtrar a tabela Publishers do banco de dados Biblio.mdb usando a cidade (City) como critério para filtragem. Vamos filtrar todos os registros cuja cidade é New York . O  critério para filtro deverá ser:  rstemp.filter = "city = 'New York'"

Abaixo o código :

Public Function FiltraCampo(rstTemp As ADODB.Recordset, strCampo As String, strcriterio As String) As ADODB.Recordset

  ' filtra o recordset usando o criterio indicado
  rstTemp.Filter = strCampo & " = '" & strcriterio & "'"
  Set FiltraCampo = rstTemp

End Function

Private Sub Command1_Click()

Dim rstPublishers As ADODB.Recordset
Dim rstPublishersCidade As ADODB.Recordset
Dim strCnn As String
Dim intPublisherContador As Integer
Dim strCidade As String
Dim strMensagem As String

strCnn = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\biblio.mdb;"
Set rstPublishers = New ADODB.Recordset
rstPublishers.CursorType = adOpenStatic
rstPublishers.Open "publishers", strCnn, , , adCmdTable

' Numero de registros no recordset original
intPublisherContador = rstPublishers.RecordCount

' Informa cidade para usar como filtro
strCidade = Trim(InputBox("Informe a Cidade para Filtrar :", "Filtrando o Recordset pela cidade", "New York", 1000, 2000))

If strCidade <> "" Then
' Filtra e abre o recordset filtrado.
   Set rstPublishersCidade = FiltraCampo(rstPublishers, "City", strCidade)

If rstPublishersCidade.RecordCount = 0 Then
       MsgBox "Não há editores para esta cidade.", vbInformation, "Filtrando Recordsets"
Else
    'Compara os registros dos recordsets
    strMensagem = "Registros no recordset Original: " & vbCr & intPublisherContador & vbCr & _
     "Registros para o filtro -> (City = '" & strCidade & "'): " & vbCr & _
    rstPublishersCidade.RecordCount
    MsgBox strMensagem
End If
rstPublishersCidade.Close

End If

End Sub

A função FiltraCampo    rstTemp.Filter = strCampo & " = '" & strcriterio & "'"  recebe como parâmetro o campo que deverá ser usado no filtro e o critério para filtragem e gera o recordset filtrado. Usando a cidade de New York obtivemos um recordset filtrado com 35 registros . Veja abaixo:

Para remover o filtro basta fazer rstemp.filter=  "".

2-) Filtrando um Recordset com um array de bookmarks

Você já deve saber o que é um bookmark e como usá-lo , se ainda tiver dúvidas leia o artigo - ADO - Localizando Informações

Para filtrar um recordset usando bookmarks usamos as seguintes etapas:

Abaixo temos o código que irá filtrar a tabela Publishers do banco de dados Biblio.mdb. Estamos Utilizando 21 bookmarks.

Private Sub Command1_Click()

Dim rstPublishers As ADODB.Recordset
Dim rstPublishersCidade As ADODB.Recordset
Dim strCnn As String
Dim intPublisherContador As Integer
Dim intbookmark As Integer
Dim arrBookmark() As Variant
Dim strMensagem As String

ReDim arrBookmark(20)

strCnn = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\biblio.mdb;"
Set rstPublishers = New ADODB.Recordset
rstPublishers.CursorType = adOpenStatic
rstPublishers.Open "publishers", strCnn, , , adCmdTable

' Numero de registros no recordset original
intPublisherContador = rstPublishers.RecordCount

' vamos obter alguns bookmarks
intbookmark = 0

While Not rstPublishers.EOF And intbookmark <= 20
   arrBookmark(intbookmark) = rstPublishers.Bookmark
   rstPublishers.MoveNext
   intbookmark = intbookmark + 1
Wend

ReDim Preserve arrBookmark(intbookmark - 1)

' utilizando os bookmarks para filtrar
rstPublishers.Filter = arrBookmark

MsgBox " O numero total de registros é : " & intPublisherContador & vbCrLf _
& " Após o filtro o número de registros é : " & rstPublishers.RecordCount

rstPublishers.Filter = ""

MsgBox " O filtro foi removido" & vbCrLf _
& " Numero de registros : " & rstPublishers.RecordCount, vbInformation, "Filtrando registros com bookmarks "

rstPublishers.Close
Set rstPublishers = Nothing

End Sub

Comentários:

  1. Perceba de definimos uma variável array dinâmica para armazenar os bookmarks em : Dim arrBookmark() As Variant
  2. Como definimos usar 21 bookmarks dimensionamos nossa variável para 20: ReDim arrBookmark(20)
  3. Armazenamos os bookmarks na variável array assim:  arrBookmark(intbookmark) = rstPublishers.Bookmark
  4. A seguir aplicamos o filtro rstPublishers.Filter = arrBookmark
  5. Apos o filtro exibimos o número de registros filtrados  - rstPublishers.RecordCount
  6. e removemos o filtro - rstPublishers.Filter = ""

3-) Filtrando registros em um estado específico no Recordset

Os registros durante uma atualização ou outra operação podem estar nos seguintes estados:

Para saber qual o estado de um registro podemos usar a propriedade Status do Recordset .Assim:

If (rs.Status AND adRecModified ) <> 0 then

      msgbox " O registro foi modificado"

endif

Podemos então usar a propriedade Filter do Recordset para filtrar registros em um determinado estado. Para isto podemos aplicar a constante FilterGroupEnum exibida na tabela 1.0 acima.

Vamos mostrar um exemplo prático onde iremos alterar o estado de alguns registros da tabela Publishers do banco de dados biblio.mdb e a seguir filtrar os registros que foram afetados usando a constante FilterGroupEnum. O código é exibido a seguir:

Private Sub Command1_Click()

Dim rstPublishers As ADODB.Recordset
Dim rstPublishersCidade As ADODB.Recordset
Dim strCnn As String
Dim intPublisherContador As Integer
Dim strMensagem As String
Dim sql As String

sql = " Select * from Publishers"
strCnn = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\biblio.mdb;"
Set rstPublishers = New ADODB.Recordset
rstPublishers.CursorType = adOpenStatic
rstPublishers.CursorLocation = adUseClient
rstPublishers.Open sql, strCnn, , adLockBatchOptimistic

' Numero de registros no recordset original
intPublisherContador = rstPublishers.RecordCount

'vamos alterar alguns registros

While Not rstPublishers.EOF
   If rstPublishers("Zip") = "01867" Then
       rstPublishers("Zip") = "01877"
   End If
   rstPublishers.MoveNext
Wend

' agora vamos incluir alguns registros
rstPublishers.AddNew
rstPublishers("name") = "Macoratti"
rstPublishers("Company Name") = "JcmSoft Inc."
rstPublishers("Address") = "Rua Maranhao 100"
rstPublishers("City") = "Sao Paulo"
rstPublishers("State") = "SP"
rstPublishers.MoveFirst

'vamos filtrar as mudanças pendentes
rstPublishers.Filter = adFilterPendingRecords

MsgBox "Registros com mudancas pendentes filtrados : " & rstPublishers.RecordCount

'vamo cancelar a atualização
rstPublishers.CancelBatch

'vamos agora filtrar os registros afetados
rstPublishers.Filter = adFilterAffectedRecords

MsgBox "Registros afetados : " & rstPublishers.RecordCount

'remove o filtro
rstPublishers.Filter = ""

MsgBox " O filtro foi removido" & vbCrLf _
& " Numero de registros : " & rstPublishers.RecordCount, vbInformation, "Filtrando registros com bookmarks "

rstPublishers.Close
Set rstPublishers = Nothing

End Sub

Comentários:

  1. Observe que utilizamos um bloqueio otimista em batch para o recordset ( adLockBatchOptimistic ) , pois vamos usar o modo de atualização em Batch.
  2. Fizemos duas alterações no estado de alguns registros
  3. Alteramos os registros cujo campo zip for igual a "01867" ( Temos três registros que atendem esta condição) 
  4. Incluímos um registro na tabela ( note que nao usamos o método update de imediato )
  5. A seguir filtramos o recordset usando a constante para os registros pendentes (alterados mas ainda não escritos no banco de dados)  : rstPublishers.Filter = adFilterPendingRecords
  6. Cancelamos as atualizações pendentes e  filtramos novamente para os registros afetados pelo método CancelBatch : rstPublishers.Filter = adFilterAffectedRecords
  7. Removemos o filtro : rstPublishers.Filter = ""

Classificando registros em um recordset

Para classificar registros em um recordset podemos usar a propriedade Sort do recordset. A sintaxe é a seguinte:

objeto_Recordset.Sort  criterio [, criterio1, ... , criterion]

onde:

criterio  representa uma string que indica um campo do banco de dados pelo qual desejamos filtrar o recordset

obs: podemos usar as cláusulas ASC e DESC para indicar a ordem da classificação: Assim:

rs.Sort = "Nome ASC"   - classifica o recordset por nome na ordem ascendente         

rs.Sort = "Nome ASC , Nascimento DESC "  - classifica o recordset por nome na ordem ascendente e por data de nascimento na ordem descendente.

Para usar a propriedade Sort devemos considerar o seguinte:

Vejamos um exemplo onde classificamos a tabela Publishers por Nome e nome da companhia:

Dim rstPublishers As ADODB.Recordset
Dim rstPublishersCidade As ADODB.Recordset
Dim strCnn As String
Dim intPublisherContador As Integer
Dim sql As String
Dim i As Integer

Private Sub Command1_Click()
rstPublishers.Sort = "Name"
List1.Clear

For i = 1 To 50
  List1.AddItem rstPublishers.Fields(0) & vbTab & rstPublishers.Fields(1)
  rstPublishers.MoveNext
Next

End Sub


Private Sub Command2_Click()

rstPublishers.Sort = "PubId"
List1.Clear
For i = 1 To 50
  List1.AddItem rstPublishers.Fields(0) & vbTab & rstPublishers.Fields(1)

  rstPublishers.MoveNext
Next

End Sub


Private Sub Form_Load()

sql = "Select * from publishers "
strCnn = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\biblio.mdb;"
Set rstPublishers = New ADODB.Recordset
rstPublishers.CursorType = adOpenStatic
rstPublishers.cursorlocation = adUseClient
rstPublishers.Open sql, strCnn, , adLockReadOnly

End Sub

No formulário temos dois botões de comando : um para classificar por  nome e outro por código. Ao clicar em cada um devemos obter:

Nota: os dados não são fisicamente rearranjados mas apenas acessados na ordem  da classificação.

Comentários:

Tchau...


Copyright (c) 2001 - José Carlos Macoratti e amigos da web