Skip to content

Processamento de dados

O DataProcessor recebe a definição e o payload, e produz um ProcessedData com:

  • detailRows: registros resolvidos para cada data source
  • aggregates: valores calculados (SUM, COUNT, AVG, MAX, MIN)
  • calculated: campos de expressão resolvidos
  • errors: erros encontrados em modo resilient

Bindings

Um FieldElement usa a propriedade binding para referenciar campos do registro:

json
{ "type": "field", "id": "f1", "x": 0, "y": 0, "width": 200, "binding": "product" }

O engine substitui product pelo valor do registro atual na detail band.

Expressões em bindings

O binding aceita expressões aritméticas:

json
{ "binding": "quantity * price" }

Variáveis de contexto

O engine disponibiliza variáveis automáticas que podem ser usadas em bindings, expressões e condições. O escopo depende do tipo de band e do tipo de elemento:

VariávelDisponível emSintaxe
Campo do registroFieldElement em detailbinding: "campo"
Campo do payload global (dot-path)FieldElement em header/footer/summarybinding: "empresa.nome"
Número de páginaFieldElement e TextElementsomente PDFbinding: "page" ou {page} no content
Total de páginasFieldElement e TextElementsomente PDFbinding: "totalPages" ou {totalPages} no content
Número de página (expressão)printWhen de bands — somente PDFpageNumber
Total de páginas (expressão)printWhen de bands — somente PDFtotalPages
Data atualbindings e printWhenTODAY()
Data e hora atualbindings e printWhenNOW()

Ver a referência completa de expressões →

Formatação

A propriedade format controla como o valor é exibido:

FormatExemplo de saídaDescrição
""2500Sem formatação (toString)
"currency:BRL"R$ 2.500,00Real brasileiro
"currency:USD"$2,500.00Dólar americano
"date:dd/MM/yyyy"16/02/2026Data formatada
"datetime:dd/MM/yyyy HH:mm"16/02/2026 14:30Data e hora
"integer"42Sem casas decimais
"number:2"42.502 casas decimais
"#,##0.00"1.250,75Padrão estilo Excel/JasperReports
"#,##0"1.250Inteiro com separador de milhar
"0.00"250,75Decimal sem separador de milhar

Tokens de data: dd (dia), MM (mês), yyyy (ano), HH (hora 24h), mm (minuto), ss (segundo).

Padrões numéricos estilo Excel

O engine aceita padrões no formato #,##0.00, #,##0, 0.00, etc. (mesmo estilo do Excel e JasperReports). A vírgula (,) ativa o separador de milhar (ponto .) e o ponto (.) determina a quantidade de casas decimais:

PadrãoEntradaSaída
#,##0.001250.751.250,75
#,##012501.250
0.00250.75250,75
#,##0.0001250.71.250,700

O separador de milhar usa . e o decimal usa , (convenção brasileira). Para outros separadores use currency:BRL ou currency:USD.

json
{
  "type": "field",
  "id": "price",
  "x": 300,
  "y": 5,
  "width": 100,
  "binding": "amount",
  "format": "currency:BRL"
}

Arredondamento

Para campos numéricos, é possível configurar o arredondamento:

json
{
  "type": "field",
  "id": "avg",
  "x": 0,
  "y": 0,
  "width": 100,
  "binding": "value",
  "format": "number:2",
  "rounding": {
    "precision": 2,
    "mode": "half_even"
  }
}

Modos de arredondamento (exemplos com precisão 2):

ModoO que faz2.5452.534
half_evenNo empate (dígito 5), vai para o par mais próximo. Padrão bancário, evita viés.2.542.53
half_upNo empate, arredonda para cima. O arredondamento clássico.2.552.53
half_downNo empate, arredonda para baixo.2.542.53
upSempre para cima (direção +∞).2.552.54
downSempre para baixo (direção −∞).2.542.53
truncateCorta as casas decimais excedentes.2.542.53

Agregados

AggregateElement calcula valores sobre todos os registros de um data source:

json
{
  "type": "aggregate",
  "id": "total",
  "x": 300,
  "y": 10,
  "width": 100,
  "verb": "SUM",
  "dataSourceId": "items",
  "targetKey": "price",
  "format": "currency:BRL"
}

Verbos disponíveis: SUM, COUNT, AVG, MAX, MIN.

Expressões avançadas

O ExpressionEvaluator suporta funções, comparações e ternários. Ver a referência completa de expressões.

Exemplos rápidos:

quantity * price           → aritmética
UPPER(customer)            → texto
if(amount > 1000, 'VIP', 'Regular') → ternário
TODAY()                    → data atual

Pipeline no código

dart
final engine = SulfiteEngineImpl();
final report = await engine.parseReport(jsonString);
final context = await engine.processData(report, payload);

// context contém '_processedData', 'detailRows', 'aggregates', etc.
// Passe direto para qualquer renderer:
final pdf = await engine.renderToPdf(context);

O processData retorna um Map<String, dynamic> que deve ser passado intacto ao renderer.

Próximo passo

Visão geral dos elementos →

Sulfite do 🇧🇷 para o mundo © 2026 Rafael S. Pinheiro