Smartsheet To Template Excel(场景二:上传系统统一格式)
业务边界(先看这里)
业务上有两种 Excel 输出场景,对应两个技能,不要混用:
| 场景 | 特征 | 归属技能 |
|---|---|---|
| 场景一:主播打印 | 给主播阅读、打印用;不同主播有不同标准(字段选择、顺序、排版不同);无统一格式 | excel-format-standardizer(标准= assets/standards/<主播>.json,含雪大/小洛) |
| 场景二:上传系统 | 上传业务系统用;不区分主播、只有一个统一格式;固定 53 列,不做字段增删,不支持按主播切换 | 本技能 |
判断口径:用户说"上传/导入系统/统一格式/按模板导出" → 本技能;用户说"给某主播打印/按【格式标准-某某】/打印排版" → 交给 excel-format-standardizer,不要用本技能。
功能
把源数据按唯一的标准模板(53 列选品运营表)转换输出为 Excel:序号自动编号、字段固定映射、数值列纯数字、图片嵌入 DISPIMG 单元格。不提供按主播新增标准的能力(那是场景一的职责)。
前置依赖
- 模板固定:
assets/选品运营表标准模板.xlsx(53 列)。本技能只认这一个模板,用户另给模板文件时才用--template覆盖(视为临时例外,不要固化成第二套标准)。 wecom-cli已安装(≥1.2.1)且已授权(先跑wecom-cli --version和wecom-cli auth show --status;未授权时wecom-cli auth init --noninteractive扫码)。首次执行前按wecomcli-shared技能完成公共检查。- Python + openpyxl 可用。若无:
python -m venv <env> && <env>/pip install openpyxl。 - 注意:若模板文件名只由点号组成(如
.....xlsx),openpyxl 无法识别,必须先复制为正常文件名再操作。
执行流程
Step 1:定位子表
wecom-cli smartsheet sheets list --json '{"docid": "<docid>"}'
- docid 从用户链接中提取:
https://doc.weixin.qq.com/smartsheet/<docid>?... - 从返回的 sheets 中确认目标子表标题(通常是
Sheet1)及其字段列表,核对与模板表头的对应关系。
Step 2:导出全部记录
wecom-cli smartsheet records list --json '{"docid": "<docid>", "sheet_title": "<子表名>", "limit": 100}' > records.json
- 约束:
limit × 字段数 < 10000。字段超过 100 列时调小 limit,并用返回的next_cursor分页,多个 JSON 文件一起传给转换脚本即可。 - 若
records query报 538005(无全部权限),直接用本命令降级读取,不要重试 query。 - 字段值是富文本结构(
[{text, imageUrl, ...}]),脚本内部已处理,不要手工解析。
Step 3:按模板转换(核心,脚本一键完成)
<python> "<skill目录>/scripts/build_from_records.py" \
--records records.json \
--template "<skill目录>/assets/选品运营表标准模板.xlsx" \
--output "<输出目录>/<文档名>_标准格式.xlsx"
- 用户指定了别的模板时,
--template传用户模板路径;模板要求:表头在第 1 行第 1 个工作表,第 2 行留一行示例数据(样式来源)。 - 脚本自动完成:表头"去空白精确匹配"字段映射、序号列自动顺序编号 1..N(忽略源表序号值)、图片下载并嵌入 WPS 嵌入单元格(DISPIMG)、数值列转纯数字、套用模板样式与列宽、zip 注入 cellimages.xml。
- 映射规则:模板有而智能表格没有的字段 → 留空;智能表格有而模板没有的字段(如"总裁办审核")→ 丢弃;图片列取不到图片时回退写文本。
- 图片单元格必须写成 WPS 原生格式才能正常显示:
<c ... t="str"><f>_xlfn.DISPIMG("ID_xxx",1)</f><v>=DISPIMG("ID_xxx",1)</v></c>(带t="str"与缓存值<v>)。脚本已在 zip 手术阶段自动改写;写成空<v/>会导致 WPS 打开不显示图片。
Step 4:验证与交付
- 脚本结尾自动打印
SUMMARY(records / columns / image_cells / unique_images)和 zip 完整性,据此向用户汇报。 - 用 openpyxl 重开输出文件抽查 2-3 行数据(产品名称、供应商、直播价格)确认映射正确。
- 输出文件交给用户前用 present_files 呈现。
模板 53 列速查
序号 / 群名 / 平台编号 / 商品ID / 货号款号 / 69码 / 合作方式 / 商家款式编码 / 贸易方式 / 产地 / 商品图片 / 赠品图片 / 赠品类型 / 一级类目 / 品牌 / 产品名称 / 规格汇总 / sku数量 / 产品备案号 / 店铺名 / 店铺ID / 直播机制 / 坑位费 / 保比 / 保比类型 / 机制备注 / 线上佣金 / 线下佣金 / 团长佣金 / 定向佣金成功截图 / 现货发货时效 / 现货库存 / 15天预售库存 / 不包邮地区 / 不发货地区 / 生产日期 / 子账号 / 店铺所属权 / 客服承接 / 发货方 / 供应商名称 / 我司合同主体 / 一级部门 / 四级部门 / 对接人 / 业绩归属人助理 / 直播价格 / 场次库存 / 总货值 / 备注 / 备用商品ID / 是否讲解 / 商品类型
数值列(脚本自动转纯数字):坑位费、保比、直播价格、总货值、线上/线下/团长佣金、场次库存。
图片列(自动嵌 DISPIMG):商品图片、赠品图片、定向佣金成功截图。
故障排查
- openpyxl 报 InvalidFileException 且格式名为空 → 模板文件名异常(如全为点号),复制为正常文件名。
- 图片列空白 → 源表对应字段无
imageUrl;检查是否取了文本兜底字段。图片下载失败会抛异常,重跑即可(已下载的会命中缓存)。 - WPS 打开看不到图片 → ①检查图片单元格是否带
t="str"和缓存值<v>=DISPIMG("ID_...",1)</v>(脚本自动改写,用 openpyxl 二次保存会丢失);②检查[Content_Types].xml是否有 cellimages Override、xl/_rels/workbook.xml.rels是否有 cellImage Relationship。注意:Microsoft Excel 和部分网页预览器不支持 DISPIMG,需用 WPS 打开验证。 - 序号不是 1,2,3... → 模板首列表头必须能被识别为"序号"(去空白后精确等于"序号");源表序号值会被忽略。
- 转换后文件打不开 → 确认未用 openpyxl 二次保存(openpyxl 保存会丢弃 cellimages 注入结果,必须以脚本输出为最终产物)。