none
Automação/Referência a variável global definida e inicializada em outro objeto "Application" RRS feed

  • 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.

    segunda-feira, 26 de novembro de 2012 01:03

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

    quarta-feira, 28 de novembro de 2012 21:54
    Moderador

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

    segunda-feira, 26 de novembro de 2012 20:40
    Moderador
  • 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.

    
    
    
    
    terça-feira, 27 de novembro de 2012 22:58
  • "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

    quarta-feira, 28 de novembro de 2012 01:15
    Moderador
  • 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
    quarta-feira, 28 de novembro de 2012 02:36
  • 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

    quarta-feira, 28 de novembro de 2012 21:54
    Moderador