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:
{ "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:
{ "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ável | Disponível em | Sintaxe |
|---|---|---|
| Campo do registro | FieldElement em detail | binding: "campo" |
| Campo do payload global (dot-path) | FieldElement em header/footer/summary | binding: "empresa.nome" |
| Número de página | FieldElement e TextElement — somente PDF | binding: "page" ou {page} no content |
| Total de páginas | FieldElement e TextElement — somente PDF | binding: "totalPages" ou {totalPages} no content |
| Número de página (expressão) | printWhen de bands — somente PDF | pageNumber |
| Total de páginas (expressão) | printWhen de bands — somente PDF | totalPages |
| Data atual | bindings e printWhen | TODAY() |
| Data e hora atual | bindings e printWhen | NOW() |
Ver a referência completa de expressões →
Formatação
A propriedade format controla como o valor é exibido:
| Format | Exemplo de saída | Descrição |
|---|---|---|
"" | 2500 | Sem formatação (toString) |
"currency:BRL" | R$ 2.500,00 | Real brasileiro |
"currency:USD" | $2,500.00 | Dólar americano |
"date:dd/MM/yyyy" | 16/02/2026 | Data formatada |
"datetime:dd/MM/yyyy HH:mm" | 16/02/2026 14:30 | Data e hora |
"integer" | 42 | Sem casas decimais |
"number:2" | 42.50 | 2 casas decimais |
"#,##0.00" | 1.250,75 | Padrão estilo Excel/JasperReports |
"#,##0" | 1.250 | Inteiro com separador de milhar |
"0.00" | 250,75 | Decimal 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ão | Entrada | Saída |
|---|---|---|
#,##0.00 | 1250.75 | 1.250,75 |
#,##0 | 1250 | 1.250 |
0.00 | 250.75 | 250,75 |
#,##0.000 | 1250.7 | 1.250,700 |
O separador de milhar usa
.e o decimal usa,(convenção brasileira). Para outros separadores usecurrency:BRLoucurrency:USD.
{
"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:
{
"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):
| Modo | O que faz | 2.545 → | 2.534 → |
|---|---|---|---|
half_even | No empate (dígito 5), vai para o par mais próximo. Padrão bancário, evita viés. | 2.54 | 2.53 |
half_up | No empate, arredonda para cima. O arredondamento clássico. | 2.55 | 2.53 |
half_down | No empate, arredonda para baixo. | 2.54 | 2.53 |
up | Sempre para cima (direção +∞). | 2.55 | 2.54 |
down | Sempre para baixo (direção −∞). | 2.54 | 2.53 |
truncate | Corta as casas decimais excedentes. | 2.54 | 2.53 |
Agregados
AggregateElement calcula valores sobre todos os registros de um data source:
{
"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 atualPipeline no código
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.