设计实践

用 Canva 的批量创建(Bulk Create)给一场 120 人的活动做工牌:一个工牌模板 + 一张报名表,一次生成全部工牌

用 Canva 的批量创建(Bulk Create)给一场 120 人的活动做工牌:一个工牌模板 + 一张报名表,一次生成全部工牌。生成前用 Python 脚本清洗报名表:去掉重复和空行、提醒名字太长会溢出、超过 300 行自动拆分、不把手机号带进 Canva。

BINBHO · 图文教程

用 Canva 的批量创建(Bulk Create)给一场 120 人的活动做工牌:一个工牌模板 + 一张报名表,一次生成全部工牌。生成前用 Python 脚本清洗报名表:去掉重复和空行、提醒名字太长会溢出、超过 300 行自动拆分、不把手机号带进 Canva。

先看清成品

成品是一份多页的工牌设计,可以下载 PDF 打印。本文附带的 prepare.py 已实际运行:3 个测试通过;样例报名表 6 行,输出 4 行干净数据,找出重复 1 条、空姓名 1 条、超长字段 3 处;650 行数据自动拆成 300、300、50 三份。本文环境没有 Canva Pro 账号,批量创建的界面操作没有实际执行。

说明:中国大陆用户使用的是 Canva 可画(canva.cn),账号与国际版不通用,部分功能和素材可能不同。本文按国际版帮助中心编写,菜单名称以你看到的界面为准。

注意:报名表含个人信息,只上传工牌需要的字段(脚本只保留姓名、单位、职位),用完删除,遵守个人信息保护法。批量创建是付费功能,免费版不可用。

做完之后你会得到什么?

成果 说明
工牌模板 姓名、单位、职位三个文本框
干净的数据 bulk.csv,去重、去空格
问题清单 problems.txt,哪些人名字太长
全部工牌 一次生成,下载 PDF 打印

需要准备哪些环境?

项目 要求 说明
Canva 账号 Pro、Teams、Business 等付费计划 帮助中心:批量创建仅限付费计划,并且只能在电脑上用
报名表 CSV 或 Excel
Python 3.8+ 运行清洗脚本

官方限制:每次最多 300 行、150 个数据字段;每个单元格只能放一个媒体文件。

第一步:怎样清洗报名表?

1. 样例报名表

姓名,单位,职位,手机
张伟,星河科技,产品经理,13800000000
李娜, 星河科技 ,设计师,
张伟,星河科技,产品经理,
,某公司,工程师,
欧阳娜娜娜娜娜娜,上海某某某某信息技术有限公司,高级前端开发工程师,
Wang Lei,Nova Labs,Engineer,

2. prepare.py

"""为 Canva 批量创建(Bulk Create)准备数据:检查报名表并输出干净的 CSV。
检查项:必填、去重、超长(会在工牌上溢出)、行数上限(Canva 每次最多 300 行)。
用法:python prepare.py 报名表.csv  ->  bulk.csv + problems.txt
"""
import csv
import sys
import unicodedata

LIMITS = {"姓名": 6, "单位": 12, "职位": 8}   # 按你的工牌模板文本框宽度调整(全角字计 1,半角计 0.5)
MAX_ROWS = 300


def width(s: str) -> float:
    return sum(1 if unicodedata.east_asian_width(c) in "WF" else 0.5 for c in s)


def clean(s: str) -> str:
    return " ".join((s or "").replace("\u3000", " ").split())


def prepare(rows):
    out, problems, seen = [], [], set()
    for n, r in enumerate(rows, start=2):  # 第 1 行是表头
        rec = {k: clean(r.get(k, "")) for k in LIMITS}
        if not rec["姓名"]:
            problems.append(f"第 {n} 行:姓名为空,已跳过")
            continue
        key = (rec["姓名"], rec["单位"])
        if key in seen:
            problems.append(f"第 {n} 行:{rec['姓名']}({rec['单位']})重复,已跳过")
            continue
        seen.add(key)
        for k, lim in LIMITS.items():
            if width(rec[k]) > lim:
                problems.append(f"第 {n} 行:{k}“{rec[k]}”宽度 {width(rec[k])} 超过 {lim},请缩写或调小字号")
        out.append(rec)
    batches = [out[i:i + MAX_ROWS] for i in range(0, len(out), MAX_ROWS)]
    return batches, problems


def main(path):
    with open(path, encoding="utf-8-sig") as f:
        batches, problems = prepare(list(csv.DictReader(f)))
    for i, b in enumerate(batches, 1):
        name = "bulk.csv" if len(batches) == 1 else f"bulk-{i}.csv"
        with open(name, "w", newline="", encoding="utf-8-sig") as f:
            w = csv.DictWriter(f, fieldnames=list(LIMITS))
            w.writeheader()
            w.writerows(b)
        print(f"{name}:{len(b)} 行")
    with open("problems.txt", "w", encoding="utf-8") as f:
        f.write("\n".join(problems) + ("\n" if problems else ""))
    print(f"发现 {len(problems)} 个问题,见 problems.txt")


if __name__ == "__main__":
    main(sys.argv[1])
要点 说明
width() 汉字算 1、英文字母算 0.5,估算占用宽度
LIMITS 按模板文本框实际能放下的字数调整
去掉手机号 输出只有三列
300 行拆分 符合 Canva 单次上限

3. 运行

python prepare.py 报名表.csv

本文实际输出:

bulk.csv:4 行
发现 5 个问题,见 problems.txt
第 4 行:张伟(星河科技)重复,已跳过
第 5 行:姓名为空,已跳过
第 6 行:姓名“欧阳娜娜娜娜娜娜”宽度 8 超过 6,请缩写或调小字号
第 6 行:单位“上海某某某某信息技术有限公司”宽度 14 超过 12,请缩写或调小字号
第 6 行:职位“高级前端开发工程师”宽度 9 超过 8,请缩写或调小字号

和活动负责人确认超长的名字怎么处理(例如单位用简称),改好报名表再运行一次。

测试:

from prepare import prepare, width


def test_width():
    assert width("张伟") == 2 and width("Wang Lei") == 4


def test_prepare():
    rows = [{"姓名": "张伟", "单位": "星河科技", "职位": "产品经理"},
            {"姓名": "张伟", "单位": "星河科技", "职位": "产品经理"},
            {"姓名": "", "单位": "x", "职位": ""},
            {"姓名": "李娜", "单位": "\u3000星河科技 ", "职位": "设计师"}]
    batches, problems = prepare(rows)
    assert [r["姓名"] for r in batches[0]] == ["张伟", "李娜"]
    assert batches[0][1]["单位"] == "星河科技"
    assert any("重复" in p for p in problems) and any("姓名为空" in p for p in problems)


def test_split_300():
    rows = [{"姓名": f"人{i}", "单位": "a", "职位": "b"} for i in range(650)]
    batches, _ = prepare(rows)
    assert [len(b) for b in batches] == [300, 300, 50]

第二步:怎样做工牌模板?

  1. 创建设计 → 自定义尺寸,例如 90×130 毫米。
  2. 放三个独立的文本框,先输入示例文字“姓名”“单位”“职位”。
  3. 用最长的名字测试一次,确认字号合适,再把 prepare.py 里的 LIMITS 改成实际能放下的宽度。

帮助中心强调:每个数据字段要有一个单独的文本框。

第三步:怎样批量生成?

  1. 编辑器左侧 应用 → 找到 批量创建(Bulk Create)。
  2. 上传数据,选择 bulk.csv。
  3. 连接数据:点 自动匹配字段,或者把数据字段拖到对应文本框上。
  4. 点 继续,Canva 为每一行生成一页。
  5. 逐页翻看,重点检查 problems.txt 里提到的人。
  6. 共享 → 下载 → PDF 打印。

出问题时该怎么调?

1. 中文乱码

CSV 要用 UTF-8 编码。脚本输出的 bulk.csv 已是 UTF-8(带 BOM),Excel 也能正常打开。

2. 文字溢出文本框

调小 LIMITS 重新检查,或在模板里把文本框改成自动缩小的样式后再生成。

3. 找不到批量创建

确认是付费计划,并且在电脑浏览器或桌面应用里操作。

常见问题怎么处理?

现象 原因 解决方法
超过 300 人 单次上限 用脚本拆分后分批生成
想放个人照片 每格一个媒体文件 照片放进相框,按帮助中心的图片字段方式连接
有人临时报名 已经生成 复制一页手动改
英文名太长 半角字符也占宽度 已按 0.5 计算
打印出来尺寸不对 打印设置缩放了 打印时选“实际大小”

项目资源

用途 地址
批量创建 https://www.canva.com/help/bulk-create/
批量创建与数据自动填充 https://www.canva.com/help/bulk-create-data-autofill/
Canva 价格和计划对比 https://www.canva.com/pricing/
Canva 可画(中国大陆) https://www.canva.cn/

建议先用 5 行测试数据走完整个流程,打印一张确认尺寸和字号。

确认无误后再导入完整名单,生成后由第二个人再检查一遍姓名。