如何通过Python 3调用Smartsheet API实现多工作表批量更新
Smartsheet批量工作表升级改造实现方案
核心接口选型结论
copy sheet接口本身支持复制工作表时携带全部自动化规则、列配置、视图,但它只能基于现有工作表生成副本,没法直接套用你提前做好的优化模板,不适合你的改造场景。- 目前Smartsheet开放的自动化规则操作接口能力极弱,复杂触发条件、跨表关联类的规则根本无法通过API创建/修改,不要在这部分浪费调试时间,从已经配置好所有规则、优化项的模板创建新表,再迁移旧表数据的路径是完全可行的。
- 你之前测试的
list_all_attachments接口是附件迁移流程里的必要环节,本身可用,只是你之前的调用逻辑没走通。
现有测试代码的问题
你当前写的代码有两个核心错误,导致无法实现预期功能:
create_sheet_in_folder_from_template接口不支持传入attachments参数实现附件自动迁移,接口只会继承模板本身的结构、规则、预置内容,不会主动拉取旧表的附件。list_all_attachments返回的只是附件元数据(包含附件ID、名称、关联行ID、类型等信息),不是附件文件本身,直接把元数据传给创建表的接口没有任何作用。
全流程自动化实现步骤
整个流程可以完全通过API/SDK实现,覆盖80张表的改造不需要手动操作,单表迁移耗时在10-30秒区间:
- 提前完成优化模板的配置,确认模板内列结构、自动化规则、视图全部符合要求,记录模板ID。
- 遍历所有待改造的旧工作表,先拉取全量迁移所需的源数据:
- 调用
get sheet接口拉取旧表所有行数据,提取每行的唯一业务标识(比如工单号、项目名这类不会重复的字段),后续用来做新旧行的映射匹配 - 调用
list_all_attachments拉取全量附件元数据,区分表级附件和行级附件,记录每个附件关联的旧行ID - 调用
list_comments拉取全量评论,同样记录每个评论关联的旧行ID
- 调用
- 基于模板在目标文件夹创建新工作表,命名可沿用旧表名加迁移标识,创建时
include参数传automations,shares,确保模板上的自动化规则、共享权限完整复制到新表。 - 批量迁移旧表内容到新表:
- 按照新表的列结构做字段映射,批量调用
add rows接口把旧表所有行写入新表,生成旧行ID和新行ID的映射表 - 迁移附件:遍历附件元数据,对每个附件调用
get attachment接口拿到临时下载链接,直接下载文件流(不需要落地到本地磁盘,内存中转即可),如果是表级附件就直接上传到新表根目录,如果是行级附件就根据映射表找到对应的新行ID,上传到对应行下 - 迁移评论:逻辑和附件一致,遍历旧评论,根据行ID映射找到新表对应行,调用
create comment接口写入评论内容即可
- 按照新表的列结构做字段映射,批量调用
- 校验新表的行数、附件数量、评论数量、自动化规则状态全部正常后,可选择删除旧表,或把旧表移动到归档文件夹做备份。
关键注意事项
- 附件的临时下载链接有效期只有15分钟,不要提前批量拉取所有链接存放,要在迁移单个附件前再获取对应链接,避免链接失效
- 行级附件、行级评论的上传/写入操作,必须等行数据全部写入新表、拿到完整的新旧行ID映射关系后再执行,避免出现内容关联错位
- 如果偏好直接写JSON请求的灵活性,附件上传直接用multipart/form-data格式发请求即可,比SDK封装的附件方法调试成本更低。
核心逻辑参考代码
import requests import smartsheet from smartsheet.models import Sheet # 初始化认证 SMARTSHEET_TOKEN = "你的访问令牌" smartsheet_client = smartsheet.Smartsheet(SMARTSHEET_TOKEN) headers = {"Authorization": f"Bearer {SMARTSHEET_TOKEN}"} # 配置固定参数 TEMPLATE_ID = "提前配置好的优化模板ID" TARGET_FOLDER_ID = "新表存放的目标文件夹ID" OLD_SHEET_ID = "待迁移的旧工作表ID" # 拉取旧表全量附件元数据 old_attachments = smartsheet_client.Attachments.list_all_attachments( OLD_SHEET_ID, include_all=True ).data # 基于模板创建新表,自动继承所有自动化规则 new_sheet = smartsheet_client.Folders.create_sheet_in_folder_from_template( TARGET_FOLDER_ID, Sheet({ 'name': '迁移后的新表名称', 'from_id': TEMPLATE_ID }), include='automations,shares' ).result # --- 省略旧表行拉取、新表行写入、新旧行ID映射逻辑 --- # 映射表示例:key为旧表行ID,value为对应新表行ID row_id_map = {} # 逐个迁移附件 for att in old_attachments: # 获取单个附件的临时下载地址 att_detail = smartsheet_client.Attachments.get_attachment(OLD_SHEET_ID, att.id) # 下载附件二进制流 file_stream = requests.get(att_detail.url, stream=True).content # 判断附件关联位置 if hasattr(att, 'parent_id') and att.parent_id in row_id_map: # 行级附件:上传到对应新行 smartsheet_client.Attachments.attach_file_to_row( new_sheet.id, row_id_map[att.parent_id], (att.name, file_stream, att.mime_type) ) else: # 表级附件:上传到新工作表根级 smartsheet_client.Attachments.attach_file_to_sheet( new_sheet.id, (att.name, file_stream, att.mime_type) )
内容的提问来源于stack exchange,提问作者SkipTP9
相关产品推荐
相关产品推荐

