This commit is contained in:
2026-03-12 01:50:57 +05:00
parent ec82b528a3
commit c33befe7c2
12 changed files with 1553 additions and 69 deletions

View File

@@ -1,6 +1,8 @@
"""Загрузка исходных данных: Таблица 1 (КИ), Таблица 2, индекс MIF-файлов."""
"""Загрузка исходных данных: Таблица 1 (КИ), Таблица 2, Таблица 3, индекс MIF-файлов."""
import zipfile
from pathlib import Path
from xml.etree import ElementTree as ET
from openpyxl import load_workbook
@@ -44,3 +46,85 @@ def build_mif_index(mif_dir: str) -> dict:
for p in Path(mif_dir).rglob("*.mif"):
index[p.stem] = str(p)
return index
def load_table3(path: str):
"""
Таблица 3 (для схем): возвращает два словаря (images, scales).
images: {zu_name → PNG-байты}
scales: {zu_name → строка масштаба, например 'Масштаб: 1:150'}
Структура xlsx: каждый блок = 3 строки.
Строка 1: ('вид он', None, None, 'зу', 'название файла', zu_name)
Строка 2: изображение якорено здесь
Строка 3: масштаб в столбце A (c1)
Изображения извлекаются прямо из zip-архива xlsx через drawing/rels.
"""
# --- Читаем имена ZU и масштабы по строкам (1-based) ---
wb = load_workbook(path, data_only=True)
ws = wb.active
zu_by_row = {} # 1-based строка заголовка → zu_name
scales = {} # zu_name → масштаб (строка из c1 третьей строки блока)
for i, row in enumerate(ws.iter_rows(values_only=True), start=1):
zu_name = row[5] if len(row) > 5 else None
if zu_name and str(zu_name).strip().startswith("выявл"):
zu_name = str(zu_name).strip()
zu_by_row[i] = zu_name
# масштаб — третья строка блока (header+2)
scale_val = ws.cell(i + 2, 1).value
if scale_val:
scales[zu_name] = str(scale_val).strip()
# --- Читаем привязку картинок из drawing XML ---
_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
_XDR = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
_A = "http://schemas.openxmlformats.org/drawingml/2006/main"
ns = {"xdr": _XDR, "a": _A, "r": _R}
result = {}
with zipfile.ZipFile(path, "r") as z:
names = z.namelist()
# Найдём все drawing-файлы
drawing_files = [n for n in names if n.startswith("xl/drawings/drawing") and n.endswith(".xml")]
for draw_path in drawing_files:
rels_path = draw_path.replace("xl/drawings/", "xl/drawings/_rels/") + ".rels"
if rels_path not in names:
continue
rels_root = ET.fromstring(z.read(rels_path))
rid_to_media = {
rel.get("Id"): rel.get("Target").split("/")[-1]
for rel in rels_root
}
draw_root = ET.fromstring(z.read(draw_path))
for anchor in draw_root:
from_el = anchor.find(f"{{{_XDR}}}from")
if from_el is None:
continue
row_0b = int(from_el.find(f"{{{_XDR}}}row").text) # 0-based
img_row_1b = row_0b + 1 # 1-based
blip = anchor.find(f".//{{{_A}}}blip")
if blip is None:
continue
rid = blip.get(f"{{{_R}}}embed")
media_filename = rid_to_media.get(rid)
if not media_filename:
continue
media_path = f"xl/media/{media_filename}"
if media_path not in names:
continue
# Ищем ближайшую ZU-строку заголовка, которая <= img_row_1b
header_row = max(
(r for r in zu_by_row if r <= img_row_1b),
default=None,
)
if header_row is None:
continue
zu_name = zu_by_row[header_row]
result[zu_name] = z.read(media_path)
return result, scales