Как исправить ошибку отображения типов «КомандаФормы» и правильно передать таблицу значений с клиента на сервер?

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

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

Однако в процессе реализации этой схемы легко совершить архитектурные ошибки, которые приводят к падению системы. Проанализируем типичную ошибку «Ошибка отображения типов: Отсутствует отображение для типа 'КомандаФормы'», выясним ее причины и детально разберем правильные способы передачи табличных данных.

Выясняем причину ошибки «Отсутствует отображение для типа 'КомандаФормы'»

Рассмотрим ситуацию, когда при нажатии на кнопку формы вызывается клиентская процедура-обработчик, которая затем обращается к серверному методу. На клиенте обработчик команды всегда принимает первым параметром объект типа КомандаФормы:


&НаКлиенте
Процедура ИсполнитьКоманду(Команда)
    // Команда — это объект типа КомандаФормы
    ПередатьДанныеНаСервер(Команда); // Ошибка здесь!
КонецПроцедуры

В чем заключается проблема? Объект типа КомандаФормы является чисто клиентским объектом. Платформа 1С не умеет сериализовать (преобразовывать в XML или JSON) данный тип для отправки на сервер. Когда вы передаете этот объект в качестве параметра в процедуру с директивой &НаСервере, платформа пытается выполнить его сериализацию и выдает ошибку отображения типов.

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


&НаКлиенте
Процедура ВыполнитьДействие(Команда)
    
    // Подготавливаем только те данные, которые могут быть переданы на сервер
    МассивПараметров = Новый Массив;
    МассивПараметров.Добавить("ПримерДанных");
    
    // Вызываем серверный метод БЕЗ передачи объекта "Команда"
    ОбработатьДанныеНаСервере(МассивПараметров);
    
КонецПроцедуры

&НаСервере
Процедура ОбработатьДанныеНаСервере(МассивПараметров)
    // Серверная логика обработки данных
КонецПроцедуры

Разбор ошибок в функциях преобразования данных

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


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

В этом алгоритме допущены сразу две грубые ошибки:

  1. Добавление колонок внутри цикла по строкам: Метод Колонки.Добавить() вызывается на каждой строке данных. На второй строчке система выдаст критическую ошибку, так как колонка с таким именем уже существует в таблице. Создание структуры колонок должно происходить строго до заполнения данными.
  2. Статичный хардкод данных: Заполнение свойств строки фиксированными строками типа "Отдел 1" лишает функцию универсальности и практического смысла.

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


&НаСервереБезКонтекста
Функция ПреобразовыватьМассивВТаблицуЗначений(МассивСтруктур)
    
    ТаблицаРезультат = Новый ТаблицаЗначений;
    
    // Если массив пуст, возвращаем пустую таблицу
    Если МассивСтруктур.Количество() = 0 Тогда
        Возврат ТаблицаРезультат;
    КонецЕсли;
    
    // Шаг 1. Формируем колонки таблицы на основе ключей первой структуры в массиве
    ПервыйЭлемент = МассивСтруктур[0];
    Для Каждого КлючИЗначение Из ПервыйЭлемент Цикл
        ТаблицаРезультат.Колонки.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;
    
    // Шаг 2. Заполняем таблицу данными из массива структур
    Для Каждого СтрокаМассива Из МассивСтруктур Цикл
        НоваяСтрока = ТаблицаРезультат.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаМассива);
    КонецЦикла;
    
    Возврат ТаблицаРезультат;
    
КонецФункции

Как правильно работать с реквизитами формы типа «Таблица значений»

Рассмотрим еще одну частую ошибку, возникающую при попытке манипулировать структурой колонок реквизита управляемой формы непосредственно на клиенте:


&НаКлиенте
Функция ПредачаТаблицыЗначений()
    // Ошибка! У реквизита управляемой формы на клиенте нет свойства "Колонки"
    ТабЗнч.Колонки.Добавить("Отдел",,"Отдел");
КонецФункции

Разберем по шагам, почему это происходит:

Реквизиты формы, имеющие на сервере тип ТаблицаЗначений, на клиенте позиционируются как объект типа ДанныеФормыКоллекция. Данный тип предназначен только для отображения и редактирования данных в интерфейсе. На клиенте у него отсутствуют методы для изменения структуры метаданных (мы не можем программно добавлять или удалять колонки).

Если вам требуется работать с динамической структурой колонок, делать это нужно на сервере. Рассмотрим два основных сценария работы с табличными реквизитами формы.

Сценарий 1. Колонки таблицы определены в форме заранее

Если структура таблицы известна заранее, настройте реквизит формы (например, с именем ТабДокументы) и добавьте ему необходимые колонки в редакторе формы. В этом случае на клиенте вы можете работать со строками напрямую, без использования тяжелых серверных вызовов:


&НаКлиенте
Процедура ДобавитьДанныеНаКлиенте()
    
    // Добавлять новые строки на клиенте можно без проблем
    НоваяСтрока = ТабДокументы.Добавить();
    НоваяСтрока.Отдел = "Бухгалтерия";
    НоваяСтрока.Сотрудник = "Петров П.П.";
    НоваяСтрока.Оклад = 45000;
    
КонецПроцедуры

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


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

Сценарий 2. Динамическое создание колонок таблицы на сервере

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


&НаСервере
Процедура СоздатьТаблицуИЗаполнитьНаСервере()
    
    // 1. Описываем добавляемые реквизиты
    ДобавляемыеРеквизиты = Новый Массив;
    ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("ДинамическийОтдел", Новый ОписаниеТипов("Строка"), "ТабДокументы"));
    ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("ДинамическийОклад", Новый ОписаниеТипов("Число"), "ТабДокументы"));
    
    // 2. Изменяем структуру реквизитов формы
    ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    
    // 3. Заполняем данными
    НоваяСтрока = ТабДокументы.Добавить();
    НоваяСтрока.ДинамическийОтдел = "IT-отдел";
    НоваяСтрока.ДинамическийОклад = 90000;
    
КонецПроцедуры

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

← На главную