Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Dicas de Programação #5

DataGridView – Actualização imediata após selecção na ComboBox

O controlo DataGridView permite definir diversos tipos para as suas células, além de se poder inserir novos controlos nas células. A DataGridViewComboBoxCell é um desses tipos e permite ao utilizador efectuar um diverso número de escolhas para cada registo.

Para detectar uma alteração é necessário utilizar o evento EditingControlShowing em conjunto com a  DataGridViewComboBoxEditingControl (que representa a ComboBox alojada na célula). Sem a utilização deste evento é possível também detectar o valor através do evento CellValueChanged mas para isso é necessário mudar de célula para que o evento seja disparado.

Este exemplo mostra como implementar isto, permitindo sempre que se altere um item na ComboBox (através do SelectedIndexChanged) execute uma acção, que neste caso é a actualização do um valor numa célula.

Tratasse de uma lista de produtos com nomes e valores aleatórios em que, ao ser alterado o valor de desconto, altera também o valor do total do artigo.

    Private WithEvents dgvCombo As DataGridViewComboBoxEditingControl

    Private Sub dgvCombo_SelectedIndexChanged(ByVal sender As Object, _ 
                      ByVal e As System.EventArgs)

        ' Caso o valor seja Nothing sai do procedimento
        If dgvCombo Is Nothing Then Exit Sub

        ' Caso tenha sido alterado a coluna da ComboBox
        If Me.DataGridView1.CurrentCell.ColumnIndex = 4 Then

            Dim row As Integer = Me.DataGridView1.CurrentCell.RowIndex

            ' Guarda a informação do preço
            Dim preco As Double = Me.DataGridView1(2, row).Value
            Dim desc As Double = dgvCombo.Text.ToString.Replace("%", "")

            ' Caso o calor seleccionado não seja > 0
            If desc > 0 Then

                ' Calcula o preço com o desconto e actualiza o campo "Total"
                Me.DataGridView1(3, row).Value = preco - (preco * (desc / 100))

            Else

                ' Actualiza o campo "Total" sem desconto
                Me.DataGridView1(3, row).Value = preco

            End If

        End If

    End Sub

     

    ' Define a dgvCombo = Nothing para funcionar na próxima ComboBox
    Private Sub DataGridView1_CellLeave(ByVal sender As Object, _
        
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
         Handles
DataGridView1.CellLeave

        dgvCombo = Nothing

    End Sub

    ' Quando um controlo é editado
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
  Handles DataGridView1.EditingControlShowing

        ' Verifica se o control editado foi a ComboBox
        If TypeOf e.Control Is DataGridViewComboBoxEditingControl Then

            ' Atribui o controlo 
            If dgvCombo Is Nothing Then
                dgvCombo = e.Control
            End If

            ' Atribui um evento quando é alterado o a selecção
            AddHandler dgvCombo.SelectedIndexChanged, _
                  New EventHandler(AddressOf dgvCombo_SelectedIndexChanged)
        End If

    End Sub

     

O objectivo é mostrar como executar uma acção de imediato após a selecção de item numa combobox, facilitando a utilização deste controlo.

     

ListView – Criar coluna de hyperlinks detectando a coluna clicada

A ListView não permite inserir um tipo na coluna específico para hiperligações. Para conseguirmos criar uma coluna personalizada de hiperligações é necessário detectar qual a coluna que foi clicada e também alterar o ponteiro do rato na coluna especifica. No entanto, e para detectar a coluna clicada ou que o ponteiro do rato está sobre ela, é necessário que não esteja visível a scrollbar, ou seja, as colunas têm de estar visíveis.

Este exemplo mostra como criar a coluna personalizada, sendo introduzidos dados aleatórios e um dos SubItems da lista estar definido com a cor da fonte a azul. Não esquecer de que é necessário definir no item principal o UseItemStyleForSubItems = False para que seja possível definir vários formatos em diversos SubItems.

    ''' <summary>
    ''' Verifica qual a coluna onde o ponteiro do rato está
    ''' </summary>
    ''' <param name="e">MouseEventArgs</param>
    Private Function lvColumnNumber( _
            ByVal e As System.Windows.Forms.MouseEventArgs) As Integer

        Dim colend As Integer = 0
        Dim colstart As Integer = 0
        Dim x As Integer

        ' Ciclo nas colunas
        For x = 0 To (ListView1.Columns.Count - 1)

            ' Verifica qual a largura da coluna
            colend = colend + ListView1.Columns(x).Width

            If colstart <= e.X And e.X <= colend Then
                Return x + 1
            End If

            colstart = colstart + ListView1.Columns(x).Width
        Next

    End Function

     

    ' Quando é feito um clique na lista
    Private Sub ListView1_MouseDown(ByVal sender As Object, _
             ByVal e As System.Windows.Forms.MouseEventArgs) _
             Handles ListView1.MouseDown

        ' Verifica se a coluna é a dos URL's
        If lvColumnNumber(e) = 2 Then

            ' Verifica qual o item onde foi feito o clique
            Dim item As ListViewItem = Me.ListView1.GetItemAt(e.X, e.Y)

            ' Caso tenha sido sobre um item
            If item IsNot Nothing Then

                ' Verifica qual a coluna e lança um novo processo
                ' com o URL da lista, abrindo o explorador por defeito
                Dim col As Integer = lvColumnNumber(e) - 1

                Process.Start(item.SubItems(col).Text)

            End If

        End If

    End Sub

    ' Quando o ponteiro do rato está sobre a lista
    Private Sub ListView1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseMove

        ' Verifica se a coluna é a dos URL's
        If lvColumnNumber(e) = 2 Then
            Windows.Forms.Cursor.Current = Cursors.Hand
        Else
            Windows.Forms.Cursor.Current = Cursors.Default
        End If

    End Sub

Deste modo é possível criar uma coluna com uma aparência diferente e também detectar qual a coluna que foi clicada.

PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!


VB.NET: Introdução ao XML

O XML (eXtensible Markup Language) ou linguagem de marcação estendida, é um formatos cada vez mais populares e utilizado por diversos tipos de aplicações. O XML é muito semelhante ao HTML e a principal diferença é que o HTML serve para descrever a aparência e as acções em uma página e o XML serve para guardar dados. Além disso o HTML utiliza tags pré-definidas e o XML não, mas a estrutura é idêntica - as tags (palavras encapsuladas por sinais '<' e '>') e os atributos (definidos com nome="valor").

Existem muitos benefícios na utilização do formato XML, como por exemplo, funcionam sem pré-requisitos, grande capacidade e rapidez de utilização, múltiplas formas de visualizar os dados, fácil distribuição, utilização e compatibilidade com diversos sistemas, etc. Para mais informações podem ler World Wide Web Consortium (W3C)


Existem diversas aplicações e operações bastante fáceis. Pode-se por exemplo gravar todos os dados de uma DataTable para XML e ler os dados para uma DataGridView utlizando poucos comandos:

‘ Grava a informação de uma DataTable para um ficheiro XML
myDataTable.WriteXml("c:\MyData.xml", Data.XmlWriteMode.WriteSchema)

' Lê a informação do ficheiro para uma DataGridView utilizando um DataSet
Dim ds As New DataSet()
ds.ReadXml("c:\MyData.xml")

Me.DataGridView1.DataSource = ds.Tables("MyTable") 

Tão simples como isto!  

Mas o objectivo deste artigo é mostrar como criar um ficheiro simples de XML (para guardar configurações), inserir, listar e apagar elementos. Para criar um ficheiro XML usa-se a XmlTextWriter do namespace System.Xml

     Imports System.Xml

     Private xmlPath As String = "C:\MyData.xml"

    ' Cria um novo ficheiro XML através do clique de um botão
    Private Sub btnCriarXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCriarXML.Click

        ' Cria um novo ficheiro XML com a codificação UTF8
        Dim xmlw As New XmlTextWriter(xmlPath, System.Text.Encoding.UTF8)
        xmlw.Formatting = Formatting.Indented

        xmlw.WriteStartDocument()

        ' Adiciona um comentário geral
        xmlw.WriteComment("Configuração Geral")

        ' Criar um elemento geral
        xmlw.WriteStartElement("config")

        ' Criar o elemento "Favoritos" e alguns dados
        With xmlw
            .WriteStartElement("favoritos")
            .WriteElementString("fav", http://vbtuga.blogspot.com)
            .WriteElementString("fav", http://www.microsoft.com)
            .WriteElementString("fav", http://www.google.com)
            .WriteElementString("fav", http://www.asp.net)
            .WriteEndElement()
        End With

        ' Criar o elemento "Utilizadores" e alguns dados
        With xmlw
            .WriteStartElement("utilizadores")
            .WriteElementString("user", "Jorge Paulino")
            .WriteElementString("user", "João Costa")
            .WriteElementString("user", "Nuno Andrade")
            .WriteEndElement()
        End With

        xmlw.WriteEndElement() ' <- config
        xmlw.WriteEndDocument()

        ' Fecha o documento XML
        xmlw.Flush()
        xmlw.Close() 

    End Sub


O resultado final deverá ser um ficheiro com este:

<?xml version="1.0" encoding="utf-8" ?>
<!-- Configuração Geral>
<config>
    <favoritos>
        <fav>http://vbtuga.blogspot.com</fav>
        <fav>http://www.microsoft.com</fav>
        <fav>http://www.google.com</fav>
        <fav>http://www.asp.net</fav>
    </favoritos>
    <utilizadores>
        <user>Jorge Paulino</user>
        <user>João Costa</user>
        <user>Nuno Andrade</user>
    </utilizadores>
</config>


Com podem ver este ficheiro tem dois “grupos”: Favoritos e Utilizadores. Esses grupos são onde se guarda informação com as suas respectivas tags. Para ler um desses grupos e listar os dados em uma ListBox é apenas necessário:

        ' Cria um novo documento XML e lê o ficheiro criado anteriormente
        Dim xmlDoc As New XmlDocument
        xmlDoc.Load(xmlPath) 

        ' Selecciona os “favoritos” e faz um ciclo em todos 
        ' nodes preenchendo a ListBox1
        Dim node As XmlNode = xmlDoc.SelectSingleNode("//favoritos")
        If node IsNot Nothing Then
            For x As Integer = 0 To nodeA.ChildNodes.Count – 1
                Me.ListBox1.Items.Add(node.ChildNodes.Item(x).InnerText.ToString)
            Next
        End If 


Para apagar e inserir novos dados criei duas funções auxiliares. Estas funções servem para reduzir código e simplificar este processo.

    ''' <summary>
    ''' Remove um node de um ficheiro XML retornando
    ''' como resultado 'True' caso tenha conseguido
    ''' </summary>
    ''' <param name="nodeGroup">Nome do Grupo</param>
    ''' <param name="nodeText">Texto a Remover</param>
    Private Function RemoveXMLNode(ByVal nodeGroup As String, ByVal nodeText As String) As Boolean

        Dim result As Boolean = False

        Try

            ' Verifica se o ficheiro existe
            If Not IO.File.Exists(xmlPath) Then
                Return False
            End If

            ' Cria um novo XmlDocument e carrega o ficheiro XML
            Dim xmlDoc As New XmlDocument
            xmlDoc.Load(xmlPath)

            ' Selecciona o grupo escolhido
            Dim node As XmlNode = xmlDoc.SelectSingleNode("//" + nodeGroup)

            ' Apaga todos os nodes (caso encontre na lista)
            For x As Int16 = node.ChildNodes.Count - 1 To 0 Step -1

                If node.ChildNodes.Item(x).InnerText.ToString = nodeText Then
                    node.RemoveChild(node.ChildNodes.Item(x))
                    result = True
                End If

            Next

            ' Caso tenha eliminado o(s) node(s) grava o ficheiro
            If result = True Then
                xmlDoc.Save(xmlPath)
                Return True
            Else
                Return False
            End If

        Catch ex As Exception
            ' Em caso de erro retorna False
            Return False
        End Try 

    End Function

 

    ''' <summary>
    ''' Adiciona um node de um ficheiro XML retornando
    ''' como resultado 'True' caso tenha conseguido
    ''' </summary>
    ''' <param name="nodeGroup">Nome do Grupo</param>
    ''' <param name="nodeName">Nome que fica na tag</param>
    ''' <param name="nodeText">Texto a Inserir</param>
    Private Function AddXMLNode(ByVal nodeGroup As String, ByVal nodeName As String, ByVal nodeText As String) As Boolean

        Dim result As Boolean = False

        Try

            ' Verifica se o ficheiro existe
            If Not IO.File.Exists(xmlPath) Then
                Return False
            End If

            ' Cria um novo XmlDocument e carrega o ficheiro XML
            Dim xmlDoc As New XmlDocument
            xmlDoc.Load(xmlPath)

            ' Selecciona o grupo escolhido
            Dim node As XmlNode = xmlDoc.SelectSingleNode("//" + nodeGroup)

            ' Cria um novo elemento e define o texto
            Dim newNode As XmlNode = xmlDoc.CreateElement(nodeName)
            newNode.InnerText = nodeText

            ' Insere o novo XmlNode
            node.AppendChild(newNode)

            ' Grava as alterações
            xmlDoc.Save(xmlPath)
            Return True

        Catch ex As Exception
            ' Em caso de erro retorna False
            Return False
        End Try

End Function

Para utilizar estas funções e manipular o ficheiro XML é só necessário:

' Adicionar informação
Dim result As Boolean = AddXMLNode("utilizadores", "user", "Ana Dias")
If result Then
       Debug.WriteLine("Ficheiro XML actualizado ...")
End If

' Remover informação
Dim result As Boolean = RemoveXMLNode("favoritos", http://www.google.com)
If result Then
       Debug.WriteLine("Ficheiro XML actualizado ...")
End If

Estes são apenas alguns exemplos de como utilizar um ficheiro XML para guardar informação. Neste caso foi utilizado uma estrutura muito simples, podendo-se no entanto criar um ficheiro mais complexo com a utilização de atributos, mais tags, etc.  

O objectivo deste artigo e mostrar que é simples e prático guardar informação, podendo ser utilizado em inúmeras situações como guardar definições, fazer backups de bases de dados, copiar dados, etc.

PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!


Excel: Criação de Add-Ins

Um Excel Add-In é um ficheiro com a extensão *.xla que tem funções personalizadas, utilizando código VBA, e que inicia automaticamente quando o Excel é aberto. Estas funções personalizadas, também designadas por UDF’s (User Defined Functions), permitem ser executadas independentemente do documento que esteja aberto. Ou seja, podemos criar uma macro/função para um determinado ficheiro de Excel, mas se necessitarmos de uma macro/função que seja necessário funcionar em qualquer documento, usamos um Add-In.

Para mostrar a criação e implementação de um Add-In irá ser mostrado um exemplo de como criar um novo menu e executar um ciclo que irá apagar datas, numa lista, inferiores à data actual.

Para criarmos então um Add-In no Excel deveremos fazer o seguinte:

1 – Iniciar o Excel e abrir o Editor de Visual Basic (Tools – Macros – Visual Basic Editor ou ALT+F11)

2 – Com o Visual Basic Editor aberto fazer um duplo clique no ThisWorkbook (que é onde se insere o código comum a todas as folhas ou WorkSheets) e insere-se o seguinte código:

' Quando o Workbook é aberto, usando o evento Open()
Private Sub Workbook_Open()

  ' Insere um novo separador e um menu no final da posição 6 (Menu Tools)
  With Application.MenuBars(xlWorksheet).Menus(6).MenuItems
      .Add Caption:="-"
      .Add Caption:="&Apagar Datas", OnAction:="ApagarDatas"
  End With

End Sub

Este código irá criar um novo separador e um novo menu que executa o Sub (procedimento) ApagarDatas().

3 – Adiciona-se um novo módulo e inserir o seguinte código:

' -------------------------------------------------------------------------------------------------
' Apaga as linhas em que a data da coluna A é inferior à data actual
' -------------------------------------------------------------------------------------------------
Public Sub ApagarDatas()
  Dim msg As String
  msg = "Deseja apagar as datas da lista inferiores à actual ?"
    

  ' Pergunta ao utilizar se pretende continuar, seleccionando por defeito o botão "No"
  If MsgBox(msg, vbYesNo + vbQuestion + vbDefaultButton2) = vbYes Then

    ' Desactiva as actualizações no ecrã e altera os cálculos 
    ' para manual. Como existem dados aleatórios na folha, sempre
    ' que se apagava uma linha actualizava tudo
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual       

    ' Declaração de variáveis
    Dim firstRow As Long, lastRow As Long
    Dim x As Long

    firstRow = 2

    ' Calcula qual a ultima linha preenchida
   lastRow = Cells(65536, 1).End(XlDirection.xlUp).Row()

    ' Inicia um ciclo que irá percorrer os dados. Como se trata de
    ' apagar linha deve-se começar de baixo para cima
    For x = lastRow To firstRow Step -1

        ' Verifica se é uma data válida
        If IsDate(Cells(x, 1).Value) Then

            ' Compara com a data actual e caso seja inferior apaga a linha
            If CDate(Cells(x, 1).Value) < Date Then
                    Cells(x, 1).EntireRow.Delete
            End If

        End If

    Next x

    ' Repõe as actualizações/cálculos
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
      

  End If

End Sub

     

Este código fará então um ciclo na folha ou WorkSheet seleccionada, em todas as linhas, e verificará na coluna “A” se a data existente é inferior à actual. Caso seja inferior apagará a linha.

4 – No Visual Basic Editor ou na folha de cálculo fazer um Save As e no tipo de ficheiro seleccionar “Microsoft Office Excel Add-In (*.xla). Podemos ainda no menu Tools – VBAProject Properties indicar detalhes sobre o nosso Add-In e definir uma password. Com a password o Add-In funcionará na mesma apenas bloqueia a visualização do código.

5 – Ir ao Menu Tools – Add-Ins, seleccionar Browse e escolher o ficheiro criado.

6 – Reiniciar o Excel

Se todos os passos forem cumpridos, quando iniciarmos o Excel estará disponível um novo menu com a descrição “Apagar Datas”. Para testar esta nova opção vamos construir um ficheiro com as seguintes formulas:


 a) Inserir na célula A1 a seguinte formula e copiar até à A50 para criar uma data aleatória entre os dias 1 e 28 de qualquer mês do corrente ano:

     =DATE(2008;RANDBETWEEN(1;12);RANDBETWEEN(1;28))

b) Inserir na célula B2 a seguinte formula e copiar até B50 e depois para as colunas C,D,E, etc. Esta formula irá criar um número aleatório entre 1 e 1000.

     =RANDBETWEEN(1;1000)

Executar a nova opção – ApagarDatas() – e verificar os resultados/funcionamento.

O objectivo deste artigo é mostrar como criar um Add-In no Excel, a sua utilidade e aplicação. Mostrar também como fazer um ciclo numa lista de valores, verificando qual a última linha preenchida e efectuar algumas verificações para eliminar dados. Este exemplo serve como demonstração e poderá ser adaptado de acordo com as diversas necessidades.

PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!




Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico