Создание удобного и наглядного расписания — классическая задача при автоматизации образовательных центров, спортивных секций или любых организаций, работающих по графику. Основная сложность здесь заключается в преобразовании «вертикальных» данных из базы (записей регистра) в «горизонтальную» таблицу (шахматку), где строками являются кружки или преподаватели, а колонками — дни недели. Разберем подробно, как реализовать такой механизм с использованием Системы компоновки данных (СКД) и программных методов.
Прежде чем приступать к отчету, проанализируем, как хранятся данные. Если структура хранения изначально неверна, построение отчета превратится в мучение. Для расписания оптимально использовать Регистр сведений (например, РасписаниеЗанятий). Выясним причину, почему это важно: регистр позволяет быстро выбирать актуальные данные и накладывать фильтры по измерениям.
Рекомендуемый набор полей для регистра:
ДеньНедели (Перечисление или Число), ВремяНачала (Дата/Время), Кружок (Справочник).Преподаватель (Справочник), Аудитория (Справочник).Такая структура позволит нам легко группировать данные в запросе. Если же данные хранятся только в документе, как у автора темы, их необходимо сначала «развернуть» в таблицу значений или временную таблицу внутри запроса.
Рассмотрим первый способ реализации — создание колонок прямо в тексте запроса. Этот метод полезен, если вы используете обычный макет или хотите жестко зафиксировать структуру отчета. Мы используем конструкцию ВЫБОР КОГДА для распределения данных по соответствующим дням.
Посмотрим на пример логики построения такого запроса:
ВЫБРАТЬ
Регистр.Кружок КАК Кружок,
ВЫБОР КОГДА Регистр.ДеньНедели = &Понедельник ТОГДА Регистр.ВремяНачала ИНАЧЕ НЕОПРЕДЕЛЕНО КОНЕЦ КАК Пн,
ВЫБОР КОГДА Регистр.ДеньНедели = &Вторник ТОГДА Регистр.ВремяНачала ИНАЧЕ НЕОПРЕДЕЛЕНО КОНЕЦ КАК Вт,
ВЫБОР КОГДА Регистр.ДеньНедели = &Среда ТОГДА Регистр.ВремяНачала ИНАЧЕ НЕОПРЕДЕЛЕНО КОНЕЦ КАК Ср,
// И так далее для всех дней недели...
Регистр.Преподаватель,
Регистр.Помещение
ИЗ
РегистрСведений.РасписаниеЗанятий КАК Регистр
ГДЕ
Регистр.Период МЕЖДУ &НачалоПериода И &КонецПериода
Проанализируем ситуацию: данный подход позволяет получить «плоскую» таблицу, где для каждого занятия заполнена только одна колонка, соответствующая его дню. Однако при выводе возникнет проблема «раздувания» строк. Чтобы этого избежать, лучше использовать возможности СКД.
Система компоновки данных — самый мощный инструмент для решения этой задачи. Вместо того чтобы вручную прописывать каждый день в запросе, мы можем использовать тип настройки Таблица.
Разберем по шагам настройку в конструкторе СКД:
Таблица.Кружок.ДеньНедели.Важный момент: Чтобы колонки выводились в правильном порядке (от понедельника до воскресенья), убедитесь, что у перечисления ДниНедели правильно настроен порядок или используйте числовое поле для сортировки.
Часто программисты сталкиваются с тем, что в ячейку (пересечение кружка и дня недели) нужно вывести не только время, но и преподавателя с кабинетом. В кросс-таблицах выбранные поля группировок не работают в теле таблицы. Рассмотрим подробнее, как это исправить.
Для корректного вывода данных в «шахматку» все выводимые поля должны быть объявлены как Ресурсы на соответствующей вкладке СКД. Чтобы объединить несколько полей в одну строку, используйте выражение ресурса:
// В поле "Выражение" на закладке "Ресурсы" для поля "Информация"
СоединитьСтроки(
ВычислитьВыражениеСГруппировкойТаблицыЗначений(
"Представление(ВремяНачала) + "" - "" + Представление(Преподаватель) + "" ("" + Представление(Помещение) + "")""",
"ВремяНачала, Преподаватель, Помещение"
),
Символы.ПС
)
Если вам нужно просто вывести одно значение, можно использовать агрегатную функцию Максимум(Преподаватель), но помните, что это сработает корректно только если на одно время в один день у кружка не назначено два разных преподавателя.
Если возможности СКД кажутся недостаточными для реализации сложного дизайна (например, объединение ячеек или специфическое раскрашивание), разберем метод работы с Областями макета. Это более трудоемкий, но гибкий способ.
Алгоритм программного вывода следующий:
Шапка, СтрокаКружка, ЯчейкаДня.ТаблицаЗначений.НайтиСтроки() по двум ключам: кружок и текущий день недели.ЯчейкаДня и выводим её методом Присоединить().Пример кода для поиска и вывода данных:
Для Каждого СтрокаКружок Из ТаблицаКружков Цикл
ТабДок.Вывести(ОбластьСтрокаКружка);
Для День = 1 По 7 Цикл
Отбор = Новый Структура("Кружок, ДеньНедели", СтрокаКружок.Кружок, День);
НайденныеЗанятия = ТЗ_Данные.НайтиСтроки(Отбор);
ОбластьЯчейка = Макет.ПолучитьОбласть("ЯчейкаДня");
Если НайденныеЗанятия.Количество() > 0 Тогда
ОбластьЯчейка.Параметры.Текст = НайденныеЗанятия[0].ВремяНачала;
// Заполнение других параметров
КонецЕсли;
ТабДок.Присоединить(ОбластьЯчейка);
КонецЦикла;
КонецЦикла;
В современной платформе 1С 8.3 (особенно в Управляемых формах) существует специализированный объект — Планировщик. Это элемент управления, который предназначен именно для визуализации расписания. Он поддерживает Drag-and-drop, позволяет настраивать шкалу времени и периодичность. Если ваша задача — не просто отчет для печати, а интерактивное рабочее место администратора, рекомендуем обратить внимание именно на этот объект. Он автоматически решает проблему «перекрытия» занятий и визуального распределения по сетке времени.
Подведем итог: для быстрого построения отчета лучше всего использовать СКД с типом настройки Таблица, предварительно убедившись, что все необходимые данные (преподаватель, аудитория) добавлены в Ресурсы. Если же требуется сложная печатная форма «один в один как в Excel», используйте программный обход данных с поиском по таблице значений.