Уважаемые коллеги, давайте вместе разберем распространенную проблему, с которой сталкиваются разработчики и пользователи 1С при попытке агрегировать данные из нескольких источников: задвоение записей в отчете при использовании регистра сведений для накопления баллов студентов. Мы рассмотрим, почему первоначальные подходы могут быть неэффективны, и предложим оптимальное решение.
Автор задачи столкнулся с необходимостью построить отчет, где по строкам будут перечислены ФИО студентов, а в столбцах — итоговые баллы, полученные ими за участие в различных мероприятиях (город, вуз, область и т.д.) из нескольких документов. Каждый документ содержит поле с суммой баллов. Изначальная попытка использовать регистр сведений привела к задвоению фамилий студентов. Причина этого заключается в том, что если один и тот же студент получает баллы за разные критерии или на разных уровнях участия, для каждого такого события в регистр сведений записывается отдельная строка. Регистр сведений по своей природе хранит отдельные факты, а не агрегированные или накопительные данные.
Когда автор упоминает использование «СрезПоследних» в конструкторе запроса и то, что сведения являются периодическими, это только усугубляет проблему для накопительного учета. Периодический регистр сведений хранит значение на определенную дату или период. Если студент набрал 27 баллов сегодня, а завтра ему начисляют еще, и мы просто записываем новое значение в тот же регистр сведений на текущую дату, то «срез последних» покажет только последнее значение, а не сумму. Если же для каждого события создается новая запись, то для получения общей суммы приходится вручную агрегировать множество записей, что неэффективно и может быть медленным, особенно на больших объемах данных.
Еще одна распространенная ошибка – попытка передать итоговое поле из документа напрямую в регистр сведений как единственное значение. Если в документе мы считаем сумму баллов для наглядности, это не означает, что регистр сведений автоматически ее просуммирует по студенту из разных документов. Регистры – это не просто хранилища данных из документов, а инструменты для агрегирования и учета, каждый со своей спецификой.
Очевидно, что нам нужен механизм для накопления баллов. Для этого в системе 1С существуют регистры накопления. Это специализированные объекты метаданных, предназначенные для хранения числовых показателей в разрезе аналитик (измерений) и обеспечения быстрого получения итогов (остатков или оборотов).
Существует два основных вида регистров накопления:
Давайте подробнее разберем, какой тип регистра накопления наиболее подходит для нашей задачи с баллами студентов.
В нашей ситуации баллы студентов только начисляются (увеличиваются) и никогда не уменьшаются или обнуляются сами по себе. Это ключевой момент, который определяет выбор вида регистра накопления:
Обороты, которая является очень производительной для запросов по сумме за период.Таким образом, для задачи накопления баллов студентов, которые только увеличиваются и по которым нужен итоговый суммарный показатель, наиболее правильным и эффективным решением является использование регистра накопления оборотов.
Давайте спроектируем структуру нашего регистра накопления БаллыСтудентов:
Студент (тип СправочникСсылка.Студенты или аналогичный, если у вас есть справочник с ФИО студентов). Это измерение крайне важно, так как оно позволит нам группировать данные по каждому студенту и избежать задвоений в отчете.УровеньМероприятия (тип СправочникСсылка.УровниМероприятий или ПеречислениеСсылка.УровниМероприятий). Этот реквизит позволит нам в отчете разделять баллы по категориям (ВУЗ, Город, Область и т.д.) или выводить их в отдельные колонки.КоличествоБаллов (тип Число, точность и длина на ваше усмотрение, например, 10, 2). Здесь будет храниться сумма баллов за конкретное событие.ДокументОснование (тип ДокументСсылка.НачислениеБалловСтуденту или соответствующий тип вашего документа). Это полезно для связи движения с документом, который его создал, и для удобства отладки или перехода к регистратору.ВидМероприятия (например, СправочникСсылка.ВидыМероприятий) – для дополнительной детализации, если это требуется в отчетах.Теперь рассмотрим, как ваш документ, который начисляет баллы, должен формировать движения по новому регистру накопления БаллыСтудентов. Это делается в обработчике события ОбработкаПроведения документа.
ОбработкаПроведения мы должны указать, что наш документ будет делать движения по регистру БаллыСтудентов.Предположим, у нас есть документ НачислениеБалловСтуденту с табличной частью БаллыПоУровням, которая содержит колонки Студент, УровеньМероприятия и Баллы.
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Указываем, что документ будет делать движения по регистру накопления
Движения.БаллыСтудентов.Записывать = Истина;
// Очищаем существующие движения документа перед записью новых
// Это стандартное поведение для регистров накопления,
// гарантирующее, что при перепроведении данные будут актуальны, а не дублированы
Движения.БаллыСтудентов.Очистить();
// Перебираем данные из табличной части документа и формируем движения
Для Каждого СтрокаТЧ Из Объект.БаллыПоУровням Цикл
Движение = Движения.БаллыСтудентов.Добавить();
Движение.Период = Объект.Дата; // Дата документа
Движение.Студент = СтрокаТЧ.Студент;
Движение.УровеньМероприятия = СтрокаТЧ.УровеньМероприятия;
Движение.КоличествоБаллов = СтрокаТЧ.Баллы;
Движение.ДокументОснование = Объект.Ссылка; // Для связи с регистратором
КонецЦикла;
КонецПроцедуры
Важный нюанс: Для регистров накопления оборотов свойство ВидДвижения (Приход или Расход) не используется, так как они накапливают только объемы, а не остатки.
После того как мы настроили регистр накопления и документы формируют по нему движения, построение отчета становится простой задачей с использованием механизма Системы Компоновки Данных (СКД).
Отчет и откройте его СхемуКомпоновкиДанных.Наш запрос будет использовать виртуальную таблицу Обороты регистра накопления БаллыСтудентов. Эта таблица уже содержит агрегированные данные по нашим измерениям за указанный период.
ВЫБРАТЬ
БаллыСтудентовОбороты.Студент КАК Студент,
БаллыСтудентовОбороты.УровеньМероприятия КАК УровеньМероприятия,
БаллыСтудентовОбороты.КоличествоБаллов КАК Баллы
ИЗ
РегистрНакопления.БаллыСтудентов.Обороты(
&НачалоПериода,
&КонецПериода,
Авто, // Периодичность: Авто (по регистратору)
// Отбор: Если нужно ограничить по конкретным параметрам, например, по студенту
// Измерения: Здесь можно указать измерения, по которым нужны обороты,
// если не указывать, то обороты будут по всем измерениям регистра
Студент, УровеньМероприятия
) КАК БаллыСтудентовОбороты
Здесь &НачалоПериода и &КонецПериода — это параметры отчета, которые пользователь сможет указывать. Авто означает, что обороты будут рассчитываться по движениям регистраторов.
Перенесите выбранные поля (Студент, УровеньМероприятия, Баллы) на закладку «Поля».
Студент. Это обеспечит, что каждый студент будет в отдельной строке.Студент вы можете добавить еще одну группировку по УровеньМероприятия, если хотите видеть детализацию.На закладке «Выбранные поля» добавьте Студент и Баллы. Чтобы получить сумму баллов, для поля Баллы установите функцию Сумма().
Для поля Баллы на закладке «Итоги» также установите функцию Сумма() для общих итогов.
Если вы хотите, чтобы баллы по разным уровням мероприятий (ВУЗ, Город, Область) выводились в отдельные колонки, это можно сделать с помощью настроек группировки в СКД.
Студент (Детальные записи).Студент.УровеньМероприятия в колонки, на вкладке «Другие настройки» (или в свойствах макета группировки) найдите «Поля группировок макета» и укажите, что УровеньМероприятия должно быть в колонках.Баллы и установите для него Сумма(). СКД автоматически сгруппирует баллы по уровням мероприятий и выведет их в отдельные колонки.Таким образом, мы сможем получить отчет, где по строкам будет ФИО студента, а в колонках — суммы баллов по каждому уровню участия (ВУЗ, Город, Область) и общая сумма баллов.
Мы выяснили, что для эффективного и корректного учета накопительных баллов студентов в 1С наиболее подходящим решением является использование регистра накопления оборотов. Этот подход позволяет избежать задвоений записей в отчетах, обеспечивает актуальность данных при повторном проведении документов и предоставляет мощные инструменты для анализа с помощью Системы Компоновки Данных. Запомните: регистры накопления — это мощный инструмент, который требует понимания их принципов работы, чтобы избежать распространенных ошибок и строить производительные и точные отчеты.