*Cover photo by Carlos Muza on *Unsplash
A conference sends you a registration export on Wednesday. Five hundred rows: first name, last name, company, ticket tier, a QR string. Every badge for Saturday is already in that file. The design was signed off weeks ago. What stands between the sheet and 500 finished badges isn't design work. It's a mapping: telling the template which column fills which field, once, so every row renders the same way.
That mapping is the whole job. Get it right and the five-hundredth badge is laid out exactly like the first. Get it wrong and you find out at row 300, after the print run.
This guide walks through how to map a spreadsheet to a template, column by column, so a batch renders cleanly the first time.
💡 The short version: A template holds the design. A spreadsheet holds the values. Mapping is the contract between them. Name the fields, match the headers, clean the data, preview one row, render the rest.
Quick reference for what maps to what:
| Column in your sheet | Template field type | What it controls |
|---|---|---|
| first_name, tier, date | Text field | The words that get swapped in |
| logo_url, product_shot | Image field | A picture pulled from a URL or file |
| qr_string | Image or code field | A generated QR or barcode |
| show_discount | Visibility field | Whether a layer appears at all |
Start with the sheet, not the design
The instinct is to open the design first. Resist it. The design is already done, and the sheet is what decides whether the batch works.
One row, one output
The rule that governs everything downstream: one row produces one rendered output. Row 1 is the first badge, row 12 is the twelfth. If a single badge needs a name, a company, a tier, and a QR code, then that row needs four values in four columns. Anything the template shows has to come from somewhere in that row.
This is why a stray blank row or a merged cell causes trouble later. The renderer reads top to bottom and treats every row as a job. An empty row in the middle is an empty badge in the stack.
Columns are fields, not decoration
A column header stops being a label the moment you map it. first_name isn't a description of the data, it's the address the template reads from. Treat headers as machine-facing names from the start: short, lowercase, no spaces, no punctuation. ticket_tier survives the trip. Ticket Tier (2026!) tends not to.

*Photo by 1981 Digital on *Unsplash
Name your template fields before you touch the data
A template is a design with named holes in it. Before mapping, give every hole a name you'll recognize when you see it next to a column.
Text, image, and visibility fields
Most fields fall into three kinds. Text fields swap words: a name, a price, a date, a score. Image fields pull a picture from a URL or an uploaded file: a logo, a product shot, an avatar. Visibility fields are the quiet ones. They show or hide a whole layer based on a value, which is how one template can cover "on sale" and "full price" without becoming two templates.
Naming them well is half the battle. A field called name_text sitting next to a column called first_name tells you at a glance that the wiring is right.
Match the header to the field name
The single most common failure in a batch is a mismatch between a column header and a field name. The renderer looks for the value under the name it was given. If the field expects company and the column says company_name, the field comes back empty and you get a badge with a blank where the company should be.
⚠️ The rename trap: Changing a column header after you've mapped it silently breaks the link. If a field goes empty across every row, a renamed or misspelled header is the first place to look.
Map it column by column
With fields named and headers clean, the mapping itself is short.
- Open the template and list its fields. Note the type of each: text, image, or visibility.
- Open the sheet and confirm one column exists for each field. Add the missing ones.
- Point each field at its column by name.
name_textreadsfirst_name,logoreadslogo_url, and so on. - For image fields, make sure the column holds a reachable URL or file reference, not a picture pasted into a cell.
- For visibility fields, decide what value means "show." A common pattern is a column that holds
yesortrue.

*Photo by Luke Chesser on *Unsplash
That's the contract. From here, the same sheet and the same template produce the same output on every run, whether you trigger it by hand today or a webhook fires it a thousand times next month.
Clean the data so the render doesn't surprise you
Most "the template is broken" moments are data problems wearing a costume. Four issues cause the majority of them.
| Problem | What you see | Fix |
|---|---|---|
| Blank rows | Empty outputs in the batch | Delete the gaps before rendering |
| Header in the wrong row | Nothing maps | Keep headers in row one only |
| Punctuation in headers | Field can't find its column | Lowercase, underscores, no symbols |
| Image pasted in a cell | Blank image field | Use a URL or file reference instead |
The four things that break a batch
Blank rows come first because they're invisible until you scroll. Headers below the first row are next, since most renderers only read row one for names. Punctuation in headers is quieter but just as fatal: a colon or a stray emoji can make a column unfindable. And an image dropped into a cell looks fine to a human and means nothing to a renderer, which wants a path it can fetch.
📋 Two-minute pre-flight: Headers in row one, lowercase with underscores. No blank rows. Image columns hold URLs. One column per template field. Clear this list and the batch almost always renders on the first pass.

*Photo by Surja Sen Das Raj on *Unsplash
Preview one row, then render the whole file
Never send 500 rows on faith. Render row one and hold it up against the design. Is the name in the right place? Does the logo load? Does the discount layer hide when it should? One rendered row confirms the entire contract, because every other row travels the same path through the same template.
Once that single output looks right, the batch is a formality. Same data in, same pixels out, five hundred times. The moment you'd normally start the copy-paste marathon is the moment you're already done.
This is also where a spreadsheet beats a design tool's built-in bulk feature. Canva's Bulk Create caps at 300 rows and 150 columns, which is fine right up until the row that matters is 301. Past that ceiling the job stops being design and becomes rendering, and rendering is exactly what a data-to-template mapping is for.

*Photo by Annie Spratt on *Unsplash
FAQ
What if my template needs a field my sheet doesn't have?
Add the column. Every field on the template has to read from somewhere in the row. If there's no column for it, the field renders empty on every output.
Do column headers have to match field names exactly?
The value has to reach the field by name, so the safest path is to make the header and the field name identical: lowercase, no spaces, no punctuation. Even a trailing space can break the link.
How do I put a logo or product photo in each render?
Use an image field mapped to a column that holds a URL or file reference. Don't paste the picture into the cell. The renderer fetches the image from the path, it doesn't read pixels out of the spreadsheet.
Can one template handle "on sale" and "full price" from the same sheet?
Yes, with a visibility field. Map a column like show_discount to the discount layer and let each row decide whether that layer appears. One template, two outcomes, no duplicate design.
Why does my batch have blank outputs in the middle?
Almost always a blank row in the sheet. The renderer treats every row as a job, including the empty ones. Delete the gaps and the blanks disappear.
How big can the batch be?
That depends on the renderer, but a data-to-template setup is built for the volume that design tools cap out on. If you're hitting a 300-row wall, you've outgrown bulk-design features and want a rendering workflow instead.
Do I have to re-map every time the data changes?
No. The mapping is tied to column names, not to the specific rows. Swap in a new sheet with the same headers and the same template renders the new batch unchanged.
The design was done the first time. The spreadsheet is just the same artifact again with the values changed. Map the columns once and Lemtika renders the whole file on every trigger, on-brand and identical, whether you press the button or an event does.
