strtolower(trim((string)$h)), $hdr); foreach (['data1','data2','data3','data4','barcode'] as $req) { if (!in_array($req, $headers, true)) $errors[] = "Missing required header: {$req}."; } if ($errors) { fclose($fh); return []; } while (($row = fgetcsv($fh, 0, $delimiter)) !== false) { if ($row === [null] || $row === false) continue; if (count(array_filter($row, fn($v) => trim((string)$v) !== '')) === 0) continue; // skip blank line $assoc = []; foreach ($required as $key) { $idx = array_search($key, $headers, true); $assoc[$key] = $idx !== false && isset($row[$idx]) ? trim((string)$row[$idx]) : ''; } if (implode('', $assoc) === '') continue; $rows[] = $assoc; } fclose($fh); if (empty($rows)) $errors[] = "CSV contained no usable rows after the header."; return $rows; } function render_datamatrix_svg(string $content): string { global $autoloadOk; if (!$autoloadOk) return ''; $barcode = new Barcode(); $obj = $barcode->getBarcodeObj( 'DATAMATRIX', $content, -1, -1, 'black', [0,0,0,0] ); $obj->setBackgroundColor('white'); return $obj->getSvgCode(); } /* ---------------- Sheet Template System ---------------- */ // Default preset: Demco 1.5" x 1.0" on Letter (guess: 5x8 grid, 0.5" margins, 0.125" gaps). // You can adjust these in the UI and re-preview until alignment is perfect. $defaults = [ 'page_width_in' => 8.5, 'page_height_in' => 11.0, 'margin_top_in' => 0.5, 'margin_right_in' => 0.5, 'margin_bottom_in' => 0.5, 'margin_left_in' => 0.5, 'cols' => 5, 'rows' => 8, 'label_w_in' => 1.5, 'label_h_in' => 1.0, 'gap_h_in' => 0.125, // horizontal gap between columns 'gap_v_in' => 0.125, // vertical gap between rows 'barcode_h_in' => 0.30, // barcode height inside 1.0" label 'font_in' => 0.12, // approx 8.6pt 'show_outlines' => '1' ]; // Pull current template params from POST (template form) or keep defaults function valf($name, $def) { return isset($_POST[$name]) && $_POST[$name] !== '' ? $_POST[$name] : $def; } $page_width_in = (float) valf('page_width_in', $defaults['page_width_in']); $page_height_in = (float) valf('page_height_in', $defaults['page_height_in']); $margin_top_in = (float) valf('margin_top_in', $defaults['margin_top_in']); $margin_right_in = (float) valf('margin_right_in', $defaults['margin_right_in']); $margin_bottom_in = (float) valf('margin_bottom_in', $defaults['margin_bottom_in']); $margin_left_in = (float) valf('margin_left_in', $defaults['margin_left_in']); $cols = max(1, (int) valf('cols', $defaults['cols'])); $rows = max(1, (int) valf('rows', $defaults['rows'])); $label_w_in = (float) valf('label_w_in', $defaults['label_w_in']); $label_h_in = (float) valf('label_h_in', $defaults['label_h_in']); $gap_h_in = (float) valf('gap_h_in', $defaults['gap_h_in']); $gap_v_in = (float) valf('gap_v_in', $defaults['gap_v_in']); $barcode_h_in = (float) valf('barcode_h_in', $defaults['barcode_h_in']); $font_in = (float) valf('font_in', $defaults['font_in']); $show_outlines = isset($_POST['show_outlines']) ? '1' : $defaults['show_outlines']; // Records pipeline (single or CSV) $errors = []; $records = []; $isPosted = ($_SERVER['REQUEST_METHOD'] === 'POST'); $data1 = $_POST['data1'] ?? ''; $data2 = $_POST['data2'] ?? ''; $data3 = $_POST['data3'] ?? ''; $data4 = $_POST['data4'] ?? ''; $barcodeText = $_POST['barcode'] ?? ''; $mode = $_POST['mode'] ?? ''; if ($isPosted && $mode === 'csv') { if (!isset($_FILES['csvfile']) || !is_uploaded_file($_FILES['csvfile']['tmp_name'])) { $errors[] = "Please choose a CSV file to upload."; } else { $size = $_FILES['csvfile']['size'] ?? 0; if ($size > 10 * 1024 * 1024) { $errors[] = "CSV too large (max 10MB)."; } else { $records = read_csv_assoc($_FILES['csvfile']['tmp_name'], $errors); } } } elseif ($isPosted && $mode === 'single') { if ($barcodeText === '') $errors[] = "Please provide a Barcode value."; else { $records[] = ['data1'=>$data1,'data2'=>$data2,'data3'=>$data3,'data4'=>$data4,'barcode'=>$barcodeText]; } } // Compute pagination $perPage = $cols * $rows; $pages = []; if ($records) { $pages = array_chunk($records, $perPage); } ?> Label Generator — CSV + Sheet Template

Label Generator

Import CSV and print to a **1.5" × 1.0"** template (Demco) at 100% / Actual size.

Single Label

Data Matrix prints as SVG at in height.

Import CSV (data1,data2,data3,data4,barcode)

Delimiters (comma, tab, semicolon) auto-detected. Headers must match exactly.

Template (Demco 1.5" × 1.0")

>

Tip: Do a test print on plain paper with “Show label outlines” checked. Hold it behind a real sheet to check alignment, then tweak margins/gaps as needed.

Issues:
label(s), sheet(s) @ ×.
$pageRecs): ?>
Composer autoload not found. Install the barcode library with:
composer require tecnickcom/tc-lib-barcode
(Make sure BCMath is enabled.)