Curso de ADO.NET e BDP - Parte XIII

Acesso a dados no Delphi 8 for .NET

 

Parte XIII – Ordenando, Filtrando e Procurando

Dando continuidade ao nosso curso sobre acesso a dados no Delphi for .NET com ADO.NET e BDP, veremos neste artigo como ordenar, filtrar e procurar registros em DataTables de um DataSet.

 

Nota: A partir desta parte do curso utilizaremos o Delphi 2005, no entanto sinta-se a vontade para usar o Delphi 8, caso queira.

Configurando os componentes do BDP

Inicie uma nova aplicação do tipo Windows Forms Application. Expanda a conexão Employee no Data Explorer e arraste a tabela Department para o designer. Isso cria um BdpConnection e um BdpDataAdapter. Arraste também a tabela Employee para criar um segundo BdpDataAdapter. Coloque um DataSet, aponte a propriedade DataSet do BdpDataAdapter1 para DataSet1 e configure seu Active para True. Faça o mesmo no BdpDataAdapter2.

Configure a propriedade Relations do DataSet conforme mostrado na figura a seguir:

 

 

Configurando a interface de usuário

Coloque no formulário cinco CheckBoxes, quatro DropDownListBoxes, dois Buttons e um DataGrid (aponte o DataGrid para o DataTable1). Ajuste os controles no formulário como mostrado a seguir:

 

 

Ordenando

Veremos agora como ordenar os dados que estão no DataTable do DataSet por uma coluna, que será selecionada em um DropDownListBox. Observe que essa ordenação é feita em memória, não será necessário obter os dados novamente a partir do servidor SQL, o que ocasionaria um tráfego desnecessário de dados na rede.

No evento SelectedIndexChanged do primeiro DropDownListBox digite o seguinte:

 

procedure TWinForm1.cbSort_SelectedIndexChanged(sender: System.Object; e: System.EventArgs);

begin

  if not cbDesc.Checked then

    DataTable1.DefaultView.Sort := cbSort.Text

  else

    DataTable1.DefaultView.Sort := cbSort.Text + ' DESC';

end;

 

Aqui estamos acessando o DefaultView do primeiro DataTable. Veremos mais sobre DataViews na próxima parte do curso, por ora basta saber que cada DataTable possui um DefaultView que permite manipular, ordenar, filtrar e buscar dados. Para ordenar os dados, basta atribuir para a propriedade Sort o nome do campo desejado. Se colocarmos “DESC” ao final da propriedade, os dados serão ordenados em ordem decrescente – fazemos isso se o usuário marcou o respectivo CheckBox.

Para preencher o DropDownListBox com os nomes dos campos disponíveis, vamos varrer a coleção Columns do DataTable, que representa as colunas da tabela. No evento Load do formulário escreva o seguinte:

 

procedure TWinForm1.TWinForm1_Load(sender: System.Object; e: System.EventArgs);

var

  i: integer;

begin

for i := 0 to DataTable1.Columns.Count - 1 do

  cbSort.Items.Add(DataTable1.Columns[i].ToString);

end;

 

Caso queira, você pode utilizar o novo comando for in do Delphi 2005 (análogo ao foreach do C#), para iterar pelos itens da coleção, ao invés de usar um for indexado.

Veja o resultado na figura abaixo, onde ordenamos a tabela pelo campo Department. Observe que o DataGrid coloca uma pequena seta no cabeçalho da coluna para indicar a ordenação.

 

 

Filtrando

Para filtrar um DataTable, basta atribuir uma string de filtro (ex. “DEPT_NO > 100”) para a propriedade RowFilter do seu DefaultView (semelhante a propriedade Filter dos DataSets da VCL, exceto que você não precisa configurar algo como o Filtered para True).

Digite o seguinte no evento Click do botão Filtrar:

 

procedure TWinForm1.Button1_Click(sender: System.Object; e: System.EventArgs);

begin

  DataTable1.DefaultView.RowFilter := cbFilter.Text;

end;

 

Veja um exemplo de filtragem na figura abaixo, onde selecionamos todos os departamentos entre 110 e 120:

 

 

Veja ainda mais alguns exemplos de filtragem que você pode utilizar:

DEPARTMENT LIKE 'S%'

Estilo like do SQL; seleciona todos os departamentos onde o campo Department comece com “S”.

 

LOCATION IN ('Monterey','San Francisco')

Seleciona todos os departamentos onde o campo Location seja igual a “Monterey” ou “San Francisco”.

 

Substring(DEPARTMENT,2,1) = 'u'

Substring é uma função especial que pode ser usada em expressões de filtro. Aqui selecionamos todos os departamentos onde o campo Department tenha a segunda letra igual a “u”. Isso retorna, neste exemplo, “Quality Assurance”, “Customer Support”, “Customer Services” e “European Headquarters”.

 

IIF(DEPT_NO<600,LOCATION='San Francisco',LOCATION='Monterey')

IIF é outra função especial que pode ser usada em filtros. Passamos para ele três parâmetros: O primeiro é uma expressão booleana, se for verdadeira o ADO.NET considera o segundo parâmetro como sendo o filtro a ser usado, caso contrário, considera o terceiro. No exemplo anterior, seriam selecionados todos os departamentos como localização em San Francisco e DEPT_NO menor que 600 e todos os maiores que 600 que se localizam em Monterey. O resultado pode ser visto na figura a seguir:

 

 

Sem IIF seria necessário o uso de quatro expressões, com dois operadores and e dois operadores or. Veja como é simples fazer o mesmo com IIF no exemplo anterior.

 

Count(Child(Relation1).EMP_NO)>2

Como temos um Relation configurado entre os dois DataTables, podemos utilizar mais algumas funções especiais, como Child. No exemplo anterior, selecionamos todos os departamentos onde a tabela relacionada tenha pelo menos 2 registros, ou seja, só mostramos na tela os departamentos com mais de 2 funcionários. 

Localizando

Para localizar um registro, usamos o método Find do DefaultView do DataTable e passamos o valor a ser localizado, com base no campo chave. Isso é feito no evento Click do botão Find:

 

procedure TWinForm1.Button2_Click(sender: System.Object; e: System.EventArgs);

begin

  DataTable1.DefaultView.Find(cbFind.Text);

end;

 

Isso faz papel semelhante ao Locate, FindKey, FindNearest, GotoKey e GotoNearest dos DataSets da VCL. Veja porém que um DataTable não possui o recurso de registro atual (ele é na verdade uma matriz), quem se encarrega de gerenciar o posicionamento em tela e sincronização de controles com DataBinding é o CurrencyManager (e DataView), como vimos em artigos anteriores.

Restringindo a Edição, Alteração e Exclusão

A propriedade DefaultView ainda permite que sejam especificadas quais as operações permitidas sobre o DataTable utilizado. Em nosso exemplo, colocamos três CheckBoxes (AllowDelete, AllowEdit e AllowNew) para configurar essas opções. Aqui estão os manipuladores para os eventos CheckedChanged de cada CheckBox:

 

procedure TWinForm1.cbAllowNew_CheckedChanged(sender: System.Object; e: System.EventArgs);

begin

  DataTable1.DefaultView.AllowNew := cbAllowNew.Checked;

end;

 

procedure TWinForm1.cbAllowEdit_CheckedChanged(sender: System.Object; e: System.EventArgs);

begin

  DataTable1.DefaultView.AllowEdit := cbAllowEdit.Checked;

end;

 

procedure TWinForm1.cbAllowDelete_CheckedChanged(sender: System.Object; e: System.EventArgs);

begin

  DataTable1.DefaultView.AllowDelete := cbAllowDelete.Checked;

end;

 

Com isso os dados só porem ser alterados, excluídos ou inseridos caso essas opções estejam ativadas. Isso é ideal para criar cadastro de usuários e permissões, restringindo o acesso a determinadas operações caso o usuário não tenha permissão.

Filtrando pelo status do registro

E finalmente, o DefaultView permite que sejam exibidos na tela somente registros que estejam em um determinado estado. Por exemplo, podemos exibir em um determinado momento somente registros que foram incluídos, ou editados. Isso é feito através da sua propriedade RowStateFilter (semelhante ao que é o StatusFilter do ClientDataSet da VCL).

Isso é feito no evento SelectedIndexChanged do último DropDownListBox:

 

procedure TWinForm1.cbRowStateFilter_SelectedIndexChanged(sender: System.Object; e:   System.EventArgs);

begin 

  DataTable1.DefaultView.RowStateFilter :=

    DataViewRowState(Enum.Parse(TypeOf(DataViewRowState),cbRowStateFilter.Text));

end;

 

Aqui usamos reflexão do .NET (algo com o RTTI do Delphi) e o objeto Enum para converter para um valor de tipo enumerado o valor string escolhido no DropDownListBox. Isso nos poupa de fazer vários ifs. Os itens do DropDownListBox são preenchidos no evento Load do form:

 

Self.cbRowStateFilter.Items.AddRange(TArrayOfSystem_Object.Create('Added ',

'CurrentRows ', 'Deleted ', 'ModifiedCurrent ', 'ModifiedOriginal',

'ModifiedOriginal ', 'None ', 'OriginalRows ', 'Unchanged '));

 

A figura abaixo mostra o funcionamento do RowStateFilter, exibindo somente os registros que foram excluídos até o momento:

 

 

Download

Você pode fazer download de todos os exemplos deste curso a partir do endereço http://cc.borland.com/cc/ccweb.exe/author?authorid=222668

Na próxima parte do curso conheceremos um pouco mais sobre o DataView, um abraço a todos e até lá!

Leia todos artigos da série