Как исправить ошибку «Отсутствует отображение для типа "ЭлементСпискаЗначений"» и правильно передать ссылку с клиента на сервер в 1С 8.3

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

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

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

Для того чтобы понять природу ошибки, нам необходимо проанализировать клиент-серверную архитектуру управляемого приложения 1С. Клиентский сеанс (тонкий клиент или веб-клиент) и сервер приложений работают в разных процессах, часто на физически разных компьютерах. Любое обращение к серверу через директивы &НаСервере или &НаСервереБезКонтекста требует физической передачи параметров по сети.

Для такой передачи платформа выполняет процесс сериализации — перевод объектов из оперативной памяти в XML- или JSON-пакет данных, который затем отправляется на сервер и там десериализуется обратно в объекты. Далеко не все типы данных в 1С могут быть сериализованы.

Объект типа СписокЗначений состоит из коллекции элементов, каждый из которых имеет тип ЭлементСпискаЗначений. Этот тип является исключительно визуальным, интерфейсным представлением данных на стороне клиента. Он содержит свойства:

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

Решение проблемы: правильная передача значения на сервер

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

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


&НаКлиенте
Процедура ВыгрузитьДокументНажатие(Команда)
    
    // Получаем элемент списка, который выбрал пользователь в поле ввода
    ВыбранныйЭлемент = Элементы.ПолеВыбораДокументов.СписокВыбора.НайтиПоЗначению(РеквизитФормыДокумент);
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // ОШИБКА: Передавать ВыбранныйЭлемент напрямую на сервер нельзя!
        // ПРАВИЛЬНО: Передаем только свойство ".Значение", где лежит чистая ссылка
        ВыгрузитьНаСервере(ВыбранныйЭлемент.Значение);
    Иначе
        ПоказатьПредупреждение(, "Пожалуйста, выберите корректный документ из списка!");
    EndЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыгрузитьНаСервере(СсылкаНаДокумент)
    
    // На сервере тип параметра "СсылкаНаДокумент" распознается корректно.
    // Мы можем получить объект документа и прочитать любые его реквизиты.
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    
    // Пример формирования и записи текстовых данных
    ТекстФайла = Новый ТекстовыйДокумент;
    ТекстФайла.УстановитьТекст("Документ № " + ДокументОбъект.Номер + " от " + Формат(ДокументОбъект.Дата, "ДФ=dd.MM.yyyy"));
    
    ПутьКФайлу = "C:\temp\export_doc.txt";
    ТекстФайла.Записать(ПутьКФайлу, КодировкаТекста.UTF8);
    
КонецПроцедуры

Анализ ошибки проектирования: использование типа «Строка» для ссылок

В процессе обсуждения проблемы часто выясняется еще одна важная деталь проектирования: разработчики делают реквизит формы, связанный с полем выбора, обычным строковым типом. Мотивация проста: «Если реквизит имеет тип ссылки на конкретный документ, то при интерактивном выборе из списка поле ввода очищается или вообще не заполняется».

Давайте проанализируем, почему происходит такое поведение системы:

  1. Если реквизит формы жестко типизирован, например, как ДокументСсылка.РеализацияТоваровУслуг, а в список выбора программно помещаются ссылки на документы другого вида (например, ДокументСсылка.ПоступлениеТоваровУслуг), срабатывает встроенный контроль типов платформы.
  2. 1С блокирует попытку записать в строго типизированное поле значение неподходящего типа, в результате чего реквизит сбрасывается в пустое значение.

Использование строкового реквизита для хранения ссылок — это плохая практика (bad practice). В строке будет сохранено лишь текстовое представление ссылки, и на сервере вы не сможете напрямую обратиться к метаданным и реквизитам выбранного документа. Придется реализовывать сложный поиск по наименованию или номеру, что критически снизит производительность и надежность системы.

Для реализации корректного универсального выбора документов разного вида необходимо использовать тип данных ЛюбаяСсылка или настроить составной тип данных для реквизита формы:

Шаг 1. Настройка реквизита формы. Откройте палитру свойств вашего реквизита формы, перейдите в поле «Тип» и вместо «Строка» выберите тип ЛюбаяСсылка (или отметьте галочками только те виды документов, которые действительно могут быть выбраны).

Шаг 2. Заполнение списка выбора. Теперь вы можете наполнять список выбора реальными ссылками на любые документы информационной базы. Платформа будет автоматически сопоставлять типы, отображать красивое представление объектов и сохранять в реквизите полноценную ссылку, готовую для серверной обработки.

Современный альтернативный подход: выбор через форму

Заполнение списка выбора всеми документами информационной базы вручную с помощью запросов — крайне неоптимальный путь. Если в базе данных хранятся десятки тысяч документов, то при открытии формы интерфейс будет сильно зависать, потребляя огромные объемы оперативной памяти на клиенте.

Вместо ручного формирования выпадающих списков рекомендуется использовать штатный асинхронный механизм выбора платформы с помощью метода ПоказатьВыборИзСписка. Это современное решение, разработанное специально под интерфейс «Такси».

Давайте рассмотрим, как правильно реализовать этот подход на практике:


&НаКлиенте
Процедура ВыбратьДокумент(Команда)
    
    // Создаем список выбора локально на клиенте
    СписокДокументов = Новый СписокЗначений;
    
    // Наполняем его на сервере быстрой выборкой актуальных документов
    ПолучитьСписокДокументовНаСервере(СписокДокументов);
    
    // Описываем обработчик оповещения, который сработает после выбора пользователя
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораДокументаИзСписка", ЭтотОбъект);
    
    // Показываем красивый всплывающий список выбора рядом с кнопкой
    ПоказатьВыборИзСписка(ОписаниеОповещения, СписокДокументов, Элементы.КнопкаВыбора);
    
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПолучитьСписокДокументовНаСервере(СписокДокументов)
    
    // Выбираем, например, последние 10 созданных документов
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 10
        |	РеализацияТоваровУслуг.Ссылка КАК Ссылка,
        |	РеализацияТоваровУслуг.Представление КАК Представление
        |ИЗ
        |	Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
        |УПОРЯДОЧИТЬ ПО
        |	РеализацияТоваровУслуг.Дата УБЫВ";
        
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        // Добавляем в список Ссылку и ее строковое представление
        СписокДокументов.Добавить(ВыборкаДетальныеЗаписи.Ссылка, ВыборкаДетальныеЗаписи.Представление);
    КонецЦикла;
    
КонецПроцедуры

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

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

← На главную