feat: MIXED 完整段落解析(分割→每段最优解析)

This commit is contained in:
lhl
2026-08-09 04:07:07 +08:00
parent 539945be67
commit 1e3f702477
3 changed files with 106 additions and 2 deletions
+50 -2
View File
@@ -3,11 +3,12 @@ from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from genesis.data_models import CellComment, ExcelTable, MixedSheet
from genesis.data_models import CellComment, ExcelTable, MixedParagraph, MixedSheet
from genesis.parsers.excel_reader import open_workbook, sheet_matrix
from genesis.parsers.sheet_detector import detect_sheet_type
from genesis.parsers.sheet_nature import SheetNature, classify_sheet, find_header_row
from genesis.parsers.merge_fill import forward_fill
from genesis.parsers.paragraph_splitter import split_paragraphs
from genesis.parsers.table_extractor import extract_table
from genesis.parsers.formatting_detector import cell_formatting, collect_comments
from genesis.parsers.free_text_extractor import build_free_text_table, extract_text_blocks
@@ -36,12 +37,59 @@ class ExcelParser:
continue
detected_type = detect_sheet_type(ws.title, matrix)
nature = classify_sheet(matrix)
if nature == SheetNature.FREE_TEXT:
if nature == SheetNature.MIXED:
# 合并单元格:整 sheet 先填充再按段切片
merged = [
(r.min_row, r.min_col, r.max_row, r.max_col)
for r in ws.merged_cells.ranges
]
filled_all = forward_fill(matrix, merged) if merged else matrix
# 整 sheet 构建格式映射一次(按物理坐标)
fmt_map = {}
for row in ws.iter_rows():
for cell in row:
fmt = cell_formatting(cell)
if fmt is not None:
fmt_map[(cell.row - 1, cell.column - 1)] = fmt
mixed_sheet = MixedSheet(name=ws.title)
for (s, e) in split_paragraphs(matrix):
seg = filled_all[s:e + 1]
seg_nature = classify_sheet(seg)
if seg_nature == SheetNature.TABLE:
header_row = find_header_row(seg)
if header_row < 0:
header_row = 0
# extract_table 的 formatting_map 用段内矩阵坐标 (r,c)
# 从整 sheet 物理 map 抽出段内子 map(物理行 pr → 段内 pr-s
seg_fmt_map = {}
for (pr, pc), fmt in fmt_map.items():
if s <= pr <= e:
seg_fmt_map[(pr - s, pc)] = fmt
table = extract_table(
ws.title, seg, file_name, detected_type,
header_row=header_row, formatting_map=seg_fmt_map,
)
result.tables.append(table)
mixed_sheet.paragraphs.append(MixedParagraph(
kind="table", matrix=seg, table=table,
source_range=(s, e),
))
else:
blocks = extract_text_blocks(seg)
table = build_free_text_table(ws.title, blocks, file_name, detected_type)
result.tables.append(table)
mixed_sheet.paragraphs.append(MixedParagraph(
kind="free_text", matrix=seg,
text="\n".join(blocks), source_range=(s, e),
))
result.mixed.append(mixed_sheet)
elif nature == SheetNature.FREE_TEXT:
blocks = extract_text_blocks(matrix)
result.tables.append(
build_free_text_table(ws.title, blocks, file_name, detected_type)
)
else:
# 现有 TABLE 路径(MIXED 已独立,不折叠至此)
merged = [
(r.min_row, r.min_col, r.max_row, r.max_col)
for r in ws.merged_cells.ranges