Как исправить ошибку преобразования XDTO при установке отбора в динамическом списке 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ причины возникновения ошибки

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

Когда мы выполняем код в процедуре ПриСозданииНаСервере, платформа пытается упаковать все данные формы в пакет для передачи на сторону клиента. В этот пакет попадают и настройки динамического списка. Ошибка возникает из-за того, что объект типа ТаблицаЗначений (ValueTable) не является сериализуемым для передачи между сервером и тонким клиентом в контексте настроек компоновки данных. Система XDTO (XML Data Transfer Objects), отвечающая за передачу данных, просто «не знает», как отобразить таблицу значений в структуру, доступную на клиенте внутри элемента отбора.

Проанализируем ситуацию: в коде автора переменная СписокПремированных содержит результат функции РасчетПремии.ПолучитьСписокСотрудников, которая возвращает таблицу значений. Передавая эту таблицу в качестве правого значения отбора, мы нарушаем правила типизации платформы.

Решение проблемы: преобразование коллекции данных

Чтобы избежать ошибки, нам необходимо преобразовать таблицу значений в тип данных, который поддерживается механизмом компоновки данных и может быть передан на клиент. Наиболее подходящими типами являются Массив или СписокЗначений.

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

Пример исправленного кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если ЗначениеЗаполнено(Параметры.Подразделение) Тогда
        
        // Получаем таблицу значений с сотрудниками
        ТаблицаСотрудников = РасчетПремии.ПолучитьСписокСотрудников(Параметры.Подразделение, Параметры.Период);
        
        // Преобразуем колонку таблицы в массив (этот тип допустим для XDTO)
        МассивСотрудников = ТаблицаСотрудников.ВыгрузитьКолонку("Сотрудник");
        
        // Используем стандартную функцию БСП для установки отбора
        ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
            Список,                            // Имя реквизита формы (ДинамическийСписок)
            "Ссылка",                          // Имя поля в списке, по которому делаем отбор
            МассивСотрудников,                 // Правое значение (теперь это массив!)
            ВидСравненияКомпоновкиДанных.ВСписке, // Вид сравнения
            "Отбор по списку премированных",   // Представление отбора
            Истина,                            // Использование
            РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный
        );
        
    КонецЕсли;

КонецПроцедуры

В данном примере мы заменили передачу всей таблицы на выгрузку одной конкретной колонки в массив. Массив — это универсальный тип, который прекрасно сериализуется и принимается динамическим списком при виде сравнения ВСписке.

Использование функции ОбщегоНазначенияКлиентСервер

Стоит отдельно отметить использование метода ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка. Это рекомендуемый способ работы в конфигурациях на базе БСП. Выясним преимущества этого метода:

  1. Проверка дублей: Метод автоматически проверяет, существует ли уже отбор по данному полю с таким же представлением. Если существует — он обновляет значение, если нет — создает новый элемент. Это предотвращает замусоривание настроек списка при повторных вызовах (например, при обновлении формы).
  2. Универсальность: Функция работает как на стороне клиента, так и на стороне сервера.
  3. Упрощение кода: Вам не нужно вручную обращаться к коллекции Список.Отбор.Элементы и перебирать их в поисках нужного поля.

Альтернативный подход: использование параметров запроса

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

Сначала в тексте запроса динамического списка (в конфигураторе) нужно добавить условие:


ГДЕ
    Сотрудник В (&СписокСотрудников) ИЛИ НЕ &ИспользоватьФильтр

Затем в коде формы установим значения параметров:


&НаСервере
Процедура УстановитьФильтрЧерезПараметры(МассивСотрудников)
    
    // Устанавливаем массив как параметр запроса
    Список.Параметры.УстановитьЗначениеПараметра("СписокСотрудников", МассивСотрудников);
    
    // Включаем или выключаем логику фильтрации в запросе
    Список.Параметры.УстановитьЗначениеПараметра("ИспользоватьФильтр", МассивСотрудников.Количество() > 0);
    
КонецПроцедуры

Этот способ работает быстрее, так как условие обрабатывается непосредственно СУБД на этапе выполнения запроса, а не накладывается «поверх» уже полученных данных механизмом компоновки. Однако помните, что такой отбор пользователь не сможет увидеть или отключить через стандартную кнопку «Настроить список».

Важные нюансы работы в привилегированном режиме

В исходном сообщении темы упоминалось использование УстановитьПривилегированныйРежим(Истина). Важно понимать: привилегированный режим влияет исключительно на проверку прав доступа (RLS) в базе данных. Он помогает выполнить запрос к данным, к которым у пользователя нет прямого доступа, но он никак не влияет на возможность передачи типов данных между сервером и клиентом. Ошибка XDTO возникает на уровне транспортного уровня платформы, и никакие права доступа не позволят передать ТаблицуЗначений туда, где она не поддерживается архитектурно.

Резюме по решению проблемы

Проанализировав ситуацию, мы можем сформулировать основные правила установки программных отборов:

  1. Никогда не передавайте объекты типа ТаблицаЗначений или РезультатЗапроса в настройки компоновщика (отборы) динамического списка.
  2. Всегда преобразуйте коллекции в Массив или СписокЗначений перед установкой отбора.
  3. Если вы используете БСП, применяйте функции общего назначения — это сделает ваш код чище и стабильнее.
  4. Следите за тем, чтобы имена полей в коде (например, "Ссылка") точно соответствовали именам полей в схеме компоновки данных вашего списка.

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

← На главную