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

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

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

«Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа. Ошибка преобразования данных XDTO... Отсутствует отображение для типа '{http://v8.1c.ru/8.1/data/core}ValueTable'»

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

В чем главная причина ошибки?

Архитектура управляемых форм 1С жестко разделяет клиентский и серверный контекст. Ключевое правило, которое необходимо запомнить: Таблицу значений между клиентом и сервером передавать нельзя. Файлы Excel или другие внешние факторы здесь совершенно ни при чем. Ошибка возникает исключительно из-за того, что платформа 1С пытается преобразовать (сериализовать) объект ТаблицаЗначений в XML для передачи по сети на клиентскую сторону, но для этого типа данных такое преобразование платформой не поддерживается.

Почему конструкция «Попытка ... Исключение» не ловит эту ошибку?

Многие программисты пытаются обернуть проблемный участок серверного кода в блок обработки ошибок. Рассмотрим пример:


Попытка
    ВыгрузитьВXMLНаСервере(ИмяФайла);
Исключение
    Сообщить("Произошла ошибка");
КонецПопытки;

Но к удивлению разработчика, программа игнорирует блок исключения и все равно выдает системную ошибку. Разберем подробнее, почему так происходит.

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

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

Как Таблица Значений может передаваться неявно?

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

  1. Контекст формы: Если метод объявлен с директивой &НаСервере (а не &НаСервереБезКонтекста), платформа перед вызовом и после его завершения автоматически синхронизирует все реквизиты формы. Если где-то в реквизитах формы "застряла" таблица значений, или есть объект, который ее содержит, платформа попытается передать весь этот контекст и неизбежно выдаст ошибку.
  2. Возврат значения из функции: Если ваша серверная функция заканчивается оператором возврата таблицы, например Возврат ТЗ;, платформа попытается передать ее по сети. И это произойдет даже в том случае, если на клиенте результат этой функции вы ничему не присваиваете!
  3. Изменение параметров, переданных по ссылке: Если в процедуру передается параметр (например, Структура или Массив), и внутри серверного метода в эту структуру добавляется свойство, содержащее ТаблицаЗначений, то при завершении процедуры 1С попытается вернуть на клиент измененный параметр. Это также приведет к краху XDTO.

Способы решения и обхода проблемы

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

1. Использование директивы &НаСервереБезКонтекста

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


&НаСервереБезКонтекста
Процедура ВыгрузитьВXMLНаСервере(Знач ИмяФайла)
    // Чтение файла и обработка
    // Контекст формы здесь недоступен, неявная передача исключена
КонецПроцедуры

2. Принудительная очистка переменных

Если вы работаете в контекстной серверной процедуре &НаСервере, самый простой способ убедиться, что таблица не улетает обратно на клиент (если она была сохранена в какую-то локальную переменную или параметр формы) — принудительно очистить ее перед концом метода:


&НаСервере
Процедура ОбработатьДанныеФайла()
    МояТЗ = Новый ТаблицаЗначений;
    // ... наполнение и работа с таблицей ...
    
    // Уничтожаем объект перед возвратом на клиент
    МояТЗ = Неопределено;
КонецПроцедуры

3. Использование Временного хранилища

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


&НаСервере
Функция ПодготовитьДанныеНаСервере()
    ТЗ = ПолучитьТаблицуИзExcel();
    АдресВХранилище = ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);
    Возврат АдресВХранилище; // Передается простая строка
КонецФункции

4. Передача через массив структур

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

Как быстро найти проблемное место?

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

← На главную