NEKReport/extract_criteria_interface_...

127 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Однократная/повторная генерация criteria_interface_layout.json из Excel
«Запрос для ИИ Общий(2).xlsx» (листы с «интерфейс» в названии).
Запуск (путь к xlsx можно передать аргументом):
py extract_criteria_interface_layout.py "C:\\Users\\...\\Запрос для ИИ Общий(2).xlsx"
"""
from __future__ import annotations
import json
import os
import sys
import openpyxl
SHEET_TO_SHIPPING_TYPES: dict[str, list[str]] = {
"Авто LTL интерфейс": ["Автомобильная перевозка (LTL)"],
"Авто FTL интерфейс": ["Автомобильная перевозка (FTL)"],
"Море, море+жд, жд LCL интерфейc": [
"Морская перевозка (LCL)",
"Железнодорожная перевозка (LCL)",
"Мультимодальная перевозка море + ж/д (LCL)",
],
"Море, море+жд, жд FCL интерфейc": [
"Морская перевозка (FCL)",
"Железнодорожная перевозка (FCL)",
"Мультимодальная перевозка море + ж/д (FCL)",
],
"Авиа Интерфейс": ["Авиаперевозка"],
}
def _row_cells(ws, r: int, max_c: int = 12) -> list[tuple[int, str]]:
out: list[tuple[int, str]] = []
for c in range(1, max_c + 1):
v = ws.cell(r, c).value
if v is not None and str(v).strip():
out.append((c, str(v).strip()))
return out
def parse_interface_sheet(ws) -> list[dict]:
"""Разбор листа интерфейса в последовательность визуальных блоков."""
blocks: list[dict] = []
r = 1
max_r = ws.max_row or 1
while r <= max_r:
cells = _row_cells(ws, r)
if not cells:
r += 1
continue
# Заголовок: 7 ячеек в колонках 1,2,3,4,5,7,9 и все значения — «номера пунктов»
if (
len(cells) == 7
and {c[0] for c in cells} == {1, 2, 3, 4, 5, 7, 9}
and all(str(c[1]).strip().isdigit() or c[1].strip().replace(".", "").isdigit() for c in cells)
):
nums = [c[1] for c in sorted(cells, key=lambda x: (x[0] not in (1, 2, 3, 4, 5, 7, 9), x[0]))]
# порядок как в Excel слева направо по колонкам
nums = [c[1] for c in sorted(cells, key=lambda x: x[0])]
r2 = r + 1
cells2 = _row_cells(ws, r2)
if len(cells2) == 7 and {c[0] for c in cells2} == {1, 2, 3, 4, 5, 7, 9}:
labels = [c[1] for c in sorted(cells2, key=lambda x: x[0])]
blocks.append({"type": "header", "nums": nums, "labels": labels})
r += 2
continue
# Только правая пара (6 = номер, 7 = текст) — например «20 Место таможни»
if len(cells) == 2 and cells[0][0] == 6 and cells[1][0] == 7:
blocks.append({"type": "right_67", "num": cells[0][1], "label": cells[1][1]})
r += 1
continue
# Две пары: 1-2 и 6-7
if len(cells) == 4 and {cells[i][0] for i in range(4)} == {1, 2, 6, 7}:
blocks.append(
{
"type": "pair",
"left": {"num": cells[0][1], "label": cells[1][1]},
"right": {"num": cells[2][1], "label": cells[3][1]},
}
)
r += 1
continue
# Только левая пара 1-2 (один блок на строку)
if len(cells) == 2 and cells[0][0] == 1 and cells[1][0] == 2:
blocks.append({"type": "left_12", "num": cells[0][1], "label": cells[1][1]})
r += 1
continue
r += 1
return blocks
def main() -> None:
xlsx = (
sys.argv[1]
if len(sys.argv) > 1
else os.path.join(os.path.dirname(__file__), "Запрос для ИИ Общий(3).xlsx")
)
if not os.path.isfile(xlsx):
print("Файл не найден:", xlsx)
sys.exit(1)
wb = openpyxl.load_workbook(xlsx, read_only=False, data_only=True)
out: dict = {"version": 1, "source_xlsx": os.path.basename(xlsx), "by_shipping_type": {}}
for sheet_name, type_names in SHEET_TO_SHIPPING_TYPES.items():
if sheet_name not in wb.sheetnames:
print("Пропуск: лист не найден:", sheet_name)
continue
blocks = parse_interface_sheet(wb[sheet_name])
for tn in type_names:
out["by_shipping_type"][tn] = {"sheet": sheet_name, "blocks": blocks}
out_path = os.path.join(os.path.dirname(__file__), "criteria_interface_layout.json")
with open(out_path, "w", encoding="utf-8") as f:
json.dump(out, f, ensure_ascii=False, indent=2)
print("Записано:", out_path, "типов:", len(out["by_shipping_type"]))
if __name__ == "__main__":
main()