84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
#!/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)
|