Files
site/WESP_REL/app/lab/etl/agrostar_xlsx_import.py
T
2026-07-17 12:57:18 +03:00

73 lines
2.6 KiB
Python

"""AgroStar xlsx (сводка проб) → AgrostarParseResult."""
from __future__ import annotations
import io
from typing import Any
from openpyxl import load_workbook
from app.lab.etl.agrostar_tabular import map_tabular_label, sample_from_agro_fields, tabular_rows_to_agro_fields
from app.lab.etl.agrostar_xml_import import AgrostarParseResult, _parse_float
def parse_agrostar_xlsx(data: bytes) -> AgrostarParseResult:
result = AgrostarParseResult(lab_name="АгроСтар")
try:
wb = load_workbook(io.BytesIO(data), data_only=True, read_only=False)
except Exception as exc: # noqa: BLE001
result.errors.append(f"Не удалось открыть xlsx: {exc}")
return result
ws = wb.active
if ws.max_row < 4 or ws.max_column < 2:
result.errors.append("Пустой или неузнаваемый xlsx")
return result
sample_nos: list[str] = []
farms: list[str] = []
labels: list[str] = []
for col in range(2, ws.max_column + 1):
no = ws.cell(1, col).value
if no is None:
continue
sample_nos.append(str(no).strip())
farms.append(str(ws.cell(2, col).value or "").strip())
labels.append(str(ws.cell(3, col).value or "").strip())
if not sample_nos:
result.errors.append("В xlsx нет колонок с пробами")
return result
row_values: list[tuple[str, list[str]]] = []
for row in range(4, ws.max_row + 1):
label = ws.cell(row, 1).value
if label is None:
continue
label_str = str(label).strip()
if not label_str or not map_tabular_label(label_str):
continue
vals = []
for col in range(2, 2 + len(sample_nos)):
raw = ws.cell(row, col).value
vals.append("" if raw is None else str(raw))
row_values.append((label_str, vals))
for idx, sample_no in enumerate(sample_nos):
pairs = [(label, vals[idx]) for label, vals in row_values if idx < len(vals)]
agro_fields = tabular_rows_to_agro_fields(pairs)
if "DM" not in agro_fields:
result.errors.append(f"Проба {sample_no}: нет СВ")
continue
sample = sample_from_agro_fields(
sample_no=sample_no,
farm_name=farms[idx] if idx < len(farms) else "",
desc_1=labels[idx] if idx < len(labels) else sample_no,
agro_fields=agro_fields,
)
result.samples.append(sample)
if not result.samples and not result.errors:
result.errors.append("Не удалось разобрать пробы из xlsx")
return result