Quando eu quero encontrar o último valor de célula usado, eu uso:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
Estou obtendo a saída errada quando coloco um único elemento em uma célula. Mas quando eu coloco mais de um valor na célula, a saída está correta. Qual a razão por trás disso?
excel
vba
excel-formula
James
fonte
fonte
Respostas:
NOTA : Pretendo fazer deste um "posto único" onde você possa usar o
Correct
caminho para encontrar a última linha. Isso também abordará as práticas recomendadas a serem seguidas ao encontrar a última linha. E, portanto, continuarei atualizando sempre que encontrar um novo cenário / informação.Maneiras não confiáveis de encontrar a última linha
Algumas das maneiras mais comuns de encontrar a última linha que não são confiáveis e, portanto, nunca devem ser usadas.
UsedRange
NUNCA deve ser usado para encontrar a última célula que possui dados. É altamente não confiável. Tente este experimento.Digite algo na célula
A5
. Agora, quando você calcula a última linha com qualquer um dos métodos fornecidos abaixo, ele fornecerá 5. Agora, pinte a célula deA10
vermelho. Se você agora usa qualquer um dos códigos abaixo, ainda receberá 5. Se você usarUsedrange.Rows.Count
o que recebe? Não será 5.Aqui está um cenário para mostrar como
UsedRange
funciona.xlDown
é igualmente não confiável.Considere este código
O que aconteceria se houvesse apenas uma célula (
A1
) com dados? Você chegará à última linha da planilha! É como selecionar uma célulaA1
e pressionar a Endtecla e pressionar a Down Arrowtecla. Isso também fornecerá resultados não confiáveis se houver células em branco em um intervalo.CountA
também não é confiável porque fornecerá resultados incorretos se houver células em branco no meio.E, portanto, deve-se evitar o uso de
UsedRange
,xlDown
eCountA
para encontrar a última célula.Localizar última linha em uma coluna
Para encontrar a última linha na Col E, use este
Se você perceber que temos um
.
antesRows.Count
. Muitas vezes escolhemos ignorar isso. Veja ESTA pergunta sobre o possível erro que você pode receber. Eu sempre aconselho usar.
antesRows.Count
eColumns.Count
. Essa pergunta é um cenário clássico em que o código falhará porqueRows.Count
retorna65536
para o Excel 2003 e versões anteriores e1048576
para o Excel 2007 e versões posteriores. Da mesma formaColumns.Count
retorna256
e16384
, respectivamente.O fato acima que o Excel 2007+ possui
1048576
linhas também enfatiza o fato de que sempre devemos declarar a variável que manterá o valor da linha, pois, emLong
vez dissoInteger
, você receberá umOverflow
erro.Observe que essa abordagem ignorará todas as linhas ocultas. Olhando para a minha captura de tela acima da coluna A , se a linha 8 estivesse oculta, essa abordagem retornaria em
5
vez de8
.Localizar última linha em uma planilha
Para encontrar a
Effective
última linha na planilha, use isto. Observe o uso deApplication.WorksheetFunction.CountA(.Cells)
. Isso é necessário porque, se não houver células com dados na planilha,.Find
você forneceráRun Time Error 91: Object Variable or With block variable not set
Localizar última linha em uma tabela (ListObject)
Os mesmos princípios se aplicam, por exemplo, para obter a última linha na terceira coluna de uma tabela:
fonte
Usedrange.Rows.Count
o que obtém? Não será 5. Usedrange é altamente confiável para encontrar a última linha.remembers
a última configuração. Mesmo quando você faz manualmente umFind
, ele se lembra a última definição que na verdade é uma benção quando se sabe este "fato"UsedRange
( é altamente confiável encontrar a última célula que possui dados ) é enganosa.UsedRange
simplesmente não se destina a esse fim, mesmo que em alguns casos possa dar o resultado correto. Eu acho que o experimento proposto aumenta a confusão. O resultado obtido comUsedRange
($ A $ 1: $ A $ 8) não depende da entrada dos dados e da exclusão deles. A figura à direita ainda será a mesma, mesmo sem ter inserido os dados e excluído. Por favor, veja minha resposta.Nota: esta resposta foi motivada por este comentário . O objetivo de
UsedRange
é diferente do mencionado na resposta acima.Quanto à maneira correta de encontrar a última célula usada, é preciso primeiro decidir o que é considerado usado e depois selecionar um método adequado . Concebo pelo menos três significados:
Usado = não em branco, ou seja, com dados .
Used = "... em uso, significando a seção que contém dados ou formatação ." De acordo com a documentação oficial , este é o critério usado pelo Excel no momento da economia. Veja também esta documentação oficial . Se não estiver ciente disso, o critério pode produzir resultados inesperados, mas também pode ser explorado intencionalmente (com menos frequência, com certeza), por exemplo, para destacar ou imprimir regiões específicas, que podem eventualmente não ter dados. E, é claro, é desejável como critério o intervalo a ser usado ao salvar uma pasta de trabalho, para não perder parte do trabalho.
Usado = "... em uso, significando a seção que contém dados ou formatação " ou formatação condicional. O mesmo que 2., mas também incluindo células que são o destino de qualquer regra de Formatação Condicional.
Como encontrar a última célula usada depende do que você deseja (seu critério) .
Para o critério 1, sugiro ler esta resposta . Observe que
UsedRange
é citado como não confiável. Eu acho que isso é enganoso (ou seja, "injusto"UsedRange
), poisUsedRange
simplesmente não se destina a relatar a última célula que contém dados. Portanto, não deve ser usado neste caso, conforme indicado nessa resposta. Veja também este comentário .Para o critério 2,
UsedRange
é a opção mais confiável , em comparação com outras opções também projetadas para esse uso. Até torna desnecessário salvar uma pasta de trabalho para garantir que a última célula seja atualizada. Ctrl+ Endirá para uma célula incorreta antes de salvar ("A última célula não será redefinida até você salvar a planilha", em http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% 29.aspx É uma referência antiga, mas válida a esse respeito).Para o critério 3, não conheço nenhum método interno . O critério 2 não considera a formatação condicional. Pode-se ter células formatadas, com base em fórmulas, que não são detectadas por
UsedRange
ou Ctrl+ End. Na figura, a última célula é B3, pois a formatação foi aplicada explicitamente a ela. As células B6: D7 têm um formato derivado de uma regra de Formatação Condicional e isso não é detectado nem porUsedRange
. A contabilização disso exigiria alguma programação VBA.Quanto à sua pergunta específica : Qual é a razão por trás disso?
Seu código usa a primeira célula do seu intervalo E4: E48 como um trampolim, para saltar com ele
End(xlDown)
.A saída "incorreta" será obtida se não houver células não vazias no seu intervalo além da primeira. Então, você está pulando no escuro , ou seja, descendo a planilha (observe a diferença entre as sequências em branco e as vazias !).
Observe que:
Se seu intervalo contiver células não-contíguas e não-vazias, ele também fornecerá um resultado errado.
Se houver apenas uma célula não em branco, mas não for a primeira, seu código ainda fornecerá o resultado correto.
fonte
Criei essa função de parada única para determinar a última linha, coluna e célula, seja para dados, células formatadas (agrupadas / comentadas / ocultas) ou formatação condicional .
Os resultados são assim:
Para resultados mais detalhados, algumas linhas no código podem ser descomentadas:
Existe uma limitação - se houver tabelas na planilha, os resultados podem se tornar não confiáveis, por isso decidi evitar a execução do código neste caso:
fonte
Uma observação importante a ser lembrada ao usar a solução ...
... é garantir que sua
LastRow
variável seja doLong
tipo:Caso contrário, você acabará recebendo erros de SOBRECARGA em determinadas situações nas pastas de trabalho .XLSX
Esta é a minha função encapsulada que uso em vários usos de código.
fonte
Eu acrescentaria à resposta dada por Siddarth Rout para dizer que a chamada CountA pode ser pulada fazendo com que Find retorne um objeto Range, em vez de um número de linha, e depois teste o objeto Range retornado para ver se é Nothing (planilha em branco) .
Além disso, gostaria que minha versão de qualquer procedimento LastRow retornasse zero para uma planilha em branco, para que eu saiba que está em branco.
fonte
Gostaria de saber que ninguém mencionou isso, mas a maneira mais fácil de obter a última célula usada é:
Isso essencialmente retorna a mesma célula que você recebe Ctrl+ Endapós selecionar Célula
A1
.Uma palavra de cautela: o Excel monitora a célula mais à direita que já foi usada em uma planilha. Portanto, se, por exemplo, você digitar alguma coisa em B3 e outra em H8 e depois excluir o conteúdo de H8 , pressionar Ctrl+ Endainda o levará à célula H8 . A função acima terá o mesmo comportamento.
fonte
Last Cell
no Excel, às vezes se refere a uma célula vazia (deUsed Range
) diferente deLast Used Cell
;).Cells(1,1).Select()
são inválidasActiveSheet.Cells(1,1).Select
; talvez seja ; Também no VBA não é recomendável usarSelect
;).Set
.Como a pergunta original é sobre problemas em encontrar a última célula, nesta resposta listarei as várias maneiras pelas quais você pode obter resultados inesperados ; consulte minha resposta para "Como posso encontrar a última linha que contém dados na planilha do Excel com uma macro?" pela minha opinião sobre como resolver isso.
Começarei expandindo a resposta de sancho.s e o comentário de GlennFromIowa , adicionando ainda mais detalhes:
Outras coisas que você pode querer considerar:
Com isso em mente, vamos ver como as maneiras comuns de obter a "última célula" podem produzir resultados inesperados:
.End(xlDown)
código da pergunta será quebrado mais facilmente (por exemplo, com uma única célula não vazia ou quando houver células em branco no meio ) pelos motivos explicados na resposta aqui por Siddharth Rout (procure por "xlDown é igualmente não confiável" ).Count
ing (CountA
ouCells*.Count
) ou.CurrentRegion
também será interrompida na presença de células ou linhas em branco..End(xlUp)
pesquisar para trás a partir do final de uma coluna, assim como CTRL + UP, procura dados (as fórmulas que produzem um valor em branco são considerados "dados") nas linhas visíveis (portanto, usá-lo com o filtro automático ativado pode produzir resultados incorretos ⚠️ )Você deve tomar cuidado para evitar as armadilhas padrão (para obter detalhes, consultarei novamente a resposta de Siddharth Rout aqui, procure a seção "Encontrar a última linha em uma coluna" ), como codificar a última linha (
Range("A65536").End(xlUp)
) em vez de confiarsht.Rows.Count
..SpecialCells(xlLastCell)
é equivalente a CTRL + END, retornando a célula mais abaixo e mais à direita do "intervalo usado"; portanto, todas as advertências que se aplicam ao "intervalo usado" também se aplicam a esse método. Além disso, o "intervalo usado" é redefinido apenas ao salvar a pasta de trabalho e ao acessarworksheet.UsedRange
, portanto,xlLastCell
pode produzir resultados obsoletos⚠️ com modificações não salvas (por exemplo, após a exclusão de algumas linhas). Veja a resposta próxima do dotNET .sht.UsedRange
(descrito em detalhes na resposta de sancho.s aqui) considera os dados e a formatação (embora não seja a formatação condicional) e redefine o "intervalo usado" da planilha , que pode ou não ser o que você deseja.Observe que um erro comum ️ é usar
.UsedRange.Rows.Count
⚠️, que retorna o número de linhas no intervalo usado, não o número da última linha (elas serão diferentes se as primeiras linhas estiverem em branco). Para obter detalhes, consulte a resposta do newguy em Como posso encontrar última linha que contém dados na planilha do Excel com uma macro?.Find
permite encontrar a última linha com quaisquer dados (incluindo fórmulas) ou um valor que não esteja em branco em qualquer coluna . Você pode escolher se está interessado em fórmulas ou valores, mas o problema é que redefine os padrões na caixa de diálogo Localizar do Excel ️️⚠️, o que pode ser altamente confuso para os usuários. Também precisa ser usado com cuidado, veja a resposta de Siddharth Rout aqui (seção "Encontrar a última linha em uma planilha" )Cells
em um loop geralmente são mais lentas do que reutilizar uma função do Excel (embora ainda possa ter bom desempenho), mas permitem especificar exatamente o que você deseja encontrar. Veja minha solução baseada emUsedRange
e matrizes VBA para encontrar a última célula com dados na coluna fornecida - ele lida com linhas ocultas, filtros, espaços em branco, não modifica os padrões de localização e é bastante eficiente.Qualquer que seja a solução que você escolher, tenha cuidado
Long
vez deInteger
armazenar os números das linhas (para evitar ficarOverflow
com mais de 65 mil linhas) eDim ws As Worksheet ... ws.Range(...)
vez deRange(...)
).Value
(que é aVariant
), evite lançamentos implícitos.Value <> ""
como eles falharão se a célula contiver um valor de erro.fonte
No entanto, esta pergunta está procurando encontrar a última linha usando o VBA, acho que seria bom incluir uma fórmula de matriz para a função da planilha, pois isso é visitado com freqüência:
Você precisa inserir a fórmula sem colchetes e pressionar Shift+ Ctrl+ Enterpara torná-la uma fórmula de matriz.
Isso fornecerá o endereço da última célula usada na coluna D.
fonte
Aqui, A65536é a última célula na coluna A, este código foi testado no Excel 2003.
fonte
Eu estava procurando uma maneira de imitar o CTRL+ Shift+ End, para que a solução dotNET seja ótima, exceto no Excel 2010 que eu preciso adicionar um
set
se quiser evitar um erro:e como verificar isso por si mesmo:
fonte
Aqui estão meus dois centavos.
IMHO o risco de uma linha oculta com a exclusão de dados é muito significativo para
xlUp
ser considerado uma resposta completa . Concordo que é simples e funcionará a maior parte do tempo, mas apresenta o risco de subestimar a última linha, sem nenhum aviso. Isso poderia produzir CATASTRÓFICOS resultados em algum poinit para alguém que saltou sobre Stack Overlow e estava olhando para "caminho certo" para capturar esse valor.O
Find
método é impecável e eu o aprovaria como resposta de uma parada . No entanto, a desvantagem de alterar asFind
configurações pode ser irritante, principalmente se isso faz parte de uma UDF.As outras respostas postadas estão bem, no entanto, a complexidade fica um pouco excessiva. Portanto, aqui está minha tentativa de encontrar um equilíbrio entre confiabilidade, complexidade mínima e não uso
Find
.Por que isso é bom:
Find
configuraçõesPor que isso é ruim:
No entanto, acho que uma solução completa que apresenta uma desvantagem de desarrumar as
find
configurações ou executar mais lentamente é uma solução geral melhor. Um usuário pode, então, mexer com suas configurações para tentar melhorar, sabendo o que está acontecendo com seu código. O usoxLUp
não avisa dos riscos potenciais e eles podem continuar por quem sabe há quanto tempo não sabe que seu código não está funcionando corretamente.fonte
Nos últimos 3 anos ou mais, estas são as funções que estou usando para encontrar a última linha e a última coluna por coluna definida (para linha) e linha (para coluna):
Última coluna:
Última fila:
Para o caso do OP, esta é a maneira de obter a última linha da coluna
E
:Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Última linha, contando linhas vazias com dados:
Aqui, podemos usar as fórmulas conhecidas do Excel , que nos dão a última linha de uma planilha no Excel, sem envolver o VBA -
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Para colocar isso no VBA e não escrever nada no Excel, usando os parâmetros para as últimas funções, algo como isto pode estar em mente:
fonte
EVAL()
a famosa fórmula do Excel. Embora as pessoas pensem que issoEval()
é mau e essa é outra história interessante sobre a qual escrever ...fonte