При работе с типовыми и кастомизированными отчетами в конфигурациях на платформе «1С:Предприятие 8.3» разработчики часто сталкиваются с неприятным поведением компоновщика настроек. Сценарий выглядит следующим образом: мы открываем отчет из формы какого-либо объекта (например, карточки партнера, номенклатуры или договора), при этом программно устанавливается отбор по выбранному элементу или группе элементов. При первом открытии отчет формируется абсолютно корректно. Однако стоит нам нажать кнопку «Сформировать» повторно, как отбор таинственным образом очищается или принимает пустое значение, из-за чего отчет выводит неверные данные.
В этой статье мы подробно разберем, почему возникает эта проблема на примере отчета «Ведомость расчетов с партнерами» в конфигурации «Управление торговлей 11.4», проанализируем внутренние механизмы платформы и предложим два варианта решения: быстрое и универсальное.
Для того чтобы понять природу этой ошибки, проанализируем жизненный цикл формы отчета и то, как платформа работает с настройками схемы компоновки данных (СКД). Когда мы открываем отчет параметрически (например, из карточки партнера), срабатывает экспортная процедура инициализации. В отчете «Ведомость расчетов с партнерами» (объект Отчет.РасчетыСПартнерами) за это отвечает серверная процедура СформироватьПараметрыФормыНаСервере.
При первом открытии формы в качестве параметра передается переменная ПараметрКоманды, которая содержит массив выбранных партнеров (тип Массив). Инициализирующий код устанавливает этот массив напрямую в правое значение элемента отбора компоновщика:
ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;
Платформа 1С при первоначальной компоновке отчета успешно обрабатывает этот массив. СКД понимает, что для вида сравнения В группе из списка или В списке в качестве правого значения передан массив элементов, и корректно выводит отчет. Однако при повторном нажатии кнопки «Сформировать» форма отчета не открывается заново. Вместо этого происходит повторная компоновка результата выполнения отчета на основе текущих пользовательских настроек формы (свойство КомпоновщикНастроек.ПользовательскиеНастройки).
Перед тем как отправить запрос на сервер для повторного формирования, платформа сериализует пользовательские настройки, чтобы передать их между клиентом и сервером. И здесь кроется главная проблема: тип данных Массив не предназначен для сериализации и хранения в пользовательских настройках компоновщика СКД. Платформа ожидает, что для множественных отборов (таких как «В списке» или «В группе из списка») будет использоваться специализированный тип данных — СписокЗначений.
Поскольку Массив не может быть корректно сохранен и восстановлен в пользовательских настройках формы, при повторном обращении к серверу правое значение отбора зануляется, превращаясь в пустое значение. В результате мы получаем пустой отбор вида «Партнер В группе из списка ""» и некорректный результат работы отчета.
Рассмотрим быстрое решение проблемы, которое часто применяется разработчиками «на скорую руку». Если мы точно знаем, что в параметрах команды всегда передается массив, содержащий только один элемент (например, одну конкретную группу партнеров), мы можем извлечь эту единственную ссылку и присвоить ее напрямую в правое значение отбора.
Для этого в процедуре СформироватьПараметрыФормыНаСервере заменим строку присвоения массива на присвоение первого элемента этого массива:
// Было:
// ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;
// Стало:
ЭлементОтбора.ПравоеЗначение = ПервыйЭлемент; // Где ПервыйЭлемент - это ПараметрКоманды[0]
Выясним, почему это решение работает. Когда мы записываем в ПравоеЗначение одиночную ссылку (тип СправочникСсылка.Партнеры), платформа 1С без проблем сериализует ее. Ссылочные типы данных отлично сохраняются в пользовательских настройках компоновщика между вызовами сервера. При повторном нажатии кнопки «Сформировать» ссылка никуда не исчезает.
При этом система компоновки данных достаточно интеллектуальна: даже если вид сравнения установлен как В группе из списка, а в правом значении указана одиночная ссылка, СКД автоматически приведет ее к списку из одного элемента и построит правильный отчет.
Важное ограничение данного метода: этот способ не сработает, если пользователь выделит в списке несколько партнеров или групп и попытается сформировать отчет по ним одновременно. Отчет построится только по первому выбранному элементу, проигнорировав остальные.
Для того чтобы сохранить возможность полноценной фильтрации по множеству выбранных элементов и гарантировать, что отбор не слетит при повторной генерации отчета, мы должны преобразовать переданный Массив в СписокЗначений. Тип данных СписокЗначений полностью поддерживается сериализатором настроек компоновщика СКД.
Давайте реализуем универсальный алгоритм заполнения правого значения отбора, который корректно обработает любые входные типы данных (будь то массив, список значений или одиночная ссылка):
// Вместо прямого присвоения массива напишем безопасное приведение типов:
СписокПараметров = Новый СписокЗначений;
Если ТипЗнч(ПараметрКоманды) = Тип("Массив") Тогда
СписокПараметров.ЗагрузитьЗначения(ПараметрКоманды);
ЭлементОтбора.ПравоеЗначение = СписокПараметров;
ИначеЕсли ТипЗнч(ПараметрКоманды) = Тип("СписокЗначений") Тогда
ЭлементОтбора.ПравоеЗначение = ПараметрКоманды;
Иначе
// Если пришла одиночная ссылка, поместим её в список для универсальности
СписокПараметров.Добавить(ПараметрКоманды);
ЭлементОтбора.ПравоеЗначение = СписокПараметров;
КонецЕсли;
Этот код гарантирует, что в правое значение элемента отбора всегда будет передан объект типа СписокЗначений (или одиночная ссылка, которая также корректно сериализуется). Теперь при повторном формировании отчета все выбранные пользователем элементы сохранятся в настройках компоновщика, и отчет покажет правильные данные.
Если вы столкнулись с похожим поведением в другом отчете и не уверены, где именно происходит очистка параметров, рекомендуем придерживаться следующей методики анализа:
КомпоновщикНастроек). Это поможет локализовать процедуру, в которой происходит модификация настроек.ПриКомпоновкеРезультата модуля объекта) вычислите выражение ЭтотОбъект.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы и найдите ваш элемент отбора. Посмотрите, какой тип значения находится в его правом значении при первом и втором формировании.Применение этих несложных правил и понимание механизмов сериализации СКД позволит вам быстро и качественно решать проблемы с программной установкой отборов в любых конфигурациях на платформе «1С:Предприятие 8.3».