Tutorial: Etiquetas de envio
Neste tutorial você criará etiquetas de envio no estilo logístico — duas etiquetas por folha A4, cada uma com logo, código de barras e endereço do destinatário. Usa o exemplo Etiqueta_de_Envio_Jadlog do repositório.
O que você vai aprender:
- Configurar impressão de etiquetas com
labelConfig - Usar
RectElementcomchildrencomo container de seção - Vincular um
BarcodeElementa um campo de dados - Combinar
ImageElement,FieldElementeRichTextElementem layout compacto
Pré-requisitos
- Sulfite instalado (Instalação →)
- Familiaridade com Bands e Data Sources
Passo 1 — Estrutura geral
O relatório tem apenas uma DetailBand que serve de template para cada etiqueta. O labelConfig cuida de replicar o template nas posições corretas da folha.
{
"reportId": "jadlog_label_001",
"reportName": "Etiqueta de Envio",
"pageSettings": {
"format": "A4",
"orientation": "portrait",
"margins": { "left": 14.17, "right": 14.17, "top": 14.17, "bottom": 14.17 },
"labelConfig": {
"format": "sheet",
"columns": 2,
"rows": 1,
"labelWidthMm": 100.0,
"labelHeightMm": 70.0,
"columnGapMm": 5.0,
"rowGapMm": 2.0,
"sheetMarginTopMm": 5.0,
"sheetMarginBottomMm": 5.0,
"sheetMarginLeftMm": 5.0,
"sheetMarginRightMm": 5.0
}
},
"dataSources": [
{ "id": "shipments", "type": "list", "schema": {} }
],
"bands": [
{
"type": "detail",
"id": "label_body",
"dataSourceId": "shipments",
"height": 198.43,
"elements": []
}
]
}labelConfig — parâmetros essenciais:
| Propriedade | Descrição |
|---|---|
format | "sheet" (múltiplas por página) ou "roll" (contínuo) |
columns / rows | Grade de etiquetas na folha |
labelWidthMm / labelHeightMm | Dimensões de cada etiqueta em mm |
columnGapMm / rowGapMm | Espaçamento entre etiquetas |
sheetMargin*Mm | Margens da folha em mm |
presetName | Nome de preset pré-configurado (opcional) |
INFO
labelConfig só é suportado pelo PDF renderer. HTML, CSV e Excel ignoram esse campo.
Passo 2 — Logo da transportadora
Adicione um ImageElement no canto superior esquerdo:
{
"type": "image",
"id": "logo_carrier",
"x": 5, "y": 5, "width": 80, "height": 30,
"imageUrl": "https://sua-empresa.com/logo.png",
"fit": "contain",
"opacity": 1.0
}Passo 3 — Cabeçalhos de seção com Rect children
Use RectElement com children para criar seções com fundo escuro e texto branco:
{
"type": "rect",
"id": "header_destinatario",
"x": 0, "y": 65, "width": 110, "height": 15,
"fill": "000000",
"hasBorder": true,
"borderColor": "000000",
"children": [
{
"type": "text",
"id": "label_dest",
"x": 2, "y": 2,
"content": "DESTINATÁRIO",
"fontSize": 9,
"bold": true,
"color": "ffffff"
}
]
}O children permite aninhar elementos dentro de um RectElement, criando containers visuais sem band extra.
Passo 4 — Endereço do destinatário
Vincule um FieldElement a um campo com dot-path para acessar objetos aninhados:
{
"type": "field",
"id": "dest_address",
"x": 8, "y": 88, "width": 100,
"binding": "receiver.fullAddress",
"fontSize": 9
}Passo 5 — Código de barras
Use BarcodeElement com o prefixo binding: no campo value para vincular o código a um campo do registro:
{
"type": "barcode",
"id": "bc_shipment",
"x": 115, "y": 85, "width": 165, "height": 60,
"value": "binding:shipmentId",
"format": "CODE128",
"drawText": false
}value: "binding:fieldName"— vincula o código ao campofieldNamedo registroformat—CODE128é o formato padrão para logísticadrawText: false— omite o texto legível abaixo do código de barras
Passo 6 — Informações do remetente com RichText
Use RichTextElement para combinar trechos com estilos diferentes:
{
"type": "richText",
"id": "sender_info",
"x": 8, "y": 169,
"spans": [
{ "content": "Remetente: ", "fontSize": 8, "bold": true, "color": "000000" },
{ "content": "Empresa Teste\nRua Exemplo, 1234\nCidade - UF", "fontSize": 8, "color": "000000" }
]
}Passo 7 — Payload e geração
import 'dart:io';
import 'package:sulfite_core/sulfite_core.dart';
void main() async {
final engine = SulfiteEngineImpl();
final report = await engine.parseReport(reportJson);
final pdfBytes = await engine.renderToPdf(report, {
'shipments': [
{
'shipmentId': 'JD123456789BR',
'orderSummary': '12345 / NF-001',
'receiver': {
'fullAddress': 'João da Silva\nRua das Flores, 100\nSão Paulo - SP\nCEP: 01310-100',
},
},
{
'shipmentId': 'JD987654321BR',
'orderSummary': '12346 / NF-002',
'receiver': {
'fullAddress': 'Maria Souza\nAv. Paulista, 200\nSão Paulo - SP\nCEP: 01310-200',
},
},
],
});
await File('etiquetas.pdf').writeAsBytes(pdfBytes);
}O engine distribui automaticamente os registros nas posições de etiqueta definidas pelo labelConfig (2 colunas × 1 linha por folha neste exemplo). Para mais de 2 registros, páginas adicionais são geradas automaticamente.
Diagrama da folha
┌─────────────────────────────────────┐
│ [Etiqueta 1] [Etiqueta 2] │
│ ┌──────────┐ ┌──────────┐ │
│ │ logo │ │ logo │ │
│ │ DEST. │ │ DEST. │ │
│ │ ||||||||│ │ ||||||||│ │
│ │ barcode │ │ barcode │ │
│ │ remetente│ │ remetente│ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────┘Presets disponíveis
| Preset | Dimensões |
|---|---|
Rolo 100×50mm | 100 × 50 mm, roll |
Rolo 50×30mm | 50 × 30 mm, roll |
Rolo 80×40mm | 80 × 40 mm, roll |
Couché 50×30mm | 50 × 30 mm, sheet |
A4 33×21mm | 33 × 21 mm, sheet |
A4 50×30mm | 50 × 30 mm, sheet |
A4 70×33mm | 70 × 33 mm, sheet |
A4 100×42mm | 100 × 42 mm, sheet |
A4 105×74mm | 105 × 74 mm, sheet |
Para usar um preset, defina "presetName": "A4 100×42mm" e omita os campos de medida — eles serão preenchidos automaticamente.