Почему возникает ошибка «Значение недопустимого типа» при открытии формы в тонком клиенте 1С и как её исправить?

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

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

Проанализируем исходный код, который может приводить к подобной проблеме:


Номер = СтрЗаменить(Строка(Команда.Имя), "ком", "");
Для каждого Сц Из НастройкиСценариев Цикл
    Если Сц.Код = Номер Тогда
        ОткрытьФорму("Документ.бит_РеестрПлатежей.Форма.ФормаДокументаУправляемая", Новый Структура("Сценарий", Номер));    
        Прервать;
    КонецЕсли;
КонецЦикла;

На первый взгляд, в вызове метода ОткрытьФорму передается обычная структура, содержащая строковый или числовой параметр. Однако, как показывает практика и обсуждение на форуме, причина кроется глубже. Разберем по шагам, почему возникает эта ошибка и как правильно передавать сложные данные между формами.

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

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

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

  1. ТаблицаЗначений
  2. ДеревоЗначений
  3. Объектные типы (например, СправочникОбъект, ДокументОбъект)
  4. Запрос и РезультатЗапроса

В рассматриваемом примере выяснилось, что переменная, которая передавалась в качестве параметра или содержалась внутри структуры, содержала в себе ТаблицаЗначений. Платформа 1С строго проверяет все уровни вложенности: если у вас есть разрешенная Структура, внутри которой лежит Массив, но в этом массиве находится ТаблицаЗначений, система выдаст ошибку именно в момент попытки передачи этого сложного объекта на клиент.

Решение 1: Использование временного хранилища (Рекомендуемый способ)

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

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

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


// 1. Код в вызывающей форме (где-то на сервере)
ТаблицаДанных = ПолучитьСложнуюТаблицуНаСервере();
АдресВХранилище = ПоместитьВоВременноеХранилище(ТаблицаДанных, УникальныйИдентификатор);

// Возвращаем АдресВХранилище на клиент...

// 2. Код на клиенте
ПараметрыФормы = Новый Структура("АдресТаблицы", АдресВХранилище);
ОткрытьФорму("Документ.НашДокумент.Форма.ФормаДокумента", ПараметрыФормы);

// 3. Код в модуле открываемой формы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("АдресТаблицы") Тогда
        // Извлекаем реальную таблицу значений на сервере
        ТаблицаИзПараметров = ПолучитьИзВременногоХранилища(Параметры.АдресТаблицы);
        // Выполняем нужные действия с таблицей...
    КонецЕсли;
КонецПроцедуры

Решение 2: Упаковка таблицы в Массив Структур

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

И Массив, и Структура (содержащая примитивные типы или ссылки) отлично передаются на клиент. Однако, этот метод не рекомендуется для больших таблиц, так как процесс перепаковки и передача большого объема данных могут вызвать серьезные «тормоза».

Особенности работы с типом ДанныеФормыКоллекция

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

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

Чтобы полноценно обработать такую коллекцию, её необходимо передать на сервер и преобразовать с помощью встроенных функций:

  1. Функция РеквизитФормыВЗначение("ИмяРеквизита") превращает коллекцию в настоящую ТаблицаЗначений на сервере.
  2. Функция ЗначениеВРеквизитФормы(Таблица, "ИмяРеквизита") выгружает измененный результат обратно на форму для отображения клиенту.

Советы по локализации подобных ошибок

Сложность диагностики ошибки «Значение недопустимого типа» заключается в том, что отладчик на клиенте останавливается не на той строке, где была создана переменная с ошибкой, а в момент вызова контекста (например, при вызове ОткрытьФорму или возврате с сервера на клиент). Разберем, как быстро найти причину:

  1. Проверка подменой параметров: Если вы передаете сложную структуру, попробуйте временно заменить её на пустую или передать простую строку. Как советовали на форуме: замените Новый Структура("Сценарий", Номер) на Новый Структура("СценарийТест", "ПростоСтрока"). Если ошибка ушла, проблема точно в содержимом переменной Номер.
  2. Проверка типов: Внимательно изучите все переменные, которые функция возвращает с сервера на клиент. Обратите внимание на вложенные структуры.
  3. Использование сериализатора: Для поиска "спрятанного" несериализуемого типа внутри большого массива данных можно использовать объект СериализаторXDTO в отладчике на сервере. На каком элементе сериализатор выдаст ошибку записи, тот объект и является причиной сбоя передачи данных.
← На главную