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

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!


VB.NET: Windows Service + FileSystemWatcher

Os Windows Services, normalmente conhecidos por Serviços NT, permite criar aplicações executáveis que correm junto dos serviços do sistema operativo do Windows. Estes serviços arrancam com o sistema operativo, independentemente do utilizador activo, e não são visíveis (correm em background), sendo portanto indicados para operações em servidores ou operações que não interferem com o utilizador. Antes do lançamento do.Net este processo era apenas conseguido por aplicações em C++, complicadas e não acessíveis a todos.

Como os Windows Services correm como serviço, não é possível utilizar controlos, mostrar mensagens ao utilizador através de msgbox’s, etc. Também não é possível validar o código criado, sendo aconselhável criar um programa normal “Windows Project”, testar e só depois colocar o código no serviço.

Para um exemplo de como criar e instalar um Windows Service, será utilizado outro componente do .Net Framework, o FileSystemWatcher.

O FileSystemWatcher é um componente no namespace System.IO que permite observar uma directoria específica. Ele verifica alterações nos ficheiros e sub-directorias de acordo com um determinado filtro e detecta se um ficheiro foi apagado, criado, modificado, etc, sendo uma excelente ferramenta de monitorização.

Neste exemplo será criado um serviço que irá monitorizar numa directoria os ficheiros mp3 e gravar num ficheiro log todas as alterações efectuadas.

Para criar o serviço é necessário executar os seguintes passo:

1 - Criar um novo projecto e seleccionar um “Windows Service”. Alterar o nome do projecto para myWindowsService. Irá ser criado um novo serviço com o nome Service1.vb


2 – Criar com o botão direito do rato sobre a área criada e seleccionar “Add Installer”. O Visual Studio irá criar dois itens: ServiceInstaller1 e ServiceProcessInstaller1.


O ServiceInstaller não faz parte do serviço em si, servindo apenas para registar o serviço quando este for instalado. É através dele que se especifica que tipo de arranque o serviço tem (Manual, Automatic ou Disabled), qual o nome visível, qual a descrição geral do serviço, entre outras definições.

O ServiceProcessInstaller é chamado pelo aplicativo de instalação e serve para escrever no registry do Windows informações sobre o serviço que se vai instalar.

Em conjunto estas duas classes permitem instalar um serviço de uma forma bastante simples.

3 – Seleccionado o ServiceInstaller1 alterar alguns dados, como a Description e DisplayName na janela Properties. Seleccionar o ServiceProcessInstaller1 e alterar a propriedade Account para LocalService.

4 – Seleccionar o Service1.vb e mudar para o código. É aqui que se desenvolve o código que o serviço irá executar. Utilizar o seguinte código.

Nota: Criar a directoria “c:\mp3\” ou alterar a localização no código do serviço

 

Imports System.IO

Public Class Service1

    ' Indicação do nome do ficheiro log
    Private Const logFileName As String = "c:\mp3\history.log"
    Private watcher As FileSystemWatcher

    ' No arranque do serviço 
    Protected Overrides Sub OnStart(ByVal args() As String)

        ' Cria uma nova instância do FileSystemWatcher
        watcher = New FileSystemWatcher

        ' Atribui eventos ao FileSystemWatcher
        AddHandler watcher.Deleted, AddressOf OnChanged
        AddHandler watcher.Created, AddressOf OnChanged
        AddHandler watcher.Renamed, AddressOf OnRenamed

        ' Indicação do filtro, caminho e activação
        With watcher
            .NotifyFilter = NotifyFilters.FileName
            .Path = "c:\mp3"
            .Filter = "*.mp3"
            .EnableRaisingEvents = True
        End With

        ' Mensagem inicial de arranque do serviço
        Dim logMsg As String = "Serviço iniciado em " & DateTime.Now.ToString
        My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

    End Sub

 

    ' Quando o serviço for parado
    Protected Overrides Sub OnStop()
        Dim logMsg As String = "Serviço parado em " & DateTime.Now.ToString
        My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)
    End Sub


   
' Quando um ficheiro for renomeado
    Sub OnRenamed(ByVal sender As Object, ByVal e As System.IO.RenamedEventArgs)

        Try

            ' Mensagem com o nome anterior e o novo nome do ficheiro
            Dim logMsg As String = _
                String.Format("Ficheiro renomeado de ""{0}"" para ""{1}"" em {2}", _
                e.OldName, e.Name, DateTime.Now.ToString)

            ' Escreve no ficheiro log
            My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

        Catch ex As Exception
            ' Em caso de erro, escreve a mensagem geral com o erro
            Dim logError As String = ex.Message.ToString & " - " & DateTime.Now.ToString
            My.Computer.FileSystem.WriteAllText(logFileName, logError & vbNewLine, True)

        End Try

    End Sub

 

    ' Caso algum ficheiro seja apagado ou criado
    Private Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs)

        Try 

            Dim logMsg As String = String.Empty

            ' Verifica qual a acção e cria a mensagem
            Select Case e.ChangeType
                Case WatcherChangeTypes.Created
                    logMsg = String.Format("Ficheiro ""{0}"" criado em {1}", e.Name, DateTime.Now.ToString)

                Case WatcherChangeTypes.Deleted
                    logMsg = String.Format("Ficheiro ""{0}"" apagado em {1}", e.Name, DateTime.Now.ToString)

            End Select

            ' Escreve no ficheiro log
            My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

        Catch ex As Exception
            ' Em caso de erro, escreve a mensagem geral com o erro
            Dim logError As String = ex.Message.ToString & " - " & DateTime.Now.ToString
            My.Computer.FileSystem.WriteAllText(logFileName, logError & vbNewLine, True)

        End Try

      End Sub

End Class


5 – Compilar o programa (build) e irá ser criado o myWindowsService.exe

Com o serviço já criado é apenas necessário instalá-lo. Para instalar um serviço é necessário utilizar um utilitário disponível com o .Net Framework e que corre em ambiente DOS - o InstallUtil.exe. Este ficheiro encontra-se na directoria de instalação da plataforma .Net Framework, como por exemplo para a versão 2.0 em C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\

6 – Ir ao menu do Windows Start – Run e escrever cmd para abrir uma janela do DOC


7 – Indicar a localização do ficheiro e do serviço criado para proceder à instalação. Exemplo:

Instalar:

<localização do ficheiro>\InstallUtil.exe <localização do serviço>\myWindowsService.exe

Desinstalar:

<localização do ficheiro>\InstallUtil.exe /u <localização do serviço>\myWindowsService.exe


 

Nota: Uma solução mais simples é copiar o ficheiro executável do serviço e o ficheiro InstallUtil.exe para o mesmo directório/pasta simplificando o comando no DOS.


8 – Para terminar ir ao Control PanelAdministrative ToolsServices e iniciar o serviço criado.


Para testar o serviço é só copiar ficheiros mp3 para dentro da directoria c:\mp3\, apaga-los, alterar os nomes e verificar o registo no ficheiro log. Caso seja necessário alterar algum código ao serviço é preciso desinstala-lo (ver ponto 7), efectuar as alterações, compilar o projecto e instalar novamente.

Este é um exemplo de como criar Windows Services e como são úteis para diversas aplicações. O FileSystemWatcher é utilizado no exemplo mas pode, obviamente, ser utilizado numa aplicação normal para o Windows.

 

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