При работе с управляемыми формами в 1С часто возникает задача заполнить или изменить данные в табличной части на сервере. Интуитивно может показаться, что для обновления части данных формы можно использовать те же методы, что и для всей формы, например, ЗначениеВРеквизитФормы. Однако такой подход приводит к ошибке: "Недопустимое значение параметра". Разберем, почему так происходит и какие способы работы с табличными частями являются правильными и эффективными.
Для начала выясним причину проблемы. Ошибка возникает из-за неверного понимания принципов работы методов РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы(). Эти функции предназначены для преобразования типов между данными формы и прикладными объектами базы данных.
Рассмотрим по шагам, что происходит при вызове:
Объект), мы имеем дело не с самим объектом базы данных (типа ДокументОбъект.ЗаказКлиента), а с его представлением — данными формы (типа ДанныеФормыСтруктура).РеквизитФормыВЗначение("Объект") преобразует эти данные формы в полноценный прикладной объект. Это необходимо, чтобы получить доступ к методам, описанным в модуле самого объекта, которых у данных формы просто нет.ЗначениеВРеквизитФормы(ПолученныйОбъект, "Объект") выполняет обратное действие — обновляет данные формы на основе изменений в прикладном объекте.Ключевой момент в том, что эти методы работают только с реквизитами формы верхнего уровня. Табличная часть, например Объект.тчДопУслуги, является не самостоятельным реквизитом, а частью (коллекцией) другого реквизита. У нее свой тип — ДанныеФормыКоллекция. Система не умеет преобразовывать этот тип в ТаблицуЗначений и обратно с помощью этих функций, поэтому и возникает ошибка во втором параметре, который ожидает имя реквизита формы, а не путь к его части.
Самый простой, правильный и производительный способ — это напрямую работать с данными табличной части в серверной процедуре. Этот метод является частным случаем более общей задачи, такой как программный вывод произвольной таблицы значений на управляемую форму. Когда мы выполняем серверный вызов с контекстом (&НаСервере), мы получаем полный доступ ко всем данным формы, и никакие преобразования не нужны.
Вам не нужно "вытаскивать" табличную часть из объекта. Достаточно просто обратиться к ней:
&НаСервере
Процедура ЗаполнитьТабЧастьНаСервере()
// Получаем данные из любого источника, например, через запрос
тз = ПолучитьДанныеДляЗаполнения();
// Используем стандартный метод Загрузить() для табличной части формы
// Это самый эффективный способ для массового заполнения
Объект.тчДопУслуги.Загрузить(тз);
КонецПроцедуры
Если нужно не полностью перезаполнить, а изменить существующие данные или добавить несколько строк, можно работать с табличной частью как с обычной коллекцией:
&НаСервере
Процедура ДобавитьСтрокиНаСервере()
// Можно очистить перед добавлением, если нужно
// Объект.тчДопУслуги.Очистить();
// Добавляем новые строки в цикле
Для i = 1 По 5 Цикл
НоваяСтрока = Объект.тчДопУслуги.Добавить();
НоваяСтрока.Номенклатура = //... какое-то значение
НоваяСтрока.Количество = i;
НоваяСтрока.Цена = 100 * i;
КонецЦикла;
КонецПроцедуры
Важно: При таком подходе не требуется вызывать ЗначениеВРеквизитФормы, так как мы меняем данные непосредственно в форме. Платформа сама позаботится об отображении этих изменений на клиенте после завершения серверного вызова.
Этот способ похож на первый, но может быть полезен, если вам нужно произвести сложные манипуляции с данными табличной части, которые удобнее делать с объектом ТаблицаЗначений. Подобные подходы являются частью общих методик программного изменения форм, которые полезно стандартизировать для ускорения разработки.
Алгоритм действий следующий:
ТаблицуЗначений.Посмотрим на пример:
&НаСервере
Процедура ИзменитьДанныеТЧНаСервере()
// 1. Выгружаем данные
ТаблицаДанных = Объект.тчДопУслуги.Выгрузить();
// 2. Манипулируем данными в ТаблицеЗначений
// Например, увеличим цену для всех строк
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
СтрокаТЗ.Цена = СтрокаТЗ.Цена * 1.1; // Увеличиваем на 10%
КонецЦикла;
// 3. Загружаем измененные данные обратно
Объект.тчДопУслуги.Загрузить(ТаблицаДанных);
КонецПроцедуры
В обсуждении возник интересный вопрос: а что если, для "экономии трафика", не передавать всю форму на сервер, а сделать бесконтекстный вызов? Этот подход иногда называют "методом сильных экономистов", однако он часто противоречит приемам построения эффективных интерфейсов.
Сравним два подхода:
&НаСервере:
Объект.ТЧ.Загрузить()).&НаСервереБезКонтекста:
Тесты показывают, что в клиент-серверной архитектуре "метод экономиста" почти всегда проигрывает в производительности. Причина проста: он создает гораздо больше накладных расходов.
Проанализируем шаги "экономиста":
МассивСтруктур).Стандартный же подход максимально лаконичен: данные выбраны и сразу загружены в нужную коллекцию на сервере. Всю дальнейшую работу по оптимизации берет на себя платформа.
Современные версии платформы 1С (начиная с 8.3.21) содержат мощные механизмы оптимизации передачи данных формы. Пытаться "перехитрить" платформу вручную чаще всего бессмысленно и даже вредно.
Как это работает:
Таким образом, стандартный контекстный вызов &НаСервере с прямым изменением данных формы — это не только самый простой в написании, но и самый оптимизированный с точки зрения платформы способ. Вы пишете простой код, а 1С сама эффективно управляет сетевым трафиком.