none
pedido de Socorro de um Dinossauro!! Programação em VBA para EXCEL RRS feed

  • Pergunta

  • Consulta

    Por favor estou com problemas p rodar uma aplicação que acabou ficando mais extensa do que pretendia e estou tendo erros de "variável do objeto não definida ou a variável do bloco with não foi definida", principalmente, e alguns outros problemas.

    Segue abaixo uma descrição dos problemas, já que o código ficou extenso, mas posso enviar o arquivo só com o código em PDF para ser analisado.

    Esta aplicação deverá rodar em versões antigas do EXCEL como 2003-2007 e 2010, além do 2013, por isso não posso utilizar recursos exclusivos do 2013 que é o que estou utilizando para desenvolver.

    Por indicação de um site resolvi definir todos os nomes e variáveis utilizadas na seção Options Explicit em um módulo padrão com o procedimento Sub Auto_open pretendendo com isso utilizar nos diversos módulos apenas o nome criado nesta área sem mais referências.

    Em um módulo padrão Sub Auto_Open declarei o seguinte:

    Os módulos de procedimentos foram nomeados (propriedade name) como m01_AbreFecha (apenas com os procedimentos SUB Auto_Open e Auto_Close), m02_Principal, etc, indicando as características dos procedimentos que continham (limpeza de elementos de tela, formatação de linhas, cálculos, etc.).

    Utilizei o módulo Sub Auto_Open também para executar alguns procedimentos de inicialização e formatação da tela que não funcionaram muito bem, pois foram executados apenas depois da ativação da primeira planilha, e tentei deixar neste módulo apenas as instruções para as definições e colocar os procedimentos de inicialização em um outro módulo, entretanto não fez nenhuma diferença.

    Todos os Nomes procurei colocar com significado o mais próximo do que efetivamente fazem (herança de programação estruturada em COBOL)

    1. Variáveis referentes  a Nomes de planilhas (Sheets) as Worksheets

    Os nomes internos (propriedade name) foram alterados p melhor visualização como p01_Inicio para planilha de Inicio do programa e os nomes externos (caption) para nomes identificáveis pelo usuário como Início para a planilha de abertura.

    Na seção Options Explicit defini esses nomes como "PUBLIC nome as Worksheet" e na seção Sub atribuí, através do comando: SET NomeInterno = NomeDaAplicacao.NomeInterno. Mesmo assim, qdo fiz referência apenas pelo nome criado  nos módulos de procedimentos deu erro. Apenas em alguns casos e não funcionou como esperava.


    2. Variáveis referentes a objetos RANGE.

    Todas as variáveis referentes a objetos RANGE, seja de área de planilha, uma célula, colunas ou linhas foram definidas nomeando no cpo de referência na linha de formulas, aparecendo no gerenciador de nomes, sendo todas com escopo de PASTA DE TRABALHO. Aqui além de outros problemas encontrei dificuldade para excluir (não excluía, ou melhor excluía, mas qdo abria o gerenciador estavam lá de volta e não alteravam, criando uma segunda com o mesmo nome e a nova referência).

    Essas variáveis tb foram explicitadas na Options Explicit como objeto RANGE e na seção Sub eu as repeti como comando SET repetindo as referências que apareciam no gerenciador de nomes:
    NomeDaArea = NomeDaAplicacao.NomeInternoDaPlanilha.Range("A1:C5") (tentei com o nome da planilha atribuído e deu erro, assim como sem o nome da aplicação)

    Nos módulos fui obrigado a referenciar sempre com: aplicação.planilha.Range("ref"), às vezes funcionou colocando o NomeDaArea definido, outras não, tive de utilizar a referencia às células. Não consegui entender porque, não reconheci um padrão.


    3. Variáveis referentes a nomes de procedimentos e macros.

    Também foram definidas na seção Options Explicit como objeto STRING, experimentei usar como objeto ACTION mas retornou erro.

    Na seção SUB procurei atribuir os nomes dos procedimentos às variáveis e, primeiro com o comando SET NomeDoProcedimento = "NomeDaAplicação.NomeDoMódulo.NomeDoProcedimento" (entre asas mesmo pq dava erro de compilação), depois sem o comando SET.
     
    Além da atribuição do nomes ás variáveis, utilizei o comando Application.MacroOptions(NomeDoProcedimento) para ativar as macros, mas não consegui o resultado esperado que seria utilizar apenas o NomeDoProcedimento, e tive de utilizar sempre referenciando NomeDaAplicação.NomeDoModulo.NomeDoProcedimento. No entanto funcionou qdo, em alguns procedimentos designei uma tecla para acionar a macro. O que me deu uma pista que estava no caminho certo.

    Além desses problemas, tive também dificuldade em copiar e colar conteúdos de áreas em planilhas que estavam ocultas, me obrigando a torná-las visíveis, executar o procedimento e ocultá-las novamente (Ainda bem que em uma das consultas aprendi a utilizar o Aplication.ScreenUpdating que melhorou o desempenho), mas não consegui fazê-lo quando utilizei procedimentos Worksheet_Activate nas planilhas de acesso ao usuário com comandos para esconder/mostrar elementos de tela como barras de rolagem, títulos, etc.).

    Eu gostaria também de poder impedir o redimensionamento da janela e deixar somente ativo o botão de encerrar
    porque os usuários que irão operar a planilha são muito básicos e não gostaria de deixar abertura para que conseguissem acessar o que não devem.

    PS: Não sou neófito em programação, minha experiência vem desde a década de 70, com linguagens procedurais como RPGII, COBOL, NATURAL (BD ADABAS) e um pouco de FORTRAN IV, além de ter um bom conhecimento em assembler da IBM da família /360, 370, 4341, A9), fui programador a analista até o final da década de 90 e meu conhecimento de C, pascal, VB, Delphi e outras linguagens pós 4ª geração, ficou mais na teoria e muito pouca prática. Planilhas eletrônicas eu as uso desde as primeiras como Open Access e outras, portanto peço ajuda e um pouco de paciência com um dinossauro. rsrsrsrs.

    Obrigado.

    Rui Martins


    quarta-feira, 15 de abril de 2015 20:31

Respostas

  • Suas perguntas são muito boas, no entanto, sugiro que na próxima vez crie um tópico por pergunta para não nos embaralharmos nas respostas. Verá que minha resposta está confusa e dividida em seções.

    ---

    Toda vez que quiser verificar se seu código está OK, clique no menu Depurar do VBE e selecione Compilar <nome do projeto>. Dessa forma, o VBE irá verificar se ainda há erros de compilação no seu projeto.

    ---

    Sobre procedimentos de inicialização e término: tudo bem colocar no Auto_Open e Auto_Close. Pessoalmente, prefiro utilizar os eventos de pasta de trabalho Workbook_Open e Workbook_BeforeClose, mas, como disse, é uma questão pessoal.

    ---

    Não dê nomes a procedimentos como m01_NomeProcedimento. Chame apenas de NomeProcedimento. Não polua ou dificulte a leitura do seu código dessa forma.

    ---

    Sobre seção 1, de planilhas.

    Nomeie as planilhas com, por exemplo, wsInício (sendo que ws significa Worksheet).

    Veja como faço:


    Fazendo apenas isso, não é necessário declarar variáveis nem atribuir planilhas à objetos. Você pode simplesmente utilizar wsCliente.Range("A1") = "Teste" e funcionará.

    ---

    Sobre objetos Range:

    "encontrei dificuldade para excluir (não excluía, ou melhor excluía, mas qdo abria o gerenciador estavam lá de volta e não alteravam, criando uma segunda com o mesmo nome e a nova referência)."
    Poderia explicar com mais detalhes essa questão? Não entendi.

    Você fez certo, crie Nomes com escopo de Pasta de Trabalho. Para acessá-los, é bem simples. Simplesmente utilize a forma [SeuNome]. Por exemplo:

        [Montante] = 5000
        MsgBox "O montante é: " & [Montante], vbInformation
    

    ---

    3 - Sobre variáveis

    "Também foram definidas na seção Options Explicit como objeto STRING, experimentei usar como objetoACTION mas retornou erro."
    Não entendi o que quis dizer com isso também. Poderia explicar com mais detalhes?

    ---

    "Na seção SUB procurei atribuir os nomes dos procedimentos às variáveis (...) NomeDoProcedimento = "NomeDaAplicação.NomeDoMódulo.NomeDoProcedimento" (...)"
    Por que está fazendo isso? Qual a necessidade?

    ---

    "Além desses problemas, tive também dificuldade em copiar e colar conteúdos de áreas em planilhas que estavam ocultas, me obrigando a torná-las visíveis, executar o procedimento e ocultá-las"
    É possível acessar e gravar conteúdo de células em planilhas ocultas. Poderia mostrar um exemplo de código que está utilizando para fazer isso?
    Sua observação sobre o Application.ScreeUpdating está correta.

    ---

    "mas não consegui fazê-lo quando utilizei procedimentos Worksheet_Activate nas planilhas de acesso ao usuário com comandos para esconder/mostrar elementos de tela como barras de rolagem, títulos, etc.).

    Se não quiser que eventos disparem ao selecionar planilhas que contém eventos, simplesmente altere a propriedade Application.EnableEvents = False, faça sua ação, e depois retorne Application.EnableEvents = True.

    ---

    "Eu gostaria também de poder impedir o redimensionamento da janela e deixar somente ativo o botão de encerrar"
    Isso pode ser um pouco complicado, infelizmente. Veja: http://stackoverflow.com/questions/20486944/detecting-in-vba-when-the-window-containing-an-excel-instance-becomes-active

    ---



    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    sexta-feira, 17 de abril de 2015 17:10
    Moderador

Todas as Respostas

  • Suas perguntas são muito boas, no entanto, sugiro que na próxima vez crie um tópico por pergunta para não nos embaralharmos nas respostas. Verá que minha resposta está confusa e dividida em seções.

    ---

    Toda vez que quiser verificar se seu código está OK, clique no menu Depurar do VBE e selecione Compilar <nome do projeto>. Dessa forma, o VBE irá verificar se ainda há erros de compilação no seu projeto.

    ---

    Sobre procedimentos de inicialização e término: tudo bem colocar no Auto_Open e Auto_Close. Pessoalmente, prefiro utilizar os eventos de pasta de trabalho Workbook_Open e Workbook_BeforeClose, mas, como disse, é uma questão pessoal.

    ---

    Não dê nomes a procedimentos como m01_NomeProcedimento. Chame apenas de NomeProcedimento. Não polua ou dificulte a leitura do seu código dessa forma.

    ---

    Sobre seção 1, de planilhas.

    Nomeie as planilhas com, por exemplo, wsInício (sendo que ws significa Worksheet).

    Veja como faço:


    Fazendo apenas isso, não é necessário declarar variáveis nem atribuir planilhas à objetos. Você pode simplesmente utilizar wsCliente.Range("A1") = "Teste" e funcionará.

    ---

    Sobre objetos Range:

    "encontrei dificuldade para excluir (não excluía, ou melhor excluía, mas qdo abria o gerenciador estavam lá de volta e não alteravam, criando uma segunda com o mesmo nome e a nova referência)."
    Poderia explicar com mais detalhes essa questão? Não entendi.

    Você fez certo, crie Nomes com escopo de Pasta de Trabalho. Para acessá-los, é bem simples. Simplesmente utilize a forma [SeuNome]. Por exemplo:

        [Montante] = 5000
        MsgBox "O montante é: " & [Montante], vbInformation
    

    ---

    3 - Sobre variáveis

    "Também foram definidas na seção Options Explicit como objeto STRING, experimentei usar como objetoACTION mas retornou erro."
    Não entendi o que quis dizer com isso também. Poderia explicar com mais detalhes?

    ---

    "Na seção SUB procurei atribuir os nomes dos procedimentos às variáveis (...) NomeDoProcedimento = "NomeDaAplicação.NomeDoMódulo.NomeDoProcedimento" (...)"
    Por que está fazendo isso? Qual a necessidade?

    ---

    "Além desses problemas, tive também dificuldade em copiar e colar conteúdos de áreas em planilhas que estavam ocultas, me obrigando a torná-las visíveis, executar o procedimento e ocultá-las"
    É possível acessar e gravar conteúdo de células em planilhas ocultas. Poderia mostrar um exemplo de código que está utilizando para fazer isso?
    Sua observação sobre o Application.ScreeUpdating está correta.

    ---

    "mas não consegui fazê-lo quando utilizei procedimentos Worksheet_Activate nas planilhas de acesso ao usuário com comandos para esconder/mostrar elementos de tela como barras de rolagem, títulos, etc.).

    Se não quiser que eventos disparem ao selecionar planilhas que contém eventos, simplesmente altere a propriedade Application.EnableEvents = False, faça sua ação, e depois retorne Application.EnableEvents = True.

    ---

    "Eu gostaria também de poder impedir o redimensionamento da janela e deixar somente ativo o botão de encerrar"
    Isso pode ser um pouco complicado, infelizmente. Veja: http://stackoverflow.com/questions/20486944/detecting-in-vba-when-the-window-containing-an-excel-instance-becomes-active

    ---



    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    sexta-feira, 17 de abril de 2015 17:10
    Moderador
  • OK! Felipe.

    Muito obrigado. Como a pergunta foi mto grande são muitas informações para verificar e vou seguir sua recomendação nas próximas vezes em fazer uma questão por tópico.

    Muito obrigado.

    Rui Martins

    domingo, 19 de abril de 2015 19:25