Загрузка данных


import openpyxl
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
from openpyxl.utils import get_column_letter

# Данные плана
plan = {
    "Тяжелая": {
        "Понедельник": [
            ("Отведение бедра назад в кроссовере", "Предутомление", "3×12", 8, "30–60 сек перед базой"),
            ("Ягодичный мостик со штангой", "База", "4×8–10", 9, "2–3 мин"),
            ("Румынская тяга со штангой", "База", "4×8–10", 9, "2–3 мин"),
            ("Тяга верхнего блока к груди широким хватом", "База", "4×8–10", "8–9", "2 мин"),
            ("Сгибания рук со штангой стоя", "Изоляция", "4×8–10", 9, "90 сек"),
            ("Сгибания на блоке с канатной рукоятью", "Изоляция", "3×10–12", "8–9", "60 сек"),
        ],
        "Среда": [
            ("Разведение в стороны на блоке (одна рука)", "Предутомление", "3×12", 8, "30–60 сек перед базой"),
            ("Жим штанги стоя (армейский)", "База", "4×8–10", 9, "2–3 мин"),
            ("Разведение в наклоне на блоке (задний пучок)", "Изоляция", "4×10–12", "8–9", "60–90 сек"),
            ("Французский жим со штангой стоя", "Изоляция", "4×8–10", 9, "90 сек"),
            ("Разгибания на блоке с канатом", "Изоляция", "3×10–12", "8–9", "60 сек"),
        ],
        "Пятница": [
            ("Отведение бедра назад в кроссовере", "Предутомление", "3×12", 8, "30–60 сек перед базой"),
            ("Жим ногами с высокой постановкой стоп", "База", "4×8–10", 9, "2–3 мин"),
            ("Тяга нижнего блока к поясу (горизонтальная)", "База", "4×8–10", "8–9", "2 мин"),
            ("Гиперэкстензия с круглой спиной", "Изоляция", "4×10–12", "8–9", "90 сек"),
            ("Сгибания ног лёжа (бицепс бедра)", "Изоляция", "3×10–12", 8, "60–90 сек"),
            ("Тяга штанги к подбородку широким хватом", "Изоляция", "4×8–10", "8–9", "90 сек"),
            ("Обратные разведения в тренажёре «бабочка»", "Изоляция", "3×10–12", 8, "60 сек"),
            ("Суперсет: сгибания с EZ-грифом + разгибания на блоке обратным хватом", "Изоляция", "3×8–10 + 8–10", 9, "Между упр. без отдыха, после 90 сек"),
        ],
    },
    "Средняя": {
        "Понедельник": [
            ("Отведение бедра назад в кроссовере", "Предутомление", "3×12", 7, "30–60 сек"),
            ("Ягодичный мостик со штангой", "База", "3–4×10–12", 8, "2–3 мин"),
            ("Румынская тяга со штангой", "База", "3–4×10–12", 8, "2–3 мин"),
            ("Тяга верхнего блока к груди", "База", "3×10–12", "7–8", "2 мин"),
            ("Сгибания рук со штангой стоя", "Изоляция", "3×10–12", 8, "90 сек"),
            ("Сгибания на блоке с канатом", "Изоляция", "3×12", "7–8", "60 сек"),
        ],
        "Среда": [
            ("Разведение в стороны на блоке", "Предутомление", "3×12", 7, "30–60 сек"),
            ("Жим штанги стоя", "База", "3–4×10–12", 8, "2–3 мин"),
            ("Разведение в наклоне на блоке", "Изоляция", "3×12", "7–8", "60–90 сек"),
            ("Французский жим со штангой", "Изоляция", "3×10–12", 8, "90 сек"),
            ("Разгибания на блоке с канатом", "Изоляция", "3×12", "7–8", "60 сек"),
        ],
        "Пятница": [
            ("Отведение бедра назад в кроссовере", "Предутомление", "3×12", 7, "30–60 сек"),
            ("Жим ногами с высокой постановкой", "База", "3×10–12", 8, "2–3 мин"),
            ("Тяга нижнего блока к поясу", "База", "3×10–12", "7–8", "2 мин"),
            ("Гиперэкстензия с круглой спиной", "Изоляция", "3×12", "7–8", "90 сек"),
            ("Сгибания ног лёжа", "Изоляция", "3×12", "7–8", "60–90 сек"),
            ("Тяга штанги к подбородку", "Изоляция", "3×10–12", "7–8", "90 сек"),
            ("Обратные разведения в «бабочке»", "Изоляция", "3×12", 7, "60 сек"),
            ("Суперсет: сгибания EZ + разгибания обр. хватом", "Изоляция", "3×10–12 + 10–12", 8, "Без отдыха внутри, 90 сек после"),
        ],
    },
    "Легкая": {
        "Понедельник": [
            ("Отведение бедра в кроссовере", "Предутомление", "2×15", 5, "30 сек"),
            ("Ягодичный мостик со штангой (лёгкий вес)", "База", "2–3×15", "5–6", "60–90 сек"),
            ("Румынская тяга (лёгкий вес)", "База", "2×15", "5–6", "60–90 сек"),
            ("Тяга верхнего блока", "База", "2×15", 5, "60 сек"),
            ("Сгибания со штангой", "Изоляция", "2×15", "5–6", "45 сек"),
            ("Сгибания на блоке", "Изоляция", "2×15", 5, "45 сек"),
        ],
        "Среда": [
            ("Разведение в стороны на блоке", "Предутомление", "2×15", 5, "30 сек"),
            ("Жим штанги стоя (лёгкий)", "База", "2×15", "5–6", "60–90 сек"),
            ("Разведение в наклоне", "Изоляция", "2×15", 5, "45 сек"),
            ("Французский жим (лёгкий)", "Изоляция", "2×15", "5–6", "45 сек"),
            ("Разгибания с канатом", "Изоляция", "2×15", 5, "45 сек"),
        ],
        "Пятница": [
            ("Отведение бедра в кроссовере", "Предутомление", "2×15", 5, "30 сек"),
            ("Жим ногами (лёгкий)", "База", "2×15", "5–6", "60–90 сек"),
            ("Тяга нижнего блока", "База", "2×15", 5, "60 сек"),
            ("Гиперэкстензия без веса", "Изоляция", "2×15", 5, "45 сек"),
            ("Сгибания ног лёжа", "Изоляция", "2×15", 5, "45 сек"),
            ("Тяга к подбородку", "Изоляция", "2×15", 5, "45 сек"),
            ("Обратная «бабочка»", "Изоляция", "2×15", 5, "45 сек"),
            ("Суперсет: сгибания + разгибания (лёгкие)", "Изоляция", "2×15 + 15", 5, "Без отдыха внутри, 45 сек после"),
        ],
    },
    "Силовая": {
        "Понедельник": [
            ("Отведение бедра в кроссовере (с весом)", "Предутомление", "3×8", 8, "45–60 сек"),
            ("Ягодичный мостик со штангой", "База", "4×4–6", "9–10", "3–4 мин"),
            ("Румынская тяга со штангой", "База", "4×4–6", "9–10", "3–4 мин"),
            ("Тяга верхнего блока", "База", "4×4–6", 9, "2–3 мин"),
            ("Сгибания рук со штангой стоя", "Изоляция", "3×6–8", 9, "90–120 сек"),
            ("Сгибания на блоке с канатом", "Изоляция", "3×6–8", "8–9", "90 сек"),
        ],
        "Среда": [
            ("Разведение в стороны на блоке", "Предутомление", "3×8", 8, "45–60 сек"),
            ("Жим штанги стоя", "База", "4–5×4–6", "9–10", "3–4 мин"),
            ("Разведение в наклоне на блоке", "Изоляция", "3×6–8", "8–9", "90 сек"),
            ("Французский жим со штангой", "Изоляция", "4×4–6", "9–10", "2–3 мин"),
            ("Разгибания с канатом", "Изоляция", "3×6–8", "8–9", "90 сек"),
        ],
        "Пятница": [
            ("Отведение бедра в кроссовере", "Предутомление", "3×8", 8, "45–60 сек"),
            ("Жим ногами с высокой постановкой", "База", "4×4–6", "9–10", "3–4 мин"),
            ("Тяга нижнего блока к поясу", "База", "4×4–6", 9, "2–3 мин"),
            ("Гиперэкстензия с весом", "Изоляция", "3×6–8", 9, "90 сек"),
            ("Сгибания ног лёжа", "Изоляция", "3×6–8", "8–9", "90 сек"),
            ("Тяга штанги к подбородку", "Изоляция", "4×4–6", "9–10", "2–3 мин"),
            ("Обратная «бабочка»", "Изоляция", "3×6–8", "8–9", "90 сек"),
            ("Суперсет: сгибания EZ + разгибания обр. хватом", "Изоляция", "3×6–8 + 6–8", 9, "Без отдыха внутри, 2 мин после"),
        ],
    },
}

# Создаём книгу и стили
wb = openpyxl.Workbook()
ws = None
first_sheet = True

header_font = Font(name='Arial', bold=True, size=11, color='FFFFFF')
header_fill = PatternFill(start_color='2F5496', end_color='2F5496', fill_type='solid')
day_fill = PatternFill(start_color='D6E4F0', end_color='D6E4F0', fill_type='solid')
border = Border(
    left=Side(style='thin'), right=Side(style='thin'),
    top=Side(style='thin'), bottom=Side(style='thin')
)
wrap_align = Alignment(wrap_text=True, vertical='center')

# Заголовки столбцов (общие для всех листов)
columns = [
    ("День", 12),
    ("Упражнение", 45),
    ("Тип", 16),
    ("Подходы × Повторения", 22),
    ("RPE", 7),
    ("Отдых", 20),
]

for week_name, days in plan.items():
    if first_sheet:
        ws = wb.active
        ws.title = week_name
        first_sheet = False
    else:
        ws = wb.create_sheet(title=week_name)

    # Записываем заголовки столбцов
    for col_idx, (col_title, width) in enumerate(columns, 1):
        cell = ws.cell(row=1, column=col_idx, value=col_title)
        cell.font = header_font
        cell.fill = header_fill
        cell.border = border
        cell.alignment = Alignment(horizontal='center', vertical='center')
        ws.column_dimensions[get_column_letter(col_idx)].width = width

    row = 2
    for day_name, exercises in days.items():
        start_row = row
        for i, (ex_name, ex_type, sets_reps, rpe, rest) in enumerate(exercises):
            ws.cell(row=row, column=2, value=ex_name).border = border
            ws.cell(row=row, column=2).alignment = wrap_align
            ws.cell(row=row, column=3, value=ex_type).border = border
            ws.cell(row=row, column=3).alignment = Alignment(horizontal='center', vertical='center')
            ws.cell(row=row, column=4, value=sets_reps).border = border
            ws.cell(row=row, column=4).alignment = Alignment(horizontal='center', vertical='center')
            ws.cell(row=row, column=5, value=rpe).border = border
            ws.cell(row=row, column=5).alignment = Alignment(horizontal='center', vertical='center')
            ws.cell(row=row, column=6, value=rest).border = border
            ws.cell(row=row, column=6).alignment = wrap_align
            row += 1

        # Объединяем ячейки для дня
        if len(exercises) > 1:
            ws.merge_cells(start_row=start_row, start_column=1, end_row=row-1, end_column=1)
        elif len(exercises) == 1:
            ws.cell(row=start_row, column=1, value=day_name).border = border
        day_cell = ws.cell(row=start_row, column=1, value=day_name)
        day_cell.font = Font(name='Arial', bold=True, size=11)
        day_cell.fill = day_fill
        day_cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        # Добавляем границы объединённой ячейке
        for r in range(start_row, row):
            ws.cell(row=r, column=1).border = border

# Сохраняем файл
wb.save("План_тренировок.xlsx")
print("Файл сохранён: План_тренировок.xlsx")