исправь и оптимизируй код, измени так чтобы не было дубликатов, измени названия переменных чтобы они все были в 1 стиле который рекомендуется pep8 и чтобы работало быстрее, посоветуй чем поменять openpyxl или как изменить xlsx в csv

app.py:
import datetime

from aiogram import Router, types
from aiogram.enums import ParseMode
from aiogram.filters import CommandStart
from aiogram.types import Message
from select import select

import app.keyboards as kb
from data import config
from utils.table_utils import get_column_by_course_group_subgroup, get_shedule_by_column_week_day_of_week

router = Router()


@router.message(CommandStart())
async def cmd_start(message: Message):
await message.reply("Выбери свой курс:", reply_markup=kb.main)


@router.callback_query()
async def process_course_selection(callback_query: types.CallbackQuery):
selected = callback_query.data.split("-")
if len(selected) == 1:
selected_course = selected[0].replace("", " ")
await callback_query.message.reply(
text=f"Вы выбрали курс '{selected_course}', выберите группу: ",
reply_markup=kb.get_groups_by_course(selected_course))
elif len(selected) == 2:
selected_course = selected[0].replace("", " ")
selected_group = selected[1].replace("", " ")
await callback_query.message.reply(
text=f"Вы выбрали курс '{selected_course}', группу '{selected_group}', выберите подгруппу: ",
reply_markup=kb.get_subgroup_by_course_and_group(selected_course, selected_group))
elif len(selected) == 3:
selected_course = selected[0].replace("", " ")
selected_group = selected[1].replace("", " ")
selected_subgroup = selected[2].replace("", " ")

column = get_column_by_course_group_subgroup(selected_course, selected_group, selected_subgroup)
daysOfWeek = {
1: "Понедельник",
2: "Вторник",
3: "Среда",
4: "Четверг",
5: "Пятница",
6: "Суббота",
}

daysSokr = {i[:3]: i for i in daysOfWeek.values()}

nowDayOfWeek = daysOfWeek[datetime.datetime.now().isoweekday()]
info, schedule = get_shedule_by_column_week_day_of_week(column, config.week, nowDayOfWeek)

s = f"""{"\n".join([f"<b>{i[0]}</b> - {i[1] if i[1] != '' else 'Нет'}" for i in info])}


{"\n".join([f"<b>{i.split()[0]} {i.split()[1]} пара {i.split()[3]}</b> - {j}" for i, j in schedule])}
"""
await callback_query.message.reply(s, parse_mode=ParseMode.HTML,
reply_markup=kb.get_days_by_subgroup_course_and_group(selected_course,
selected_group,
selected_subgroup))

elif len(selected) == 4:
selected_course = selected[0].replace("", " ")
selected_group = selected[1].replace("", " ")
selected_subgroup = selected[2].replace("", " ")
selected_day = selected[3].replace("", " ")

daysOfWeek = {
1: "Понедельник",
2: "Вторник",
3: "Среда",
4: "Четверг",
5: "Пятница",
6: "Суббота",
}

daysSokr = {i[:3]: i for i in daysOfWeek.values()}
nowDayOfWeek = daysSokr[selected_day]

column = get_column_by_course_group_subgroup(selected_course, selected_group, selected_subgroup)
info, schedule = get_shedule_by_column_week_day_of_week(column, config.week, nowDayOfWeek)

s = f"""{"\n".join([f"<b>{i[0]}</b> - {i[1] if i[1] != '' else 'Нет'}" for i in info])}


{"\n".join([f"<b>{i.split()[0]} {i.split()[1]} пара {i.split()[3]}</b> - {j}" for i, j in schedule])}
"""
await callback_query.message.reply(s,
parse_mode=ParseMode.HTML,
reply_markup=kb.get_chOrZn_by_days_subgroup_course_and_group(selected_course,
selected_group,
selected_subgroup,
selected_day))
elif len(selected) == 5:
selected_course = selected[0].replace("", " ")
selected_group = selected[1].replace("", " ")
selected_subgroup = selected[2].replace("", " ")
selected_day = selected[3].replace("", " ")
selected_chOrZn = selected[4].replace("", " ")

daysOfWeek = {
1: "Понедельник",
2: "Вторник",
3: "Среда",
4: "Четверг",
5: "Пятница",
6: "Суббота",
}

daysSokr = {i[:3]: i for i in daysOfWeek.values()}
nowDayOfWeek = daysSokr[selected_day]
chOrZn = "Числитель" if selected_chOrZn == "Ч" else "Знаменатель"

column = get_column_by_course_group_subgroup(selected_course, selected_group, selected_subgroup)
info, schedule = get_shedule_by_column_week_day_of_week(column, chOrZn, nowDayOfWeek)

s = f"""{"\n".join([f"<b>{i[0]}</b> - {i[1] if i[1] != '' else 'Нет'}" for i in info])}


{"\n".join([f"<b>{i.split()[0]} {i.split()[1]} пара {i.split()[3]}</b> - {j}" for i, j in schedule])}
"""
await callback_query.message.reply(s,
parse_mode=ParseMode.HTML,
reply_markup=kb.get_chOrZn_by_days_subgroup_course_and_group(selected_course,
selected_group,
selected_subgroup,
selected_day))


from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton

from utils.table_utils import get_dict

main = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text=i, callback_data=i.replace(" ", "")) for i in get_dict().keys()]
],
resize_keyboard=True,
input_field_placeholder="Выберите свой курс",
one_time_keyboard=True
)


def get_groups_by_course(course_name):
a = get_dict()[course_name.replace("", " ")]
keys = list(a.keys()) # Преобразуем dict_keys в список
num_rows = 4
num_keys = len(keys)
num_buttons_per_row = (num_keys + num_rows - 1) // num_rows # Округляем вверх

keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text=keys[i * num_buttons_per_row + j],
callback_data=f"{course_name.replace(" ", "")}-{keys[i * num_buttons_per_row + j].replace(" ", "")}")
for j in range(num_buttons_per_row)
if i * num_buttons_per_row + j < num_keys]
for i in range(num_rows)
],
resize_keyboard=True,
input_field_placeholder="Выберите свою группу",
one_time_keyboard=True
)

return keyboard


def get_subgroup_by_course_and_group(selected_course, selected_group):
a = get_dict()[selected_course.replace("", " ")][selected_group.replace("", " ")]
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(text="1 подгруппа",
callback_data=f"{selected_course.replace(" ", "")}-{selected_group.replace(" ", "")}-1_подгруппа"),
InlineKeyboardButton(text="2 подгруппа",
callback_data=f"{selected_course.replace(" ", "")}-{selected_group.replace(" ", "")}-2_подгруппа")]],
resize_keyboard=True,
input_field_placeholder="Выберите свою группу",
one_time_keyboard=True
)

return keyboard


def get_days_by_subgroup_course_and_group(selected_course, selected_group, selected_subgroup):
daysOfWeek = {
1: "Понедельник",
2: "Вторник",
3: "Среда",
4: "Четверг",
5: "Пятница",
6: "Суббота",
}

daysSokr = {i[:3]: i for i in daysOfWeek.values()}

keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(text=f"{daysSokr[i]}",
callback_data=f"{selected_course.replace(" ", "")}-{selected_group.replace(" ", "")}-{selected_subgroup.replace(" ", "")}-{i}")]
for i in daysSokr.keys()
], resize_keyboard=True,
input_field_placeholder="Выберите свою группу",
one_time_keyboard=True
)

return keyboard


def get_chOrZn_by_days_subgroup_course_and_group(selected_course, selected_group, selected_subgroup, dayOfWeek):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(text=f"Числитель", callback_data=f"{selected_course.replace(" ", "")}-{selected_group.replace(" ", "")}-{selected_subgroup.replace(" ", "")}-{dayOfWeek}-Ч"),
InlineKeyboardButton(text=f"Знаменатель", callback_data=f"{selected_course.replace(" ", "")}-{selected_group.replace(" ", "")}-{selected_subgroup.replace(" ", "")}-{dayOfWeek}-З"),
]
], resize_keyboard=True,
input_field_placeholder="Выберите свою группу",
one_time_keyboard=True
)

return keyboard


from os.path import split

import openpyxl


def get_sheet():
wb = openpyxl.load_workbook(r"C:\Users\user\PycharmProjects\botSheduleVsuFkn\data\tables\table.xlsx")
sheet = wb['Расписание норм']
sheetRasp = wb['Лист2']
return sheet, sheetRasp


def get_dict():
sheet, sheetRasp = get_sheet()
a = dict()
for i in range(1, sheet.max_column):
group = sheet.cell(1, i).value
sub_group = sheet.cell(2, i).value
item = sheet.cell(3, i).value
profile = sheet.cell(4, i).value if sheet.cell(4, i).value != "" else "Профиля нет."

a.setdefault(group, {}).setdefault(sub_group, {})[item] = profile

return a


def get_column_by_course_group_subgroup(course, group, subgroup):
sheet, sheetRasp = get_sheet()
data = [sheet.cell(1, _) for _ in range(1, sheet.max_column) if
sheet.cell(1, _).value == course and sheet.cell(2, _).value == group]
if subgroup == "1 подгруппа":
return data[0].column
else:
return data[1].column

def get_shedule_by_column_week_day_of_week(column, week, day_of_week):
sheet, sheetRasp = get_sheet()
day_of_week = str(day_of_week)
dataRasp = [sheetRasp.cell(row=i, column=1).value for i in range(1, 103)]

dataOfGroup = [[str(dataRasp[i - 1]), str(sheet.cell(row=i, column=column).value).replace("\n", "")]
for i in range(1, sheet.max_row)][:4]

dataOfShedule = [[str(dataRasp[i - 1]), str(sheet.cell(row=i, column=column).value).replace("\n", "")]
for i in range(1, sheet.max_row) if sheet.cell(row=i, column=column).value is not None][4:]


returned = [[i, j] for i,j in dataOfShedule if i.split()[0] == str(day_of_week) and i.split()[2] == week]
return dataOfGroup, returned