![]() |
||||||||
|
||||||||
|
com exemplos em VB |
Componente para deixar forms em Vb semelhantes às telas do winnamp |
Componente para colocar sua aplicação VB no Systray |
Componente para transformar sua aplicação VB em serviço |
Ferramentas úteis para quem usa Olap Server |
![]() |
|
||||||||||||||||||||||||||||
![]()
Pesquisa personalizada
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.
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 :
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 :
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 |
||||||||||||||||||||||||||||
Veja abaixo os comentários já enviados :
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 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