Usuário com melhor resposta
Automação/Referência a variável global definida e inicializada em outro objeto "Application"

Pergunta
-
Boa noite amigos do fórum!
É possível inicializar uma referência a uma variável global definida em um dos módulos de um objeto Application (outra instância de qualquer aplicativo Office)?
vejam o contexto:
Private Sub teste() Dim app As Access.Application Dim master As bancoDados.masterModel Set app = GetObject("C:\bancoDados.accdb")
1 Debug.Print TypeName(app.Run("GetMasterModel")) 2 app.Run("GetMasterModel").locais.obter 3 Debug.Print app.Run("GetMasterModel").locais.Str '4 Set master = app.Run("GetMasterModel") Set app = Nothing End Sub
"GetMasterModel" retorna uma referência a uma variável global, do tipo masterModel, definida e inicializada em um dos módulos de bancoDados.
"1" - funciona, retornando "masterModel";
"2" - "locais", um membro de "masterModel", usa o método "obter" para carregar uma lista de uma das tabelas de bancoDados. Funciona graciosamente, como é comprovado em "3", que imprime a lista.
"4" - Ai está o problema, gera erro de "Tipos incompatíveis".
Se alguém puder me ajudar, ficaria agradecido. Outras alternativas também são bem vindas, a intenção final é conseguir a bendita referência.
Respostas
-
Não tenho Access para fazer testes agora. No entanto, consegui, com sucesso, utilizando o exemplo de ligação tardia (late binding), criar, alterar propriedades e executar um método de um objeto definido numa classe de uma pasta de trabalho (Excel como servidor) a partir de um módulo do Word (como cliente). A rotina que usei foi:
Sub ExemploLigaçãoTardia() Dim wb As Object 'Workbook Dim Galinha As Object Set wb = GetObject("C:\Users\Felipe\AppData\Local\Temp\Rar$DI02.662\MinhasAves.xlsm") Set Galinha = wb.Parent.Run("NewGalinha") Galinha.Nome = "Giselda" Galinha.Cacarejar End Sub
Nota: não foi necessário criar referência ao projeto MinhasAves.xlsm e nem ao Excel.
Felipe Costa Gualberto - http://www.ambienteoffice.com.br
- Sugerido como Resposta Hezequias VasconcelosModerator quinta-feira, 29 de novembro de 2012 12:48
- Marcado como Resposta Hezequias VasconcelosModerator sábado, 1 de dezembro de 2012 14:33
Todas as Respostas
-
Quando desejo obter uma variável global de outro projeto, utilizo a seguinte técnica:
1 - Utilizo o CreateObject ou GetObject, como fez;
2 - Executo o procedimento desejado, como fez, para inicializar e atribuir o valor à variável desejada.
3 - Executo uma função específica só para obter o valor da variável global. Suponha que a variável global se chama GsNome. Um exemplo seria:
Public GsNome As String Public GlIdade As Long '... outras variáveis globais ... Function ObterGlobal(sVariável As String) As Variant Dim Temp As Variant Select Case sVariável Case "GsNome": Temp = GsNome Case "GsIdade": Temp = GlIdade '... End Select ObterGlobal = Temp End Function
Acima, basta você chamar a função ObterGlobal("GsNome") para obter o valor dessa variável global.
Felipe Costa Gualberto - http://www.ambienteoffice.com.br
- Sugerido como Resposta Hezequias VasconcelosModerator terça-feira, 27 de novembro de 2012 18:34
-
Boa noite a todos!
Benzadeus, obrigado pela atenção parceiro!
O problema é que a técnica que usamos parece funcionar somente com tipos de dados simples (int, long, string, etc.) (retorno byValue). Se o objeto global que a função retorna, for um tipo definido pelo usuário, ao tentar criar uma referência para ele (retorno byRef) "set master = app.Run("GetMasterModel")", ocorre erro "Tipos incompatíveis". O engraçado é que passando o retorno para uma função da biblioteca como TypeName(), ou usando a notação ponto "bla.blabla", funciona como desejado.
E para piorar as coisas amigo, para meu projeto funcionar como desejado, eu ainda tenho que conseguir passar, byRef, objetos do banco atual, Ex.: app.Run("GetMasterModel").locais.addObserver(objASerPassado), o que, segundo testes que andei fazendo, gera o mesmo erro "Tipos incompatíveis". Inclusive, no desespero, tentei mudar "GetMasterModel" para "GetMasterModel(byRef objAReceberAReferencia)".
Generalizei o retorno da função "GetMasterModel" para "Object". Deixou de gerar o erro, porém, a variável que reteria a referência "set master = " fica vazia!
Me parece que essa técnica só funciona com valores retornados byValue. Se você Benzadeus, ou algum amigo, souber uma solução, por gentileza...
Obrigado a todos.
-
"Generalizei o retorno da função "GetMasterModel" para "Object". Deixou de gerar o erro, porém, a variável que reteria a referência "set master = " fica vazia!"
Tentou declarar como Variant?
Se nada disso der certo, sugiro você converter o tipo definido do outro projeto e convertê-lo numa classe, e então instanciá-lo de uma forma como mostrada aqui: http://www.ambienteoffice.com.br/officevba/criar_objetos_de_classes_definidas_em_outro_documento/
Felipe Costa Gualberto - http://www.ambienteoffice.com.br
-
Obrigado Benzadeus. Na realidade estou fazendo exatamente como sujerido no tutorial recomendado. Para simplificar meu primeiro post, alterei um pouco a função teste, veja o código mais aproximado do real:
No projeto servidor:
Public glb_model As masterModel Public Function getMasterModel() As masterModel If glb_model Is Nothing Then Set glb_model = New masterModel End If Set getMasterModel = glb_model End Function Public Function getInstance() As Access.Application Set getInstance = GetObject("C:\bancoDados.accdb") End Function
Nos projetos cliente(s):
Private Sub teste() Dim app As Access.Application Dim master As bancoDados.masterModel 1 Set app = bancoDados.getInstance 2 Set master = app.Run("GetMasterModel") "vai gerar erro" End Sub
Estou usando early binding. MasterModel é uma classe que criei. A intenção é ter vários projetos clientes que, ao inicializarem, executarão código parecido ao da Sub teste(). O projeto servidor inializará uma única vez, indiferente de quantos projetos clientes solicitarem uma instância "1", ele manterá as tabelas e as classes de modelo que representarão as tabelas. É por isso que não posso chamar "GetMasterModel" diretamente, como o fiz para obter a instância do servidor em "1". Eu necessito chamar "GetMasterModel" da instância já inicializada "2". Petendo fazer algo parecido com Model/View/Controller. Eu acho que o problema está em "Application.Run" que não está retornando a referência como "1" retorna, ou como se eu chamasse diretamente "GetMasterModel" retornando um novo "masterModel".
Obrigado novamente, parceiro...
- Editado HOTango quarta-feira, 28 de novembro de 2012 06:10
-
Não tenho Access para fazer testes agora. No entanto, consegui, com sucesso, utilizando o exemplo de ligação tardia (late binding), criar, alterar propriedades e executar um método de um objeto definido numa classe de uma pasta de trabalho (Excel como servidor) a partir de um módulo do Word (como cliente). A rotina que usei foi:
Sub ExemploLigaçãoTardia() Dim wb As Object 'Workbook Dim Galinha As Object Set wb = GetObject("C:\Users\Felipe\AppData\Local\Temp\Rar$DI02.662\MinhasAves.xlsm") Set Galinha = wb.Parent.Run("NewGalinha") Galinha.Nome = "Giselda" Galinha.Cacarejar End Sub
Nota: não foi necessário criar referência ao projeto MinhasAves.xlsm e nem ao Excel.
Felipe Costa Gualberto - http://www.ambienteoffice.com.br
- Sugerido como Resposta Hezequias VasconcelosModerator quinta-feira, 29 de novembro de 2012 12:48
- Marcado como Resposta Hezequias VasconcelosModerator sábado, 1 de dezembro de 2012 14:33