При разработке в среде управляемого приложения разработчики нередко сталкиваются с ситуацией, когда данные, сформированные на сервере в виде таблицы значений, требуется проанализировать или отобразить на стороне тонкого клиента. Попытка передать объект ТаблицаЗначений напрямую или через вызов функции ПолучитьИзВременногоХранилища() на клиенте завершается системной ошибкой XDTO: «Отсутствует отображение для типа ValueTable».
Разберем природу этого ограничения и рассмотрим практические способы решения задачи: от конвертации данных в сериализуемые структуры до быстрой визуализации без включенной серверной отладки.
Проанализируем контекст выполнения кода. Метод ПоместитьВоВременноеХранилище() на сервере отрабатывает корректно, поскольку объект ТаблицаЗначений поддерживается серверным контекстом. Однако сбой происходит именно в тот момент, когда на клиенте вызывается метод:
&НаКлиенте
Процедура Тест(Команда)
АдресХранилища = ТестНаСервере();
ТЗССервера = ПолучитьИзВременногоХранилища(АдресХранилища);
КонецПроцедуры
В этот момент платформа пытается передать сериализованные данные между сервером и клиентским приложением и воссоздать объект на клиенте. В соответствии с синтакс-помощником тип ТаблицаЗначений имеет контекстную доступность: Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер). На тонком и веб-клиенте такой тип данных физически отсутствует в объектной модели. Платформа 1С:Предприятие не может инициализировать таблицу значений на клиенте, о чем и сообщает ошибка десериализации XDTO.
Если данные таблицы требуются непосредственно в программном коде на клиенте для перебора или выполнения логики, преобразуем таблицу значений в универсальную коллекцию, поддерживаемую на тонком клиенте — массив структур. В типовых конфигурациях для этого уже предусмотрена готовая функция из библиотеки стандартных подсистем (БСП).
Посмотрим на пример реализации серверного метода:
&НаСервере
Функция ПолучитьДанныеТаблицы()
// Создаем или получаем исходную таблицу значений
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Код");
ТЗ.Колонки.Добавить("Наименование");
// Заполняем данными
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Код = "001";
НоваяСтрока.Наименование = "Товар 1";
// Преобразуем таблицу в массив структур
МассивРезультат = ОбщегоНазначения.ТаблицаЗначенийВМассив(ТЗ);
Возврат МассивРезультат;
КонецФункции
Если в вашей конфигурации нет библиотеки БСП, выполним аналогичное преобразование вручную:
&НаСервере
Функция ПреобразоватьТЗВМассив(ТаблицаИсточника)
Массив = Новый Массив;
Колонки = ТаблицаИсточника.Колонки;
Для Каждого СтрокаТЗ Из ТаблицаИсточника Цикл
СтруктураСтроки = Новый Структура;
Для Каждого Колонка Из Колонки Цикл
СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
КонецЦикла;
Массив.Добавить(СтруктураСтроки);
КонецЦикла;
Возврат Массив;
КонецФункции
На стороне клиента результат работы такой функции успешно считывается в виде стандартного массива:
&НаКлиенте
Процедура ОбработатьДанные(Команда)
ДанныеВВидеМассива = ПолучитьДанныеТаблицы();
Для Каждого Элемент Из ДанныеВВидеМассива Цикл
Сообщить(Элемент.Наименование);
КонецЦикла;
КонецПроцедуры
Если данные таблицы необходимо отобразить пользователю на форме или использовать в элементах формы, правильнее связать таблицу значений с реквизитом управляемой формы. На клиенте такой реквизит будет доступен как тип ДанныеФормыКоллекция.
Разберем по шагам порядок работы:
ТаблицаДанных) и устанавливаем ему тип ТаблицаЗначений.ТаблицаФормы.ЗначениеВРеквизитФормы().Посмотрим на пример серверной процедуры:
&НаСервере
Процедура ЗаполнитьРеквизитФормы(ТЗДанные)
// Преобразуем объект ТаблицаЗначений в данные формы
ЗначениеВРеквизитФормы(ТЗДанные, "ТаблицаДанных");
КонецПроцедуры
Если в дальнейшем потребуется обратное преобразование на сервере для сложных манипуляций (поиск, группировка, сортировка), используем обратный метод: ТЗ = РеквизитФормыВЗначение("ТаблицаДанных");.
Нередко программисту требуется просто быстро просмотреть структуру и строки сформированной таблицы значений прямо в пользовательском режиме (например, когда на рабочем сервере отключена отладка, а выводить реквизиты на форму долго).
Для этого воспользуемся возможностями объекта ПостроительОтчета. Он умеет формировать ТабличныйДокумент напрямую из таблицы значений, а табличный документ, в отличие от таблицы значений, полностью доступен на тонком клиенте.
Рассмотрим реализацию:
&НаСервере
Функция ПолучитьТабличныйДокументИзТЗ(ТЗ)
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗ);
ТабДок = Новый ТабличныйДокумент;
Построитель.Вывести(ТабДок);
Возврат ТабДок;
КонецФункции
&НаКлиенте
Процедура ПросмотретьТЗ(Команда)
// Вызываем серверную функцию и сразу открываем окно с результатом
ТабДок = ПолучитьТабличныйДокументССервера();
ТабДок.Показать("Анализ данных таблицы");
КонецПроцедуры
Данный подход позволяет за несколько строк кода открыть отдельное окно с форматированной таблицей, содержащей все имена колонок и строки вычисленной таблицы значений.
Если анализ данных необходим в процессе разработки, лучшим решением остается включение штатного механизма отладки на сервере 1С:Предприятия.
Разберем параметры запуска службы:
ragent должна запускаться с ключом -debug. В операционной системе Windows этот флаг прописывается в системном реестре в параметре ImagePath соответствующей службы.Подключение серверной отладки снимает необходимость вставлять временный код для передачи структур данных на клиент и позволяет анализировать содержимое коллекций штатными средствами табло и вычислителя выражений.