#!/usr/bin/env python # -*- coding: utf-8 -*- """扩展后 mergeData 行偏移重算""" from __future__ import annotations import copy from typing import Any, Dict, List, Tuple def _int(v: Any, default: int = 0) -> int: try: return int(v) except (TypeError, ValueError): return default def compute_row_insertions( before: Dict[str, Any], after: Dict[str, Any], ) -> Dict[str, List[Tuple[int, int]]]: """ 对比扩展前后 cellData 行数,推断每个 sheet 在各行插入的额外行数。 返回 sheet_id -> [(anchor_row, rows_added), ...](按 anchor_row 升序)。 """ insertions: Dict[str, List[Tuple[int, int]]] = {} before_sheets = (before or {}).get("sheets") or {} after_sheets = (after or {}).get("sheets") or {} for sheet_id, after_sheet in after_sheets.items(): before_sheet = before_sheets.get(sheet_id) or {} before_rows = sorted(int(k) for k in (before_sheet.get("cellData") or {}).keys()) after_rows = sorted(int(k) for k in (after_sheet.get("cellData") or {}).keys()) if len(after_rows) <= len(before_rows): continue added = len(after_rows) - len(before_rows) # 默认在最后一个原数据行之后插入(legacy down band 常见模式) anchor = before_rows[-1] if before_rows else 0 insertions.setdefault(sheet_id, []).append((anchor, added)) return insertions def recalculate_merge_data( snapshot: Dict[str, Any], row_insertions: Dict[str, List[Tuple[int, int]]], ) -> Dict[str, Any]: """按行插入量下移 merge 区域(仅处理 startRow/endRow)。""" if not row_insertions: return snapshot result = copy.deepcopy(snapshot) sheets = result.get("sheets") or {} for sheet_id, inserts in row_insertions.items(): sheet = sheets.get(sheet_id) if not sheet: continue merge_list = sheet.get("mergeData") or [] if not merge_list: continue sorted_inserts = sorted(inserts, key=lambda x: x[0]) new_merges: List[Any] = [] for region in merge_list: if not isinstance(region, dict): new_merges.append(region) continue start_row = _int(region.get("startRow"), 0) end_row = _int(region.get("endRow"), start_row) shift = 0 for anchor, delta in sorted_inserts: if start_row > anchor: shift += delta if shift: region = {**region, "startRow": start_row + shift, "endRow": end_row + shift} new_merges.append(region) sheet["mergeData"] = new_merges return result def apply_merge_recalc_after_expand( original_snapshot: Dict[str, Any], expanded_snapshot: Dict[str, Any], ) -> Dict[str, Any]: insertions = compute_row_insertions(original_snapshot, expanded_snapshot) return recalculate_merge_data(expanded_snapshot, insertions)