Automatize seu fluxo no Excel: ao selecionar um Status em uma lista suspensa, a linha inteira é movida automaticamente para a aba cujo nome coincide com o valor escolhido (ex.: “Zone1”). A mesma lógica traz a linha de volta se o Status for alterado novamente.
Visão geral e objetivo
Em muitos controles operacionais (cadastros, filas de atendimento, kanbans, checklists), a coluna Status indica para onde cada registro deve “andar” no processo. Este artigo mostra como implementar, em Excel/VBA, uma movimentação automática: sempre que você altera o Status na planilha Register (ou em qualquer aba, na versão global), a linha completa de A:M
é transferida para a planilha cujo nome é exatamente o novo Status. A linha deixa de existir na origem, evitando duplicação. Se o Status mudar de novo, a linha volta a ser movida, mantendo um único “dado mestre”.
Quando usar esta abordagem
- Você precisa mover fisicamente os dados entre abas (não apenas filtrá-los).
- Os nomes dos Status coincidem com os nomes das planilhas de destino (ex.: Zone1, Zone2, Finalizados).
- Você quer simplificar o trabalho do usuário: basta trocar o Status na lista suspensa.
Pré-requisitos
- Arquivo salvo como .xlsm (pasta de trabalho habilitada para macro).
- Macros habilitadas (Central de Confiabilidade do Excel).
- Planilhas de destino já criadas e nomeadas exatamente como os valores da lista.
- Coluna de Status posicionada na coluna I (ajustável, veja personalizações).
- Dados por linha ocupando colunas A até M (ajustável).
Como preparar a lista suspensa de Status
- Liste os nomes de Status (idênticos às abas) em uma área do arquivo, preferencialmente em uma planilha de parâmetros.
- Selecione as células da coluna I na planilha Register (onde o usuário irá escolher o Status).
- Vá a Dados > Validação de Dados > Permitir: Lista > Fonte: selecione o intervalo com os nomes dos Status.
- Confirme. Agora cada célula dessa coluna terá um drop-down.
Solução funcional na planilha Register
Se você deseja que a movimentação aconteça apenas quando o Status for alterado na aba Register, use o evento Worksheet_Change
no módulo da própria planilha Register.
Passo a passo
- Salve como .xlsm e habilite as macros.
- Pressione Alt+F11 para abrir o Editor do VBA.
- No Project Explorer, dê duplo‑clique em Planilha (Register).
- Na barra superior do módulo, escolha Worksheet (à esquerda) e Change (à direita).
- Cole o código abaixo e salve.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Fim
' Executa apenas para uma única célula
If Target.CountLarge > 1 Then Exit Sub
' Coluna I (9)
If Target.Column <> 9 Then Exit Sub
If Len(Trim$(Target.Value)) = 0 Then Exit Sub
Dim wsDest As Worksheet, ultLinha As Long
On Error Resume Next
Set wsDest = ThisWorkbook.Worksheets(CStr(Target.Value))
On Error GoTo 0
If wsDest Is Nothing Then
MsgBox "A planilha '" & Target.Value & "' não existe.", vbExclamation
Exit Sub
End If
Application.EnableEvents = False
' Próxima linha livre na coluna A da planilha destino
ultLinha = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row + 1
' Copia A:M da linha alterada
With Me
.Range(.Cells(Target.Row, "A"), .Cells(Target.Row, "M")).Copy _
Destination:=wsDest.Cells(ultLinha, "A")
' Apaga a linha original (toda a linha para manter alinhamento)
.Rows(Target.Row).Delete
End With
Fim:
Application.EnableEvents = True
End Sub
Como o código funciona
Etapa | Descrição |
---|---|
Filtro do evento | Executa apenas quando uma única célula da coluna I é alterada e o valor não é vazio. |
Validação do destino | Confere se existe uma planilha com o nome exatamente igual ao valor selecionado no drop‑down. |
Movimentação | Copia o intervalo A:M da linha onde houve a mudança, cola no próximo espaço livre da planilha de destino e exclui a linha original. |
Segurança | Desliga e religa Application.EnableEvents para evitar que o próprio código dispare em cascata. |
Essencial: os nomes do drop‑down devem coincidir 100% com os nomes das abas de destino; qualquer divergência faz o código avisar e não mover a linha.
Versão aprimorada que funciona em qualquer aba
Se você prefere que a movimentação ocorra mesmo quando o usuário altera o Status fora da Register, coloque este código no módulo ThisWorkbook. Ele reage à mudança na coluna de Status em qualquer planilha do arquivo.
Passos
- No Editor do VBA, dê duplo‑clique em ThisWorkbook.
- Cole o código a seguir e salve.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo Fim
Const STATUS_COL As Long = 9 ' 9 = Coluna I
Const FIRST_COL As Long = 1 ' 1 = Coluna A
Const LAST_COL As Long = 13 ' 13 = Coluna M
If Target.CountLarge > 1 Then Exit Sub
If Intersect(Target, Sh.Columns(STATUS_COL)) Is Nothing Then Exit Sub
If Len(Trim$(Target.Value)) = 0 Then Exit Sub
Dim nomeDest As String: nomeDest = CStr(Target.Value)
Dim wsDest As Worksheet
On Error Resume Next
Set wsDest = ThisWorkbook.Worksheets(nomeDest)
On Error GoTo Fim
If wsDest Is Nothing Then
MsgBox "Planilha '" & nomeDest & "' não encontrada.", vbExclamation
Exit Sub
End If
' Se o destino for a própria planilha, não faz nada
If wsDest.Name = Sh.Name Then Exit Sub
Application.EnableEvents = False
Dim lin As Long, proxima As Long
lin = Target.Row
proxima = wsDest.Cells(wsDest.Rows.Count, FIRST_COL).End(xlUp).Row + 1
Sh.Range(Sh.Cells(lin, FIRSTCOL), Sh.Cells(lin, LASTCOL)).Copy _
Destination:=wsDest.Cells(proxima, FIRST_COL)
Sh.Rows(lin).Delete
Fim:
Application.EnableEvents = True
End Sub
Vantagens desta versão
- Independente da aba: altera o Status onde estiver e a linha será movida.
- Constantes fáceis de ajustar: mude
STATUSCOL
,FIRSTCOL
eLAST_COL
conforme sua estrutura. - Prevenção de loop: não movimenta se o destino for a própria aba (
If wsDest.Name = Sh.Name Then Exit Sub
).
Adaptações rápidas e comuns
Trocar a coluna do Status
- Versão por planilha: substitua
If Target.Column <> 9 Then
porIf Target.Column <> 7 Then
para usar a coluna G. - Versão aprimorada: mude
Const STATUS_COL As Long = 9
para7
.
Alterar o intervalo copiado
- Quer levar A:P? Ajuste na versão global:
Const LAST_COL As Long = 16
(P = 16). - Na versão por planilha, troque
"M"
por"P"
onde aplicável.
Colar apenas valores (sem fórmulas)
Substitua a linha com Copy Destination
por:
Sh.Range(Sh.Cells(lin, FIRSTCOL), Sh.Cells(lin, LASTCOL)).Copy
wsDest.Cells(proxima, FIRST_COL).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Preservar formatação do destino
Se as abas de destino têm tabelas formatadas, considere colar apenas valores e aplicar formatação de tabela (“Formatar como Tabela”) para que novas linhas herdem o estilo automaticamente.
Evitar mover o cabeçalho
Caso sua planilha tenha cabeçalho na primeira linha, você pode impedir a movimentação se o usuário alterar o Status do cabeçalho por engano:
' Acrescente logo após as constantes:
Const FIRSTDATAROW As Long = 2
' E antes de processar:
If Target.Row < FIRSTDATAROW Then Exit Sub
Tabela de referência rápida
Elemento | Valor padrão do artigo | Função |
---|---|---|
STATUS_COL | 9 (coluna I) | Coluna onde o usuário escolhe o Status. |
FIRST_COL | 1 (coluna A) | Primeira coluna do bloco de dados a mover. |
LAST_COL | 13 (coluna M) | Última coluna do bloco de dados a mover. |
Intervalo padrão | A:M | Bloco de dados do registro (linha inteira) que será transferido. |
Erros comuns e como resolver
- Nada acontece: confirme se o código foi colado no módulo correto (Planilha (Register) para a versão local, ThisWorkbook para a global). Verifique se o arquivo está como .xlsm e se os eventos estão ativos. No Imediato do VBA, execute:
Application.EnableEvents = True
. - Planilha não encontrada: a validação lista valores que devem existir como abas. Corrija nomes ou crie a planilha correspondente.
- Mudança por fórmula: o evento
Change
não dispara quando a célula muda por resultado de fórmula. O Status deve ser selecionado/alterado pelo usuário (ou por macro). - Linhas mescladas: mesclagens costumam causar comportamentos inesperados ao copiar e excluir linhas. Evite mesclar no bloco A:M.
- Planilhas protegidas: se a origem ou o destino estiverem protegidos, o código pode falhar ao excluir/colar. Desproteja ou trate com
Unprotect/Protect
no código. - Desempenho lento em listas longas: veja as Boas práticas de desempenho abaixo.
Boas práticas de desempenho
- Desabilite atualizações visuais durante a cópia e exclusão:
Dim oldScr As Boolean, oldCalc As XlCalculation oldScr = Application.ScreenUpdating oldCalc = Application.Calculation Application.ScreenUpdating = False Application.Calculation = xlCalculationManual ' ... sua lógica de cópia/exclusão ... Application.Calculation = oldCalc Application.ScreenUpdating = oldScr
- Evite selecionar/ativar objetos (no
VBA
, “Select
” é quase sempre supérfluo). - Padronize faixas com tabelas do Excel para herdar formatação e validações.
Fluxo de trabalho recomendado
- Crie/valide as abas de destino (Zone1, Zone2, Zone3 etc.).
- Monte a lista suspensa de Status na coluna I.
- Instale a versão de macro que melhor se encaixa (apenas Register ou global no ThisWorkbook).
- Teste com 3–5 linhas de exemplo, variando os Status e validando se as linhas foram removidas da origem.
- Proteja o cabeçalho contra edições indevidas e, se necessário, use a regra de
FIRSTDATAROW
.
Alternativa sem VBA
Se não é necessário mover fisicamente os dados, uma alternativa mais simples e robusta é manter todos os registros na Register e criar abas por zona exibindo apenas os dados filtrados por fórmula dinâmica:
=FILTER(Register!A:M, Register!I:I="Zone1")
Crie uma fórmula dessas em cada aba (ajustando o valor do Status). Você reduz riscos, mantém uma única fonte de verdade e dispensa macros. É perfeito para cenários de leitura/consulta.
Perguntas frequentes
Posso mover para outra pasta de trabalho?
Sim. Desde que a outra pasta esteja aberta e tenha uma planilha com o mesmo nome do Status, você pode apontar o destino. Exemplo ilustrativo na versão global:
Dim wbDest As Workbook
Set wbDest = Workbooks("Destino.xlsx") ' já aberta
Set wsDest = wbDest.Worksheets(nomeDest)
Em vez de copiar e excluir, posso “cortar” a linha?
É possível usar .Cut
para mover células e limpar a origem, mas normalmente você ainda desejará excluir a linha vazia para manter o alinhamento. A abordagem “copiar & deletar” é direta e previsível.
Como impedir que o usuário escolha um Status inexistente?
Alimente a validação de dados diretamente a partir do nome das abas (por exemplo, com um intervalo que liste dinamicamente as planilhas válidas) ou mantenha um intervalo de referência único para o drop‑down e para a criação das abas — o importante é que a escrita do Status corresponda ao nome da planilha.
Checklist de implantação
- Arquivo salvo em .xlsm e macros habilitadas.
- Abas de destino criadas e nomeadas.
- Lista suspensa de Status configurada.
- Código instalado na posição correta (Register ou ThisWorkbook).
- Teste com casos simples e com mudanças de Status sequenciais (ex.: Register → Zone1 → Zone2 → Register).
- Eventos reativados (
Application.EnableEvents = True
) após testes.
Exemplo prático
Suponha as abas Register, Zone1, Zone2 e Concluídos. Um registro novo é criado em Register. O usuário escolhe Zone1 na coluna I; automaticamente, a linha vai para a aba Zone1 e some de Register. Mais tarde, o operador muda o Status para Concluídos na própria aba Zone1; a versão global move a linha para a aba Concluídos. O histórico lógico do processo é mantido através do próprio Status, sem duplicações.
Segurança e manutenção
- Armazene o arquivo em local confiável (OneDrive/SharePoint) para reduzir prompts de segurança de macro.
- Crie cópias de segurança antes de publicar mudanças no VBA.
- Registre convenções de nomenclatura de abas e de Status para a equipe.
Resumo em uma frase
Com um pequeno evento VBA, você transforma a coluna de Status em um “trilho” que leva cada linha exatamente para a aba correspondente, de forma automática, segura e reversível pela própria mudança do Status.
Solução pronta para copiar
Versão por planilha (Register):
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Fim
If Target.CountLarge > 1 Then Exit Sub
If Target.Column <> 9 Then Exit Sub
If Len(Trim$(Target.Value)) = 0 Then Exit Sub```
Dim wsDest As Worksheet, ultLinha As Long
On Error Resume Next
Set wsDest = ThisWorkbook.Worksheets(CStr(Target.Value))
On Error GoTo 0
If wsDest Is Nothing Then
MsgBox "A planilha '" & Target.Value & "' não existe.", vbExclamation
Exit Sub
End If
Application.EnableEvents = False
ultLinha = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row + 1
With Me
.Range(.Cells(Target.Row, "A"), .Cells(Target.Row, "M")).Copy _
Destination:=wsDest.Cells(ultLinha, "A")
.Rows(Target.Row).Delete
End With
```
Fim:
Application.EnableEvents = True
End Sub </code></pre>
<p><strong>Versão aprimorada (ThisWorkbook):</strong></p>
<pre><code class="language-vba">Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo Fim
Const STATUS_COL As Long = 9
Const FIRST_COL As Long = 1
Const LAST_COL As Long = 13```
If Target.CountLarge > 1 Then Exit Sub
If Intersect(Target, Sh.Columns(STATUS_COL)) Is Nothing Then Exit Sub
If Len(Trim$(Target.Value)) = 0 Then Exit Sub
Dim nomeDest As String: nomeDest = CStr(Target.Value)
Dim wsDest As Worksheet
On Error Resume Next
Set wsDest = ThisWorkbook.Worksheets(nomeDest)
On Error GoTo Fim
If wsDest Is Nothing Then
MsgBox "Planilha '" & nomeDest & "' não encontrada.", vbExclamation
Exit Sub
End If
If wsDest.Name = Sh.Name Then Exit Sub
Application.EnableEvents = False
Dim lin As Long, proxima As Long
lin = Target.Row
proxima = wsDest.Cells(wsDest.Rows.Count, FIRST_COL).End(xlUp).Row + 1
Sh.Range(Sh.Cells(lin, FIRST_COL), Sh.Cells(lin, LAST_COL)).Copy _
Destination:=wsDest.Cells(proxima, FIRST_COL)
Sh.Rows(lin).Delete
```
Fim:
Application.EnableEvents = True
End Sub
Alternativa sem VBA para quem só precisa visualizar por Status
Manter uma única base em Register e projetar cada Status em sua aba com fórmulas dinâmicas simplifica manutenção e reduz risco de quebra por macro:
=FILTER(Register!A:M, Register!I:I="Zone1")
Dica final: para ajustes rápidos, lembre-se — mude a coluna do Status (ex.: G = 7), ajuste o intervalo copiado (ex.: P = 16), e troque a cópia por “somente valores” quando necessário. O núcleo da solução permanece o mesmo.