基于引用信息的结构重排(xlsx_restructure.py)
scripts/xlsx_restructure.py 可用于插入或删除一行/一列,并自动重写所有引用这些移动单元格的内容。本文档详细说明了具体的重写规则及实际限制。
会被重写的元素
| 对象类型 | 范围 | 行为表现 |
|---|---|---|
| 公式引用 | 所有工作表 | 引用被编辑工作表的 A1 单元格的公式会相应移动;若引用完全被删除的区域,则会变为 #REF! 错误值 |
| 合并单元格范围 | 被编辑工作表 | 位置会发生移动;若合并范围包含插入点,则会扩大;若完全被删除,则会被移除(显示为 to: null) |
| 自动筛选引用 | 被编辑工作表 | 与普通单元格范围类似,会发生移动或扩大 |
| 冻结窗格 | 被编辑工作表 | 冻结窗格的锚定单元格位置会移动(永远不会低于该窗格最低行的下方或最低列的左侧) |
| 数据验证规则 | 被编辑工作表 | sqref 中指定的每个范围都会相应移动;被删除的范围则会被移除 |
| 条件格式规则 | 被编辑工作表 | 应用范围(sqref)会发生移动 |
| 原生表格 | 被编辑工作表 | 表格的引用位置会移动或扩大 |
| 定义名称 | 整个工作簿 | 引用被编辑工作表的 attr_text 定义名称的内容会被重写 |
| 行高/列宽 | 被编辑工作表 | 相关尺寸键的值会重新编号 |
支持处理的引用语法
- 可混合使用相对坐标与绝对坐标:
B2、$/B2、B$/2、$/B$/2——无论进行何种移动操作,\$符号都会保持不变。 - 区间引用,如
B2:D9,包括包含部分绝对坐标的区间。 - 跨工作表引用:
Data!B2、'My Sheet'!$/A$/1:C$/9(带引号的名称中可包含双引号'')。只有其工作表标识与正在编辑的工作表匹配的引用才会被修改;未指定工作表的引用则相对于公式所在的工作表进行解析。 - 公式中的字符串字面量(如
"See B2")永远不会被重写。 - 形状类似单元格的函数名称(如
LOG10())不会被修改(因为引用后绝不会紧跟()。) - 整行/整列引用(如
B:B、2:2)将保持不变——Excel 的规则确保其在所在区域内的插入操作后依然有效。
移动规则说明
在索引 i 处插入 N 个单元格:所有坐标值大于或等于 i 的都会向后移动 N 个单位;区间两端点则独立移动,因此覆盖索引 i 的区间也会随之扩大 N 个单位。
在索引 i 处删除 N 个单元格:索引 i 之前的坐标保持不变;被删除区域之后的坐标会向前移动 N 个单位;位于被删除区域内的单个单元格会变为 #REF!;部分覆盖该区域的区间会被限制在有效范围内(Excel 也会做相同处理);完全位于被删除区域内的区间则要么变为 #REF!(针对公式),要么会被移除(针对合并单元格或验证规则)。
无法移动的情况(实际限制)
- 图表锚点与绘图范围——openpyxl 图表对象在数据传输过程中无法保持稳定性,其锚点位置会保持不变。若数据发生移动,建议在重新构建图表时重新设置这些锚点。
- 图片/图形——原因相同。
- 条件格式规则公式——虽然应用范围会发生偏移,但
cell_is/expression规则中的公式(例如$B1>100)仍会保持原样。若这些公式引用了已移动的单元格,则需进行核查。 - 工作表内部定义的名称,以及使用 R1C1 格式或并集/交集运算符的名称,仅当它们能被解析为普通的 A1 引用时才会被重写;其他类型的名称则不会被修改,直接保留原状。
- 公式中的结构化表格引用(如
Table1[Sales])无需调整位置(因为它们会随表格一同移动),因此也会保持不变。
每次运行都会生成一份 JSON 报告,详细列出所有被修改的公式、合并区域、表格、名称及范围,同时还会包含上述各项未发生变动的 not_shifted 列表——在进行任何结构修改后,请务必查看该报告。
每次调用仅执行一个操作
CLI 命令只允许使用 --insert-rows/--delete-rows/ --insert-cols/--delete-cols 中的某一个选项(格式为 IDX[:N];列标识可使用字母)。若需执行多个操作,需重复运行命令——因为历史上的电子表格工具往往因在单次操作中顺序处理多个调整而导致引用出错。