Как исправить ошибку «Отсутствует отображение для типа 'ВыборкаИзРезультатаЗапроса'» в 1С при передаче данных между клиентом и сервером

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

При переходе к разработке на управляемых формах в 1С:Предприятии 8 разработчики часто сталкиваются с системной ошибкой: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа... Ошибка отображения типов: Отсутствует отображение для типа 'ВыборкаИзРезультатаЗапроса'». Эта проблема возникает из-за непонимания архитектурных принципов клиент-серверного взаимодействия платформы.

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

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

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


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

В момент выполнения строки Выборка = СформироватьВыборкуИЗЗапроса(); платформа пытается передать объект типа ВыборкаИзРезультатаЗапроса с сервера на клиент. На этом этапе происходит сбой.

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

Объект типа ВыборкаИзРезультатаЗапроса (как и сам РезультатЗапроса) жестко привязан к контексту базы данных, к памяти сервера и к СУБД. Платформа 1С физически не может сериализовать этот объект и воссоздать его на клиенте, где нет прямого доступа к базе данных. Именно поэтому мы получаем ошибку отсутствия отображения типов.

Что категорически нельзя передавать с сервера на клиент?

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

  1. Результаты запросов и выборки: объекты типов РезультатЗапроса и ВыборкаИзРезультатаЗапроса.
  2. Объекты базы данных напрямую: любые ссылочные объекты в режиме редактирования (например, СправочникОбъект.Пользователи, ДокументОбъект.РеализацияТоваровУслуг). На клиенте разрешено работать только с их ссылками (СправочникСсылка, ДокументСсылка).
  3. Менеджеры прикладных объектов: например, СправочникиМенеджер или ДокументыМенеджер.
  4. Тяжелые универсальные коллекции: типы ТаблицаЗначений и ДеревоЗначений. Они также не поддерживают сериализацию для передачи на тонкий и веб-клиент.

Важное примечание: иногда разработчики ошибочно полагают, что таблицу значений можно передать на клиент, ссылаясь на то, что в толстом клиенте это работает. Действительно, в режиме толстого клиента это допустимо, но при работе в тонком клиенте или через веб-браузер попытка вернуть ТаблицаЗначений приведет к точно такой же ошибке. Это плохая практика, от которой нужно отказываться.

Какие типы данных разрешены для обмена?

Безопасно переносить между сервером и клиентом можно только легковесные и сериализуемые типы данных:

  1. Примитивные типы: Число, Строка, Булево, Дата, Null, Неопределено.
  2. Ссылки: ссылки на элементы справочников, документов, бизнес-процессов и других объектов метаданных. Ссылка — это простой UUID и базовая информация, которая легко передается по сети.
  3. Сериализуемые коллекции: объекты типов Массив, Структура, Соответствие, СписокЗначений (при условии, что элементы внутри этих коллекций также имеют разрешенные типы).

Теперь рассмотрим подробнее, как правильно решить проблему и передать данные из запроса на сторону клиента.

Способ 1. Преобразование выборки в массив структур (Универсальный)

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

Давайте разберем по шагам, как переписать наш исходный код:


&НаКлиенте
Процедура Загрузить(Команда)
    // Получаем массив структур, который без проблем передается на клиент
    МассивДанных = СформироватьМассивИзЗапроса(); 
    
    // Теперь мы можем безопасно обойти данные на клиенте
    Для Каждого СтрокаДанных Из МассивДанных Цикл
        ПоказатьПредупреждение(, "Пользователь: " + СтрокаДанных.Наименование);
    КонецЦикла;
КонецПроцедуры
    
&НаСервере
Функция СформироватьМассивИзЗапроса()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                  |    Пользователи.Ссылка КАК Ссылка,
                  |    Пользователи.Наименование КАК Наименование
                  |ИЗ
                  |    Справочник.Пользователи КАК Пользователи";
    
    // Выгружаем результат запроса в таблицу значений на сервере
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // Создаем массив для передачи на клиент
    МассивРезультатов = Новый Массив;
    
    // Заполняем массив структурами
    Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
        СтруктураСтроки = Новый Структура("Ссылка, Наименование");
        ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТЗ);
        МассивРезультатов.Добавить(СтруктураСтроки);
    КонецЦикла;
    
    Возврат МассивРезультатов; // Этот тип данных успешно сериализуется!
КонецФункции

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

Способ 2. Использование реквизитов формы для отображения на экране

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

Выясним, как это реализовать:

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

Посмотрим на пример кода:


&НаКлиенте
Процедура Загрузить(Команда)
    // Вызываем серверную процедуру без возвращаемого значения
    ЗаполнитьТаблицуНаФормеНаСервере(); 
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьТаблицуНаФормеНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                  |    Пользователи.Ссылка КАК Ссылка,
                  |    Пользователи.Наименование КАК Наименование
                  |ИЗ
                  |    Справочник.Пользователи КАК Пользователи";
                  
    // Получаем таблицу значений на сервере
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // Переносим данные из обычной таблицы значений в реквизит нашей управляемой формы
    ЗначениеВРеквизитФормы(ТаблицаДанных, "ТаблицаПользователей");
    // Данные мгновенно отобразятся на экране у пользователя без лишней передачи типов!
КонецПроцедуры

Этот способ является наиболее производительным и правильным с точки зрения стандартов разработки фирмы «1С», так как платформа берет на себя всю оптимизацию по передаче данных на клиентскую часть отображения.

Способ 3. Передача данных через Временное хранилище

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

В таких сценариях мы рекомендуем использовать механизм Временного хранилища. Рассмотрим, как это работает:


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

&НаСервере
Функция ПоместитьДанныеВоВременноеХранилище()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                  |    Пользователи.Ссылка КАК Ссылка,
                  |    Пользователи.Наименование КАК Наименование
                  |ИЗ
                  |    Справочник.Пользователи КАК Пользователи";
                  
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // Помещаем таблицу во временное хранилище, привязывая её к уникальному идентификатору формы
    АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаДанных, ЭтаФорма.УникальныйИдентификатор);
    
    // На клиент возвращается легкая строка-адрес
    Возврат АдресХранилища; 
КонецФункции

&НаСервереБезКонтекста
Процедура ОбработатьДанныеИзХранилища(Знач АдресДанных)
    // Извлекаем таблицу значений на сервере по адресу
    ТаблицаДанных = ПолучитьИзВременногоХранилища(АдресДанных);
    
    // Выполняем необходимую серверную обработку данных
    Если ТаблицаДанных <> Неопределено Тогда
        Для Каждого Строка Из ТаблицаДанных Цикл
            // Здесь ваш алгоритм обработки
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Использование метода ПоместитьВоВременноеХранилище с привязкой к ЭтаФорма.УникальныйИдентификатор гарантирует, что данные будут автоматически удалены из памяти сервера после закрытия формы пользователем, предотвращая утечки оперативной памяти на сервере приложений.

Подведем итоги

Мы проанализировали ключевую ошибку начинающих разработчиков при работе на управляемых формах 1С и выяснили механизмы работы платформы. Помните три простых правила:

  1. Никогда не возвращайте результаты запросов, выборки и таблицы значений напрямую на клиент.
  2. Для простых операций на клиенте преобразуйте выборки в массивы структур.
  3. Для визуализации используйте реквизиты формы и встроенную функцию ЗначениеВРеквизитФормы, а для тяжелых промежуточных расчетов — временное хранилище.

Эти подходы позволят вашим разработкам работать стабильно, быстро и соответствовать стандартам разработки фирмы «1С».

← На главную