Label renderer generuje PDF se štítky ve dvou režimech:
Obsah štítku se definuje jako pole bloků s absolutní pozicí (v mm) uvnitř jednoho štítku. Podporované bloky: text, čárový kód, čára, obdélník, obrázek, QR kód.
⚠️ HTML = náhled, PDF = tisk. HTML preview slouží k rychlé kontrole rozložení při editaci šablony ve VS Code. Pro tisk vždy generujte PDF — HTML preview má odchylky v rozměrech způsobené scalingem prohlížeče a bitmapovými čárovými kódy. V HTML náhledu se zobrazuje vodoznak „NÁHLED — PRO TISK POUŽIJTE PDF".
Důležité: Všechny rozměry a pozice v JSON jsou v milimetrech. Počátek (0,0) je levý horní roh štítku.
{
"renderer": "label",
"layout": { ... },
"data": { ... },
"calibration": { ... },
"defaultFont": "Segoe UI",
"content": [ ... ]
}
| Sekce | Povinná | Popis |
|---|---|---|
renderer |
Ano | Vždy "label" |
layout |
Ano | Rozměry štítku a rozložení na archu |
data |
Ano | Odkaz na XML element s daty |
calibration |
Ne | Korekce tiskárny, debug mód |
defaultFont |
Ne | Výchozí font (default: "Segoe UI") |
content |
Ano | Pole bloků uvnitř štítku |
{
"layout": {
"type": "sheet",
"pageSize": "A4",
"columns": 3,
"rows": 8,
"labelWidth": 63.5,
"labelHeight": 33.9,
"marginTop": 13,
"marginLeft": 5,
"gapX": 2.5,
"gapY": 0,
"startPosition": 1
}
}
| Vlastnost | Popis |
|---|---|
columns |
Počet sloupců na archu |
rows |
Počet řádků na archu |
labelWidth |
Šířka jednoho štítku v mm |
labelHeight |
Výška jednoho štítku v mm |
marginTop |
Horní okraj archu v mm |
marginLeft |
Levý okraj archu v mm |
gapX |
Mezera mezi sloupci v mm |
gapY |
Mezera mezi řádky v mm |
startPosition |
Od které pozice tisknout (1-based). Pro načatý arch: 5 = začne od 5. pozice, první 4 jsou prázdné. |
{
"layout": {
"type": "roll",
"labelWidth": 100,
"labelHeight": 80
}
}
U pásu stačí zadat šířku a výšku. Každý štítek je samostatná PDF stránka — tiskárna kalibruje automaticky.
{
"data": {
"element": "zbozi",
"copiesField": "pocet_stitku",
"where": "typ=A"
}
}
| Vlastnost | Popis |
|---|---|
element |
Název XML elementu s daty (kontejner s <row> potomky) |
copiesField |
Pole na řádku s počtem kopií (např. "3" → 3 stejné štítky) |
copies |
Fixní počet kopií per řádek (default: 1) |
where |
Filtr: "typ=A" (rovnost), "!pole" (prázdné), "pole" (neprázdné) |
<root>
<zbozi>
<row nazev="Jablka" kod="JAB001" ean="8590123456789" cena="45.90" />
<row nazev="Hrušky" kod="HRU002" ean="8590123456790" cena="62.50" />
</zbozi>
</root>
{
"calibration": {
"xOffset": 0.5,
"yOffset": -0.3,
"showBorders": true
}
}
xOffset / yOffset — posun celého archu v mm. Každá tiskárna má drobný posun — tímto se kompenzuje bez změny souřadnic prvků.showBorders — debug mód:
Tip: Zapněte
showBorders: true, vytiskněte jeden arch a změřte odchylky. Pak nastavtexOffset/yOffseta vypněte debug.
Všechny tři hodnoty mohou být řízeny z XML dat přes placeholdery:
{
"calibration": {
"xOffset": "{parametr.cal_x}",
"yOffset": "{parametr.cal_y}",
"showBorders": "{parametr.debug}"
}
}
{
"content": [
{ "type": "rect", "x": 0, "y": 0, "width": 63.5, "height": 33.9, "fill": "#f8f8f8" },
{ "type": "text", "x": 2, "y": 2, "width": 59, "height": 8, "field": "nazev" },
{ "type": "barcode", "x": 5, "y": 14, "width": 53, "height": 10, "field": "ean" }
]
}
Pořadí bloků v poli = pořadí vykreslování (z-index). Obdélník s pozadím dejte na začátek (pod text), text na konec (navrch).
Všechny souřadnice jsou relativní k levému hornímu rohu štítku, ne k archu.
{
"type": "text",
"x": 2, "y": 1.5, "width": 59, "height": 7,
"field": "nazev",
"fontSize": 9,
"style": "bold",
"align": "center",
"maxLines": 2
}
| Vlastnost | Výchozí | Popis |
|---|---|---|
field |
— | Pole z XML |
template |
— | Šablona: "{nazev} ({kod})". Má přednost před field. |
format |
— | Formát: "N2" (2 des. místa), "dd.MM.yyyy", "###.###" (text maska) |
fontSize |
8 |
Velikost v pt |
style |
"normal" |
"bold", "italic", "bold-italic" |
align |
"left" |
"left", "center", "right" |
valign |
"top" |
"top", "center", "bottom" |
wordWrap |
true |
Zalamování slov (automaticky přes PdfSharp XTextFormatter) |
maxLines |
0 |
Maximální počet řádků (0 = bez limitu) |
color |
"black" |
Barva textu: "red", "#FF0000" |
background |
— | Barva pozadí boxu |
visibleWhen |
— | Zobrazit jen když pole není prázdné: "ean", "!sleva" |
{
"type": "barcode",
"x": 5, "y": 14, "width": 53, "height": 10,
"field": "ean",
"format": "EAN13",
"showText": true,
"quietZone": 2,
"visibleWhen": "ean"
}
| Vlastnost | Výchozí | Popis |
|---|---|---|
field |
— | Pole s hodnotou kódu |
format |
"EAN13" |
"EAN13", "EAN8", "Code128", "Code39", "ITF14", "UPCA" |
showText |
true |
Zobrazit čísla pod čárovým kódem |
textFontSize |
7 |
Velikost textu pod kódem |
quietZone |
2 |
Bílý prostor kolem kódu v mm (nutný pro spolehlivé skenování) |
Důležité: Čárové kódy jsou vektorové (ne bitmapové) — ostré čáry na jakémkoli DPI. Pokud je pole prázdné, kód se automaticky přeskočí.
EAN-13 vyžaduje 12 nebo 13 číslic. Kratší řetězec se automaticky doplní zleva nulami.
EAN-13 a EAN-8 mají automaticky delší guard bars (start, center, end čáry) — standardní vzhled.
Pokud data obsahují mix EAN-13 a Code128, formát lze řídit podmínkou:
{
"type": "barcode",
"field": "bar_kod",
"format": "{ean=true?EAN13:Code128}",
"showText": true,
"visibleWhen": "bar_kod"
}
Ternární výraz {pole=hodnota?ano:ne} se vyhodnotí per řádek z XML dat.
{ "type": "line", "x": 2, "y": 25, "width": 59, "style": "thin" }
width > 0, height = 0 → horizontální čárawidth = 0, height > 0 → vertikální čára"thin" (0.3pt), "normal" (0.5pt), "thick" (1pt), "dashed"{ "type": "rect", "x": 0, "y": 0, "width": 63.5, "height": 33.9, "border": "#000", "fill": "#f0f0f0", "rounded": 1 }
border — barva rámečku (bez border = žádný rámeček)fill — barva výplněrounded — zaoblení rohů v mm{ "type": "image", "x": 50, "y": 2, "width": 12, "height": 12, "file": "{parametr.logo}", "fit": "contain" }
| Vlastnost | Výchozí | Popis |
|---|---|---|
file |
— | Cesta k souboru nebo {field} placeholder (např. "{parametr.logo}") |
fit |
"contain" |
"contain" = zachovat poměr stran a centrovat, "stretch" = vyplnit celý box |
Tip:
containje ideální pro loga (zachová proporce).stretchpoužijte pokud chcete vyplnit celý box (např. pozadí).
{ "type": "qr", "x": 70, "y": 55, "width": 20, "height": 20,
"template": "https://example.com/{kod}", "quietZone": 1 }
| Vlastnost | Výchozí | Popis |
|---|---|---|
field |
— | Pole z XML s hodnotou pro QR |
template |
— | Šablona s placeholdery: "SPD*1.0*ACC:{ucet}*AM:{castka}" |
quietZone |
1 |
Bílý prostor kolem QR v mm |
Bloky text, barcode, image a qr lze otočit o 90°, 180° nebo 270°:
{ "type": "text", "x": 55, "y": 14, "width": 5, "height": 20,
"field": "popis", "fontSize": 7, "rotate": 90 }
| Vlastnost | Výchozí | Popis |
|---|---|---|
rotate |
0 |
Úhel: 0, 90, 180, 270 (stupně po směru hodinových ručiček) |
Souřadnice x, y, width, height v JSON vždy popisují výsledný box — tak, jak ho vidíte na vytištěném štítku. Rotace se provádí kolem středu boxu. Interně se pro 90°/270° automaticky prohodí šířka a výška.
Příklad: x=55, y=5, width=5, height=25, rotate=90
Na štítku vidíte: Interně (před rotací):
┌─────┐ ┌─────────────────────────┐
│ T │ 5×25mm │ T E X T │ 25×5mm
│ E │ úzký box │ │ široký box
│ X │ text rotovaný └─────────────────────────┘ rotovaný CSS/PdfSharp
│ T │ 90° CW kolem středu
└─────┘
Důležité: Bloky
linearectrotaci nepodporují. Pro otočenou čáru použijte vertikální/horizontální variantu (nastavením width/height).
Rotace funguje i na čárovém kódu — pro vertikální barcode na boku štítku:
{ "type": "barcode", "x": 55, "y": 2, "width": 5, "height": 30,
"field": "ean", "format": "EAN13", "showText": true, "rotate": 90 }
Pro texty s variabilní délkou — automaticky zmenší font pokud se text nevejde do boxu:
{ "type": "text", "x": 2, "y": 2, "width": 59, "height": 7,
"field": "nazev", "fontSize": 14, "overflow": "shrinkFont" }
| Vlastnost | Výchozí | Popis |
|---|---|---|
overflow |
"clip" |
"clip" = oříznutí textu, "shrinkFont" = zmenšení fontu |
Jak to funguje:
fontSize z JSON (např. 14pt)wordWrap)⚠️ ShrinkFont funguje pouze v PDF. HTML preview tuto funkci nepodporuje — slouží jen k orientační kontrole rozložení.
Typické použití: Dlouhé názvy produktů — nastavte velký
fontSize(12–14pt) jako ideál aoverflow: "shrinkFont". Krátké názvy se zobrazí velkým písmem, dlouhé se automaticky zmenší.
V template i field fungují stejné placeholdery jako v tabulkových sestavách:
| Syntax | Příklad | Popis |
|---|---|---|
{pole} |
{nazev} |
Hodnota z XML řádku |
{pole:format} |
{cena:N2} |
S formátem (2 des. místa) |
{element.pole} |
{parametr.firma} |
Tečková notace (z jiného elementu) |
{a\|b\|'text'} |
{nazev_en\|nazev\|'Bez názvu'} |
Coalesce — první neprázdná |
{pole:UPPER} |
{kod:UPPER} |
Velká písmena |
{podm?ano:ne} |
{ean=true?EAN13:Code128} |
Ternární — podmíněný text per řádek |
{
"renderer": "label",
"layout": {
"type": "sheet", "pageSize": "A4",
"columns": 3, "rows": 8,
"labelWidth": 63.5, "labelHeight": 33.9,
"marginTop": 13, "marginLeft": 5,
"gapX": 2.5, "gapY": 0
},
"data": { "element": "zbozi" },
"content": [
{ "type": "text", "x": 2, "y": 2, "width": 59, "height": 7,
"field": "nazev", "fontSize": 9, "style": "bold", "align": "center", "maxLines": 2 },
{ "type": "text", "x": 2, "y": 10, "width": 35, "height": 4,
"template": "Kód: {kod}", "fontSize": 7 },
{ "type": "barcode", "x": 5, "y": 15, "width": 53, "height": 10,
"field": "ean", "format": "EAN13", "visibleWhen": "ean" },
{ "type": "line", "x": 2, "y": 26, "width": 59, "style": "thin" },
{ "type": "text", "x": 2, "y": 27, "width": 40, "height": 5,
"template": "{cena:N2} Kč/{mj}", "fontSize": 12, "style": "bold" }
]
}
{
"renderer": "label",
"layout": { "type": "sheet", "columns": 3, "rows": 4,
"labelWidth": 63.5, "labelHeight": 60, "marginTop": 15, "marginLeft": 8, "gapX": 3 },
"data": { "element": "zbozi", "where": "typ=A" },
"content": [
{ "type": "rect", "x": 0, "y": 0, "width": 63.5, "height": 60, "fill": "#fff8e0" },
{ "type": "text", "x": 3, "y": 3, "width": 57, "height": 6,
"template": "★ AKCE", "fontSize": 10, "style": "bold", "color": "red", "align": "center" },
{ "type": "text", "x": 3, "y": 12, "width": 57, "height": 10,
"field": "nazev", "fontSize": 11, "style": "bold", "align": "center" },
{ "type": "text", "x": 3, "y": 30, "width": 57, "height": 12,
"template": "{cena:N2} Kč", "fontSize": 18, "style": "bold", "align": "center" },
{ "type": "text", "x": 3, "y": 45, "width": 57, "height": 8,
"template": "SLEVA {sleva}%", "fontSize": 12, "style": "bold", "color": "red",
"align": "center", "visibleWhen": "sleva" }
]
}
{
"renderer": "label",
"layout": { "type": "roll", "labelWidth": 100, "labelHeight": 80 },
"data": { "element": "palety" },
"content": [
{ "type": "rect", "x": 1, "y": 1, "width": 98, "height": 78, "border": "#000" },
{ "type": "text", "x": 3, "y": 3, "width": 94, "height": 8,
"field": "firma", "fontSize": 12, "style": "bold", "align": "center" },
{ "type": "barcode", "x": 8, "y": 15, "width": 84, "height": 22,
"field": "sscc", "format": "Code128", "showText": true },
{ "type": "text", "x": 3, "y": 48, "width": 60, "height": 8,
"template": "Množství: {mnozstvi} {mj}", "fontSize": 11, "style": "bold" }
]
}
Stávající FoxPro LBX štítky (CENK3X8.xml, ADR_2X6.xml, STITEK128.xml atd.) lze automaticky konvertovat na JSON:
*--- Konverze jednoho souboru ---
loBuilder.ConvertLbxToJsonFile("CENK3X8.xml", "cenk3x8.json")
*--- Do složky ---
loBuilder.ConvertLbxToAllFiles("CENK3X8.xml", "C:\output\")
*--- Nebo přes obecnou metodu (auto-detekce LBX z objcode=53) ---
loBuilder.ConvertFrxToJsonFile("CENK3X8.xml", "cenk3x8.json")
Konvertor automaticky rozpozná:
otiskserv.BarCodeImage) včetně formátu (Code128, EAN13)logofile())PrintWhen výrazůsl("label"), concatenace, str(), transform()Tip: Po konverzi zkontrolujte JSON a upravte
element(datový zdroj), případnělayoutrozměry.
loBuilder = CREATEOBJECT("XmlStackBuilder.Core.XmlStackBuilder")
loBuilder.CreateRoot("root")
*--- Header s parametry ---
loBuilder.Push("parametr")
loBuilder.AddAttribute("firma", "EFES spol. s r.o.")
loBuilder.AddAttribute("logo", "C:\images\logo.png")
loBuilder.Pop()
*--- Datové řádky pro štítky ---
CURSORTOXML("tmpStitky", "lcXml", 3, 16)
loBuilder.AddElementWithXmlContent("zbozi", m.lcXml)
*--- Render ---
loBuilder.Render("stitky.pdf", "cenikove_stitky.json")
*--- Pokud arch má spotřebovaných 4 štítků ---
* V JSON: "startPosition": 5
* Nebo dynamicky přes parametr:
loBuilder.Push("parametr")
loBuilder.AddAttribute("start", TRANSFORM(lnPocetSpotrebovanych + 1))
loBuilder.Pop()
* V JSON: "startPosition": "{parametr.start}"
*--- Každý řádek má pole "pocet_stitku" ---
* V JSON: "copiesField": "pocet_stitku"
* Řádek s pocet_stitku=3 → 3 stejné štítky
"showBorders": true v calibration"xOffset" a "yOffset" (kladné = posun doprava/dolů)showBorders"visibleWhen": "ean" aby se prázdný kód nepokusil vykreslitheight bloku"maxLines": 2 pro dvouřádkový textwidth pro delší textydata.element<row> potomky s atributywhere filtr — nefiltruje všechny řádky?"N2" → 2 desetinná místa (45,90)"N0" → celé číslo (46)"###.###" → textová maska (123.456)