dudys2004

extrair-financeiro

"Extrai dados financeiros de qualquer documento enviado pelo usuario (Excel, PDF, imagem, PPT, CSV) e cria uma planilha Excel padronizada com 8 colunas: DATA DA COMPETENCIA, MOVIMENTACAO (Entrada/Saida), HISTORICO, CLASSIFICACAO, VALOR (R$), VENCIMENTO, DATA DE PAGAMENTO e ORIGEM. Use SEMPRE que o usuario digitar EXTRAIR junto com um arquivo. Tambem acione quando o usuario mencionar extrair custos, consolidar despesas, organizar lancamentos, extrair do extrato, montar planilha financeira, consolidar financeiro, ou qualquer variacao de extracao e organizacao de dados de custo, despesa ou receita a partir de um documento. Se o usuario enviar um arquivo com dados financeiros e pedir para organizar, tabular ou consolidar, use esta skill."

dudys2004 0 Updated 4d ago

Resources

26
GitHub

Install

npx skillscat add dudys2004/dashfinance

Install via the SkillsCat registry.

SKILL.md

Objetivo

Ler o arquivo enviado, identificar todos os lancamentos financeiros (despesas, receitas, impostos, provisoes, etc.) e gerar uma planilha Excel (.xlsx) com os dados normalizados em 8 colunas padronizadas.

Esta skill e autossuficiente: o codigo gerador do Excel esta embutido neste arquivo (Passo 4). Nao depende de scripts externos.


Colunas da planilha de saida

# Coluna Regra
1 DATA DA COMPETENCIA Data de competencia do lancamento. Se ausente, use a data mais proxima disponivel no documento.
2 MOVIMENTACAO Entrada para receitas, creditos, depositos. Saida para despesas, debitos, pagamentos.
3 HISTORICO Descricao exata do item como aparece no documento original. Preserve o texto.
4 CLASSIFICACAO Sua interpretacao do tipo de transacao (veja lista abaixo).
5 VALOR (R$) Valor em reais, sempre positivo (numero sem simbolo R$).
6 VENCIMENTO Data de vencimento. Se nao houver, repita a DATA DA COMPETENCIA.
7 DATA DE PAGAMENTO Data efetiva do pagamento. Deixar vazia se nao informado.
8 ORIGEM Nome do banco, nome do arquivo, nome do relatorio ou outra referencia de origem.

Categorias para CLASSIFICACAO

Use estas categorias (ou crie uma mais especifica quando nenhuma se encaixa):

  • IMPOSTO / TRIBUTO (ISS, ICMS, PIS, COFINS, IRPJ, CSLL, IOF, DAS, etc.)
  • ALUGUEL
  • ENERGIA ELETRICA
  • AGUA / SANEAMENTO
  • SALARIO / FOLHA
  • PRO-LABORE
  • COMPRA DE MERCADORIA / ESTOQUE
  • SERVICO / PRESTADOR
  • FINANCEIRO / JUROS / ENCARGOS
  • FORNECEDOR
  • TRANSFERENCIA
  • RECEITA DE VENDAS
  • MARKETING / PUBLICIDADE
  • TRANSPORTE / FRETE
  • MANUTENCAO
  • EQUIPAMENTO / ATIVO
  • SEGURO
  • COMUNICACAO / INTERNET / TELEFONE
  • ALIMENTACAO
  • OUTROS

Processo passo a passo

Passo 1 — Ler o arquivo

Dependendo do formato recebido:

  • Excel (.xlsx / .xls / .csv): Leia todas as abas.
  • PDF: Use a skill pdf se disponivel, ou leia o arquivo diretamente.
  • Imagem (.jpg / .png / etc.): Analise visualmente o conteudo.
  • PPT (.pptx): Leia cada slide e extraia os dados financeiros.

Passo 2 — Extrair e normalizar os dados

Para cada linha ou registro no documento:

  1. Identifique data, valor, descricao e outros campos disponiveis.
  2. Determine se e Entrada ou Saida com base no contexto:
    • Sinais negativos, parenteses, colunas de debito = Saida
    • Colunas de credito, palavras como receita, venda, deposito = Entrada
  3. Classifique usando as categorias acima.
  4. Formate datas como DD/MM/AAAA.
  5. Valores: use ponto como separador decimal, sem simbolo R$ (ex: 1234.56).
  6. Ignore linhas de totais e subtotais.

Passo 3 — Salvar os dados como JSON

Salve os registros extraidos num arquivo dados_financeiros.json. IMPORTANTE no Windows: salve em UTF-8 SEM BOM (se usar PowerShell, use [System.IO.File]::WriteAllText com [System.Text.UTF8Encoding]::new($false); Set-Content adiciona BOM e quebra o JSON.parse do Node).

Formato de cada registro:

[
  {
    "data_competencia": "01/05/2026",
    "movimentacao": "Saida",
    "historico": "Descricao exata como aparece no documento",
    "classificacao": "ALUGUEL",
    "valor": 3500.00,
    "vencimento": "05/05/2026",
    "data_pagamento": "05/05/2026",
    "origem": "Extrato Bradesco Maio/2026"
  }
]

Campos obrigatorios: data_competencia, movimentacao, historico, classificacao, valor
Campos opcionais: vencimento, data_pagamento, origem (use string vazia "" se nao disponivel).

Passo 4 — Gerar o Excel

Escreva o codigo abaixo num arquivo temporario create_excel.js e execute com Node.js. O script instala exceljs automaticamente na primeira execucao e cria o Excel formatado (cabecalho azul, verde para Entradas, vermelho para Saidas, totais automaticos).

const { execSync } = require("child_process");
const path = require("path");
const fs = require("fs");
const os = require("os");

function ensureExceljs() {
  const installDir = path.join(os.tmpdir(), "extrair_node_modules");
  if (!fs.existsSync(path.join(installDir, "node_modules", "exceljs"))) {
    fs.mkdirSync(installDir, { recursive: true });
    console.error("Instalando exceljs...");
    execSync("npm install exceljs --prefix \"" + installDir + "\" --silent", { stdio: "inherit" });
  }
  return path.join(installDir, "node_modules", "exceljs");
}
const ExcelJS = require(ensureExceljs());

const args = process.argv.slice(2);
const jsonFile = args[args.indexOf("--json-file") + 1];
const outputFile = args[args.indexOf("--output") + 1];
const data = JSON.parse(fs.readFileSync(jsonFile, "utf-8").replace(/^/, ""));

async function main() {
  const wb = new ExcelJS.Workbook();
  const ws = wb.addWorksheet("Lancamentos Financeiros");
  ws.columns = [
    { key: "data_competencia", width: 20 }, { key: "movimentacao", width: 14 },
    { key: "historico", width: 54 }, { key: "classificacao", width: 28 },
    { key: "valor", width: 16 }, { key: "vencimento", width: 18 },
    { key: "data_pagamento", width: 20 }, { key: "origem", width: 38 },
  ];
  const headers = ["DATA DA COMPETENCIA","MOVIMENTACAO","HISTORICO","CLASSIFICACAO","VALOR (R$)","VENCIMENTO","DATA DE PAGAMENTO","ORIGEM"];
  const thin = { style: "thin" };
  const hr = ws.addRow(headers);
  hr.height = 30;
  hr.eachCell(function(c) {
    c.font = { bold: true, color: { argb: "FFFFFFFF" }, name: "Arial", size: 10 };
    c.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FF1F4E79" } };
    c.alignment = { horizontal: "center", vertical: "middle", wrapText: true };
    c.border = { top: thin, left: thin, bottom: thin, right: thin };
  });
  for (var i = 0; i < data.length; i++) {
    var r = data[i];
    var mov = (r.movimentacao || "").trim();
    var bg = (i % 2 === 0) ? "FFF5F5F5" : "FFFFFFFF";
    if (mov.toLowerCase() === "entrada") bg = "FFE8F5E9";
    if (mov.toLowerCase() === "saida" || mov.toLowerCase() === "saída") bg = "FFFFEBEE";
    var v = parseFloat(String(r.valor || "").replace(/[R$\s]/g, "").replace(",", "."));
    if (isNaN(v)) v = null;
    var row = ws.addRow({ data_competencia: r.data_competencia||"", movimentacao: mov, historico: r.historico||"", classificacao: r.classificacao||"", valor: v, vencimento: r.vencimento||"", data_pagamento: r.data_pagamento||"", origem: r.origem||"" });
    row.eachCell({ includeEmpty: true }, function(c, n) {
      c.fill = { type: "pattern", pattern: "solid", fgColor: { argb: bg } };
      c.font = { name: "Arial", size: 10 };
      c.border = { top: thin, left: thin, bottom: thin, right: thin };
      if (n === 3) c.alignment = { horizontal: "left", vertical: "middle" };
      else if (n === 5) c.alignment = { horizontal: "right", vertical: "middle" };
      else c.alignment = { horizontal: "center", vertical: "middle" };
    });
    row.getCell(5).numFmt = "#,##0.00";
  }
  var last = data.length + 1, ts = last + 2, tbg = "FFE3F2FD";
  function tot(rn, label, formula, color) {
    var row = ws.getRow(rn);
    var l = row.getCell(2);
    l.value = label; l.font = { bold: true, name: "Arial", size: 10, color: { argb: "FF"+color } };
    l.fill = { type: "pattern", pattern: "solid", fgColor: { argb: tbg } };
    l.alignment = { horizontal: "center", vertical: "middle" };
    l.border = { top: thin, left: thin, bottom: thin, right: thin };
    var val = row.getCell(5);
    val.value = { formula: formula }; val.numFmt = "#,##0.00";
    val.font = { bold: true, name: "Arial", size: 10, color: { argb: "FF"+color } };
    val.fill = { type: "pattern", pattern: "solid", fgColor: { argb: tbg } };
    val.alignment = { horizontal: "right", vertical: "middle" };
    val.border = { top: thin, left: thin, bottom: thin, right: thin };
  }
  tot(ts, "TOTAL SAIDAS", "SUMIF(B2:B"+last+",\"Saida\",E2:E"+last+")", "C62828");
  tot(ts+1, "TOTAL ENTRADAS", "SUMIF(B2:B"+last+",\"Entrada\",E2:E"+last+")", "2E7D32");
  tot(ts+2, "SALDO", "E"+(ts+1)+"-E"+ts, "1F4E79");
  ws.views = [{ state: "frozen", ySplit: 1 }];
  await wb.xlsx.writeFile(outputFile);
  console.log("SUCCESS: " + data.length + " registros -> " + outputFile);
}
main().catch(function(e) { console.error(e.message); process.exit(1); });

Execute:

node create_excel.js --json-file "dados_financeiros.json" --output "resultado_financeiro.xlsx"

Se Node.js nao estiver disponivel, use Python com openpyxl como alternativa, gerando as mesmas 8 colunas e os mesmos totais.

Passo 5 — Reportar ao usuario

Informe:

  • Nome e caminho do arquivo gerado
  • Quantidade total de registros extraidos
  • Quaisquer ambiguidades encontradas e como foram resolvidas
  • Se algum dado ficou incerto e pode precisar de revisao manual

Principios de qualidade

  • Nao invente dados que nao estao no documento. Campo ausente = string vazia.
  • Preserve o HISTORICO fiel ao texto original — a CLASSIFICACAO e a sua interpretacao.
  • Nao inclua totais e subtotais como lancamentos individuais.
  • Datas de vencimento ausentes: repita a data de competencia.
  • Documentos com multiplas abas ou paginas: processe todas e una em uma unica tabela.

Categories