Projetos /

Nero

Ferramenta desktop (PyQt5) para consolidação de dados e geração de relatórios Excel formatados (Consolidado e Individual).

Interface da Aplicação Nero - Aba Relatório Consolidado

O Desafio

Após a validação dos dados financeiros pelo Módulo Validador, era necessário consolidar as informações de múltiplas planilhas (uma por convênio ou consignatária) em relatórios finais padronizados e bem formatados para análise gerencial. A criação manual desses relatórios era demorada e sujeita a inconsistências.

O objetivo era desenvolver uma ferramenta que automatizasse a geração de dois tipos principais de relatórios em Excel: um Consolidado, agrupando dados de vários ficheiros, e um Individual, sumarizando informações por consignatária.

A Solução: Aplicação Desktop Nero

Desenvolvi o "Nero", uma aplicação desktop com interface gráfica (PyQt5) focada na geração de relatórios Excel. Ele complementa o fluxo de trabalho iniciado pelo Módulo Validador:

  • Interface com Abas (PyQt5): Organiza as funcionalidades em duas abas claras: "Relatório Consolidado" e "Relatório Individual".
  • Processamento Consolidado (Pandas/QThread): A aba "Consolidado" permite carregar múltiplas planilhas de resultados (geradas pelo Validador). Um worker em background (QThread) processa cada ficheiro, extraindo KPIs (Valor Lançado, Contratos Lançados/Não Lançados, Saldos) com base em aliases de colunas flexíveis (`config.py`).
  • Geração de Relatório Individual (Pandas/QThread): A aba "Individual" permite configurar um relatório sumarizado por consignatária, lendo dados de planilhas separadas e calculando totais.
  • Exportação Profissional para Excel (Openpyxl): Gera ficheiros `.xlsx` com formatação detalhada:
    • Cabeçalhos com cores personalizáveis (definidas via UI).
    • Fontes, cores e alinhamentos específicos para títulos, KPIs e dados.
    • Bordas em todas as células.
    • Formatação numérica (Moeda R$, Inteiro).
    • Linhas de Total Geral com fórmulas `=SUM()`.
    • Ajuste automático da largura das colunas.
  • Configuração Flexível (config.py): Permite definir aliases para nomes de colunas (tornando o sistema robusto a pequenas variações nos ficheiros de entrada), mapear tipos de convênio e definir cores para o Excel.
  • Feedback de Processamento: Uma área de "Log de Execução" em cada aba informa o usuário sobre o progresso e o resultado da geração.

Interface das Abas de Relatório

Visualização das duas principais funcionalidades da aplicação Nero.

Aba Relatório Consolidado
Aba "Relatório Consolidado": Carregamento e processamento de múltiplas planilhas.
Aba Relatório Individual
Aba "Relatório Individual": Configuração e geração de sumário por consignatária.

Código em Destaque

Trecho do `processing.py` (dentro da classe `MiniReportWorker`) que demonstra a utilização da biblioteca Openpyxl para aplicar estilos e formatação avançada às células do relatório Excel gerado, incluindo cores, fontes, bordas e formatos numéricos.

processing.py (Formatação Excel)

# (Trecho adaptado de processing.py - MiniReportWorker.run)
import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from openpyxl.utils import get_column_letter
from openpyxl.utils.dataframe import dataframe_to_rows

# --- (Após processar os dados e ter o resumo_df em Pandas) ---

            workbook = openpyxl.Workbook()
            sheet = workbook.active
            
            # --- ESTILOS ---
            header_fill = PatternFill(fill_type="solid", fgColor=self.header_color_code) # Cor vinda da UI
            white_fill = PatternFill(fill_type="solid", fgColor="FFFFFF")
            
            # Fontes
            header_font = Font(bold=True, color="FFFFFF", size=11)
            title_font = Font(bold=True, size=18, color="2c3e50")
            subtitle_font = Font(bold=True, size=14, color="2c3e50")
            total_font = Font(bold=True, color="2c3e50", size=11)
            data_font = Font(color="2c3e50") # Fonte escura para dados
            
            # Alinhamentos
            center_align = Alignment(horizontal="center", vertical="center", wrap_text=True)
            left_align = Alignment(horizontal="left", vertical="center")
            right_align = Alignment(horizontal="right", vertical="center")
            
            # Bordas
            thin_border = Border(
                left=Side(style="thin"), right=Side(style="thin"), 
                top=Side(style="thin"), bottom=Side(style="thin")
            )
            
            # Formatos Numéricos (Estilo Brasileiro)
            accounting_format = 'R$ #,##0.00' 
            integer_format = '#,##0'
            
            # --- CABEÇALHO FIXO (Título, Convênio, Data) ---
            # ... (código para mesclar células e aplicar estilos de título/subtítulo) ...

            current_row = 4 # Linha onde começam os cabeçalhos da tabela
            
            # --- CABEÇALHOS DA TABELA (CONSIGNATARIA, VALIDAÇÃO, etc.) ---
            headers = list(resumo_df.columns)
            for col_idx, header_text in enumerate(headers, 1):
                cell = sheet.cell(row=current_row, column=col_idx, value=header_text)
                cell.font = header_font
                cell.fill = header_fill
                cell.alignment = center_align
                cell.border = thin_border
            
            # --- DADOS (Linha 5+) ---
            start_data_row = current_row + 1
            for r_idx, row_data in enumerate(dataframe_to_rows(resumo_df, index=False, header=False)):
                for c_idx, value in enumerate(row_data, 1):
                    row = start_data_row + r_idx
                    cell = sheet.cell(row=row, column=c_idx, value=value)
                    cell.font = data_font # Aplica fonte escura
                    cell.fill = white_fill # Aplica fundo branco
                    cell.alignment = left_align if c_idx == 1 else center_align # Alinha a primeira coluna à esquerda
                    cell.border = thin_border # Aplica borda fina
                    
                    # Aplica formatação numérica específica
                    if headers[c_idx-1] in ["VALIDAÇÃO", "LANÇAMENTO"]:
                        cell.number_format = accounting_format
                    elif headers[c_idx-1] == "QTD CONTRATOS LANÇADOS":
                        cell.number_format = integer_format

            # --- LINHA TOTAL GERAL ---
            total_row_idx = sheet.max_row + 1
            total_label_cell = sheet.cell(row=total_row_idx, column=1, value="TOTAL")
            # ... (aplicar estilos na célula TOTAL) ...

            # Adiciona FÓRMULAS de soma e formata as células de total
            for col_idx in range(2, 5): # Colunas B, C, D (Validação, Lançamento, QTD)
                col_letter = get_column_letter(col_idx)
                formula = f"=SUM({col_letter}{start_data_row}:{col_letter}{total_row_idx - 1})"
                total_cell = sheet.cell(row=total_row_idx, column=col_idx, value=formula)
                # ... (aplicar estilos e formato numérico na célula de total) ...
            
            # ... (Código para ajustar largura das colunas e salvar o workbook) ...