Notifications
Clear all

Ocultar Linha e Coluna via VBA com condição

16 Posts
4 Usuários
0 Reactions
3,790 Visualizações
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Ola a todos, boa tarde.

Há algum tempo aqui no fórum, consegui através da ajuda de vocês uma macro que ocultava e reexibia determinadas linhas que tivessem o valor Zero em uma coluna específica. Hoje eu gostaria de aperfeiçoar essa idéia com a possibilidade de também ocultar e reexibir as colunas. Tudo junto, na mesma ação.

Em anexo tem uma planilha que exemplifica a minha idéia. Explicando, ficaria dessa forma:

Existe um intervalo de linhas e colunas, no caso, "A6:Q54" que possuem algum tipo de dado, no caso serão valores. No intervalo A5:R5 tem fórmulas que contam quantos valores existem em cada coluna desse intervalo. Esse é o intervalo que deve ser analisado para ocultar e/ou reexibir essas colunas. Quando o resultado da contagem for ZERO, a coluna correspondente deve ser ocultada.

Também existe no intervalo "R6:R54" a mesma fórmula de contagem, porém esta conta quantos valores existem nas linhas do intervalo, da mesma forma que as colunas, caso o resultado da contagem na linha for ZERO, esta deve ser ocultada e/ou reexibida.

Caso o código estivesse em prática, do intervalo "A5:R54" seriam ocultadas as linhas: 22, 26, 29, 31, 44, 48 e 54, e seriam ocultadas as colunas: K, L, N, O, P e Q.

Os valores internos ao intervalo são dinâmicos, o que por consequência podem alterar os totais na linha 5 e na coluna R onde será realizado a pesquisa para ocultar/reexibir.

Sendo assim, o evento recomendável seria o Calculate, mas Isso poderia deixar a planilha um pouco lenta. Como a idéiaa é que tal procedimento seja fruto de uma pesquisa, acho que o evento mais adequado seriam o CHANGE, acionado pela alteração de uma célula específica, neste caso a A2.

Em resumo, a macro deve ser acionada pela alteração da célula A2, percorrendo a linha 5 e a coluna R buscando pelo valor ZERO e ocultado linhas e colunas correspondentes.

É isso.

 
Postado : 21/05/2016 10:15 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Como citou o evento Change e Range A2 mas não citou o que vai em digitar em A2, defini se o valor for "1" Oculta Linhas e Colunas e se for "2" exibe tudo, faça o teste.

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Application.ScreenUpdating = False
    
    If Target.Address(False, False) = "A2" Then
        Application.EnableEvents = False
        
        Dim sValor
        
        sValor = Target
        
        If sValor = 1 Then
        
            Dim i As Long
            'Oculta Colunas
            For i = Cells(5, Columns.Count).End(xlToLeft).Column To 5 Step -1
                If Cells(5, i) = 0 Then Cells(5, i).EntireColumn.Hidden = True
            Next i
            
            'Oculta as linhas
            For i = Cells(Rows.Count, 18).End(xlUp).Row To 6 Step -1
                If Cells(i, 18) = 0 Then Cells(i, 18).EntireRow.Hidden = True
            Next i
        
        ElseIf sValor = 2 Then
            'Exibe toas as colunas e linhas ocultas
            Columns.EntireColumn.Hidden = False
            Rows.EntireRow.Hidden = False
        
        End If
        
        Application.EnableEvents = True
        
        Application.ScreenUpdating = True
       
    End If
    
End Sub

[]s

 
Postado : 22/05/2016 12:06 am
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Mauro, bom dia.

Obrigado pela ajuda, você que já me ajudou bastante aqui no fórum. Seguinte, o código está funcionando.mMas se você verificar o meu post vai identificar uma duplicidade de ação que não precisa existir. Note que, a ação "ocultar/reexibir" está condicionada ao resultado das fórmulas nos extremos do range e não a escolha através da alteração na célula A1. Entendi sua dúvida pela ausência do valor que seria colocado nesta célula, mas como descrevi, a célula A1 é apenas o gatilho.

Nessa época de olimpíadas, vou dar um exemplo. Natação, todos os competidores posicionados aguardam o "sinal" para percorrer a piscina no menor espaço de tempo.
Se o juíz não disparar o sinal, em tese, eles permanecerão lá posicionados. Mas se o sinal for acionado eles saltarão.

EXPLICAÇÕES:

Os valores do intervalo são dinâmicos, eles são frutos de uma pesquisa que retorna valores diversos. É possível que essa pesquisa não me traga nenhum valor em toda a linha. Por isso, se a soma dos valores retornados for ZERO aquela linha cheia de zeros só vai ocupar espaço, então não deve estar visível. O mesmo raciocínio para as colunas.
A célula A1 é o disparo do juíz no exemplo.
Em comparação com a prova de natação, todos os competidores percorrerão a mesma piscina, nesse caso o percurso é o intervalo das fórmulas, o tempo almejado é o ZERO, e independente da prova ou do tamanho da piscina, os competidores só largam após o disparo do juíz. Também podemos comparar o código ao ato de nadar, se o disparar, o código é acionado, ou no caso, os nadadores começam. Em resumo, o código é uma sequência com somente um IF, o da célula A2.

Seu código funcionado pela ação de ocultar, mas só funciona condicionado a 1 ou 2, é aí que existe a duplicidade de ação que faleijá que o ZERO já é a condição para ocultar.

O código deve procurar o ZERO toda vez que acionado, independente do valor da célula A1, mas será acionado toda vez que a A1 for alterada.

É isso.

 
Postado : 22/05/2016 6:05 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Mauro, bom dia.

Entendi sua dúvida pela ausência do valor que seria colocado nesta célula, mas como descrevi, a célula A1 é apenas o gatilho.

Luiz, com certeza não sou quem tem duvida, eu montei o código baseado em sua solicitação, talvez não esteja da forma que quer devido a muita informação, eu geralmente procuro pegar os pontos direto, seja mais direto, e ficará mais simples ajudarmos.

acho que o evento mais adequado seriam o CHANGE, acionado pela alteração de uma célula específica, neste caso a A2.
Em resumo, a macro deve ser acionada pela alteração da célula A2, percorrendo a linha 5 e a coluna R buscando pelo valor ZERO e ocultado linhas e colunas correspondentes

Para utilizarmos o evento CHANGE atrelado a alteração de uma única célula (gatilho), é da forma que indiquei, a única questão seria com qual valor colocado em A2 a a rotina deve continuar, isto que você não informou, se tem de ser "zero" é só alterar na rotina.
[]s

 
Postado : 22/05/2016 7:38 am
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Mauro,

Abaixo tem um código o qual utilizo bastante. Você vai perceber que ele tem duas funções. A primeira é bloquear todas as células com fórmulas. A outra é percorrer o range ("$BW$1:$BW$150") em busca do ZERO, e caso encontre, oculta a linha. Ele funciona caso as células uma das 4 células forem alteradas, "...If Target.Address = "$C$7" Or Target.Address = "$N$57" Or Target.Address = "$S$7" Or Target.Address = "$AC$7" Then"....independente do valor das mesmas. Por isso não especifiquei nenhum valor na A2, pelo que entendo do evento CHANGE, não precisa especificar o valor, mas a simples alteração já serve como resposta ao evento.

No seu código, o evento change é acionado não pela alteração, mas pelo conteúdo 1 dispara uma ação, 2 dispara outra ação. É como um interruptor, liga e desliga...se for digitado qualquer outro valor, o código não faz nada, ele não reage como deveria, ou seja, buscar o ZERO. Logo, CHANGE perde em parte a funcionalidade. A visão é que não
se trata do evento CHANGE, mas de um IF. Mas claro que existe uma "alteração" entre digitar 1 ou 2. Se teclar repetidamente F2 e ENTER, o código deve ser acionado. No seu código é acionado, mas apenas com uma ação, ocultar...

'Private Sub Worksheet_Change(ByVal Target As Range)
'    Dim rng As Range, arrayrang()
'
'    Application.ScreenUpdating = False
'    Application.Calculation = xlCalculationManual
'    ActiveSheet.Unprotect Password:="senha"
'    ActiveSheet.Protect Password:="senha", UserInterfaceOnly:=True
'    Cells.Locked = False
'    On Error Resume Next
'    Set rng = Cells.SpecialCells(xlCellTypeFormulas)
'    'Set rng = Cells.SpecialCells(XlCellTypeText) 'Text se quiser travar texto
'    If Err.Number > 0 Then
'        Set rng = Cells.SpecialCells(xlCellTypeConstants)
'    Else
'        Set rng = Union(rng, Cells.SpecialCells(xlCellTypeFormulas))
'        Set rng = Cells.SpecialCells(XlCellTypeText)
'    End If
'    On Error GoTo 0
'    If Not rng Is Nothing Then rng.Locked = True
'
'    If Target.Address = "$C$7" Or Target.Address = "$N$57" Or Target.Address = "$S$7" Or Target.Address = "$AC$7" Then
'
'        arrayrang = Range("$BW$1:$BW$150")
'        For l = 1 To UBound(arrayrang, 1)
'            If arrayrang(l, 1) = 0 Then
'                Rows(l + 1).EntireRow.Hidden = True
'            Else
'                Rows(l + 1).EntireRow.Hidden = False
'            End If
'        Next
'
'                For Each cell In Range("$BW$1:$BW$150")
'                    If cell.Value = 0 Then
'                        cell.EntireRow.Hidden = True
'                    Else
'                        cell.EntireRow.Hidden = False
'                    End If
'                Next
'    End If
'    Application.Calculation = xlCalculationAutomatic
'    Application.ScreenUpdating = True
'
'    'Range("C13").Select
'
'End Sub
 
Postado : 22/05/2016 8:44 am
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

...quando me referi "Entendi sua dúvida pela ausência do valor que seria colocado nesta célula.....", a falta de referência a célula estava correta, a célula era apenas para acionar o evento. Vi a dúvida na sua atitude de definir...1 para ocultar e 2 para reexibir, uma vez que não foi indicado criar esse teste lógico.

Retirando tudo que foi dito:

Código que busque no intervalo A5:Q5 pelo número zero, encontrando, oculte a coluna.
Código que busque no intervalo R6:Q54 pelo número zero, encontando, oculte a linha.
Método para acionar o código, qualquer alteração na célula A2.
o ocultar linha e coluna são simultâneos, no mesmo evento.

Hipótese: Acionado a primeira vez, linhas e coluna são ocultadas. Acionado pela segunda vez, nada acontece uma vez que os valores não foram alterados (ZERO),
mas havendo alteração, na segunda vez que acionado, novas linhas e colunas serão ocultadas. Linhas e colunas ocultadas anteriormente tendem a permanecer ocultas caso o ZERO permaneça nas respectivas linhas e colunas.

É isto.

 
Postado : 22/05/2016 8:56 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

luiz, temos de ser mais pratico e direto, geralmente quando usamos programação temos de seguir algumas lógicas, sequências etc, eu tenho por principio criar um organograma.

Então como citou executar ações se determinada for alterada, resolvi acrescentar condição para a execução, mas se não precisa disto, é só tirar as instruções de Condição e comparação.
Alias, se você já tem uma rotina que funciona da forma que pretende, é só alterar a condição :
If Target.Address = "$C$7" Or Target.Address = "$N$57" Or Target.Address = "$S$7" Or Target.Address = "$AC$7" Then

para :
If Target.Address = "$A$2" Then

[]s

 
Postado : 22/05/2016 11:40 am
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Mauro,

Pediria que relesse meu post inicial e procurasse comparar com tudo que foi dito até aqui. Queria saber o que ficou incompreensível para que possamos chegar a uma conclusão, mesmo que depois essa conclusão seja que minha dúvida não tem solução.

A SÍNTESE: " Ocultar Linha e Coluna via VBA com condição "

LINHA E COLUNA "...Existe um intervalo de linhas e colunas, no caso, "A6:Q54" que possuem algum tipo de dado, no caso serão valores...."

CONDIÇÃO (Linha ) " ...No intervalo A5:R5 tem fórmulas que contam quantos valores existem em cada coluna desse intervalo. Esse é o intervalo que deve ser analisado para ocultar e/ou reexibir essas colunas. Quando o resultado da contagem for ZERO, a coluna correspondente deve ser ocultada...."

CONDIÇÃO (Coluna) "...Também existe no intervalo "R6:R54" a mesma fórmula de contagem, porém esta conta quantos valores existem nas linhas do intervalo, da mesma forma que as colunas, caso o resultado da contagem na linha for ZERO, esta deve ser ocultada e/ou reexibida.

Obs: A condição é o valor ZERO. A opção 1 ou 2 não deve ser a condição.

CONDIÇÃO (Linha e Coluna) " Quando o resultado da contagem for ZERO, a coluna correspondente deve ser ocultada..." "... da mesma forma que as colunas, caso o resultado da contagem na linha for ZERO, esta deve ser ocultada e/ou reexibida...."

VBA "...Como a idéiaa é que tal procedimento seja fruto de uma pesquisa, acho que o evento mais adequado seriam o CHANGE, acionado pela alteração de uma célula específica, neste caso a A2...."

Obs: A alteração consiste em mudar o valor da célula, não requer que seja especificado qual valor a célula assumiu depois de alterada. Não requer tipo de dado.

SÍNTESE "...Em resumo, a macro deve ser acionada pela alteração da célula A2, percorrendo a linha 5 e a coluna R buscando pelo valor ZERO e ocultado linhas e colunas correspondentes...."

Veja que tudo foi especificado, só faltou a codificação.

Quanto ao código que postei,"...Abaixo tem um código o qual utilizo bastante. Você vai perceber que ele tem duas funções. A primeira é bloquear todas as células com fórmulas. A outra é percorrer o range ("$BW$1:$BW$150") em busca do ZERO, e caso encontre, oculta a linha. ..."

Ou seja, ele apenas oculta a "linha" e não a coluna. Postei para que visse que não existe a necessidade de digitar um valor para acionar o código, apenas que a célula seja alterada de alguma forma, até mesmo com F2 + ENTER.

Seu código funciona, isso eu falei na minha primeira resposta. Mas ainda não era a resposta que eu pretendia. Agradeço pela ajuda, mas daí que são necessários mais detalhes para se chegar a plenitude da solução.

Eu sempre procuro agradecer pela ajuda que recebo aqui no fórum. O Fernando, TSA, Prudencio, Patropi, você inclusive já me ajudaram com diversos códigos. Vasculho o fórum todos os dias a qualquer hora, sou fascinado pelo excel, tenho mais conhecimento com as fórmulas do que com o VBA e sempre desço ao nível mais pleno de informação daquilo que pretendo. Por isso tudo é que às vezes não dá para aceitar as recomendações ou observações de falta de ordem, critério e lógica dos posts. Eu também tenho postado algumas ajudas quando o assunto são fórmulas, funções ou formatações. Eu sei o que é ter que entender aquilo que o usuário quer e não sabe como como explicar, paciência.

Como disse no início, reveja meu post, compare e veja se é possível uma solução daquilo que foi exposto.

Obrigado.

 
Postado : 22/05/2016 5:10 pm
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

luiz, sinceramente, quando vejo posts com muitas linhas, geralmente nem leio e vou para outro, e só vi o seu por já conhece-lo.

Mas resumindo tudo, se entendi agora, bastava simplesmente colocar :

CONDIÇÃO (Linha e Coluna) "Quando o resultado das formulas forem = ZERO, a coluna e/ou Linha correspondente devem ser ocultada...", e se os resultados voltarem a serem diferentes de ZERO Reexibi-las.

Se for isto, veja se agora acertamos :

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Application.ScreenUpdating = False
    
    If Target.Address(False, False) = "A2" Then
        Application.EnableEvents = False
        
            Dim iCol As Long
            Dim iRow As Long
            
            'Oculta / Exibe Colunas
            For iCol = Cells(5, Columns.Count).End(xlToLeft).Column To 1 Step -1
                If Cells(5, iCol) = 0 Then
                    Cells(5, iCol).EntireColumn.Hidden = True
                Else
                    Cells(5, iCol).EntireColumn.Hidden = False
                End If
            Next iCol
            
            'Oculta / Exibe as Linhas
            For iRow = Cells(Rows.Count, 18).End(xlUp).Row To 6 Step -1
                If Cells(iRow, 18) = 0 Then
                    Cells(iRow, 18).EntireRow.Hidden = True
                Else
                    Cells(iRow, 18).EntireRow.Hidden = False
            Next iRow
        
        Application.EnableEvents = True
        
        Application.ScreenUpdating = True
       
    End If
    
End Sub

[]s

 
Postado : 22/05/2016 6:35 pm
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Olá Mauro,

Está dando "erro decompilação - Next sem For" nessa parte "...."Next iRow"

 
Postado : 22/05/2016 7:10 pm
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Faltou o End If antes de "Next iRow" é só adicionar

 
Postado : 22/05/2016 7:16 pm
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Coloquei um "End If" antes da linha ...Next IRow, e funcionou...
Não sei se era essa a solução, mas comparei a lógica das instruções anteriores e funcionou.

Era isso!

O código está completo, funcional e de acordo com todos os parâmetros informados.

Parabéns! Muito obrigado !

 
Postado : 22/05/2016 7:19 pm
(@luizhcosta)
Posts: 0
New Member
Topic starter
 

Ops! Mandei antes de ver sua resposta, bom que era isso mesmo.

Muito obrigado mais uma vez.

 
Postado : 22/05/2016 7:20 pm
(@osvaldomp)
Posts: 857
Prominent Member
 
Private Sub Worksheet_Change(ByVal Target As Range)
 Dim k As Long, m As Long
 If Target.Address <> "$A$2" Then Exit Sub
 Rows("6:54").Hidden = False
 Columns("A:Q").Hidden = False
 For k = 1 To 17
  If Cells(5, k) = 0 Then Columns(k).Hidden = True
 Next k
 For m = 6 To 54
  If Cells(m, 17) = 0 Or Cells(m, 18) = 0 Then Rows(m).Hidden = True
 Next m
End Sub
 
Postado : 22/05/2016 7:30 pm
(@edilsonfl)
Posts: 227
Estimable Member
 

Tente este,

Faltou apenas um "End IF",
acontece até nas melhores fámílias.

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Application.ScreenUpdating = False
    
    If Target.Address(False, False) = "A2" Then
        Application.EnableEvents = False
        
            Dim iCol As Long
            Dim iRow As Long
            
            'Oculta / Exibe Colunas
            For iCol = Cells(5, Columns.Count).End(xlToLeft).Column To 1 Step -1
                If Cells(5, iCol) = 0 Then
                    Cells(5, iCol).EntireColumn.Hidden = True
                Else
                    Cells(5, iCol).EntireColumn.Hidden = False
                End If
            Next iCol
            
            'Oculta / Exibe as Linhas
            For iRow = Cells(Rows.Count, 18).End(xlUp).Row To 6 Step -1
                If Cells(iRow, 18) = 0 Then
                    Cells(iRow, 18).EntireRow.Hidden = True
                Else
                    Cells(iRow, 18).EntireRow.Hidden = False
                End If  '<<== ESTAVA FALTANDO
            Next iRow
        
        Application.EnableEvents = True
        
        Application.ScreenUpdating = True
       
    End If
    
End Sub
 
Postado : 22/05/2016 8:03 pm
Página 1 / 2