quinta-feira, 24 de abril de 2008

Ordenar DataGridView

No Post anterior “Ordenar Listview” mostrei como fazer um Sort personalizado no Listview agora irei mostrar como fazer o Sort no DataGridView, pois bem o DataGridView diferente do Listview possui um evento de nome DataGridView_SortCompare o que vai facilitar muito a nossa vida pois a única coisa que teremos de fazer é comparar os valores para retornar a ordem.

Crie um novo projeto no Visual Studio e altere seu nome para OrdenarDataGridView.



Acesse o código do Form1 e insira o código abaixo:

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'CRIA DUAS COLUNAS NO DataGridView
DataGridView1.Columns.Add("NOME", "NOME")
DataGridView1.Columns.Add("DTNASC", "DTNASC")
'INSERI ALGUNS ITEM NO DataGridView ALTERANDO O VALOR DAS DATAS
For X As Int16 = 101 To 200
DataGridView1.Rows.Add("DANIEL" & X, _
DateTime.Now.AddDays(X + 150))
Next X
End Sub

Private Sub DataGridView1_SortCompare(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewSortCompareEventArgs) _
Handles DataGridView1.SortCompare
Dim DataValida As DateTime
'VERIFICA SE COLUNA É DO TIPO DATA PARA FAZER A COMPARAÇÃO
'CASO A COLUNA NÃO SEJA UMA DATA VALIDA COMPARA STRING
If DateTime.TryParse(e.CellValue1, DataValida) = False Then
e.SortResult = System.String.Compare(e.CellValue2, e.CellValue1)
Else
If DateTime.TryParse(e.CellValue1, DataValida) = False Then
e.SortResult = -1
Else
e.SortResult = System.DateTime.Compare(CType(e.CellValue2, _
Date), CType(e.CellValue1, Date))
End If
End If
e.Handled = True
End Sub
End Class

Para baixar este projeto completo em Visual Studio 2008 clique no link abaixo:

Ordenar DataGridView


Pronto com base neste código você pode fazer a comparação de acordo com a sua necessidade.

sexta-feira, 18 de abril de 2008

Ordenar Listview

Um problema que muitas vezes enfrentamos quando estamos trabalhando com Grid e Listview é a classificação, pois a mesma nunca se comporta da forma esperada quando trabalhamos com datas ou números. A minha idéia neste artigo é mostrar como fazer isso utilizando uma classe personalizada. Pois bem, o primeiro passo a ser seguido é abrir o Visual Studio - no meu caso estou utilizando o VB 2008 Express - e criar um novo projeto. Vamos nomear este projeto como OrdenarListview.vb.


Feito isso clique em Project Add Class...
Iremos renomear esta classe para CompararItensListview.vb.


Vamos ao código.

A primeira coisa a ser feita é definir o que você vai precisar ordenar. Neste exemplo irei demonstrar como ordenar Data, números e Texto. Iremos agora declarar nossas variáveis e criar o codigo para receber as mesmas sempre que a nossa classe for chamada. Usaremos a palavra Implements para implementar a Interface IComparer. Interfaces são classes que possuem apenas metodos e não possuem implementação, ou seja, a mesma não possui código apenas chamadas de metodos. A classe que herdar a Inteface terá que implementar o seu método e seguir o modelo de sua chamada.

'IMPLEMENTA A Interface IComparer

Implements IComparer
VERIFICAR ORDEM

Private Coluna As Integer
'VARIAVEL QUE VAI RECEBER O TIPO DE ORDEM
'QUE NOSSO LISTVIEW VAI SEGUIR
“Descending ou Ascending”
Private
OrdemSort As SortOrder

Agora definiremos como iremos receber os valores Coluna e OrdemSort. Neste exemplo, os mesmos serão recebidos junto à chamada da Classe, ou seja, no procedimento Public Sub New.

Public
Sub New(ByVal ColunaClique As Integer,ByVal OrdemSort As SortOrder)
Coluna = ColunaClique
Me.OrdemSort = OrdemSort
End Sub

Nosso código deve ficar assim:

Class CompararItensListview
Implements IComparer
Private Coluna As Integer
Private OrdemSort As SortOrder

Public Sub New(ByVal ColunaClique As _
Integer, ByVal OrdemSort As SortOrder)
Coluna = ColunaClique
Me.OrdemSort = OrdemSort
End Sub
End Class

O que temos que fazer agora é a função que vai organizar o Listview. O método que iremos implementar da Classe IComparer é a função compare que possui dois parâmetros: o X que representa o item que vai ser comparado; e o Y, o item anterior a este na ordem conforme exemplo abaixo:

Public Function Compare(ByVal x As Object,ByVal y As
Object) As Integer _
Implements System.Collections.IComparer.Compare
End Function

Veremos agora como fazer a comparação entre os valores do Listview para estabelecer a ordem dos mesmos. O que faremos agora é uma verificação do tipo de dados da coluna selecionada e sua validação conforme este. Por exemplo, suponhamos que na sua coluna você possui datas. Para fazer esta verificação usaremos a função DateTime.TryParse que é semelhante ao IsDate do antigo VB6.

'PARA UTILIZAR A FUNÇÃO DateTime.TryParse TEMOS QUE DEFINIR UMA DATA VÁLIDA CONFORME EXEMPLO ABAIXO
Dim DataValida As DateTime
If DateTime.TryParse(CType(x, _
ListViewItem).SubItems(Coluna).Text, DataValida) Then

Perceba que na função acima utilizamos a função CType, função esta que serve para converter uma variável de um tipo para outro CType(x, ListViewItem).SubItems(Coluna).Text. Neste caso, estamos convertendo um tipo Objeto para um tipo ListViewItem e capturando assim o seu valor. Utilizaremos também a função Double.TryParse para verificar se o valor é numérico. Bem, a partir daqui não vou me ater muito, pois é apenas uma lógica de comparação para verificar a ordem que cada um vai se posicionar em relação ao item superior, conforme tabela abaixo.

0 – Igual ao item anterior fica onde esta
-1 – É menor sobe para a posição do item anterior
1 – Vai uma posição para frente

Para fazer a comparação entre os valores usaremos as funções.
DateTime.Compare – Comparar duas dadas
Convert.ToDouble – transforma em valor para comparação
String.Compare -
compara duas strings
O código da nossa Classe deve ficar semelhante a este:


Class CompararItensListview

    Implements IComparer

    Private Coluna As Integer

    Private OrdemSort As SortOrder

 

    Public Sub New(ByVal ColunaClique As Integer, ByVal _

    OrdemSort As SortOrder)

 

        Coluna = ColunaClique

        Me.OrdemSort = OrdemSort

 

    End Sub

 

    Public Function Compare(ByVal x As Object, ByVal y As Object) _

    As Integer Implements System.Collections.IComparer.Compare

 

        Dim OrdemItem As Integer

        Dim DataValida As DateTime

        Dim NumeroValido As Double

 

        If DateTime.TryParse(CType(x, ListViewItem).SubItems(Coluna).Text, _

        DataValida) Then

 

            If DateTime.TryParse(CType(y, ListViewItem).SubItems(Coluna).Text, _

            DataValida) Then

 

                OrdemItem = DateTime.Compare(CType(x, ListViewItem).SubItems _

                (Coluna).Text, CType(y, ListViewItem).SubItems(Coluna).Text)

 

                MsgBox(CType(x, ListViewItem).SubItems(Coluna).Text)

                MsgBox(CType(y, ListViewItem).SubItems(Coluna).Text)

 

            Else

                OrdemItem = -1

            End If

 

        ElseIf Double.TryParse(CType(x, ListViewItem).SubItems(Coluna) _

            .Text, NumeroValido) Then

 

            If Double.TryParse(CType(y, ListViewItem).SubItems(Coluna).Text _

            , NumeroValido) Then

 

                If Convert.ToDouble(CType(x, ListViewItem).SubItems(Coluna).Text) _

                = Convert.ToDouble(CType(y, ListViewItem).SubItems(Coluna).Text) Then

 

                    OrdemItem = 0

                ElseIf Convert.ToDouble(CType(x, ListViewItem).SubItems _

                (Coluna).Text) > Convert.ToDouble(CType(y, ListViewItem). _

                SubItems(Coluna).Text) Then

 

                    OrdemItem = 1

                Else

                    OrdemItem = -1

                End If

            Else

                OrdemItem = -1

            End If

        Else

            If CType(x, ListViewItem).SubItems(Coluna).Text.Trim = "" Then

                OrdemItem = 1

            Else

                OrdemItem = String.Compare(CType(x, ListViewItem). _

                SubItems(Coluna).Text, CType(y, ListViewItem).SubItems _

                (Coluna).Text)

 

            End If

        End If

 

        'INVERTE O RETORNO EM CASO DE ORDEM DECRESCENTE

        If OrdemSort = SortOrder.Descending Then

            OrdemItem *= -1

        End If

 

        Return OrdemItem

 

    End Function

End Class

Vamos ao codigo do formulário insira um Listview no Form criado e coloque o código abaixo:

Dim ColunaSelecionada As Integer = -1
Private Sub ListView1_ColumnClick(ByVal sender As Object, _
ByVal e As System.Windows.Forms.ColumnClickEventArgs)
Handles ListView1.ColumnClick


'VERIFICA SE CLIQUE É NA MESMA COLUNA
'SE FOR ORDENA DECRESCENTE
If e.Column <> ColunaSelecionada Then
ColunaSelecionada = e.Column
ListView1.Sorting = SortOrder.Ascending
Else
If ListView1.Sorting = SortOrder.Ascending Then
ListView1.Sorting = SortOrder.Descending
Else
ListView1.Sorting = SortOrder.Ascending
End If
End If
'CHAMA METODO QUE IRA ORDENAR O LISTIVEW
ListView1.ListViewItemSorter = New _
CompararItensListview(e.Column, ListView1.Sorting)

End Sub


Para testar insira alguns dados no seu Listview varie as colunas com datas, numeros e texto para ver se funciona abraços e até o proximo.

Baixe o projeto completo escrito no Visual Studio 2008 no link abaixo:

Ordenar Listview

quarta-feira, 16 de abril de 2008

Tipos de Dados e Variaveis

Tipos inteiros

No VB.NET foi acrescentado um novo tipo de dados inteiro, o Short, que é o substituto do antigo valor Integer do VB6. Mas não se assuste! O tipo Integer ainda existe, só que agora está suportando o valor de um Long do VB6, valor este que no VB.NET está aceitando uma quantidade de números bem considerável. Além do novo tipo no VB.NET, foram acrescidos 6 tipos alternativos Int16, UInt16, Int32, UInt32, Int64 e UInt64.

Abaixo uma tabela com os Tipos inteiros:

Tipo
Memória
Valor Mínimo
Valor Maximo
Short2 Bytes-3276832767
Int162 Bytes-3276832767
UInt162 Bytes065535
Integer4 Bytes-21474836482147483647
Int324 Bytes-21474836482147483647
UInt324 Bytes04294967295
Long8 Bytes-92233720368547758089223372036854775807
Int648 Bytes-92233720368547758089223372036854775807
UInt648 Bytes0184467440737095551615

Bem, olhando este quadro provavelmente você deve estar se perguntando: qual tipo devo usar? Meu conselho, por questões de compatibilidade com plataformas 64 Bits no caso de ter que usar um tipo Integer, é usar o Int32. Nos demais casos acredito ser indiferente.

Na tabela acima podemos ver que existem alguns tipos de dados começando com a Letra U. Estes tipos, além de poderem obter um buffer um pouco maior, são também utilizados para conversar com outras aplicações que esperam algum tipo especifico. O tipo UInt16 tem as mesmas características do Character e o tipo UInt32 tem as mesmas características de um ponteiro de memória do sistema.

Tipos Decimais

Bem, uma das primeiras coisas que um desenvolvedor migrando do VB6 para VB.NET vai perceber é que o tipo de dados Currency sumiu. Pois é... o nosso querido amigo se tornou obsoleto no VB.NET cedendo o seu lugar para um novo tipo de dados, o Decimal.

Abaixo uma tabela com os tipos decimais:

Tipo
Memória
Intervalo Negativo
Intervalo Positivo
Single4 Bytes-3,402823E38 a
-1,401298E-45
1,401298E-45 a 3,402823E38
Double8 Bytes-1,79769313486231E308 a
-4,94065645841247E-324
4,94065645841247E-324 a 1,79769313486231E308
Decimal16 Bytes-79228162514264
337593543950335 a -0,0000000000000
000000000000001
0,00000000000000
00000000000001 a 79228162514264337
593543950335

Tipo Booleano

O tipo Booleano permanece inalterado no VB.NET. A única recomendação que tenho a fazer sobre este tipo é sempre utilizar as constantes True e False quando for verificar valores, pois por questões de compatibilidade a constante -1 foi mantida, mas pode não se comportar como o esperado nas conversões porque o mesmo vira 1 automaticamente.

Tipos Char e Byte

As variáveis do Tipo Char ocupam dois Bytes, pois no VB.NET o conjunto de caracteres padrão é o Unicode. Portanto, a variável recebe apenas um caractere. Existem duas maneiras de se declarar uma variável Char: uma delas, a mais simples é colocar a letra c logo após sua declaração da variável; outra maneira seria usando as funções Chr e ChrW. Abaixo alguns exemplos.

Dim teste1 As Char = "b"c
Dim teste2 As Char = Chr("96")
Dim teste3 As Char = ChrW("96")

O tipo Byte espera um valor numérico então caso queira colocar uma letra em uma variável do tipo Byte poderíamos usar a função Asc. Abaixo um exemplo de declaração Byte.

Dim Letra As Byte = Asc(“c”)