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: Utilizando o controlo ComboBox

O controlo ComboBox é um controlo muito utilizado nas aplicações. É na realidade a combinação de uma TextBox com uma ListBox. Este permite que sejam definidos alguns estilos o que permite ao utilizado inserir ou escolher dados, ou apenas escolher.

Apesar de bastante simples de utilizar, existem diferentes formas de adicionar itens à lista. Este artigo pretende mostrar algumas das formas de adicionar itens à ComboBox.

A utilização de uma base de dados com fonte de dados é muito comum. Neste pequeno exemplo é lida uma tabela de Access, através de um OleDbDataAdapter e preenchido um DataSet. Depois é definida a fonte de dados (DataSource), o item a listar (DisplayMember) e o item que guarda o valor (ValueMember).

A utilização de parâmetros para o comando Transact-SQL é muito importante. Neste caso tratasse de um exemplo simples, mas o uso de parâmetros evita um grande número de problemas, com é o caso de: formatos das datas (não é necessário especificar o formato correcto), nomes com aspas simples (não é necessário substituir as aspas dos nomes, como é o caso de O’Brien), valores numérico (não é necessário formatar os números), etc.

Imports System.Data.OleDb

    ' No evento Form Load irá ser carregados os dados da base de dados na combobox
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Try

            Dim connString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\dados.mdb;"

            ' Inicia uma ligação à base de dados
            Using connection As New OleDbConnection(connString)

                ' Select Statement que irá mostrar todos os vendedores activos, 
                ' excepto o vendedor que será definido no parâmetro
                Dim SQL As String = "SELECT * FROM Vendedores WHERE activo = ? AND vendedor <> ?"

                ' Define o DataAdapter e os parâmetros. O DataAdapter guarda a ligação, não
                ' sendo necessário abrir com o comando connection.Open()
                Dim da As New OleDbDataAdapter(SQL, connection)
                da.SelectCommand.Parameters.Add("activo", OleDbType.Boolean).Value = True
                da.SelectCommand.Parameters.Add("vendedor", OleDbType.VarChar).Value = "Jorge Paulino"

                ' Preenche o Dataset com os valores da base de dados
                Dim ds As New DataSet
                da.Fill(ds)

                ' Preenche a combobox
                With Me.ComboBox1
                    .DisplayMember = "vendedor"
                    .ValueMember = "id"
                    .DataSource = ds.Tables(0).DefaultView 

                    ' Definições para autocomplete
                    .DropDownStyle = ComboBoxStyle.DropDown
                    .AutoCompleteMode = AutoCompleteMode.Suggest
                    .AutoCompleteSource = AutoCompleteSource.ListItems
                End With

                ' Insere um novo item geral na posição 0
                ' com uma descrição geral a indicar o tipo de lista
                Dim dr As DataRow
                dr = ds.Tables(0).NewRow
                dr.Item("id") = 0
                dr.Item("vendedor") = "Lista Vendedores"
                ds.Tables(0).Rows.InsertAt(dr, 0)

               
' Selecciona o item inserido
                Me.ComboBox1.SelectedIndex = 0 

            End Using

        Catch ex As Exception
            MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)

        End Try 

    End Sub

 

Para verificar o item seleccionado, ou o valor, basta fazer o seguinte:

        Debug.WriteLine("Valor seleccionado: " & Me.ComboBox1.SelectedValue)

        Debug.WriteLine("Texto seleccionado: " & Me.ComboBox1.Text)


Depois, pode-se validar e forçar a seleccionar o item da lista. Para o fazer pode-se utilizar o seguinte código, que verifica se o texto da ComboBox está disponível na sua lista, e caso contrário, mostra uma mensagem de erro e selecciona o item por defeito.

Este exemplo não se aplica se o estilo seleccionado for o DropDownList.

    ' No evento Leave verifica se o item escolhido/inserido existe na lista
    Private Sub ComboBox1_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.Leave

        ' Guarda a informação do texto actual
        Dim comboText As String = Me.ComboBox1.Text 

        ' Pesquisam texto na ComboBox e caso não encontre
        If Me.ComboBox1.FindString(comboText) = -1 Then
            MessageBox.Show("O vendedor seleccionado não é válido")
            Me.ComboBox1.SelectedIndex = 0
        End If 

    End Sub

 

Mas existem métodos mais simples de carregar dados na ComboBox. Pode-se, por exemplo, usar um destes métodos para inserir itens à ComboBox em modo run-time .

        ' Define um array de meses
        Dim items() As String = {"Jan", "Fev", "Mar", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"}

        ' Adiciona o itens à ComboBox e define o estilo com 
        ' DropDownList, ou seja, apenas é possível seleccionar
        With Me.ComboBox2
            .DropDownStyle = ComboBoxStyle.DropDownList
            .Items.AddRange(items)
        End With
   

Finalmente um método bastante usual que insere 50 itens com o formato “01”, “02”, “03”, …

        ' Ciclo que insere 50 itens
        For x As Byte = 0 To 49
            Me.ComboBox2.Items.Add("Item " & x.ToString.PadLeft(2, "0"))
        Next

São pequenos exemplos que pretendem apenas mostrar alguma alternativas de inserir dados em modo run-time à ComboBox, em especial com a utilização de uma base de dados em Access como fonte de dados.                                           

 

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


VB.NET: Criando HotKeys (teclas de atalho)

Em diversos programas é usual existirem combinações de teclas que executam determinadas tarefas. Estas combinações, normalmente designadas por HotKeys, simplificam a utilização da aplicação. Por exemplo, a combinação CTRL+A abre o Form A, Shift+B imprimir o relatório B, etc. Esta funcionalidade é bastante prática e simples de implementar mas apenas funciona quando o Form está seleccionado (com focus).


Para criar uma ou mais HotKeys que funcionem mesmo sem a aplicação estar seleccionada, utilizasse a função RegisterHotKey(). Deste modo é possível detectar e manipular sempre que uma tecla ou uma combinação de teclas é executada.

Existem combinações que podem ser sobrepostas (por exemplo CTRL+C, ALT+TAB, etc) e por isso é preciso bastante cuidado ao utilizar este código. A má ou incorrecta utilização pode prejudicar o correcto funcionamento do sistema operativo. O objectivo não é desabilitar combinações de teclas mas sim criar combinações ou atalhos que permitam, por exemplo, abrir uma aplicação que está escondida ou que se encontra no "system tray".

O seguinte exemplo mostra como criar algumas HotKeys. Algumas servem apenas para mostrar as implicações caso exista uma má utilização. No final é necessário fazer o processo inverso, ou seja, remover a HotKey do registo, utilizando a função UnregisterHotKey().

   

    ' Cria uma nova lista que guarda os ID's registados
    Private RegistedIDs As New List(Of Integer)

    ' Declara um evento que irá indicar o número do ID registado
    Public Event HotkeyPressedID(ByVal ID As Integer)

    Public Enum HotKeyModifiers
        None = 0
        Alt = 1
        Control = 2
        Shift = 4
        Windows = 8
    End Enum

    ' API's para registar e remover o registo das hotkeys
    Private Declare Function RegisterHotKey Lib "user32" (ByVal handle As IntPtr, ByVal ID As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Boolean
    Private Declare Function UnregisterHotKey Lib "user32" (ByVal handle As IntPtr, ByVal ID As Integer) As Boolean


   
''' <summary>
    ''' Regista (ou tenta) um HotKey usando a respectiva API
    ''' </summary>
    ''' <param name="ID">Número único do registo</param>
    ''' <param name="Modifiers">Indicação do modifier</param>
    ''' <param name="KeyCombo">Indicação da tecla</param>
    Public Function RegisterHotKey(ByVal ID As Integer, ByVal Modifiers As HotKeyModifiers, ByVal KeyCombo As Integer) As Boolean

        ' Caso consiga registar a hotkey
        If RegisterHotKey(Me.Handle, ID, Modifiers, KeyCombo) Then   

            ' Adiciona à lista dos ID's registados
            RegistedIDs.Add(ID)
            Return True
        End If

    End Function

    ''' <summary>
    ''' Subrotina que executa uma acção de acordo com a combinação efectuada
    ''' </summary>
    ''' <param name="ID">Número do ID registado</param>
    Private Sub RegisterHotKeyExample_HotkeyPressedID(ByVal ID As Integer) Handles Me.HotkeyPressedID

        Select Case ID
            Case 0
                Me.TextBox1.AppendText(Now & " - Ctrl+Shift+F" & vbNewLine)
            Case 1
                Me.TextBox1.AppendText(Now & " - Windows+T" & vbNewLine)
            Case 2
                Me.TextBox1.AppendText(Now & " - Alt+Tab bloqueado" & vbNewLine)
            Case 3
                Me.TextBox1.AppendText(Now & " - Letra ‘a’ bloqueada" & vbNewLine)
            Case 4
                Me.TextBox1.AppendText(Now & " - Letra ‘b’ bloqueada" & vbNewLine)
        End Select

    End Sub

    ' Overrides ao WndProc e detecção se a combinação foi efectuada
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_HOTKEY As Integer = &H312

        ' Caso seja uma HotKey
        If m.Msg = WM_HOTKEY Then
            RaiseEvent HotkeyPressedID(m.WParam.ToInt32)
        End If   

        MyBase.WndProc(m)

    End Sub

   

    Private Sub RegisterHotKeyExample_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' No evento Form Load são registadas algumas teclas. Os ID's 2,3 e 4 servem
        ' apenas para mostrar que é preciso ter algum cuidado a utilizar este código  

        ' Ctrl-Shift-F
        RegisterHotKey(0, HotKeyModifiers.Control Or HotKeyModifiers.Shift, Keys.F)

        ' Windows+T
        RegisterHotKey(1, HotKeyModifiers.Windows, Keys.T)

        ' Alt+Tab (que irá apenas desabilitar esta combinação)
        RegisterHotKey(2, HotKeyModifiers.Alt, Keys.Tab)

        ' Desabilita as teclas ‘a’ e ‘b’
        RegisterHotKey(3, HotKeyModifiers.None, Keys.A)
        RegisterHotKey(4, HotKeyModifiers.None, Keys.B)

    End Sub


   
' MUITO IMPORTANTE: Garantir sempre que as teclas saem do registo, caso
    ' contrário o sistema operativo pode não funcionar correctamente
    Private Sub RegisterHotKeyExample_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

        ' Ciclo nos ID's registados
        For Each ID As Integer In RegistedIDs
            UnregisterHotKey(Me.Handle, ID)
        Next

    End Sub


Cada número da HotKey tem de ser único e a combinação de teclas não pode estar a ser utilizada por outra thread. Caso aconteça o resultado do registo é falso e a combinação não é registada.

   

Este exemplo mostra numa caixa de texto a informação da HotKey pressionada, mas é apenas ilustrativo. Existem diversas combinações que podem ser utilizadas que podem melhorar a funcionalidade da aplicação.   

Exemplo do artigo: DOWNLOAD DO FICHEIRO

   

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


Excel: Lista de Contactos - Parte I

O Microsoft Excel não é uma base de dados mas sim, como todos sabem, uma folha de cálculo. No entanto, e por ser bastante versátil e simples de trabalhar, há quem o utilize para tal. Não é aconselhável, pois existem outras formas de gerir dados, mas quando se trata de pouca informação e/ou informação que utilize muitos cálculos e gráficos, então porque não?

Para mostrar como criar uma gestão de dados em Excel, este artigo irá mostrar a criação de uma lista de contactos. É um exemplo simples, que será dividido em alguns artigos, irá mostrar a criação de um formulário para inserção de novos contactos. Nos próximos artigos deste exemplo, será mostrado como criar listagens, modificar dados, personalizar a folha, etc.

Neste artigo inicial podem-se ver alguns pontos de interesse: criação de funções, criação de sub rotinas ou rotinas auxiliares, ciclo nos controlos do userform, validação de dados, etc.

Para seja mais fácil a análise do código e como está a funcionar, será adicionado um exemplo no final do artigo.

Nesta folha de cálculo existem duas Worksheets: Principal e Registos. A Principal é onde serão colocado os botões de comando (para chamar os userforms), e a Registos onde serão guardados os dados. Foi ainda inserido um Userform. No userform, onde está o código principal, o código utilizado é o seguinte:

Option Explicit

' Função que verifica se o campo é válido e retorna o resultado da validação
Private Function ValidaContacto(ByVal Contacto As String, ByVal NomeCampo As String) As Boolean

    ' Verifica se o número de caracteres é diferente de 9 e não está vazio
    If Len(Contacto) <> 9 And Len(Contacto) <> 0 Then
        MsgBox "O campo " & NomeCampo & " não é válido.", vbExclamation
        ValidaContacto = False
        Exit Function
    End If

    ' Verifica se o campo é numérico e não está vazio
    If Not IsNumeric(Contacto) And Len(Contacto) <> 0 Then
        MsgBox "O campo " & NomeCampo & " não é numérico.", vbExclamation
        ValidaContacto = False
        Exit Function
    End If

    ' Caso não existam erros a função retorna um valor verdadeiro
    ValidaContacto = True

End Function

         

' Subrotina que limpa o formulário
Sub LimpaFormulario()
    Dim c As Control

    ' Faz um ciclo em todos os controls
    For Each c In Me.Controls

        ' Se o controlo for um TextBox
        ' limpa o texto do controlo
        If TypeOf c Is MSForms.TextBox Then
            c.Text = ""
        End If

    Next

    ' Coloca seleccionada a primeira opção
    OptionButton1.Value = True
    OptionButton2.Value = False
    OptionButton3.Value = False         

End Sub

         

' Insere o registo
Private Sub btnInserir_Click()

    ' Verifica se o campo nome está preenchido. Como este campo é de
    ‘ preenchimento obrigatório, não será utilizada a função ValidaContacto()
    If Len(txtNome.Text) = 0 Then
        MsgBox "O campo NOME é de preenchimento obrigatório.", vbExclamation
        Exit Sub
    End If

    ' Valida todos os campos. Como estes campos têm validações
    ' comuns (numérico e nove dígitos) foi criada uma função
    ' auxiliar de modo a reduzir e optimizar o código.
    If Not ValidaContacto(txtTelefone.Text, "TELEFONE") Then Exit Sub
    If Not ValidaContacto(txtTelemovel.Text, "TELEMÓVEL") Then Exit Sub
    If Not ValidaContacto(txtTrabalho.Text, "TELF. TRABALHO") Then Exit Sub
    If Not ValidaContacto(txtFax.Text, "FAX") Then Exit Sub

    ' Confirma se utilizador quer mesmo inserir o registo
    If MsgBox("Deseja inserir este registo ?", vbQuestion + vbYesNo + vbDefaultButton2) = vbYes Then

        Dim strGrupo As String
        Dim ultimaLinha As Long
        Dim ws As Worksheet

        Set ws = Worksheets("Registos")

        ' Verifica qual a ultima linha preenchida
        ultimaLinha = ws.Cells(65536, 1).End(xlUp).Row + 1

        ' Preenche as células
        ws.Cells(ultimaLinha, 1).Value = txtNome.Text

        ' Verifica qual a opção seleccionada
        If OptionButton1.Value Then
            strGrupo = "Familia"
        ElseIf OptionButton2.Value Then
            strGrupo = "Amigos"
        ElseIf OptionButton3.Value Then
            strGrupo = "Trabalho"
        End If

        ws.Cells(ultimaLinha, 2).Value = strGrupo
        ws.Cells(ultimaLinha, 3).Value = txtTelefone.Text
        ws.Cells(ultimaLinha, 4).Value = txtTelemovel.Text
        ws.Cells(ultimaLinha, 5).Value = txtTrabalho.Text
        ws.Cells(ultimaLinha, 6).Value = txtFax.Text
        ws.Cells(ultimaLinha, 7).Value = txtObs.Text

        ' Limpa o formulário
        Call LimpaFormulario()

        ' Coloca o cursor no campo Nome, para ficar pronto
        ' para a inserção de novos contactos
        txtNome.SetFocus

    End If

End Sub         

' Fechar o formulário
Private Sub btnFechar_Click()
    Unload Me
End Sub

' Limpar o formulário
Private Sub btnLimpar_Click()
    Call LimpaFormulario()
End Sub 

Este exemplo utiliza algum código mas poderá ser ainda mais complexo. Poderá, por exemplo, ser validado no campo telemóvel se inicia por 91,93 ou 96, obrigar o preenchimento de mais campos, obrigar a um número mínimo de caracteres, etc. O objectivo é no entanto mostrar como funciona e a implementação de alguns conceitos gerais.

Exemplo do artigo: DOWNLOAD DO FICHEIRO

         

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


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

Funções Recursivas

Recursão é um método de programação no qual uma função pode chamar a si mesma. O termo é usado de maneira mais geral para descrever o processo de repetição de um objecto de um jeito similar ao que já fora mostrado. Um bom exemplo disso são as imagens repetidas que aparecem quando dois espelhos são apontados um para o outro. (Fonte Wikipédia)

As funções recursivas são muito utilizadas nas diversas linguagens de programação. São funções que se chamam a si mesmo, permitindo simplificar código e executar tarefas que seriam bastante complicadas sem a sua utilização. Por exemplo, o preenchimento de uma Treeview ou mesmo o sistema utilizado na construção de fóruns, em que uma questão tem sub-questões e essa sub-questão pode ter mais sub-questões, e por aí fora.


Outro dos exemplos de aplicação deste método é a procura de controlos dentro de um Form. Através de um ciclo nos controlos do Form conseguem-se encontrar todos os seus controlos, mas os Containers (controlos que conseguem alojar outros controlos, como é o caso de um Panel ou GroupBox) podem por sua vez ter mais controlos. Um método recursivo resolve o problema.

No seguinte exemplo serão procuradas todas as CheckBoxes dentro do Form (incluindo dentro dos Containers) e seleccionar ou não seleccionar todas, de acordo com a escolha efectuada.


   
' Definição do tipo de acção
    Enum SelectOption
        Unselect = 0
        [Select] = 1
    End Enum


   
''' <summary>
    ''' Função recursiva que irá percorrer todos os controlos dentro
    '''  de um controlo principal, que será indicado
    ''' </summary>
    ''' <param name="ctrl">Controlo a </param>
    ''' <param name="option">Acção a efectuar</param>
    Private Sub SelectCheckBoxes(ByVal ctrl As Control, ByVal [option] As SelectOption)

        ' Ciclo em todos os controlos
        For Each c As Control In ctrl.Controls   

            ' Se o control for do tipo CheckBox converte para
            '  o tipo CheckBox e executa a opção indicada
            If TypeOf c Is CheckBox Then
                Dim cb As CheckBox = DirectCast(c, CheckBox)
                cb.Checked = [option]
            End If   

            ' Caso o controlo tenha sub-controlos, chama novamente
            ' a função actual (recursivamente) até não existirem mais.
            If c.HasChildren Then
                SelectCheckBoxes(c, [option])
            End If   

        Next

    End Sub


Finalmente para utilizar o Sub criado é apenas necessário:

    ' Selecciona todos os controlos
    Private Sub btnAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAll.Click
        SelectCheckBoxes(Me, SelectOption.Select)
    End Sub

    ' Retira a selecção de todos os controlos
    Private Sub btnNone_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNone.Click
        SelectCheckBoxes(Me, SelectOption.Unselect)
    End Sub

Este é um exemplo de como utilizar funções recursivas para seleccionar CheckBoxes mas poderá ser utilizado para procurar um controlo, contar o número de CheckBoxes seleccionadas, etc, etc.




Copiar dados do Excel para uma DataGridView

A DataGridView já tem a possibilidade de permitir copiar os seus dados e colar em outra aplicação. A propriedade que permite isto é a ClipboardCopyMode, que por defeito está seleccionada para EnableWithAutoHeaderText. No entanto o inverso não está previsto.

Para se adicionar está possibilidade à DataGridView é necessário ler a classe Clipboard através da sua função GetText(). Deste modo consegue-se ler o que está no Clipboard e colocar na DataGridView.

Este exemplo, que mostra como implementar esta funcionalidade, utiliza uma DataGridView sem estar vinculada a dados e utiliza a combinação de teclas Ctrl+V para colar os dados. Verifica ainda se o número de colunas copiadas é igual ao número de colunas existentes.

    ' No evento KeyDown da DataGridView
    Private Sub DataGridView1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown

        ' Caso as teclas pressinadas sejam CTRL+V
        If e.Control AndAlso e.KeyCode = Keys.V Then

            Try   

                ' Ciclo nas linhas copiadas
                For Each line As String In Clipboard.GetText.Split(vbNewLine)

                    ' Separa as colunas referentes à linha actual
                    Dim item() As String = line.Trim.Split(vbTab)

                    ' Se o número de colunas for diferente mostra uma mensagem de erro
                    If item.Length <> Me.DataGridView1.ColumnCount Then
                        Dim str As String = "O número de colunas copiadas é diferente do número de colunas da DataGridView"
                        Throw New Exception(str)
                    End If

                    ' Adicionar a linha a DataGridView
                    Me.DataGridView1.Rows.Add(item)

                Next

            Catch ex As Exception

                ' Mensagem de erro caso exista
                MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)

            End Try

        End If

    End Sub

   

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