Jump to content

Recommended Posts

Posted

Bom dia!

Quero fazer uma macro, mas não sei grande coisa sobre o assunto.
Queria saber se alguém me pode ajudar a fazer o que preciso.
O que eu quero fazer é o seguinte:
Tenho uma folha de excel com muitos dados e nas células da coluna B quero que apareça o valor que estiver na célula seguinte a uma célula que contem determinado texto.
Por exemplo: na célula B2 quero que apareça o valor que estiver na célula seguinte à célula da linha 2 que contém o texto Joana, e isso para todas as linhas seguintes, B3,B4,...B9999,...Bn.
e na coluna C quero o mesmo procedimento mas copia o valor da célula que está 2 células à frente da célula que contém Joana.
O procedimento pode ser accionado através de um botão.
Isso é possível fazer?
Espero que tenha ficado claro o que preciso fazer.

Obrigado antecipadamente.

Cumprimentos

pieiro

Posted

Bom. Penso que é melhor explicares com exatidão o que pretendes para que possas receber ajuda. A célula seguinte quer dizer o quê? Para a direita ou para baixo?

As células têm nomes e deves utilizá-los.

A resolução não parece complicada, portanto não podes complicar tu na exposição do teu problema.

Posted (edited)

Insere um Botão Activex na folha, clica 2 vezes no botão e cola este código.

Private Sub CommandButton1_Click()

Dim address As Variant, NOMES As Range, LINHA As Range


    Set NOMES = Sheets("REGISTOS").Range("C2:E10000")

        For Each LINHA In NOMES.Rows
            If LINHA.Cells(1, 1) <> "" Then
                address = LINHA.Cells(1, 2)
                
                LINHA.Cells(1, 2).Select
                
                ActiveCell = address
                ActiveCell.Offset(0, -2).Select
                 ActiveCell.Value = LINHA.Cells(1, 2).Value
                
                
            End If
        Next
End Sub

Adapta de acordo com a tua necessidade. Para outros Range, duplica o código de forma a contemplar o Range que quiseres. É só

alterar o address e o offset conforma a necessidade.

Edited by manuel antonio
Posted

Bom dia manuel antonio,

Antes de mais obrigado pela resposta, de facto poderia ter deixado alguns exemplo do que quero para deixar mais claro o que pretendo, assim sendo aqui ficam exemplos do que pretendo:

Se na coluna A  houver uma linha com texto diferente de 0 (zero), nessa linha procura a palavra ex: joana (está em W6) (mas não está sempre na coluna W pode está em qualquer coluna da Range) então copia o texto que está na célula seguinte X6 para célula B6 e copia também o texto da célula Y6 para a célula C6 e assim para todas as linhas da range.

Se a célula da coluna A estiver com o valor (texto) igual a 0 (zero) não faz nada e passa à frente para a linha seguinte.

Se a célula da coluna A estiver com um valor diferente de 0 (zero) e nessa linha não existir a palavra ex:joana na Range de colunas, então passa à frente para a linha seguinte.

A Range para as colunas é até à coluna CG.

A Range para as linhas é até à linha 8000.

Se me puder ajudar agradeço muito, pois não percebo grande coisa do assunto.

 

Muito obrigado

Pieiro

Posted (edited)

Olá esta linguagem já não é muito utilizada aqui no Brasil, mas eu adoro e luto para mate-la viva. Para começar é importante entender a hierarquia dos objetos, assim fica fácil decifrar a utilização de qualquer método ou atributo de qualquer objeto. No exemplo do Manuel Antonio, ele esta utilizando um ".select" para ativar a célula que irá receber as informações, isso não é considerado uma boa prática já que ao selecionar uma célula é disparado uma serie de eventos no excel que pode sobrecarregar a memoria ram deixando o código lendo, na prática quem utiliza este recurso nem pode se dizer programador vba, pois nesses casos quem acaba levando a culpa é o VBA, quando na verdade o programador é que não fez direito.

Tente fazer dessa forma: 

thisworkbook.sheets("nomedaguiadestino").range("celuladestino").value = thisworkbook.sheets("nomedaguiaorigem").range("celulaorigem").value

caso esteja manipulando somente uma pasta de trabalho não seria necessário especificar o objeto thisworkbook e caso esteja manipulando celulas dentro de uma mesma planilha não é necessário especificar a sheets, adapte o código acima conforme sua necessidade respeitando a hierarquia de objetos, este é o segredo básico para dominar o VBA. 

Espero ter ajudado, muitas pessoas vão dizer que esta é uma linguagem defasada no mercado, mas eu ainda acredito que ela tenha um potencial para continuar no mercado por mais alguns anos.

Edited by Poncio Elias
Posted (edited)

Boa noite.

O Poncio tem razão quando diz que esta linguagem não é de programador, pois eu não sou programador. Sou apenas um curioso que aprendi pesquisando e pedindo ajuda e as primeiras ajudas saíram deste forum.

Pesquisando aprende-se muito e ficando parado não se aprende nada. Pedindo ajuda também se aprende. Tenho muito pouca prática e não sei que espécie de sobrecarga poderá recair sobre a Ram, mas sei que funciona.

Para um programador, exige-se desempenho na aplicação que se concebe. Para um curioso na matéria, se o código roda sem erros e faz o que esperamos dele, então é um código perfeito. É o meu caso. Os melhoramentos vêm depois com a aquisição de novos conhecimentos.

Gradualmente, vai-se aprendendo cada vez mais e começa-se a gostar.

Então é assim:

Na rotina que postei em cima, o Range que testei inclui a coluna "C" até à coluna "E" englobando 10.000 linhas. No teu caso, substitui as letras que representam as colunas segundo a tua folha de trabalho. No teu caso, substitui o Range("C2:E10000"), por Range("D2:CG8000"). e substitui o nome "REGISTOS" pelo nome da tua folha. O Excel vai-te procurar o nome Joana nesse Range.

Em 10/11/2016 às 10:25, manuel antonio disse:

If LINHA.Cells(1, 1) <> "" Then

A linha em cima, diz que se as células estiverem ocupadas com valores, vai passar à linha seguinte. Se queres o nome Joana, coloca-o dentro das " " e ele só procura a Joana alterando o sinal de <> para =.

Em 10/11/2016 às 10:25, manuel antonio disse:

address = LINHA.Cells(1, 2)

LINHA.Cells(1, 2).Select

Detetando o nome Joana no lugar que o Excel chama de Cells(1,1), vai selecionar o valor que lhe está imediatamente à direita Cell(1,2).

 

Em 10/11/2016 às 10:25, manuel antonio disse:

ActiveCell.Offset(0, -2).Select

Relativamente à última seleção, o ActiveCell.Offset vai-te deslocar o foco duas colunas para a esquerda. Neste caso alteras de acordo com o desejado ou Substituis pela expressão utilizado pelo Poncio, Sheets("Nome da tua Folha").Range("B" & LINHA).value= LINHA.Cells (1,2).value. A palavra LINHA, é a variável que utilizei no exemplo e deves mantê-la. Se a alterares tens que alterar em toda a rotina pela mesma palavra.

A rotina que postei ignora sempre as células vazias, por isso escrevi <> "", (Diferente de vazio).

Em 10/11/2016 às 10:25, manuel antonio disse:

If LINHA.Cells(1, 1) <> "" Then

Se quiseres excluir zeros que a folha contenha alteras a linha de código para:

If LINHA.Cells(1,1)<>"" and LINHA,Cells (1,1) <> "0" then

Antes do End if, acrescentas na rotina Sheets("Nome da tua Folha").Range("C" & LINHA).value= LINHA.Cells (1,3).value

Roda o código, vê o que ele faz e procede a alterações de acordo com a disposição da tua folha.

Edited by manuel antonio
Posted

Bom dia,

antes de mais obrigado a todos os que têm tentado resolver o meu problema, mas eu de facto sou bastante leigo nesta matéria.

Então é assim, quando coloco o código com o Botão Activex depois de colocar o código o botão não faz nada, quando clico nele fica seleccionado para edição de forma (tamanho largura e também não consigo alterar o seu nome, mas consigo viver com isso).

Dessa forma coloquei um botão de controlo de formulário e experimentei os seguintes códigos todos sem sucesso aparece o erro subscript out of range.

os códigos que experimentei foram:

1) 

Sub Carregar_BOM()


Dim address As Variant, NOMES As Range, LINHA As Range


    Set NOMES = Sheets("Folha1").Range("D2:CG10000")

        For Each LINHA In NOMES.Rows
            If LINHA.Cells(1, 1) <> "joana" Then
                address = LINHA.Cells(1, 2)
                
                LINHA.Cells(1, 2).Select
                               
                Sheets("Folha1").Range("B" & LINHA).Value = LINHA.Cells(1, 2).Value
                Sheets("Folha1").Range("C" & LINHA).Value = LINHA.Cells(1, 3).Value
                
                
            End If
        Next
End Sub

 

2)

Sub Carregar_BOM()


Dim address As Variant, NOMES As Range, LINHA As Range


    Set NOMES = Sheets("Folha1").Range("D2:CG10000")

        For Each LINHA In NOMES.Rows
            If LINHA.Cells(1, 1) <> "joana" Then
                address = LINHA.Cells(1, 2)
                
                LINHA.Cells(1, 2).Select
                ActiveCell = address
                ActiveCell.Offset(0, -2).Select
                ActiveCell.Value = LINHA.Cells(1, 2).Value
                
                Sheets("Folha1").Range("B" & LINHA).Value = LINHA.Cells(1, 2).Value
                Sheets("Folha1").Range("C" & LINHA).Value = LINHA.Cells(1, 3).Value
                
            End If
        Next
End Sub

 

3)

Sub Carregar_BOM()


Dim address As Variant, NOMES As Range, LINHA As Range


    Set NOMES = Sheets("Folha1").Range("D2:CG10000")

        For Each LINHA In NOMES.Rows

If LINHA.Cells(1,1)<>"" and LINHA,Cells (1,1) <> "0" then

If LINHA.Cells(1, 1) <> "joana" Then
                address = LINHA.Cells(1, 2)
                
                LINHA.Cells(1, 2).Select
                ActiveCell = address
                ActiveCell.Offset(0, -2).Select
                ActiveCell.Value = LINHA.Cells(1, 2).Value
               
                Sheets("Folha1").Range("B" & LINHA).Value = LINHA.Cells(1, 2).Value
                Sheets("Folha1").Range("C" & LINHA).Value = LINHA.Cells(1, 3).Value
                
            End If
        Next
End Sub

 

4)

Sub Carregar_BOM()


Dim address As Variant, NOMES As Range, LINHA As Range


    Set NOMES = Sheets("Folha1").Range("D2:CG10000")

        For Each LINHA In NOMES.Rows

If LINHA.Cells(1,1)<>"" and LINHA,Cells (1,1) <> "0" then

If LINHA.Cells(1, 1) <> "joana" Then
                address = LINHA.Cells(1, 2)
                
                LINHA.Cells(1, 2).Select           
                
                Sheets("Folha1").Range("B" & LINHA).Value = LINHA.Cells(1, 2).Value
                Sheets("Folha1").Range("C" & LINHA).Value = LINHA.Cells(1, 3).Value
                
            End If
        Next
End Sub

 

Como disse anteriormente sou bastante leigo na matéria e preciso mesmo disto a funcionar porque actualmente tenho de ir linha a linha alterar as células, devem imaginar o que isso é, podem por favor tentar criar o código o mais aproximado possível com o que eu preciso para que fique a funcionar? Se precisarem de mais informação por favor não hesitem em perguntar/pedir pode haver alguma coisa que seja necessário e eu não esteja a ver.

Mais uma vez obrigado por tentar ajudar.

Cumprimentos

pieiro

Posted

Penso que estás a fazer demasiadas coisas erradas.

cola uma pequena imagem da tua folha para se tentar reproduzir o que pretendes.

Primeiro colocas o botão e depois colas o código e não ao contrário. O nome do botão pode ser alterado, tanto no nome específico como na Caption.

As condições If... têm que ter sempre um end if respetivo. Etc.  

Posted

Manuel não consigo encontrar no meu texto anterior um trecho que diga que vba não é linguagem de programador. Na verdade eu tento explicar exatamente o contrario. 

Pieiro, todos os seus exemplos estão usando o "for each" este tipo de laço de repetição instancia um objeto em memória o que não é uma boa pratica principalmente porque você esta manipulando uma matriz razoavelmente grande, creio que foi criado com o objetivo de simplificar o código, para ficar mais legível a leigos, o problema é que nem isso conseguiu, pois eu mesmo precisei analisar por alguns minutos até entender tudo...

Procure entender a lógica envolvida em um script, não se limite somente a copiar um código mudar algumas coisas e executar para ver o que acontece.

Tente aprender um pouco sobre controle de fluxo, seria possível resolver o seu problema apenas com aquela linha de comando que passei no meu exemplo anterior, pois ali só esta faltando mesmo a lógica.  

Poderia até te passar alguns exemplos prontos, mas não acho uma boa ideia ficar esperando exemplos prontos pois assim você não irá evoluir, tente quebrar a cabeça e codificar por conta própria, se fizer isso certamente em poucos dias voltará aqui com ótimas soluções criadas por você mesmo, fique atento quanto ao desempenho do seu código, não basta apenas que ele faça o que você precisa, tem que estar bem feito, se for pra fazer de qualquer jeito é melhor nem fazer, pense na qualidade do seu serviço.

Posted (edited)

Certo, pode ter um exit sub.

Mas regra geral para principiantes é a boa prática.

 

21 horas atrás, Poncio Elias disse:

na prática quem utiliza este recurso nem pode se dizer programador vba, pois nesses casos quem acaba levando a culpa é o VBA, quando na verdade o programador é que não fez direito.

Poncio, está transcrita a frase, mas tem toda a razão no que diz, pois não sou mesmo programador. Apenas comecei a gostar e com pesquisas e ajudas, vou levando a água ao meu moinho.

Já estive no lugar do colega que colocou a dúvida e sei que é frustrante não conseguir resultados, principalmente quando numa pesquisa que fazemos, não percebendo nada do assunto, verificamos que existem montes de erros de sintaxe aos quais não conseguimos dar a volta.

Pieiro.

Eu falei anteriormente em controlos Activex e não controlos de formulário.

Aqui não dá para colar imagens, mas na tua folha, insere um botão activex e uma combobox activex.

Depois colas este código na Folha1. Para isso tens que ativar o programador.

Dim mwksDados As Excel.Worksheet
Dim mclcNomes As VBA.Collection


Private Sub CommandButton1_Click()
  Dim lngRow As Long, COL As Long
  
   Set mwksDados = ThisWorkbook.Worksheets("Folha1")
  Set mclcNomes = New Collection
 
  If Me.ComboBox1.Value = -1 Then Exit Sub
  
  With mwksDados
    For COL = 4 To 88
        For lngRow = 2 To .Cells(.Rows.Count, COL).End(xlUp).Row
          If .Cells(lngRow, COL).Value = Me.ComboBox1.Value Then
          
            Sheets("Folha1").Range("B" & lngRow) = .Cells(lngRow, COL + 1).Value
          
          End If
        Next
    Next COL
  End With
End Sub

Private Sub Worksheet_Activate()

  Dim lng As Long, COL As Long
  Dim str As String
  Dim TotNomes As Integer
  
  Set mwksDados = ThisWorkbook.Worksheets("Folha1")
  Set mclcNomes = New Collection
  
  With mwksDados
    On Error Resume Next
        For COL = 4 To 88
            For lng = 2 To .Cells(.Rows.Count, 4).End(xlUp).Row
              str = .Cells(lng, COL).Value
              mclcNomes.Add str, str
                TotNomes = mclcNomes.Count
            Next lng
        Next COL
    On Error GoTo 0
  End With

Dim linha As Integer
linha = 1
Do Until Folha1.Range("A" & linha).Value = ""
Me.ComboBox1.AddItem Folha1.Range("A" & linha).Value
linha = linha + 1
Loop



End Sub

Claro que tens que ter cuidado com os nomes. Se a tua folha tem nome diferente de "Folha1", não vais colocar Folha1 só porque este bloco de código diz Folha1.

Testei aqui e funciona 100%, portanto não há razão para dizeres que dá erros. A rotina lê todos os nomes até à coluna 88, quer dizer uma ou duas a seguir à coluna "CG" e vai até à última linha que tem dados, quer seja a linha 100 ou a linha 9999.

Na Combobox podes selecionar o nome que quiseres.

Edited by manuel antonio
correção
Posted (edited)

Na verdade não é só um exit sub que pode ter, acho que você não pesquisou direito essa parte ou se pesquisou interpretou do mesmo jeito que interpretou a minha frase, ou seja totalmente errado. Eu também não sou Programador, mas sou um amador que presa pela qualidade do meu serviço, não basta fazer o que eu preciso, tem que fazer da melhor forma possível.

Pieiro seria um prazer ajudar expondo códigos, mas creio que é melhor você estudar um pouco de conceito básico, assim você pega gosto suficiente para conseguir se aprofundar, já vi muitas pessoas que se dizem experientes em VBA mas erram em conceitos básicos exatamente por querer pular esta etapa, neste forum mesmo ja tem conteúdo suficiente para resolver o problema que você precisa.

Edited by Poncio Elias
Posted

Cada aplicação é uma aplicação e requer situações diferentes. Inegavelmente, para principiantes é boa prática. Depois vêm as situações particulares com por exemplo a sintaxe de linha única em que a estrutura se altera "If A > 10 Then A = A + 1 : B = B + A : C = C + B". Haverá com certeza outras situações, mas ultrapassam as minhas capacidades.

Importante é ajudar, pois as primeiras ajudas são um incentivo a desenvolver conhecimentos. 

Quando isso não acontece, também nos apercebemos disso e quando pedem peixe, entregamos uma cana para aprender a pescar.

Posted

Eu acabei de te ajudar, te fazendo pesquisar novamente sobre um tema básico que você não dominava totalmente.

Ajuda não é a mesma coisa que fazer para a pessoa. Se me pedir AJUDA para conseguir um peixe, posso até fornecer as ferramentas e dicas necessárias, mas não vou pescar, limpar e cozinhar o peixe para você. pois se eu fizer isso na próxima vez que precisar de peixe vai querer me pedir novamente porque não aprendeu como fazer isso.

Posted (edited)
54 minutos atrás, manuel antonio disse:

Importante é ajudar, pois as primeiras ajudas são um incentivo a desenvolver conhecimentos. 

Quando isso não acontece, também nos apercebemos disso e quando pedem peixe, entregamos uma cana para aprender a pescar.

Exatamenter isso que eu disse.

Edited by manuel antonio
Posted (edited)

Manuel você postou um exemplo que usa controle activex, instancia objeto e aciona eventos, ou seja é muito código para pouco problema. Por favor não me entenda mal, adoro conversar com quem discorda de mim, mas como isso pode ser vantajoso para quem esta começando? O que o nosso amigo Pieiro precisa resolver é simples, tem que ser resolvido com código simples, eu passei a linha de comando que ele precisa para atribuir o valor de uma celula para outra só falta implementar lógica, e lógica vai de cada programador não é igual receita de bolo que é só passar e fazer igual. É muito mais vantajoso dominar bem conceitos simples, do que dominar muito mal conceitos avançados. -

Edited by Poncio Elias
Posted

Poncio.

16 horas atrás, Poncio Elias disse:

Manuel você postou um exemplo que usa controle activex, instancia objeto e aciona eventos, ou seja é muito código para pouco problema. Por favor não me entenda mal, adoro conversar com quem discorda de mim, mas como isso pode ser vantajoso para quem esta começando?

Eu entendo o queres dizer e que tudo podia ser resolvido de maneira mais simples. O problema? O Pieiro não sabe o que é um ciclo e penso pelas dúvidas dele que não sabe os mínimos de VBA. Apenas sei que ele tem um problema e penso que se deve motivar a aprender fornecendo algumas pistas no início.

Se depois continuar sem querer aprender, é aí que lhe dizemos onde comprar uma cana de pesca.

Ainda não sabemos se resolveu ou não o problema, mas espero bem que sim. Só falta mesmo o feedback.

Poncio continua a fazer bons códigos e posta aí uma ajuda se eu precisar.

Cumprimentos

Posted (edited)

Manuel na verdade é assustador ver um código complexo para problema simples! Se um iniciante ver um código tão complexo como o seu para uma tarefa simples, é mais provável ele se desanimar de aprender do que se motivar, eu estou com medo de ver um código seu para um problema mais complexo. Aprender do jeito errado para depois aprender do jeito certo é apenas adiar uma coisa que ele vai ter que fazer, e vai ser pior pois vai ter que reaprender, é melhor controlar a ansiedade de ver macros funcionando de qualquer jeito e entender primeiro os conceitos básicos que não é difícil e não leva tanto tempo para depois começar a usar os recursos mais complexos, com os conceitos básicos bem definidos em mente já da para fazer muita coisa bem elaborada. Em programação menos é mais.

Edited by Poncio Elias
Posted

Olá manuel antonio boa tarde,

Fiz o que disseste, mas o código está a dar um erro, após investigar o que pode ser, descobri que o código pára na linha 521 coluna 4 isto porque essa linha está preenchida por um erro #N/D (existem muitas mais células com este valor de erro isto porque não se aplica nada a essa situação) e parece que isso é o que faz o código parar, a linha de código onde pára é: If .Cells(lngRow, COL).Value = Me.ComboBox1.Value Then

vou colocar o código aqui novamente e destacar a linha com o erro para ser mais fácil de visualizar:

Dim mwksDados As Excel.Worksheet
Dim mclcNomes As VBA.Collection


Private Sub CommandButton1_Click()
  Dim lngRow As Long, COL As Long
  
   Set mwksDados = ThisWorkbook.Worksheets("Folha1")
  Set mclcNomes = New Collection
 
  If Me.ComboBox1.Value = -1 Then Exit Sub
  
  With mwksDados
    For COL = 4 To 88
        For lngRow = 2 To .Cells(.Rows.Count, COL).End(xlUp).Row
          If .Cells(lngRow, COL).Value = Me.ComboBox1.Value Then
          
            Sheets("Folha1").Range("B" & lngRow) = .Cells(lngRow, COL + 1).Value
          
          End If
        Next
    Next COL
  End With
End Sub

Private Sub Worksheet_Activate()

  Dim lng As Long, COL As Long
  Dim str As String
  Dim TotNomes As Integer
  
  Set mwksDados = ThisWorkbook.Worksheets("Folha1")
  Set mclcNomes = New Collection
  
  With mwksDados
    On Error Resume Next
        For COL = 4 To 88
            For lng = 2 To .Cells(.Rows.Count, 4).End(xlUp).Row
              str = .Cells(lng, COL).Value
              mclcNomes.Add str, str
                TotNomes = mclcNomes.Count
            Next lng
        Next COL
    On Error GoTo 0
  End With

Dim linha As Integer
linha = 1
Do Until Folha1.Range("A" & linha).Value = ""
Me.ComboBox1.AddItem Folha1.Range("A" & linha).Value
linha = linha + 1
Loop

End Sub

 

no entanto as linhas anteriores não foram preenchidas com os valores pretendidos, não percebi se só no fim do varrimento é que faz a cópia e a colagem nas colunas B e C ou se está a falhar mais qualquer coisa.

obrigado pelo empenho na resolução do meu problema.

Cumps

pieiro

Posted

Não sei o que tens na folha e que faz dar erro mas a única coisa que aí diz é que se o valor da célula que está a ler for igual ao valor constante na combobox...

Nessa linha apenas faz a comparação entre a célula que está a ler e valor que selecionaste na combobox.

o resto, coloca-te o valor da célula à direita do nome Joana na coluna B e na linha correspondente. Testei com células vazias, com células com numeros e com simbolos e não deu qualquer erro transcrevendo todos os valores à direita do nome Joana. Não sei o que estás a fazer errado ou o que há de errado com a tua folha. Arranja uma forma de disponibilizar uma parte da tua folha.

Sobretudo, analisa o erro que te dá e tenta ver o que está errado comparando por exemplo o conteúdo das células.

Sem um pedaço da tua folha, não faço ideia do que estás a manusear.

Ou então tenta um simples ciclo for...next inserindo a instrução que o Poncio te disponibilizou.

Há muitos sites onde podes colocar o teu ficheiro. Depois colocas aqui o link.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.