При разработке в 1С на управляемых формах многие разработчики сталкиваются с непредвиденным поведением платформы при работе с файлами, например, Excel. Код может успешно загружать данные в табличный документ на сервере, но в момент завершения процедуры или при возврате управления на клиент система внезапно обрывает выполнение с сообщением:
«Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа. Ошибка преобразования данных XDTO... Отсутствует отображение для типа '{http://v8.1c.ru/8.1/data/core}ValueTable'»
Давайте подробно проанализируем эту ситуацию, выясним причину возникновения ошибки и разберем по шагам, как правильно работать с данными, чтобы избегать подобных сбоев сериализации XDTO.
Архитектура управляемых форм 1С жестко разделяет клиентский и серверный контекст. Ключевое правило, которое необходимо запомнить: Таблицу значений между клиентом и сервером передавать нельзя. Файлы Excel или другие внешние факторы здесь совершенно ни при чем. Ошибка возникает исключительно из-за того, что платформа 1С пытается преобразовать (сериализовать) объект ТаблицаЗначений в XML для передачи по сети на клиентскую сторону, но для этого типа данных такое преобразование платформой не поддерживается.
Многие программисты пытаются обернуть проблемный участок серверного кода в блок обработки ошибок. Рассмотрим пример:
Попытка
ВыгрузитьВXMLНаСервере(ИмяФайла);
Исключение
Сообщить("Произошла ошибка");
КонецПопытки;
Но к удивлению разработчика, программа игнорирует блок исключения и все равно выдает системную ошибку. Разберем подробнее, почему так происходит.
Дело в том, что сама серверная процедура выполняется абсолютно успешно и без ошибок. Ошибка возникает после того, как серверный код полностью отработал и завершился. Сбой происходит на базовом платформенном (транспортном) уровне, когда 1С собирает измененные данные контекста и пытается их сериализовать в формат XDTO для возврата обратно на клиент.
Так как серверный контекст выполнения вашего кода к этому моменту уже закрыт, внутреннее серверное Исключение просто не может сработать. Сбой вываливается уже в клиентском коде, в той самой строке, откуда изначально был вызван метод сервера.
Часто разработчики утверждают: «Я передаю между клиентом и сервером только строку с именем файла, откуда там берется таблица значений?». Посмотрим на примеры того, как сериализация ТаблицаЗначений может происходить скрыто:
&НаСервере (а не &НаСервереБезКонтекста), платформа перед вызовом и после его завершения автоматически синхронизирует все реквизиты формы. Если где-то в реквизитах формы "застряла" таблица значений, или есть объект, который ее содержит, платформа попытается передать весь этот контекст и неизбежно выдаст ошибку.Возврат ТЗ;, платформа попытается передать ее по сети. И это произойдет даже в том случае, если на клиенте результат этой функции вы ничему не присваиваете!Структура или Массив), и внутри серверного метода в эту структуру добавляется свойство, содержащее ТаблицаЗначений, то при завершении процедуры 1С попытается вернуть на клиент измененный параметр. Это также приведет к краху XDTO.Проанализируем несколько рабочих решений, которые помогут вам навсегда избавиться от этой ошибки.
1. Использование директивы &НаСервереБезКонтекста
Перевод процедуры чтения файла в бесконтекстный режим гарантирует, что 1С не будет пытаться «тянуть» за собой тяжелые реквизиты формы. В такую процедуру вы передаете только необходимые простые типы (например, адрес файла во временном хранилище), а обратно возвращаете результат выполнения.
&НаСервереБезКонтекста
Процедура ВыгрузитьВXMLНаСервере(Знач ИмяФайла)
// Чтение файла и обработка
// Контекст формы здесь недоступен, неявная передача исключена
КонецПроцедуры
2. Принудительная очистка переменных
Если вы работаете в контекстной серверной процедуре &НаСервере, самый простой способ убедиться, что таблица не улетает обратно на клиент (если она была сохранена в какую-то локальную переменную или параметр формы) — принудительно очистить ее перед концом метода:
&НаСервере
Процедура ОбработатьДанныеФайла()
МояТЗ = Новый ТаблицаЗначений;
// ... наполнение и работа с таблицей ...
// Уничтожаем объект перед возвратом на клиент
МояТЗ = Неопределено;
КонецПроцедуры
3. Использование Временного хранилища
Если данные таблицы все-таки необходимо передать между клиентом и сервером, используйте метод ПоместитьВоВременноеХранилище(). В этом случае по сети передается только строковый адрес — ссылка на хранилище, что абсолютно безопасно.
&НаСервере
Функция ПодготовитьДанныеНаСервере()
ТЗ = ПолучитьТаблицуИзExcel();
АдресВХранилище = ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);
Возврат АдресВХранилище; // Передается простая строка
КонецФункции
4. Передача через массив структур
Так как ТаблицаЗначений недопустима для передачи, но вам нужно вернуть данные на клиент, можно преобразовать таблицу в Массив, элементами которого будут выступать Структуры. Ключи структуры — это имена колонок, а значения — данные ячеек. Массивы и структуры отлично сериализуются платформой и передаются без ошибок.
Если вы не можете визуально найти, где именно создается злополучная таблица значений, используйте возможности конфигуратора. Откройте отладчик и настройте его. В меню конфигуратора выберите пункт остановки по ошибке. Когда платформа столкнется с проблемой сериализации при переходе с сервера на клиент, отладчик остановится на строке вызова метода, и вы сможете проанализировать стек вызовов и локальные переменные, чтобы найти "спрятавшуюся" таблицу.