Почему при повторном формировании отчета в 1С слетает программный отбор и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с типовыми и кастомизированными отчетами в конфигурациях на платформе «1С:Предприятие 8.3» разработчики часто сталкиваются с неприятным поведением компоновщика настроек. Сценарий выглядит следующим образом: мы открываем отчет из формы какого-либо объекта (например, карточки партнера, номенклатуры или договора), при этом программно устанавливается отбор по выбранному элементу или группе элементов. При первом открытии отчет формируется абсолютно корректно. Однако стоит нам нажать кнопку «Сформировать» повторно, как отбор таинственным образом очищается или принимает пустое значение, из-за чего отчет выводит неверные данные.

В этой статье мы подробно разберем, почему возникает эта проблема на примере отчета «Ведомость расчетов с партнерами» в конфигурации «Управление торговлей 11.4», проанализируем внутренние механизмы платформы и предложим два варианта решения: быстрое и универсальное.

Выясняем причину: почему отбор сбрасывается при повторном запуске?

Для того чтобы понять природу этой ошибки, проанализируем жизненный цикл формы отчета и то, как платформа работает с настройками схемы компоновки данных (СКД). Когда мы открываем отчет параметрически (например, из карточки партнера), срабатывает экспортная процедура инициализации. В отчете «Ведомость расчетов с партнерами» (объект Отчет.РасчетыСПартнерами) за это отвечает серверная процедура СформироватьПараметрыФормыНаСервере.

При первом открытии формы в качестве параметра передается переменная ПараметрКоманды, которая содержит массив выбранных партнеров (тип Массив). Инициализирующий код устанавливает этот массив напрямую в правое значение элемента отбора компоновщика:

ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;

Платформа 1С при первоначальной компоновке отчета успешно обрабатывает этот массив. СКД понимает, что для вида сравнения В группе из списка или В списке в качестве правого значения передан массив элементов, и корректно выводит отчет. Однако при повторном нажатии кнопки «Сформировать» форма отчета не открывается заново. Вместо этого происходит повторная компоновка результата выполнения отчета на основе текущих пользовательских настроек формы (свойство КомпоновщикНастроек.ПользовательскиеНастройки).

Перед тем как отправить запрос на сервер для повторного формирования, платформа сериализует пользовательские настройки, чтобы передать их между клиентом и сервером. И здесь кроется главная проблема: тип данных Массив не предназначен для сериализации и хранения в пользовательских настройках компоновщика СКД. Платформа ожидает, что для множественных отборов (таких как «В списке» или «В группе из списка») будет использоваться специализированный тип данных — СписокЗначений.

Поскольку Массив не может быть корректно сохранен и восстановлен в пользовательских настройках формы, при повторном обращении к серверу правое значение отбора зануляется, превращаясь в пустое значение. В результате мы получаем пустой отбор вида «Партнер В группе из списка ""» и некорректный результат работы отчета.

Вариант решения №1: Быстрое исправление (костыль)

Рассмотрим быстрое решение проблемы, которое часто применяется разработчиками «на скорую руку». Если мы точно знаем, что в параметрах команды всегда передается массив, содержащий только один элемент (например, одну конкретную группу партнеров), мы можем извлечь эту единственную ссылку и присвоить ее напрямую в правое значение отбора.

Для этого в процедуре СформироватьПараметрыФормыНаСервере заменим строку присвоения массива на присвоение первого элемента этого массива:


// Было:
// ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;

// Стало:
ЭлементОтбора.ПравоеЗначение = ПервыйЭлемент; // Где ПервыйЭлемент - это ПараметрКоманды[0]

Выясним, почему это решение работает. Когда мы записываем в ПравоеЗначение одиночную ссылку (тип СправочникСсылка.Партнеры), платформа 1С без проблем сериализует ее. Ссылочные типы данных отлично сохраняются в пользовательских настройках компоновщика между вызовами сервера. При повторном нажатии кнопки «Сформировать» ссылка никуда не исчезает.

При этом система компоновки данных достаточно интеллектуальна: даже если вид сравнения установлен как В группе из списка, а в правом значении указана одиночная ссылка, СКД автоматически приведет ее к списку из одного элемента и построит правильный отчет.

Важное ограничение данного метода: этот способ не сработает, если пользователь выделит в списке несколько партнеров или групп и попытается сформировать отчет по ним одновременно. Отчет построится только по первому выбранному элементу, проигнорировав остальные.

Вариант решения №2: Универсальное исправление (рекомендуемое)

Для того чтобы сохранить возможность полноценной фильтрации по множеству выбранных элементов и гарантировать, что отбор не слетит при повторной генерации отчета, мы должны преобразовать переданный Массив в СписокЗначений. Тип данных СписокЗначений полностью поддерживается сериализатором настроек компоновщика СКД.

Давайте реализуем универсальный алгоритм заполнения правого значения отбора, который корректно обработает любые входные типы данных (будь то массив, список значений или одиночная ссылка):


// Вместо прямого присвоения массива напишем безопасное приведение типов:
СписокПараметров = Новый СписокЗначений;

Если ТипЗнч(ПараметрКоманды) = Тип("Массив") Тогда
    СписокПараметров.ЗагрузитьЗначения(ПараметрКоманды);
    ЭлементОтбора.ПравоеЗначение = СписокПараметров;
ИначеЕсли ТипЗнч(ПараметрКоманды) = Тип("СписокЗначений") Тогда
    ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;
Иначе
    // Если пришла одиночная ссылка, поместим её в список для универсальности
    СписокПараметров.Добавить(ПараметрКоманды);
    ЭлементОтбора.ПравоеЗначение = СписокПараметров;
КонецЕсли;

Этот код гарантирует, что в правое значение элемента отбора всегда будет передан объект типа СписокЗначений (или одиночная ссылка, которая также корректно сериализуется). Теперь при повторном формировании отчета все выбранные пользователем элементы сохранятся в настройках компоновщика, и отчет покажет правильные данные.

Как проводить отладку в подобных ситуациях?

Если вы столкнулись с похожим поведением в другом отчете и не уверены, где именно происходит очистка параметров, рекомендуем придерживаться следующей методики анализа:

  1. Используйте замер производительности. Перед нажатием кнопки «Сформировать» в режиме отладки запустите замер производительности. После формирования отчета остановите замер и выполните поиск по ключевым словам (например, по имени отбора или по слову КомпоновщикНастроек). Это поможет локализовать процедуру, в которой происходит модификация настроек.
  2. Проверяйте фоновые задания. Современные отчеты в типовых конфигурациях часто формируются в фоновом режиме. Чтобы точка останова сработала в модуле объекта отчета при компоновке результата, обязательно включите автоматическое подключение фоновых заданий в настройках отладки вашей среды разработки (меню Отладка -> Подключение -> Автоматическое подключение -> Фоновые задания).
  3. Инспектируйте пользовательские настройки. В точке останова перед непосредственным выводом отчета (например, в событии ПриКомпоновкеРезультата модуля объекта) вычислите выражение ЭтотОбъект.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы и найдите ваш элемент отбора. Посмотрите, какой тип значения находится в его правом значении при первом и втором формировании.

Применение этих несложных правил и понимание механизмов сериализации СКД позволит вам быстро и качественно решать проблемы с программной установкой отборов в любых конфигурациях на платформе «1С:Предприятие 8.3».

← На главную