Este artigo explora a implementação de um sistema que verifcia mudanças na cor de células específicas em arquivos Excel (xlsx) e dispara notificações por e-mail quando alterações são detectadas. O cenário típico envolve planilhas com atualizações em tempo real onde a cor de preenchimento serve como gatilho para ações automatizadas.
A solução utiliza polling periódico para inspecionar o estado da célula monitorada, comparando o código hexadecimal da cor de preenchimento. Quando uma alteração é identificada (diferente da cor padrão), o sistema gera e envia um relatório personalizado contenod dados de outras células da planilha.
Implementação do módulo principal:
#!/usr/bin/env python3
import time
import openpyxl
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
import json
import os
def carregar_configuracao():
with open('configuracao.json', 'r', encoding='utf-8') as cfg:
return json.load(cfg)
def verificar_cor_celula(arquivo, aba, posicao):
livro = openpyxl.load_workbook(arquivo, read_only=True)
planilha = livro[aba]
return planilha[posicao].fill.fgColor.rgb
def formatar_conteudo_relatorio():
cfg = carregar_configuracao()
caminho_arquivo = obter_caminho_ativo()
conteudo = f"{cfg['mensagem_inicial']}\n"
for indice, aba in enumerate(cfg['abas_dados']):
livro = openpyxl.load_workbook(caminho_arquivo)
planilha = livro[aba]
titulo = planilha[cfg['celulas_titulo'][indice]].value
valor = planilha[cfg['celulas_valores'][indice]].value
conteudo += f"{titulo}: {valor}\n"
return conteudo + datetime.now().strftime("\nAtualizado em: %d/%m/%Y %H:%M")
def obter_caminho_ativo():
diretorio = os.getcwd()
arquivos = [f for f in os.listdir(diretorio)
if f.endswith('.xlsx') and not f.startswith('~$')]
return os.path.join(diretorio, arquivos[0])
def enviar_notificacao(corpo):
cfg = carregar_configuracao()
mensagem = MIMEText(corpo, 'plain', 'utf-8')
mensagem['Subject'] = cfg['assunto_email']
mensagem['From'] = cfg['remetente']
mensagem['To'] = ', '.join(cfg['destinatarios'])
servidor = smtplib.SMTP(cfg['servidor_smtp'], 587)
servidor.starttls()
servidor.login(cfg['usuario_smtp'], cfg['senha_smtp'])
servidor.sendmail(cfg['remetente'], cfg['destinatarios'], mensagem.as_string())
servidor.quit()
if __name__ == "__main__":
cfg = carregar_configuracao()
caminho = obter_caminho_ativo()
while True:
cor_atual = verificar_cor_celula(caminho, cfg['aba_monitorada'], cfg['celula_gatilho'])
if cor_atual != cfg['cor_padrao']:
print(f"[{datetime.now()}] Alteração detectada na célula {cfg['celula_gatilho']}")
relatorio = formatar_conteudo_relatorio()
enviar_notificacao(relatorio)
break
print(f"[{datetime.now()}] Nenhuma alteração identificada")
time.sleep(cfg['intervalo_verificacao'])
Exemplo de arquivo de configuração (configuracao.json):
{
"aba_monitorada": "Monitoramento",
"celula_gatilho": "C7",
"cor_padrao": "00000000",
"intervalo_verificacao": 3,
"mensagem_inicial": "Valores atualizados detectados:",
"assunto_email": "Alerta: Mudança na planilha",
"remetente": "sistema@empresa.com",
"destinatarios": ["analista@empresa.com", "gestor@empresa.com"],
"servidor_smtp": "smtp.empresa.com",
"usuario_smtp": "notificacoes",
"senha_smtp": "TOKEN_SEGURO_123",
"abas_dados": ["Dados", "Relatorios"],
"celulas_titulo": ["A2", "A5"],
"celulas_valores": ["B2", "B5"]
}
O sistema executa verificações periódicas com base no intervalo definido em segundos. Quando a cor de preenchimento da célula monitorada difere do valor padrão (transparência), o processo coleta dados das posições configuradas, formata o corpo do e-mail e estabelece conexão segura com o servidor SMTP para entrega da notificação. A execução é interrompida após o primeiro disparo bem-sucedido.