Нередко при работе с Универсальным отчетом в 1С возникает ситуация, которая ставит в тупик даже опытных пользователей и разработчиков. Представим, мы строим отчет по регистру накопления, например, по остаткам товаров. Пока мы используем в группировках измерения, такие как Номенклатура или Склад, все работает идеально: начальные и конечные остатки рассчитываются корректно. Но стоит добавить в группировку поле Регистратор, как отчет начинает вести себя странно: итоговые остатки либо обнуляются, либо вовсе пропадают, особенно за те периоды, где не было оборотов. Давайте вместе разберемся, почему так происходит и как это исправить, не создавая отдельный отчет.
Чтобы понять корень проблемы, нужно вспомнить саму суть объектов, с которыми мы работаем. Остатки по регистру накопления — это срез данных на определенный момент времени. Например, остаток товара на складе на начало дня. Обороты — это изменения (приход или расход) за определенный период. А Регистратор — это документ (например, "Реализация товаров и услуг" или "Поступление на расчетный счет"), который и создает эти обороты.
Ключевой момент в том, что Регистратор сам по себе не является точкой во времени для расчета остатков. Он характеризует совокупность движений, которые произошли в момент его проведения (при этом стоит помнить о рисках появления движений у непроведенных документов). Система Компоновки Данных (СКД), на которой построен Универсальный отчет, для корректного расчета нарастающего итога (а остатки — это и есть нарастающий итог) должна четко понимать хронологическую последовательность всех записей. Когда мы добавляем в группировку поле Регистратор, СКД "теряется". Она не понимает, как это поле встроить в иерархию времени, что приводит к невозможности правильно рассчитать остаток для каждой строки отчета.
Как верно подмечено в обсуждении, если за период не было оборотов, то и регистраторов в нем нет. Отчет, сгруппированный по регистратору, логично оказывается пустым, ведь ему просто нечего группировать. Но нам-то нужно видеть остатки, даже если движений не было! Именно для таких случаев в СКД существует специальный механизм.
Решение проблемы кроется в возможностях самой СКД (которые иногда приходится задействовать программно, например через СКДБилдер), а именно в настройке ролей полей. Роли — это специальные свойства полей, которые подсказывают системе, как их правильно интерпретировать при построении отчета. Для нашей задачи ключевую роль играет роль Период.
Устанавливая эту роль для полей, связанных со временем, мы выстраиваем для СКД четкую временную иерархию. Система начинает понимать, какое поле является более детализирующим по отношению к другому, и может правильно упорядочить все записи для расчета нарастающих итогов.
Хорошая новость в том, что для этого не обязательно создавать новый внешний отчет. Все необходимые настройки можно выполнить прямо в интерфейсе Универсального отчета.
Давайте по шагам разберем, как "объяснить" Универсальному отчету, что Регистратор является частью временной последовательности.
Сначала сформируйте Универсальный отчет с нужными вам настройками (выберите регистр, добавьте в группировку Регистратор и другие поля).
Нажмите кнопку "Ещё" в командной панели отчета и выберите пункт "Прочее" -> "Изменить вариант отчета...".
Откроется окно редактирования варианта. Перейдите на вкладку "Настройки" и нажмите на кнопку с изображением гаечного ключа или надписью "Настройки", чтобы открыть полную форму настроек СКД.
Вы попали в конструктор схемы компоновки данных. Здесь нам нужна вкладка "Наборы данных". Обычно там один набор данных, созданный на основе виртуальной таблицы регистра, например, ОстаткиИОбороты, хотя встречаются решения, где используются две разных схемы в отчете.
Найдите в списке полей этого набора поле Регистратор. Выделите его мышью.
В правой части окна, в палитре свойств, найдите свойство "Роль". Нажмите на него, чтобы раскрыть настройки ролей.
Установите флажок напротив роли "Период". Рядом появится поле "Номер периода". Здесь мы и зададим иерархию.
Важный момент: правильная иерархия периодов — залог успеха. СКД упорядочивает данные по возрастанию номера периода. Самый детальный уровень должен иметь наименьший номер. Стандартная иерархия для регистров накопления выглядит так:
НомерСтроки (самый детальный уровень, движения внутри одного документа): Номер периода = 1Регистратор (сам документ): Номер периода = 2ПериодСекунда (или МоментВремени): Номер периода = 3ПериодДень, ПериодМесяц и т.д. получают следующие номера по порядку.Установите для поля Регистратор номер периода 2. Если в вашем наборе данных есть поле НомерСтроки, не забудьте и для него установить роль "Период" с номером 1.
После установки ролей нажмите кнопку "Завершить редактирование" внизу окна настроек, а затем "ОК" в окне редактирования варианта отчета.
Снова сформируйте отчет. Теперь, благодаря вашим настройкам, СКД понимает, как правильно упорядочить данные, и корректно рассчитывает остатки даже при группировке по регистратору.
Хотя многие разработчики считают Универсальный отчет устаревшим и предпочитают сразу создавать отчеты на СКД, эта история показывает, что он все еще остается мощным и гибким инструментом. Умение работать с его скрытыми возможностями, такими как редактирование схемы компоновки, позволяет быстро решать нетривиальные задачи без написания кода и создания новых объектов конфигурации.
Это особенно актуально:
Таким образом, проблема с некорректными остатками при группировке по регистратору — это не ошибка отчета, а особенность работы механизма СКД, которую можно и нужно настраивать с помощью ролей полей.