Expressões
O ExpressionEvaluator resolve expressões em bindings de FieldElement e em condições. Suporta aritmética, funções de string, comparações e ternários.
Aritmética
quantity * price
price + tax
(total - discount) / installmentsOperadores: +, -, *, /, ^
Funções matemáticas: sin, cos, sqrt, abs, pow
Funções de string
| Função | Exemplo | Resultado |
|---|---|---|
UPPER(x) | UPPER('hello') | HELLO |
LOWER(x) | LOWER('HELLO') | hello |
TRIM(x) | TRIM(' text ') | text |
LEN(x) | LEN('abc') | 3 |
CONCAT(a, b, ...) | CONCAT('R$ ', amount) | R$ 100 |
PARSE_NUMBER(x) | PARSE_NUMBER('1.234,56') | 1234.56 |
PARSE_NUMBER
Converte uma string para número com suporte a localização BR e US:
| Entrada | Saída | Localização |
|---|---|---|
'10,90' | 10.9 | BR (vírgula decimal) |
'1.234,56' | 1234.56 | BR (ponto = milhar, vírgula = decimal) |
'1,234.56' | 1234.56 | US (vírgula = milhar, ponto = decimal) |
'R$ 1.234,56' | 1234.56 | Símbolo de moeda removido automaticamente |
Útil em conjunto com valueExpression em FieldElement para tratar campos string vindos de APIs antes de aplicar format numérico.
Comparações
Retornam 1.0 (verdadeiro) ou 0.0 (falso):
| Operador | Descrição |
|---|---|
> | Maior que |
< | Menor que |
== | Igual |
!= | Diferente |
>= | Maior ou igual |
<= | Menor ou igual |
Ternário
if(condition, valorVerdadeiro, valorFalso)Exemplos:
if(amount > 1000, 'VIP', 'Regular')
if(status == 'completed', 'Concluído', 'Pendente')
if(quantity > 0, quantity * price, 0)Variáveis do sistema
Datas
| Variável | Valor |
|---|---|
TODAY() | Data atual — yyyy-MM-dd |
NOW() | Data e hora — yyyy-MM-dd HH:mm:ss |
Paginação (disponível em printWhen de bands no PDF)
Quando o motor renderiza o PDF, as variáveis abaixo são injetadas automaticamente no contexto de avaliação de printWhen:
| Variável | Tipo | Valor |
|---|---|---|
pageNumber | int | Número da página atual (começa em 1) |
totalPages | int | Total de páginas do documento |
Exemplos em printWhen:
"printWhen": "pageNumber == 1"
"printWhen": "pageNumber == totalPages"
"printWhen": "pageNumber > 1"Exclusivo do PDF
pageNumber e totalPages só fazem sentido no PDF. Em HTML, CSV e Excel não existe conceito de página — expresssões que usam essas variáveis são avaliadas sem elas e tendem a retornar true (comportamento fail-open).
Paginação em FieldElement (PDF apenas)
Nas bands header, footer e summary de um PDF, um FieldElement pode usar page ou totalPages como binding:
{
"type": "field",
"id": "pg",
"x": 450, "y": 8,
"width": 80,
"binding": "page"
}{
"type": "field",
"id": "total_pgs",
"x": 530, "y": 8,
"width": 40,
"binding": "totalPages"
}Paginação em TextElement (PDF apenas)
O campo content de TextElement aceita os marcadores {page} e {totalPages} (case-insensitive). Funciona apenas na renderização PDF:
{
"type": "text",
"id": "footer_pag",
"x": 400, "y": 8,
"width": 150,
"content": "Página {page} de {totalPages}"
}Nos demais formatos (HTML, CSV, Excel), esses marcadores ficam sem substituição pois HTML é um documento contínuo e CSV/Excel não têm páginas.
Literais
Strings entre aspas simples ou duplas:
CONCAT('Prefixo: ', field_name)
if(status == "active", 'Ativo', 'Inativo')Variáveis do payload / contexto
Identificadores sem aspas são buscados no contexto disponível para o elemento:
product → busca context['product']
quantity * price → busca context['quantity'] e context['price']Em detail bands, o contexto é o registro atual do data source — cada chave do objeto da lista:
// Payload passado ao engine:
await engine.processData(report, {
'items': [
{'product': 'Notebook', 'quantity': 1, 'price': 2500.0},
],
});
// No FieldElement: binding: "quantity * price" → 2500.0Em header, footer e summary, o contexto é o payload global. Use dot-path para campos aninhados:
await engine.processData(report, {
'items': [...],
'empresa': {'nome': 'ACME Corp', 'cnpj': '00.000.000/0001-00'},
'titulo': 'Relatório de Vendas',
});
// FieldElement no header: binding: "empresa.nome" → "ACME Corp"
// FieldElement no header: binding: "titulo" → "Relatório de Vendas"Uso em FieldElement
{
"type": "field",
"id": "total",
"x": 300,
"y": 5,
"width": 100,
"binding": "quantity * price",
"format": "currency:BRL"
}{
"type": "field",
"id": "status_label",
"x": 400,
"y": 5,
"width": 80,
"binding": "if(amount > 1000, 'VIP', 'Regular')"
}Arredondamento
O ExpressionEvaluator também implementa applyRounding:
evaluator.applyRounding(2.545, 2, mode: 'half_even'); // 2.54
evaluator.applyRounding(2.545, 2, mode: 'half_up'); // 2.55Modos disponíveis
| Modo | O que faz | 2.545 → | 2.535 → |
|---|---|---|---|
half_even | No empate (dígito 5), vai para o par mais próximo. Padrão bancário. | 2.54 | 2.54 |
half_up | No empate, arredonda para cima. O "arredondamento escolar". | 2.55 | 2.54 |
half_down | No empate, arredonda para baixo. | 2.54 | 2.53 |
up | Sempre para cima, sem exceção. | 2.55 | 2.54 |
down | Sempre para baixo, sem exceção. | 2.54 | 2.53 |
truncate | Corta as casas extras. Mesmo efeito de down para positivos. | 2.54 | 2.53 |
Todos os exemplos acima consideram precisão 2.