Ouvi falar muito sobre a aversão compreensível do uso .Select
no Excel VBA, mas não tenho certeza de como evitar usá-lo. Estou descobrindo que meu código seria mais reutilizável se eu pudesse usar variáveis em vez de Select
funções. No entanto, não sei como se referir a coisas (como a ActiveCell
etc.) se não estiver usando Select
.
Encontrei este artigo sobre intervalos e este exemplo sobre os benefícios de não usar o select, mas não consigo encontrar nada sobre como ?
Select
e / ouActiveSheet
etc etc são completamente inevitáveis. Aqui está um exemplo que eu encontrei: stackoverflow.com/questions/22796286/….Select / .Selection
necessário.Respostas:
Alguns exemplos de como evitar a seleção
Use
Dim
variáveis dSet
a variável para o intervalo necessário. Existem várias maneiras de se referir a um intervalo de célula únicaou um intervalo de várias células
Você pode usar o atalho para o
Evaluate
método, mas isso é menos eficiente e geralmente deve ser evitado no código de produção.Todos os exemplos acima se referem às células na planilha ativa . A menos que você deseje trabalhar apenas especificamente com a planilha ativa, é melhor reduzir também uma
Worksheet
variávelSe você não quer trabalhar com o
ActiveSheet
, para maior clareza, é melhor ser explícito. Mas tome cuidado, pois algunsWorksheet
métodos alteram a planilha ativa.Novamente, isso se refere à pasta de trabalho ativa . A menos que você deseje trabalhar apenas apenas com o
ActiveWorkbook
ouThisWorkbook
, é melhor reduzir também umaWorkbook
variável.Se você não quer trabalhar com o
ActiveWorkbook
, para maior clareza, é melhor ser explícito. Mas tome cuidado, pois muitosWorkBook
métodos alteram o livro ativo.Você também pode usar o
ThisWorkbook
objeto para se referir ao livro que contém o código em execução.Um código (ruim) comum é abrir um livro, obter alguns dados e fechar novamente
Isto é mau:
E seria melhor como:
Passagem varia a seus
Sub
s eFunction
s como variáveis GamaVocê também deve aplicar métodos (como
Find
eCopy
) a variáveisSe você estiver fazendo loop em um intervalo de células, geralmente é melhor (mais rápido) copiar os valores do intervalo para uma matriz variante primeiro e fazer um loop sobre esse
Esta é uma pequena amostra do que é possível.
fonte
rng1(12, 12)
, funcionará mesmo que rng1 tenha sido definido[A1:A10]
apenas.Range
assim:ActiveSheet.[a1:a4]
ouws.[b6]
.variant
variável não exigeSet
até você atribuir um objeto a ela. Por exemplo,Dim x: x = 1
está tudo bem, masDim x: x = Sheets("Sheet1")
irá gerar o Erro 438. No entanto, apenas para confundir / esclarecerDim x: x = Range("A1")
, não criará um erro. Por quê? ... porque ele é atribuído o valor do objeto para a variável, não uma referência ao próprio objeto (uma vez que é o equivalente aDim x: x = Range("A1").Value
)Duas razões principais pelas quais
.Select
/.Activate
/Selection
/Activecell
/Activesheet
/Activeworkbook
etc ... devem ser evitadasComo evitamos isso?
1) Trabalhe diretamente com os objetos relevantes
Considere este código
Este código também pode ser escrito como
2) Se necessário, declare suas variáveis. O mesmo código acima pode ser escrito como
fonte
Sheets(2).[C10:D12].Value = Sheets(1).[A1:B3].Value
.Activate
para ir para a página original, basta usar #Application.Goto
Um pequeno ponto de ênfase acrescentarei a todas as excelentes respostas dadas acima:
Provavelmente, a maior coisa que você pode fazer para evitar o uso do Select é, na medida do possível, usar intervalos nomeados (combinados com nomes de variáveis significativos) no seu código VBA . Este ponto foi mencionado acima, mas encoberto um pouco; no entanto, merece atenção especial.
Aqui estão algumas razões adicionais para fazer uso liberal de intervalos nomeados, embora eu tenha certeza de que poderia pensar em mais.
Intervalos nomeados tornam seu código mais fácil de ler e entender.
Exemplo:
É bastante óbvio o que os intervalos nomeados
Months
eMonthlySales
contêm e o que o procedimento está fazendo.Por que isso é importante? Parcialmente porque é mais fácil para outras pessoas entendê-lo, mas mesmo se você for a única pessoa que verá ou usará seu código, você ainda deve usar intervalos nomeados e bons nomes de variáveis, porque VOCÊ ESQUECERÁ o que você queria fazer com ele um ano depois, e você perderá 30 minutos apenas para descobrir o que seu código está fazendo.
Os intervalos nomeados garantem que suas macros não sejam interrompidas quando (não se!) A configuração da planilha for alterada.
Considere, se o exemplo acima tivesse sido escrito assim:
Esse código funcionará bem no começo - ou seja, até você ou um usuário futuro decidir "gee wiz, acho que vou adicionar uma nova coluna com o ano na coluna
A
!" Ou colocar uma coluna de despesas entre os meses e colunas de vendas ou adicione um cabeçalho a cada coluna. Agora, seu código está quebrado. E como você usou nomes terríveis de variáveis, levará muito mais tempo para descobrir como corrigi-lo do que deveria.Se você usou intervalos nomeados para começar, as colunas
Months
eSales
podem ser movidas à sua volta, e seu código continuará funcionando perfeitamente.fonte
Vou dar a resposta curta, já que todo mundo deu a longa.
Você obterá .selecione e .ativará sempre que gravar macros e reutilizá-las. Quando você seleciona uma célula ou planilha, ela apenas a ativa. A partir desse momento, sempre que você usar referências não qualificadas, como se
Range.Value
elas apenas utilizassem a célula e a folha ativas. Isso também pode ser problemático se você não observar onde seu código está colocado ou se um usuário clicar na pasta de trabalho.Portanto, você pode eliminar esses problemas referenciando diretamente suas células. Qual é:
Ou você poderia
Existem várias combinações desses métodos, mas essa seria a ideia geral expressa o mais breve possível para pessoas impacientes como eu.
fonte
Embora eu não consiga pensar em mais do que um punhado isolado de situações em
.Select
que seria uma escolha melhor do que o referenciamento direto a células, levanto-me à defesaSelection
e aponto que ele não deve ser jogado fora pelas mesmas razões que.Select
devem ser evitadas.Há momentos em que sub-rotinas macro curtas e que economizam tempo atribuídas a combinações de teclas de atalho disponíveis com o toque de duas teclas economiza muito tempo. Ser capaz de selecionar um grupo de células para decretar o código operacional nas maravilhas do trabalho ao lidar com dados em bolso que não estão em conformidade com um formato de dados para toda a planilha. Da mesma maneira que você pode selecionar um grupo de células e aplicar uma alteração de formato, selecionar um grupo de células para executar um código de macro especial pode economizar muito tempo.
Exemplos de subestrutura baseada em seleção:
O código real a ser processado pode ser qualquer coisa, desde uma única linha até vários módulos. Eu usei esse método para iniciar rotinas de execução longa em uma seleção irregular de células que contêm os nomes de arquivos de pastas de trabalho externas.
Em resumo, não descarte
Selection
devido à sua estreita associação com.Select
eActiveCell
. Como uma propriedade da planilha, ela tem muitos outros propósitos.(Sim, eu sei que essa pergunta era sobre
.Select
, não,Selection
mas eu queria remover quaisquer conceitos errados que os iniciantes em codificadores VBA possam inferir.)fonte
Selection
pode ser qualquer coisa na planilha; portanto, teste também o tipo do objeto antes de atribuí-lo a uma variável, pois você o declarou explicitamenteRange
.Observe que, a seguir, estou comparando a abordagem Select (aquela que o OP deseja evitar), com a abordagem Range (e essa é a resposta para a pergunta). Portanto, não pare de ler quando vir o primeiro Select.
Realmente depende do que você está tentando fazer. De qualquer forma, um exemplo simples pode ser útil. Vamos supor que você deseja definir o valor da célula ativa como "foo". Usando o ActiveCell, você escreveria algo como isto:
Se você deseja usá-lo para uma célula que não é a célula ativa, por exemplo, para "B2", você deve selecioná-la primeiro, assim:
Usando intervalos, você pode escrever uma macro mais genérica que pode ser usada para definir o valor de qualquer célula desejada para o que você desejar:
Em seguida, você pode reescrever Macro2 como:
E Macro1 como:
Espero que isso ajude a esclarecer um pouco as coisas.
fonte
Evitar
Select
eActivate
é a mudança que torna você um desenvolvedor de VBA um pouco melhor. Em geral,Select
eActivate
são usadas quando uma macro é gravada, portanto, aParent
planilha ou o intervalo é sempre considerado o ativo.É assim que você pode evitar
Select
eActivate
nos seguintes casos:Adicionando uma nova planilha e copiando uma célula nela:
De (código gerado com o gravador de macro):
Para:
Quando você deseja copiar o intervalo entre as planilhas:
De:
Para:
Usando intervalos nomeados sofisticados
Você pode acessá-los com
[]
, o que é realmente bonito, comparado ao contrário. Verifique você mesmo:O exemplo acima seria assim:
Não copiando valores, mas levando-os
Geralmente, se você estiver disposto
select
, provavelmente está copiando alguma coisa. Se você está interessado apenas nos valores, esta é uma boa opção para evitar a seleção:Range("B1:B6").Value = Range("A1:A6").Value
Tente sempre fazer referência à planilha também
Este é provavelmente o erro mais comum em vba. Sempre que você copia intervalos, às vezes a planilha não é referenciada e, portanto, o VBA considera a planilha errada como a ActiveWorksheet.
Posso realmente nunca usar
.Select
ou.Activate
para qualquer coisa?.Activate
e.Select
é quando deseja garantir que uma planilha específica seja selecionada por motivos visuais. Por exemplo, seu Excel sempre abriria com a planilha de capa selecionada primeiro, desconsiderando qual era o ActiveSheet quando o arquivo era fechado.Assim, algo como o código abaixo é absolutamente bom:
Outro bom exemplo é quando você precisa exportar todas as planilhas para um arquivo PDF, como mencionado neste caso - Como evitar instruções de seleção / ativas no VBA neste exemplo?
Quando um comando só funciona com
ActiveWindow
como ActiveWindow.Zoom ou ActiveWindow.FreezePanesfonte
.Select
- e também para o meu trabalho - pode ser encontrada em Como escrever informações idênticas em todas as folhas - @Vityata :).FillAcrossSheets
, então isso está em algum lugar no meio (pelo menos na minha idéia sobre taxonomia VBA)Sempre indique a pasta de trabalho, a planilha e a célula / intervalo.
Por exemplo:
Como os usuários finais sempre clicam nos botões e, assim que o foco sai da pasta de trabalho, o código deseja trabalhar e as coisas ficam completamente erradas.
E nunca use o índice de uma pasta de trabalho.
Você não sabe quais outras pastas de trabalho serão abertas quando o usuário executar seu código.
fonte
Esses métodos são bastante estigmatizados, assumindo a liderança do @Vityata e do @Jeeped com o objetivo de desenhar uma linha na areia:
Por que não chamar
.Activate
,.Select
,Selection
,ActiveSomething
métodos / propriedadesBasicamente, porque eles são chamados principalmente para lidar com a entrada do usuário por meio da interface do usuário do aplicativo. Como são os métodos chamados quando o usuário manipula objetos através da interface do usuário, eles são os registrados pelo macro-gravador, e é por isso que chamá-los é quebradiço ou redundante na maioria das situações: você não precisa selecionar um objeto para executar uma ação
Selection
logo em seguida.No entanto, essa definição resolve situações nas quais eles são chamados:
Quando chamar
.Activate
,.Select
,.Selection
,.ActiveSomething
métodos / propriedadesBasicamente, quando você espera que o usuário final desempenhe um papel na execução.
Se você estiver desenvolvendo e espera que o usuário escolha as instâncias do objeto para o seu código, então
.Selection
ou.ActiveObject
é apropriado.Por outro lado,
.Select
e.Activate
são de uso quando você pode inferir próxima ação do usuário e você quer que seu código para guiar o usuário, possivelmente salvando-lhe algum tempo e cliques do mouse. Por exemplo, se o seu código acabou de criar uma nova instância de um gráfico ou de uma atualizada, o usuário pode querer dar uma olhada e você pode chamá.Activate
-lo ou em sua planilha para economizar o tempo que o procura; ou se você souber que o usuário precisará atualizar alguns valores de intervalo, é possível selecionar programaticamente esse intervalo.fonte
O uso do IMHO
.select
vem de pessoas que, como eu, começaram a aprender VBA por necessidade, gravando macros e modificando o código sem perceber que o.select
subsequenteselection
é apenas um intermediário desnecessário..select
pode ser evitado, como muitos já postados, trabalhando diretamente com os objetos já existentes, o que permite várias referências indiretas, como calcular iej de maneira complexa e depois editar a célula (i, j), etc.Caso contrário, não haverá nada implicitamente errado
.select
e você poderá encontrar usos para isso facilmente. Por exemplo, eu tenho uma planilha que preenche com a data, ativa uma macro que faz mágica com ela e a exporta em um formato aceitável em uma folha separada, o que , no entanto, requer algumas entradas manuais finais (imprevisíveis) em uma célula adjacente. Então, aqui chega o momento para.select
que me salve esse movimento adicional do mouse e clique.fonte
Resposta rápida:
Para evitar o uso do
.Select
método, você pode definir uma variável igual à propriedade que deseja.► Por exemplo, se você quiser o valor,
Cell A1
poderá definir uma variável igual à propriedade value dessa célula.valOne = Range("A1").Value
► Por exemplo, se você quiser o codinome 'Sheet3', poderá definir uma variável igual à propriedade codename dessa planilha.
valTwo = Sheets("Sheet3").Codename
Espero que ajude. Deixe-me saber se você tiver alguma dúvida.
fonte
Notei que nenhuma dessas respostas menciona a propriedade .Offset . Isso também pode ser usado para evitar o uso da
Select
ação ao manipular determinadas células, particularmente em referência a uma célula selecionada (como o OP mencionaActiveCell
).Aqui estão alguns exemplos.
Também assumirei que o "ActiveCell" é J4 .
ActiveCell.Offset(2, 0).Value = 12
J6
para um valor de 12ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
k4
paraL4
.i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
Isso não significa que eles são "melhores" do que as opções acima, mas apenas listando alternativas.
fonte
Trabalhando com o recurso .Parent. Este exemplo mostra como a configuração de apenas uma referência myRng permite acesso dinâmico a todo o ambiente, sem .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet e assim por diante. (Não há recurso genérico .Child)
fonte
O principal motivo para nunca usar o Select ou o Activesheet é porque a maioria das pessoas terá pelo menos mais duas pastas de trabalho abertas (às vezes dezenas) quando executam sua macro e se clicarem fora da planilha enquanto a macro estiver em execução e clicar em alguma outra livro aberto, a "Folha de atividades" é alterada e a pasta de trabalho de destino de um comando "Selecionar" não qualificado também é alterada.
Na melhor das hipóteses, sua macro falhará; na pior das hipóteses, você pode acabar escrevendo valores ou alterando células na pasta de trabalho errada, sem nenhuma maneira de "Desfazer".
Eu tenho uma regra de ouro simples que sigo: Adicione variáveis denominadas "wb" e "ws" para um objeto de pasta de trabalho e um objeto de planilha e sempre as use para se referir ao meu livro de macro. Se precisar me referir a mais de um livro ou mais de uma folha, adiciono mais variáveis.
por exemplo
O comando "Set wb = ThisWorkbook" é absolutamente essencial. "ThisWorkbook" é um valor especial no Excel e significa a pasta de trabalho em que o seu código VBA está sendo executado . Um atalho muito útil para definir sua variável da pasta de trabalho.
Depois de fazer isso na parte superior do seu Sub, usá-los não poderia ser mais simples, basta usá-los onde quer que você use "Seleção":
Portanto, para alterar o valor da célula "A1" em "Saída" para "Olá", em vez de:
Agora podemos fazer isso:
O que não é apenas muito mais confiável e menos propenso a travar se o usuário estiver trabalhando com várias planilhas, também é muito mais curto, rápido e fácil de escrever.
Como um bônus adicional, se você sempre nomear suas variáveis "wb" e "ws", poderá copiar e colar o código de um livro para outro e geralmente funcionará com as alterações mínimas necessárias, se houver.
fonte
ThisWorkbook
... Não tenho certeza se o seu comentário está correto.Este é um exemplo que limpará o conteúdo da célula "A1" (ou mais, se o tipo de seleção for xllastcell, etc). Tudo feito sem ter que selecionar as células.
Espero que isso ajude alguém.
fonte
Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1").ClearContents
qual é uma linha e não duas e, na verdade, funciona sem selecionar células.