added openpyxl support

This commit is contained in:
2025-09-11 15:42:41 +03:00
parent 414907a929
commit babf491c8e
6 changed files with 224470 additions and 41307 deletions

View File

@@ -4,6 +4,7 @@ import xlrd
import aigenerated
from coord import Coord, Merged
from translations import ExcelSheetReader
import utils
LOGGING = True
@@ -14,27 +15,27 @@ def pprint(*args, **kwargs):
class Parser:
def __init__(self, sheet: "xlrd.sheet.Sheet"):
self.sh: "xlrd.sheet.Sheet" = sheet
def __init__(self, reader: ExcelSheetReader):
self.reader = reader
self.groups = {}
self.teachers = set()
self.places = set()
pprint("Parser created for '{0}': size: {1}x{2}".format(self.sh.name, self.sh.nrows, self.sh.ncols))
pprint("Parser created for '{0}'".format(reader.info()))
def parse(self):
monday = utils.find(self.sh, "ПОНЕДЕЛЬНИК")
monday = self.reader.find("ПОНЕДЕЛЬНИК")
if monday is None:
print(" -- Failed parse! -- ")
print("ПОНЕДЕЛЬНИК НЕ НАЙДЕН!")
return
head_rx = monday[0] - 1 # выше первого понидельника
head_rx = monday.row - 1 # выше первого понидельника
if head_rx < 0:
raise Exception("head_rx < 0: Программа пыталась найти 'ПОНЕДЕЛЬНИК', но по всей видимости не нашла.")
head = self.sh.row(head_rx) # get all ROW (months, groups)
head = self.reader.get_row_values(head_rx) # get all ROW (months, groups)
pprint(f"head={head}")
self.groups = parse_groups(self.sh, head, monday, head_rx) # parse groups to self.groups
self.groups = parse_groups(self.reader, head, monday, head_rx) # parse groups to self.groups
pprint(f'self.groups={json.dumps(self.groups, indent=2, ensure_ascii=False)}')
pprint("\n\n\n")
@@ -53,12 +54,12 @@ class Parser:
# speaker
low = merged.low
speaker_pos = low.shift(down=merged.height())
speaker = speaker_pos.cell(self.sh).value
speaker = speaker_pos.cell(self.reader).value
# location
location = merged.high.shift(down=1).cell(self.sh).value
location = merged.high.shift(down=1).cell(self.reader).value
return {"loc": str(location), "leader": str(speaker), "name": str(merged.cell(self.sh).value)}
return {"loc": str(location), "leader": str(speaker), "name": str(merged.cell(self.reader).value)}
def process_group(self, group, monday):
"""
@@ -70,24 +71,24 @@ class Parser:
pprint(group_name)
row = group['position'][0] + 1 # counter for while, +1 for shift down; также номер строки в таблице (вроде с нуля)
weeknum = 1 # номер недели, щёлкнет +1 при каком-то условии.
while row < self.sh.nrows: # maybe условие чтобы не уйти ниже чем есть строк
pos = Coord(row, group['position'][1]) # текущая позиция, верхний правый угол (=low)
while row < self.reader.get_row_count(): # maybe условие чтобы не уйти ниже чем есть строк
pos = Coord(row, group['position'][1]) # текущая позиция, верхний левый угол (=low)
pos_right = pos.shift(right=3)
pair_pos = pos.replace(col=5)
weekday_pos = pos.replace(col=4)
merged = utils.get_merged_coord(self.sh, pos)
right_cell = pos_right.cell(self.sh)
merged_cell = merged.cell(self.sh)
merged = self.reader.get_merged_coord(pos)
right_cell = pos_right.cell(self.reader)
merged_cell = merged.cell(self.reader)
cv = merged_cell.value
# В конце (12 пара:>) название группы, можно использовать как якорь
if utils.unspace(cv) == group_name:
pprint("Lesson == group name; ending group loop.")
break
weekday_mr = utils.get_merged_coord(self.sh, weekday_pos)
weekday = utils.unspace(weekday_mr.cell(self.sh).value)
pair_mr = utils.get_merged_coord(self.sh, pair_pos)
pair = utils.unspace(pair_mr.cell(self.sh).value)
weekday_mr = self.reader.get_merged_coord(weekday_pos)
weekday = utils.unspace(weekday_mr.cell(self.reader).value)
pair_mr = self.reader.get_merged_coord(pair_pos)
pair = utils.unspace(pair_mr.cell(self.reader).value)
skip = 0
if weekday == "":
@@ -101,7 +102,7 @@ class Parser:
if not skip:
next = 3 # на сколько пыгнуть для следующего шага?
is_empty_lesson = right_cell.ctype in utils.EMPTY_CTYPES and merged_cell.ctype in utils.EMPTY_CTYPES
is_empty_lesson = right_cell.is_empty() and merged_cell.is_empty()
dispname = ""
parsed_discipline_name = None
parsed_location = None
@@ -115,7 +116,7 @@ class Parser:
if not is_empty_lesson:
may_prepod = merged.low.shift(down=2)
if utils.has_no_bottom_border(self.sh, may_prepod):
if utils.has_no_bottom_border(self.reader, may_prepod):
next = 6
is_2pair = True
@@ -124,7 +125,7 @@ class Parser:
parsed_location = ret['loc']
parsed_leader = ret['leader']
parsed_discipline_name = ret['name']
parsed_uncotigorized = list(utils.parse_all_dirt(self.sh, merged.low, merged.width(), next))
parsed_uncotigorized = list(utils.parse_all_dirt(self.reader, merged.low, merged.width(), next))
else:
@@ -135,7 +136,7 @@ class Parser:
dispname += (" SOLD" if is_solid else " SPLIT")
dispname += (" [ДВУПАРНЫЙ]" if is_2pair else "")
parsed_uncotigorized = list(utils.parse_all_dirt(self.sh, merged.low, 4, next))
parsed_uncotigorized = list(utils.parse_all_dirt(self.reader, merged.low, 4, next))
if parsed_leader: dispname += f" [{parsed_leader}]"
@@ -194,23 +195,23 @@ class Parser:
def parse_groups(sh, head, monday, head_rx):
def parse_groups(reader: "ExcelSheetReader", head, monday: Coord, head_rx):
"""Распознать список групп и метаданные к ним, по сути получить список названий группы и координат её верхнего header-а (AQ6:AT6)"""
groups = {}
i = 0
while i < len(head):
x = head[i]
pprint(f"while i={i} head[i]={x}")
merged = utils.get_merged_coord(sh, Coord(head_rx, i))
if i > monday[1] + 1:
if merged is None or x.value == "":
merged = reader.get_merged_coord(Coord(head_rx, i))
if i > monday.col + 1:
if merged is None or x == "":
break
if merged.width() != 4:
pprint(f"WARNING: group header witdh !=4 (found: {merged.width()}); blocks !=4 not supported by parser.")
break
name = utils.unspace(x.value)
name = utils.unspace(x)
groups[name] = {
"name": name,
"position": [head_rx, i],