Macro para verificar valores únicos e repetidos de uma lista

A macro (aqui) recebe uma lista e retorna duas: os valores únicos e os valores repetidos.

Lista

 

Existe uma forma eficiente de fazer isto, com o objeto dicionário do VBA.

 

Highlights:

‘Dicionário para a lista única
Dim dict As New Scripting.Dictionary

‘Armazena os itens repetidos
Dim dictRepet As New Scripting.Dictionary

 

 

O loop a seguir verifica se os valores são repetidos e adiciona.

A chave é a propriedade  dict.Exists(‘valor’)
‘Adiciona valores ao dicionario
For i = 1 To nl

If Not dict.Exists(listaOriginal(i, 1)) Then
‘Se nao existe, adiciona
dict.Add Key:=listaOriginal(i, 1), Item:=i
Else
‘Se já existe, coloca na lista de repetidos
dictRepet(listaOriginal(i, 1)) = 1
End If

Next i

É mais eficiente do que fazer esta verificação com um loop for, por exemplo.

 

 

 

Anúncios

Como animar objetos utilizando VBA

Pergunta: quem ganha a corrida?

Run01.png

Link para download da planilha: https://drive.google.com/open?id=1A6qdTISpCiUhEgXAygWpZbeK34Cz-cqD

 

A lógica é a seguinte.

A figura do elefante de bicicleta é um shape, que tem o nome de “Imagem 2”. Basta clicar no shape e ver o nome no painel.

Run02.png

O shape tem uma propriedade, chamada “Left”. Qual a posição, da esquerda para a direita.

Exemplo, atribuo 10 unidades à left.

Shapes(“Imagem 2”).left = 10

 

 

Para criar um efeito de animação, vou incrementando o Left por um loop (for ou while)

 

While posicaoElef < maxLeft And posicaoMenino < maxLeft

‘Elefante

With ActiveSheet.Shapes(“Imagem 2”)

posicaoElef = .Left + passoElef ‘O passo controla o quão rápido este anda

.Left = posicaoElef

DoEvents

End With

Wend

 

O comando DoEvents serve para fazer um refresh da tela.

 

 

Com o menino, é a mesma coisa, mas mudando outros parâmetros.

 

Dá para fazer outras brincadeiras, como deixar a velocidade aleatória.

 

 

Como calcular uma data menos 20 h?

Tenho um campo no formato data hora (04/09/2018 00:00)

Quero calcular este campo menos 20 horas.

A fórmula é “célula – 20/24”, conforme abaixo.

 
image014
 

Resultado:

image015
 

A lógica é que as datas são armazenadas como números no excel.
O dia 04/09/2018 = número 43.347

E 1 unidade de data = 1 dia.
O dia 05/09/2018 = número 43.348

Portanto,
1 hora = 1 / 24 dia (porque um dia tem 24h)

1 min = 1 / (24 * 60) ( porque um dia tem 24 h, e cada hora tem 60 min)

1 seg = 1 / (24* 60 *60)

Para subtrair 20h ao campo, devo subtrair o número 20 /24.

 


Bônus:

Porque 04/09/2018 = 43.347?

Porque são 43.347 dias a contar de 01/01/1900.

Se você colocar a data 01/01/1900 e subtrair 100 no excel, vai dar erro.

Fazer contas com datas é difícil, porque tem anos bissextos.
E também porque tem uma exceção à regra de bissextos a cada 100 anos.
E outra exceção de bissextos a cada 400 anos – e o ano 1900 cai exatamente na exceção da exceção.

Para entender mais, vide link a seguir.

https://ideiasesquecidas.com/2014/05/25/anos-bissextos-e-bugs-de-excel

 

Mil cardióides no Excel

Estive a folhear um livro de puzzles antigo, quando me deparo com uma curva matemática curiosa: a cardióide.

Cardiod_36_2.JPG

Esta tem este nome por parecer um coração.

Um detalhe curioso é que é possível desenhá-la somente usando régua e compasso. Como era um processo simples, mas trabalhoso para quem não tem muita coordenação motora, achei mais fácil fazer uma macro em VBA no Excel do que utilizar lápis, papel, régua e compasso.

Roteiro:
– Como desenhar a cardióide no braço
– Dicas de como usar o VBA

Link da planilha Excel para download: Google drive ou https://github.com/asgunzi/cardioidExcel (é necessário ativar macros para rodar).


Como desenhar a cardióide no braço

O desenho da cardióide segue os seguintes passos:

Pegue uma circunferência, e a divida em n ângulos iguais, formando n “casas”.

Cardiod_drawing1.JPG

Trace uma linha num diâmetro.

Cardiod_drawing2.JPG

Trace uma linha pulando uma casa do lado direito e duas do lado esquerdo.

Cardiod_drawing3.JPG

Repita o processo n vezes.

Cardiod_drawing4.JPG
Se eu chamar de “n” o número de pontos, e de “step” o número de casas puladas, posso fazer algumas variantes desta brincadeira, com efeitos muito bonitos.

Cardiod_72_2.JPG

Em geral, quanto mais linhas, maior a resolução da cardióide – porém linhas demais tornam-o ilegível.

Cardiod_33_1.JPG

Para mudar a cor, basta colorir a célula da cor da forma desejada.

Cardiod_30_0.JPG

Quanto maior o step, mais saliências a figura vai ter.

Cardiod_18_2.JPG

Cardiod_72_3.JPG

Embora cada curva dessas possa ter um nome, é mais fácil continuar chamando-as de cardióides.

Cardiod_100_4.JPG
E assim sucessivamente, é possível fazer cardióides a mil.

 

Cardiod_100_5.JPG

 


 

Como usar o vba do Excel para fazer este desenho

 

Da mesma forma que, no braço, é necessário apenas régua e compasso, no excel é necessário somente círculos, linhas e matemática.

 

Vou colocar apenas os pontos principais.

Para adicionar um círculo no Excel, é só usar o shape msoShapeOval.

 

‘Adiciona círculo na posição (left, top), com raio dado.
ActiveSheet.Shapes.AddShape(msoShapeOval, left, top, 2 * raio, 2 * raio).Select

 

Para traçar uma linha no Excel, utilizar o addLine do shapes, onde o ponto 1 é dado por coordenadas (x1,y1) e o ponto 2 por coordenadas (x2,y2).

 

‘Adiciona uma linha
ActiveSheet.Shapes.addLine(x1, y1, x2, y2).Select

 

Para saber quais os pontos a gerar.

Divido n pontos num círculo, o que equivale a um ângulo theta de 360 graus (ou 2*pi) dividido por n.

 

Cada ponto terá coordenadas (raio*cos(theta), raio*sin(theta)) em relação ao centro do círculo.

Cardiod_angulo.jpg

Como o centro do círculo tem coordenadas (latOrigin, longOrigin), deve-se compensar este valor. E crio um array para armazenar estas informações.

‘Gera coordenadas
ReDim arrRef(1 To npoints, 1 To 2) ‘lat e long

For i = 1 To npoints
  theta = (i – 1) * 2 * pi / npoints
  arrRef(i, 1) = latOrigin + raio * Cos(theta) ‘lat
  arrRef(i, 2) = longOrigin – raio * Sin(theta) ‘long
Next i
Finalmente, traço as linhas entre dois pontos (ponto i e ponto j) pulando o step dado.

For i = 1 To npoints

  ActiveSheet.Shapes.addLine(arrRef(i, 1), arrRef(i, 2), arrRef(j, 1), arrRef(j, 2)).Select
  ‘Update j: adiciona step
  j = (j + step – 1) Mod npoints + 1

Next i

 

 

A parte VBA tem que ter familiaridade com o assunto para entender, porém, os passos são exatamente os mesmos de fazer com régua e compasso, com lápis e papel!

Bônus: Cardióide com 6 saliências.

Cardiod_150_6.JPG

 

 

Links:

https://en.wikipedia.org/wiki/Cardioid

https://github.com/asgunzi/cardioidExcel

Main blog: https://ideiasesquecidas.com/

Other writings: https://medium.com/@arnaldogunzi

Exemplo de gráfico de quadrantes

Exemplo de gráfico, que plota resultados por quadrantes.

 

image001.png

No caso, foi feito de forma bem manual, para dar este efeito visual. Cada linha é considerada uma fonte de dados.

O quadrante pintado é uma caixa de texto – isto requer que as escalas sejam fixas.

Segue no link, para exemplo e inspiração.

image002.png

Se o meu Excel falasse…

O Excel tem uma função de text to speech: lê o texto e fala através de um sintetizador de voz.

É simplesmente um comando como o seguinte:

Application.Speech.Speak  "Texto a falar”

Speak.png

Infelizmente, ele só sabe falar em inglês.

Desafio: achar um plugin para falar em português.

Segue exemplo aqui.

Como imprimir a planilha inteira em uma página?

 

Há um método simples para imprimir a área da planilha toda em uma folha.

 

Ir em Arquivo -> Imprimir, onde será mostrado um menu como o seguinte.

 

excelInteiro01.jpg

Na última caixa, escolher a opção “Ajustar planilha em uma página”.

 

excelInteiro02.jpg

As demais configurações, orientação, impressora, etc, podem ser modificadas à vontade.

 

 

Desta forma, a impressão vai caber certinho na página.

Fica a dica.