FreeReportv0.1.0한국어

Barcode labels

A 3-across label sheet (detail columns) with Code128 and QR, DataMatrix or PDF417 per label, drawn as vectors.

Report definition (JSON)

{
  "name": "자산 관리 라벨",
  "page": {
    "size": "A4",
    "margins": [
      12,
      12,
      12,
      12
    ]
  },
  "font": {
    "family": "Nanum Gothic",
    "size": 8
  },
  "bands": {
    "pageHeader": {
      "height": 8,
      "elements": [
        {
          "type": "text",
          "x": 0,
          "y": 0,
          "w": 120,
          "h": 6,
          "text": "자산 관리 라벨 · (주)세컨드코리아",
          "style": {
            "bold": true,
            "fontSize": 9
          }
        },
        {
          "type": "text",
          "x": 120,
          "y": 0,
          "w": 66,
          "h": 6,
          "text": "{page} / {pages}",
          "style": {
            "align": "right",
            "color": "#6b7280"
          }
        }
      ]
    },
    "detail": {
      "height": 37,
      "columns": 3,
      "columnGap": 3,
      "canGrow": false,
      "elements": [
        {
          "type": "rect",
          "x": 0,
          "y": 1,
          "w": 60,
          "h": 34,
          "radius": 1.5,
          "color": "#9aa3b2",
          "width": 0.25
        },
        {
          "type": "field",
          "x": 2,
          "y": 3,
          "w": 36,
          "h": 5.5,
          "expr": "name",
          "style": {
            "bold": true,
            "fontSize": 9.5,
            "wrap": false,
            "shrinkToFit": true,
            "padding": [
              0,
              1,
              0,
              1
            ]
          }
        },
        {
          "type": "field",
          "x": 2,
          "y": 9,
          "w": 36,
          "h": 4.5,
          "expr": "assetNo",
          "style": {
            "fontSize": 7,
            "color": "#4a5568",
            "padding": [
              0,
              1,
              0,
              1
            ]
          }
        },
        {
          "type": "text",
          "x": 2,
          "y": 13.5,
          "w": 36,
          "h": 4.5,
          "text": "{dept} · {location}",
          "style": {
            "fontSize": 7,
            "color": "#4a5568",
            "padding": [
              0,
              1,
              0,
              1
            ]
          }
        },
        {
          "type": "text",
          "x": 2,
          "y": 18,
          "w": 36,
          "h": 4.5,
          "text": "취득 {format(acquired, \"yyyy.MM.dd\")}",
          "style": {
            "fontSize": 7,
            "color": "#4a5568",
            "padding": [
              0,
              1,
              0,
              1
            ]
          }
        },
        {
          "type": "barcode",
          "x": 40,
          "y": 3,
          "w": 18,
          "h": 18,
          "expr": "\"https://freereport.app/a/\" + assetNo",
          "format": "qr",
          "visible": "kind == \"qr\""
        },
        {
          "type": "barcode",
          "x": 40,
          "y": 3,
          "w": 18,
          "h": 18,
          "expr": "assetNo",
          "format": "datamatrix",
          "visible": "kind == \"datamatrix\""
        },
        {
          "type": "barcode",
          "x": 38,
          "y": 5,
          "w": 21,
          "h": 14,
          "expr": "assetNo + \"|\" + dept",
          "format": "pdf417",
          "visible": "kind == \"pdf417\""
        },
        {
          "type": "field",
          "x": 38,
          "y": 21,
          "w": 22,
          "h": 3.5,
          "expr": "kind == \"qr\" ? \"QR\" : kind == \"datamatrix\" ? \"DataMatrix\" : \"PDF417\"",
          "style": {
            "fontSize": 5.5,
            "color": "#9aa3b2",
            "align": "center",
            "padding": 0
          }
        },
        {
          "type": "barcode",
          "x": 3,
          "y": 24,
          "w": 54,
          "h": 10,
          "expr": "assetNo",
          "format": "code128"
        }
      ]
    }
  }
}

Data

Long lists show their first three items.

{
  "rows": [
    {
      "assetNo": "SK-2026-0001",
      "name": "노트북 15형",
      "dept": "개발팀",
      "location": "본사 7층",
      "acquired": "2026-01-01",
      "kind": "qr"
    },
    {
      "assetNo": "SK-2026-0002",
      "name": "27형 모니터",
      "dept": "개발팀",
      "location": "본사 7층",
      "acquired": "2026-02-02",
      "kind": "datamatrix"
    },
    {
      "assetNo": "SK-2026-0003",
      "name": "레이저 프린터",
      "dept": "경영지원팀",
      "location": "본사 6층",
      "acquired": "2026-03-03",
      "kind": "pdf417"
    },
    "… 21 items"
  ]
}

Code for this demo

import type { ReportDefinition, Style } from '@freereportjs/core';
import { mountViewer, select, tr, type DemoContext } from '../ui';

/**
 * A 3-across label sheet: the detail band prints rows side by side (`columns: 3`), so each row is
 * one asset tag. The 2D symbol is chosen per row with `visible`; every code is drawn as vectors.
 */
const small: Style = { fontSize: 7, color: '#4a5568', padding: [0, 1, 0, 1] };
const kind = (k: string) => `kind == "${k}"`;

export const definition: ReportDefinition = {
  name: '자산 관리 라벨',
  page: { size: 'A4', margins: [12, 12, 12, 12] },
  font: { family: 'Nanum Gothic', size: 8 },
  bands: {
    pageHeader: {
      height: 8,
      elements: [
        { type: 'text', x: 0, y: 0, w: 120, h: 6, text: '자산 관리 라벨 · (주)세컨드코리아', style: { bold: true, fontSize: 9 } },
        { type: 'text', x: 120, y: 0, w: 66, h: 6, text: '{page} / {pages}', style: { align: 'right', color: '#6b7280' } },
      ],
    },
    detail: {
      height: 37,
      columns: 3,
      columnGap: 3,
      canGrow: false,
      elements: [
        { type: 'rect', x: 0, y: 1, w: 60, h: 34, radius: 1.5, color: '#9aa3b2', width: 0.25 },
        { type: 'field', x: 2, y: 3, w: 36, h: 5.5, expr: 'name', style: { bold: true, fontSize: 9.5, wrap: false, shrinkToFit: true, padding: [0, 1, 0, 1] } },
        { type: 'field', x: 2, y: 9, w: 36, h: 4.5, expr: 'assetNo', style: small },
        { type: 'text', x: 2, y: 13.5, w: 36, h: 4.5, text: '{dept} · {location}', style: small },
        { type: 'text', x: 2, y: 18, w: 36, h: 4.5, text: '취득 {format(acquired, "yyyy.MM.dd")}', style: small },
        // one 2D symbol per label: QR, DataMatrix or PDF417
        { type: 'barcode', x: 40, y: 3, w: 18, h: 18, expr: '"https://freereport.app/a/" + assetNo', format: 'qr', visible: kind('qr') },
        { type: 'barcode', x: 40, y: 3, w: 18, h: 18, expr: 'assetNo', format: 'datamatrix', visible: kind('datamatrix') },
        { type: 'barcode', x: 38, y: 5, w: 21, h: 14, expr: 'assetNo + "|" + dept', format: 'pdf417', visible: kind('pdf417') },
        { type: 'field', x: 38, y: 21, w: 22, h: 3.5, expr: 'kind == "qr" ? "QR" : kind == "datamatrix" ? "DataMatrix" : "PDF417"', style: { fontSize: 5.5, color: '#9aa3b2', align: 'center', padding: 0 } },
        { type: 'barcode', x: 3, y: 24, w: 54, h: 10, expr: 'assetNo', format: 'code128' },
      ],
    },
  },
};

const ITEMS = [
  ['노트북 15형', '개발팀', '본사 7층'], ['27형 모니터', '개발팀', '본사 7층'], ['레이저 프린터', '경영지원팀', '본사 6층'],
  ['사무용 의자', '영업팀', '본사 6층'], ['높이조절 책상', '디자인팀', '본사 7층'], ['네트워크 스위치', '전산실', '서버실'],
  ['프로젝터', '회의실', '본사 6층'], ['태블릿', '영업팀', '부산지사'],
] as const;
const KINDS = ['qr', 'datamatrix', 'pdf417'] as const;

/** Asset rows; `kind` picks the 2D symbol ("mixed" cycles through all three). */
export function makeAssets(n: number, symbol: 'mixed' | (typeof KINDS)[number] = 'mixed') {
  return Array.from({ length: n }, (_, i) => {
    const [name, dept, location] = ITEMS[i % ITEMS.length];
    return {
      assetNo: `SK-2026-${String(i + 1).padStart(4, '0')}`,
      name, dept, location,
      acquired: `2026-${String((i % 9) + 1).padStart(2, '0')}-${String((i % 27) + 1).padStart(2, '0')}`,
      kind: symbol === 'mixed' ? KINDS[i % 3] : symbol,
    };
  });
}

export const sampleData = { rows: makeAssets(21) };

export default function mount(ctx: DemoContext) {
  const state = { n: 21, symbol: 'mixed' as Parameters<typeof makeAssets>[1] };
  const viewer = mountViewer(ctx, { definition, data: sampleData, zoom: 'page', fileName: '자산 라벨' });
  const reload = () => void viewer.setData({ rows: makeAssets(state.n, state.symbol) });
  select(ctx, tr(ctx.lang, { en: '2D code', ko: '2차원 코드' }), [['mixed', tr(ctx.lang, { en: 'Mixed', ko: '섞어서' })], ['qr', 'QR'], ['datamatrix', 'DataMatrix'], ['pdf417', 'PDF417']], 'mixed', v => { state.symbol = v; reload(); });
  select(ctx, tr(ctx.lang, { en: 'Labels', ko: '라벨 수' }), [['9', '9'], ['21', '21'], ['60', '60']], '21', v => { state.n = Number(v); reload(); });
}