feat: Sheet 性质判定(table/free_text/mixed)
This commit is contained in:
@@ -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
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user