feat: Sheet 性质判定(table/free_text/mixed)

This commit is contained in:
lhl
2026-08-08 22:54:30 +08:00
parent 66753e425d
commit 4f61d24420
2 changed files with 66 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
from __future__ import annotations
from enum import Enum
from typing import Any
class SheetNature(Enum):
TABLE = "table"
FREE_TEXT = "free_text"
MIXED = "mixed"
def _non_empty(row: list[Any]) -> list[Any]:
return [c for c in row if c is not None and str(c).strip() != ""]
def find_header_row(matrix: list[list[Any]]) -> int:
for i, row in enumerate(matrix):
if len(_non_empty(row)) >= 2:
return i
return -1
def _free_text_like(matrix: list[list[Any]]) -> bool:
if not matrix:
return True
max_cols = max((len(row) for row in matrix), default=0)
if max_cols <= 1:
return True
non_empty_rows = [r for r in matrix if _non_empty(r)]
if len(non_empty_rows) / len(matrix) < 0.7:
return True
return find_header_row(matrix) == -1
def classify_sheet(matrix: list[list[Any]]) -> SheetNature:
if _free_text_like(matrix):
return SheetNature.FREE_TEXT
header_row = find_header_row(matrix)
if header_row >= 0:
for row in matrix[header_row + 1:]:
if any(str(c).strip().startswith(("", "")) for c in _non_empty(row)):
return SheetNature.MIXED
return SheetNature.TABLE
+22
View File
@@ -0,0 +1,22 @@
from genesis.parsers.sheet_nature import SheetNature, classify_sheet, find_header_row
def test_table_detection():
m = [["機能ID", "機能名"], ["A001", "社員登録"], ["A002", "退職処理"]]
assert classify_sheet(m) == SheetNature.TABLE
def test_free_text_single_col():
m = [["新入社員を登録できる。"], ["氏名・所属・入社日を入力する。"]]
assert classify_sheet(m) == SheetNature.FREE_TEXT
def test_free_text_many_empty_rows():
m = [["要求A"], [], [], [], ["要求B"]]
assert classify_sheet(m) == SheetNature.FREE_TEXT
def test_header_row_index():
m = [["機能ID", "名前"], ["1", "田中"]]
assert find_header_row(m) == 0
assert find_header_row([["自由テキスト"]]) == -1