Skip Navigation Links



Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de Usuários
»Células Acadêmicas«
intcontpiada : 118
Os 3 Porquinhos
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
Faça um pequeno teste com 10 questões de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programação com nosso treinamento on-line de lógica de programação
.:.
Veja nosso calendário de treinamentos
Gostou da Página?
Então

para um amigo!

Pesquisa personalizada
Pesquisar Dicas:

 






Criando um ambiente de macros para sua aplicação

 

Criando um ambiente de macros para sua aplicação

 

Por mais que personalizemos nossa aplicação, sempre acaba faltando alguma coisa. Então uma boa solução é fazer como a MS fez no Office : Incluir um sistema de macros bem robusto.

 

No VB 6 podiamos utilizar um componente ActiveX para permitir executar código em VBScript através de nossa aplicação, permitindo ao usuário criar macros para manipular objetos de nossa aplicação. Temos um artigo sobre isso aqui no site, encontra-se em ...

 

No .NET temos um recurso chamado Visual Studio for Applications - VSA . O VSA nos permite incluir em nossa aplicação um sistema de macros, porém não será um sistema de macros em vbScript, mas sim em VB.NET, com todos os recursos do VB.NET .

 

Então vamos fazer uma demonstração de como inserir um sistema de macros em nossa aplicação.

 

Este artigo vai se dividir em 2 partes : primeiramente mostraremos todos os detalhes da criação da aplicação em si, para quem está iniciando em .NET será um exemplo interessante, para quem já conhece servirá para se familiarizarem com a aplicação.

 

Na 2a parte vou demonstrar como fazer a execução das macros, qual o procedimento necessário para fazer uso do VSA.

 

Criando a aplicação

 

Vamos criar uma aplicação simples que faça consulta na tabela clientes e exiba os dados em uma dataGrid. Disponibilizando o dataSet para a macro poderemos criar inúmeras macros para analisarem os dados de clientes.

 

 

As macros precisarão ser gravadas em banco de dados, então vamos criar uma tabela dentro do banco northwind para a gravação das macros.

 

NomeScript

Varchar

50

TextoScript

Varchar

2000

 

 

Vamos precisar criar menus para o disparo das macros que o usuário criar. Neste caso os menus precisarão ser criados dinamicamente de acordo com as macros que estarão gravadas em banco de dados. Veja o código de preenchimento dos menus :

 

    Public Sub preencherMenus()

        Dim dr As DataRowView

        MMacros.MenuItems.Clear()

        For Each dr In DsScripts1.Scripts.DefaultView

            Dim m As New MenuItem

            m.Text = dr("NomeScript")

            AddHandler m.Click, AddressOf disparaScript

            MMacros.MenuItems.Add(m)

        Next

    End Sub

 

 

Mmacros é o nome dado ao item de menu que irá conter as macros. Limpamos então os itens contidos em Mmacros e fazemos um laço na tabela scripts adicionando cada registro como um novo item de menu.

 

O AddHandler vincula o menu ao tratador de evento, uma sub chamada disparaScript que veremos mais adiante.

 

As macros serão utilizadas tanto pelo formulário principal da aplicação, que terá os menus para o disparo das macros, como pelo formulário de scripts, que irá permitir a edição das macros. Assim sendo teremos uma classe para gerenciar o dataSet de macros e esta classe será compartilhada por ambos os formulários. Veja como fica o código :

 

Public Class cmpScripts

    Inherits System.ComponentModel.Component

 

    Public Shared ScriptsMacros As New DSScripts

 

    Public Shared Function lerScripts() As DSScripts

        DA.Fill(ScriptsMacros)

        Return (ScriptsMacros)

    End Function

 

 

    Public Shared Sub GravarScripts()

        DA.Update(ScriptsMacros)

    End Sub

 

    Public Shared Property DA() As OleDb.OleDbDataAdapter

        Get

            If IsNothing(DAA) Then

                configurarAdapter()

            End If

            Return (DAA)

        End Get

        Set(ByVal Value As OleDb.OleDbDataAdapter)

            DAA = Value

        End Set

    End Property

 

    Private Shared Sub configurarAdapter()

        OleDbDeleteCommand1 = New System.Data.OleDb.OleDbCommand

        CN = New System.Data.OleDb.OleDbConnection

        DAA = New System.Data.OleDb.OleDbDataAdapter

        OleDbInsertCommand1 = New System.Data.OleDb.OleDbCommand

        OleDbSelectCommand1 = New System.Data.OleDb.OleDbCommand

        OleDbUpdateCommand1 = New System.Data.OleDb.OleDbCommand

        '

        'OleDbDeleteCommand1

        '

        OleDbDeleteCommand1.CommandText = "DELETE FROM Scripts WHERE (NomeScript = ?) AND (TextoScript = ? OR ? IS NULL AND " & _

        "TextoScript IS NULL)"

        OleDbDeleteCommand1.Connection = CN

        OleDbDeleteCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "NomeScript", System.Data.DataRowVersion.Original, Nothing))

        OleDbDeleteCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_TextoScript", System.Data.OleDb.OleDbType.VarChar, 8000, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "TextoScript", System.Data.DataRowVersion.Original, Nothing))

        OleDbDeleteCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_TextoScript1", System.Data.OleDb.OleDbType.VarChar, 8000, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "TextoScript", System.Data.DataRowVersion.Original, Nothing))

        '

        'CN

        '

        CN.ConnectionString = "User ID=sa;Asynchronous Connection=False;Data Source=""."";Tag with column collatio" & _

        "n when possible=False;Initial Catalog=Northwind;Client Failover=True;Auto Transl" & _

        "ate=True;Persist Security Info=False;Use Procedure for Prepare=1;Provider=""SQLOL" & _

        "EDB.1"";MARS Connection=False;Workstation ID=ALUNO77;Use Encryption for Data=Fals" & _

        "e;Packet Size=4096"

        '

        'DA

        '

        DAA.DeleteCommand = OleDbDeleteCommand1

        DAA.InsertCommand = OleDbInsertCommand1

        DAA.SelectCommand = OleDbSelectCommand1

        DAA.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "Scripts", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("NomeScript", "NomeScript"????'?;), New System.Data.Common.DataColumnMapping("TextoScript", "TextoScript")})})

        DAA.UpdateCommand = OleDbUpdateCommand1

        '

        'OleDbInsertCommand1

        '

        OleDbInsertCommand1.CommandText = "INSERT INTO Scripts(NomeScript, TextoScript) VALUES (?, ?); SELECT NomeScript, Te" & _

        "xtoScript FROM Scripts WHERE (NomeScript = ?)"

        OleDbInsertCommand1.Connection = CN

        OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, "NomeScript"))

        OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("TextoScript", System.Data.OleDb.OleDbType.VarChar, 8000, "TextoScript"))

        OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Select_NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, "NomeScript"))

        '

        'OleDbSelectCommand1

        '

        OleDbSelectCommand1.CommandText = "SELECT NomeScript, TextoScript FROM Scripts"

        OleDbSelectCommand1.Connection = CN

        '

        'OleDbUpdateCommand1

        '

        OleDbUpdateCommand1.CommandText = "UPDATE Scripts SET NomeScript = ?, TextoScript = ? WHERE (NomeScript = ?) AND (Te" & _

        "xtoScript = ? OR ? IS NULL AND TextoScript IS NULL); SELECT NomeScript, TextoScr" & _

        "ipt FROM Scripts WHERE (NomeScript = ?)"

        OleDbUpdateCommand1.Connection = CN

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, "NomeScript"))

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("TextoScript", System.Data.OleDb.OleDbType.VarChar, 8000, "TextoScript"))

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "NomeScript", System.Data.DataRowVersion.Original, Nothing))

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("O????'?riginal_TextoScript", System.Data.OleDb.OleDbType.VarChar, 8000, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "TextoScript", System.Data.DataRowVersion.Original, Nothing))

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_TextoScript1", System.Data.OleDb.OleDbType.VarChar, 8000, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "TextoScript", System.Data.DataRowVersion.Original, Nothing))

        OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Select_NomeScript", System.Data.OleDb.OleDbType.VarChar, 50, "NomeScript"))

 

    End Sub

End Class

 

Precisaremos criar também um formulário que permita ao usuário da aplicação criar suas próprias macros. Vamos chamar este formulário de Scripts. Precisaremos ter os seguintes objetos no formulário :

 

  • Uma listbox para listar as macros existentes
  • Uma textBox para a edição dos scripts
  • Um botão para salvar a macro
  • Um botão para fechar o formulário
  • Um botão para gravar a macro no servidor
  • Um botão para criar novas macros
  • Um botão para executar as macros

 

A listBox ficará vinculada com um dataSet contendo os scripts, exibindo assim a lista de macros existentes. No click da listbox programaremos para exibir o texto da macro dentro da textbox.

 

Faremos um controle para saber se o texto da textbox foi alterado ou não, se foi alertaremos o usuário da aplicação para que tenha a opção de salvar o script da textbox ou não.

 

Na criação de novas macros iremos solicitar um nome para a macro e criar um novo registro no dataSet. Neste novo registro iremos inserir um texto de script default. Vamos manter este texto guardado junto a aplicação na forma de um embeded resource.

 

Para controlar corretamente o processo de entrada em edição de um determinado registro e ter certeza de que o conteúdo da textbox foi gravado iremos centralizar esse trabalho em uma única sub. Veja como fica :

 

    Dim linEdicao As Integer

    Dim Alterado As Boolean

 

    Public Sub entrarEdicao(ByVal l As Integer)

        If Alterado Then

            Dim r As MsgBoxResult

            r = MsgBox("As alterações não estão salvas. Tem certeza que deseja descarta-las ?", MsgBoxStyle.YesNo, "Tem certeza?")

            If r = MsgBoxResult.No Then

                lstScripts.SelectedIndex = linEdicao

                Exit Sub

            End If

        End If

        txtEdicao.Text = "" & cmpScripts.ScriptsMacros.Scripts.DefaultView(l)("textoscript")

        linEdicao = l

        Alterado = False

    End Sub

 

A variável Alterado irá atuar como um flag para identificarmos se o texto contido nas textbox foi ou não alterado. Após a entrada em edição recebe, naturalmente, false, pois o texto ainda não foi alterado. No inicio da execução desta sub, porém, a variável é testada para determinar se iremos ou não exibir uma messagebox de confirmação.

 

A variável linEdicao mantém o número da linha que encontra-se em edição para que esta linha possa ser recuperada a qualquer instante.

 

Após o usuário confirmar a entrada em edição (caso necessário) atribuimos o script da macro para a textbox. Nesta linha temos o velho truque de concatenação de vazio (""), o que evita erros caso o conteúdo do campo seja dbNull.

 

O código para salvar o texto da macro contido na textbox também foi transformado em uma sub, pois será utilizado em mais de um local. Veja o código :

 

    Public Sub Salvar()

        If Alterado Then

            Alterado = False

            Dim dr As DataRowView

            dr = cmpScripts.ScriptsMacros.Scripts.DefaultView(cmpScripts.ScriptsMacros.Scripts.DefaultView.Find(lstScripts.SelectedValue))

            dr.BeginEdit()

            dr("textoscript") = txtEdicao.Text

            dr.EndEdit()

        End If

    End Sub

 

Só é necessário salvar caso o conteúdo da textbox esteja alterado, caso contrário não é necessário salvarmos. O código é simples : Obtemos a dataRowView utilizando um Find na dataView e fazemos a edição, alterando o script da macro.

 

Com isso o botão salvar apenas precisa chamar esta sub, veja :

 

    Private Sub cmdSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSalvar.Click

        Salvar()

        MsgBox("Script Gravado!")

    End Sub

 

 

A seleção de um item na listbox também fica bem simples, apenas descobrindo o número da linha do registro e pedindo que ele seja colocado em edição. Veja :

 

    Private Sub lstScripts_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstScripts.SelectedIndexChanged

        Dim linha As Integer

        linha = cmpScripts.ScriptsMacros.Scripts.DefaultView.Find(lstScripts.SelectedValue)

        entrarEdicao(linha)

    End Sub

 

O botão adicionar tem um pouco mais de trabalho mas nada que assuste :

 

    Dim sb As New StringBuilder

    Private Sub cmdAdicionar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAdicionar.Click

        Dim dr As DataRowView

        Dim nomeScript As String

        nomeScript = InputBox("Informe o nome do novo Script : ")

        If nomeScript <> "" Then

            dr = cmpScripts.ScriptsMacros.Scripts.DefaultView.AddNew()

            dr("nomeScript") = nomeScript

            dr("textoScript") = sb.ToString

            dr.EndEdit()

            lstScripts.Refresh()

            lstScripts.SelectedIndex = lstScripts.Items.Count - 1

            entrarEdicao(lstScripts.SelectedIndex)

        End If

    End Sub

 

É solicitado o nome da nova macro e, se informado, é incluido um novo registro através da datarowView. Atualiza-se a listbox e o novo registro entra em edição.

 

Observe o uso de uma variável sb do tipo stringBuilder. Esta variável estará guardando um script padrão para a macro. Esse script estará embeded dentro do assembly da aplicação e será lido no load deste form. Veja o script :

 

Imports System

Imports System.Data

Imports clDadosScr

 

Module Script

       Public sub main()

 

     end sub

end Module

 

 

Veja como fica o load do form :

 

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

 

        cmpScripts.ScriptsMacros.Scripts.DefaultView.Sort = "nomeScript"

        lstScripts.SelectedIndex = 0

        entrarEdicao(0)

 

        Dim arq As [Assembly]

        Dim srd As StreamReader

 

 

        arq = [Assembly].GetExecutingAssembly()

 

        'Observe a escrita do nome do resource embedded, um formato padrão

        srd = New StreamReader(arq.GetMani????'?festResourceStream("WindowsApplication10.modelo.txt"))

        sb.Append(srd.ReadToEnd)

 

    End Sub

 

Com este código colocamos o primeiro registro em edição e carregamos para o string builder o conteúdo de um arquivo modelo.txt, contendo o código de modelo para os scripts. Utilizamos reflections para fazer essa carga.

 

Faltam apenas poucos detalhes no código do formulário de edição de scripts. Veja :

 

        Public chamador As Form1

Private Sub cmdExecutar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdExecutar.Click

        Execucao.Executar(txtEdicao.Text, chamador.Ds1)

    End Sub

 

    Private Sub txtEdicao_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtEdicao.TextChanged

        Alterado = True

    End Sub

 

 

    Private Sub cmdFechar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdFechar.Click

        Me.Close()

    End Sub

 

    Private Sub cmdAtualizarBanco_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAtualizarBanco.Click

        If Alterado Then

            Salvar()

        End If

        cmpScripts.GravarScripts()

        MsgBox("Scripts gravados no banco!")

    End Sub

 

    Private Sub Scripts_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

        If Alterado Or cmpScripts.ScriptsMacros.HasChanges Then

            Dim r As MsgBoxResult

            r = MsgBox("Deseja mesmo perder as alterações atuais ?", MsgBoxStyle.YesNo)

            If r = MsgBoxResult.No Then

                e.Cancel = True

            End If

        End If

    End Sub

 

    Private Sub Scripts_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed

        chamador.preencherMenus()

    End Sub

 

 

A execução das macros (botão executar) será feita por uma classe separada, da qual trataremos mais adiante no artigo. Para a execução além de ser necessário o código da macro precisamos também do dataSet contendo os clientes, dataSet que encontra-se com o Form1. Por isso este formulário, Scripts, contém uma variavel "chamador" que conterá uma referência ao Form1.

 

A variável "alterado" precisa ser preenchida no textChanged da textbox, sinalizando que já ocorreram alterações na macro.

 

O botão fechar é muito simples, simplesmente um close, pois o resto do trabalho é feito nos eventos de fechamento.

 

O botão de atualização no banco também é bem simples. Apenas testa se existem atualizações não salvas no dataSet, se existirem salva. Por fim dispara o método de atualização existente na classe que faz o gerenciamento dos dados dos scripts.

 

O evento closing testa se existem alterações nas macros e se o usuário realmente deseja fechar o formulário. Já o evento closed aproveita-se novamente da variável "chamador" para disparar, no Form1, a reconstrução do menu com os nomes das macros.

 

 

Executando Macros

 

Para fazer a execução de macros com o VSA precisamos criar uma classe que irá controlar o fornecimento para o VSA dos objetos de nossa aplicação que serão manipulados pela macro. Essa classe precisará implementar a interface IVSASite

 

Esta classe irá interagir com uma classe Engine que controlará o processo de execução da macro. Nesta classe engine precisaremos estar adicionando referências para os assemblys onde estão definidas as nossas classes da aplicação, classes essas que serão manipuladas pela macro.

 

Porém não podemos adicionar ao engine referências ao arquivo executável. Consequentemente precisaremos construir as classes de nossa aplicação em um projeto a parte, uma classlibrary, para que possamos "entrega-lo" ao engine.

 

Veja como fica o código desta classe, que passaremos a chamar de Site :

 

Imports Microsoft.Vsa

Public Class AmbienteScript

    Implements Microsoft.Vsa.IVsaSite

    Dim m_Objects As New Hashtable

 

    Public Sub AdicionarObjeto(ByVal nome As String, ByVal objeto As Object)

        m_Objects.Add(nome, objeto)

    End Sub

 

    Public Sub GetCompiledState(ByRef pe() As Byte, ByRef debugInfo() As Byte) Implements Microsoft.Vsa.IVsaSite.GetCompiledState

        pe = Nothing

        debugInfo = Nothing

    End Sub

 

    Public ReadOnly Property colecaoObjetos() As Hashtable

        Get

            Return m_Objects

        End Get

    End Property

 

    Public Function GetEventSourceInstance(ByVal itemName As String, ByVal eventSourceName As String) As Object Implements Microsoft.Vsa.IVsaSite.GetEventSourceInstance

        Try

            Dim ev As Object = m_Objects(eventSourceName)

            Return ev

        Catch ex As Exception

            Throw New Microsoft.Vsa.VsaException(VsaError.GlobalInstanceInvalid)

        End Try

    End Function

 

    Public Function GetGlobalInstance(ByVal name As String) As Object Implements Microsoft.Vsa.IVsaSite.GetGlobalInstance

        Try

            Return (m_Objects(name))

        Catch ex As Exception

            Throw New Microsoft.Vsa.VsaException(VsaError.GlobalInstanceInvalid)

        End Try

    End Function

 

    Public Sub Notify(ByVal notify As String, ByVal info As Object) Implements Microsoft.Vsa.IVsaSite.Notify

 

    End Sub

 

    Public Function OnCompilerError(ByVal [error] As Microsoft.Vsa.IVsaError) As Boolean Implements Microsoft.Vsa.IVsaSite.OnCompilerError

        Dim msg1 As String = "Erro na linha " & [error].Line & vbCr & vbCr

        Dim msg2 As String = [error].LineText & vbCr

        Dim dlg As New dlgError

 

        dlg.rchError.Text = msg1 & msg2 & [error].Description

 

        dlg.ShowDialog()

        Return (True)

 

    End Function

End Class

 

 

Nesta classe definimos uma variável do tipo hashTable para podermos guardar os objetos que serão disponibilizados para a macro.

 

Implementamos então o método GetGlobalInstance e GetEventSourceInstance (este último não utilizado em nosso exemplo, já que não lidamos com eventos) para permitir a recuperação dos objetos. Esses métodos serão chamados internamente pela Engine.

 

Implementamos também o método AdicionarObjetos e a propriedade ColecaoObjetos. Não são obrigatórios mas são necessários para o bom funcionamento desta classe.

 

Implementamos então o getCompiledState e o Notify, formalidade para cumprir as exigências da interface.

Por fim implementamos o onCompileError. O interessante neste método é a gama de informações que o VSA nos fornece quando ocorre um erro de execução na macro, detalhando precisamente onde o erro ocorreu.

 

Agora que montamos a classe que será utilizada como site, veja uma sequencia de passos que serão necessários durante o processo de execução de uma macro :

 

  • Adicionar os objetos da aplicação na classe personalizada, que chamarei de site.
  • Configurar o engine e liga-lo ao site
  • Adicionar ao engine as referências aos Assemblys do framework que serão necessários para executar a macro
  • Adicionar ao engine as referências para os assemblys onde encontram-se os objetos personalizados
  • Adicionar o script da macro na engine
  • Compilar e, caso não hajam erros, executar a macro. Na verdade essa execução é a colocação da macro em um "Estado de execução", mas não o inicio da execução do código propriamente, que só acontece no passo seguinte.
  • Utilizando Reflections, obter uma referência a sub main da macro e disparar sua execução

 

 

Imports Microsoft.Vsa

Imports Microsoft.VisualBasic.Vsa

Imports System.Reflection

Public Class Execucao

    Public Shared Sub Executar(ByVal s As String, ByVal dados As clDadosScr.DS)

        Dim vsa_engine As New VsaEngine

        Dim vsa_site As New AmbienteScript

        Dim referencias As String() = {"system.dll", "mscorlib.dll", "System.drawing.dll", "system.data.dll", "System.xml.dll"}

 

        vsa_site.AdicionarObjeto("Dados", dados)

 

        'Configurações adicionais

 

        vsa_engine.RootMoniker = "DadosClientes://Dados/Clientes"

        vsa_engine.Site = vsa_site

 

        vsa_engine.InitNew()

        vsa_engine.RootNamespace = "DadosClientes"

        vsa_engine.RevokeCache()

        vsa_engine.GenerateDebugInfo = True

 

        'Inicio da configuração das referências

        Dim items As IVsaItems = vsa_engine.Items

 

        Dim ref As String

        Dim reference As IVsaReferenceItem

        For Each ref In referencias

 

            reference = items.CreateItem(ref, VsaItemType.Reference, VsaItemFlag.None)

            reference.AssemblyName = ref

        Next

 

        'Adicionar referência dos tipos personalizados, objetos globais

        Dim k As String

        For Each k In vsa_site.colecaoObjetos.Keys

            Dim al As String

            al = [Assembly].GetAssembly(vsa_site.colecaoObjetos(k).GetType).Location

            reference = items.CreateItem(al, VsaItemType.Reference, VsaItemFlag.None)

            reference.AssemblyName = al

 

            'configuração do item global

            Dim gi As IVsaGlobalItem

            gi = items.CreateItem(k, VsaItemType.AppGlobal, VsaItemFlag.None)

            gi.TypeString = vsa_site.colecaoObjetos(k).ToString

        Next

 

        'Definição do código

        Dim cod As IVsaCodeItem

        cod = items.CreateItem("script", VsaItemType.Code, VsaItemFlag.None)

        cod.SourceText = s

 

        'cod.AddEventSource("Dados", "clDadosScr.DS")

 

 

        'Compilação

 

        vsa_engine.Compile()

        If Not vsa_engine.IsCompiled Then

            vsa_engine.Close()

            Exit Sub

        End If

 

        'Execução

 

        vsa_engine.Run()

 

        'Disparar o método main

 

        Dim vsa_assembly As [Assembly] = vsa_engine.Assembly

        Dim tipo As Type

        Dim method_info As MethodInfo

 

        tipo = vsa_assembly.GetType(vsa_engine.RootNamespace & ".Script")

        method_info = tipo.GetMethod("main")

 

        method_info.Invoke(Nothing, Nothing)

        vsa_engine.Close()

    End Sub

 

End Class

 

 

Vamos analisar cada trecho do código acima para compreende-lo melhor.

 

        Dim vsa_engine As New VsaEngine

        Dim vsa_site As New AmbienteScript

        Dim referencias As String() = {"system.dll", "mscorlib.dll", "System.drawing.dll", "system.data.dll", "System.xml.dll"}

 

        vsa_site.AdicionarObjeto("Dados", dados)

 

 

Aqui criamos as variáveis site e engine e já adicionamos o dataSet (recebido como parâmetro) ao site. Temos também um array com o nome dos assemblys do framework para os quais faremos referência.

 

        vsa_engine.RootMoniker = "DadosClientes://Dados/Clientes"

        vsa_engine.Site = vsa_site

 

        vsa_engine.InitNew()

        vsa_engine.RootNamespace = "DadosClientes"

        vsa_engine.RevokeCache()

        vsa_engine.GenerateDebugInfo = True

 

 

Neste trecho inventamos o nome do rootMoniker, bem como o nome do rootNameSpace. Realizamos as configurações iniciais e vinculamos o site e a engine.

 

        'Inicio da configuração das referências

        Dim items As IVsaItems = vsa_engine.Items

 

        Dim ref As String

        Dim reference As IVsaReferenceItem

        For Each ref In referencias

 

            reference = items.CreateItem(ref, VsaItemType.Reference, VsaItemFlag.None)

            reference.AssemblyName = ref

        Next

 

A classe de Engine conterá, na propriedade items, diversos tipos diferentes de itens que serão utilizados para a execução da macro. Neste primeiro laço fazemos a adição das referências do framework, percorrendo o vetor de strings que as contem.

 

        'Adicionar referência dos tipos personalizados, objetos globais

        Dim k As String

        For Each k In vsa_site.colecaoObjetos.Keys

            Dim al As String

            Dim arl As New ArrayList

 

            al = [Assembly].GetAssembly(vsa_site.colecaoObjetos(k).GetType).Location

            If arl.IndexOf(al) = -1 Then

                reference = items.CreateItem(al, VsaItemType.Reference, VsaItemFlag.None)

                reference.AssemblyName = al

               arl.Add(al)

            End If

 

            'configuração do item global

            Dim gi As IVsaGlobalItem

            gi = items.CreateItem(k, VsaItemType.AppGlobal, VsaItemFlag.None)

            gi.TypeString = vsa_site.colecaoObjetos(k).ToString

        Next

 

 

Neste trecho utilizamos um único laço para realizar duas tarefas : Adicionar aos itens as referências aos assemblys criados por nós e que contém os objetos que estarão disponíveis para a macro e adicionar aos itens a denominação de cada objeto que estará disponível para a macro, o que fará com que eles sejam vistos como variáveis globais.

 

Considerando que utilizaremos apenas 1 objeto em nosso exemplo, um objeto dataSet, poderíamos fazer isso de forma mais simples com 3 ou 4 linhas. Mas a intenção no código acima foi criar um algorítimo generico que precise de pouca ou nenhuma correção independentemente de quantos e quais objetos sejam utilizados pela macro.

 

Desta forma realizamos um laço através da coleção de objetos no site e a cada objeto adicionamos a referência a seu assembly (utilizando reflections) e sua identificação global que será vista pela macro.

 

Quanto as referências aos assemblys, tomei o cuidado de utilizar um arraylist para controla-las. Isso porque poderíamos ter diversos dos objetos no site em um único assembly e, neste caso, não poderíamos duplicar a referência.

 

        'Definição do código

        Dim cod As IVsaCodeItem

        cod = items.CreateItem("script", VsaItemType.Code, VsaItemFlag.None)

        cod.SourceText = s

 

 

Por fim adicionamos na engine o próprio script da macro que será executada, utilizando o nome "script".

 

        'Compilação

 

        vsa_engine.Compile()

        If Not vsa_engine.IsCompiled Then

            vsa_engine.Close()

            Exit Sub

        End If

 

        'Execução

 

        vsa_engine.Run()

 

 

Neste trecho solicitamos a compilação do código da macro e, se não houverem erros, iniciamos a execução.

 

 

        Dim vsa_assembly As [Assembly] = vsa_engine.Assembly

        Dim tipo As Type

        Dim method_info As MethodInfo

 

        tipo = vsa_assembly.GetType(vsa_engine.RootNamespace & ".Script")

        method_info = tipo.GetMethod("main")

 

        method_info.Invoke(Nothing, Nothing)

        vsa_engine.Close()

 

 

Para enfim iniciarmos a execução fazemos mais uma vez uso dos recursos de reflections para obter o método main da macro e dispara-lo.

 

As Macros

 

Veja alguns exemplos de macros que podemos criar :

 

Calculo de Total

 

Imports System

Imports System.Data

Imports clDadosScr

 

Module Script

             Public sub main()

                        msgbox(dados.customers.rows.count,0,"Total de clientes")

     end sub

end Module

 

 

 

 

Dennes Torres

MCAD,MCSD,MCSE,MCDBA





Envie seus comentários sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentários nesta página

Veja abaixo os comentários já enviados :

Nome : Breno E-Mail : bmlm@ig.com.br
Mas e se eu quiser criar uma classe dentro da aplicação pra conseguir utilizar no script, como seria ?

Pois se uso uma classe interna ele referencia o próprio executável e apresenta erro de execução... esse tipo de situação tem solução ?
Nome : Dennes Torres E-Mail : dennes@bufaloinfo.com.br

No exemplo o script está utilizando a classe "dados", que é uma classe fornecida pela aplicação, para ser utilizada dentro do script.

[]'s

Dennes
Nome : KeiqAVL2 E-Mail : 68fqfqs0v7a@outlook.com
Muito bom Beto. Sem vocea jamais tmroaeis estes momentos registrados. Espero que a ABES tenha como armazenar este acervo para no futuro relembramos o nosso passado. As coisas boas que estamos fazendo Uma abrae7o, Vitorio.
Nome : 1 E-Mail : 1
1
Nome : yeezy shoes E-Mail : tqqvpgr@gmail.com
I discovered your weblog web site on google and examine a couple of of your early posts. Proceed to maintain up the very good operate. I simply additional up your RSS feed to my MSN News Reader. Searching for forward to studying more from you afterward!?
yeezy shoes https://is.gd/WKg6iO
Nome : air jordan 4 E-Mail : wgxvfibdxfj@gmail.com
plugins/guestbook

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Conheça mais sobre o nosso site :

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



Quer saber mais?
Faça um curso na Búfalo Informática, Treinamento e Consultoria e
Prepare-se para o Mercado!
Veja o que a Búfalo tem para você.

� Búfalo Informática, Treinamento e Consultoria - Rua Álvaro Alvim, 37 Sala 920 - Cinelândia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (21) 9240-5134 (21) 9240-7281 e-Mail:
contato@bufaloinfo.com.br