Как правильно обновить табличную часть на сервере и избежать ошибки "Недопустимое значение параметра"?

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

При работе с управляемыми формами в 1С часто возникает задача заполнить или изменить данные в табличной части на сервере. Интуитивно может показаться, что для обновления части данных формы можно использовать те же методы, что и для всей формы, например, ЗначениеВРеквизитФормы. Однако такой подход приводит к ошибке: "Недопустимое значение параметра". Разберем, почему так происходит и какие способы работы с табличными частями являются правильными и эффективными.

Причина ошибки: разбираемся в назначении методов

Для начала выясним причину проблемы. Ошибка возникает из-за неверного понимания принципов работы методов РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы(). Эти функции предназначены для преобразования типов между данными формы и прикладными объектами базы данных.

Рассмотрим по шагам, что происходит при вызове:

  1. Когда мы работаем с данными на форме (например, с реквизитом Объект), мы имеем дело не с самим объектом базы данных (типа ДокументОбъект.ЗаказКлиента), а с его представлением — данными формы (типа ДанныеФормыСтруктура).
  2. Метод РеквизитФормыВЗначение("Объект") преобразует эти данные формы в полноценный прикладной объект. Это необходимо, чтобы получить доступ к методам, описанным в модуле самого объекта, которых у данных формы просто нет.
  3. Метод ЗначениеВРеквизитФормы(ПолученныйОбъект, "Объект") выполняет обратное действие — обновляет данные формы на основе изменений в прикладном объекте.

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

Решение 1: Прямое изменение данных на сервере (рекомендуемый способ)

Самый простой, правильный и производительный способ — это напрямую работать с данными табличной части в серверной процедуре. Этот метод является частным случаем более общей задачи, такой как программный вывод произвольной таблицы значений на управляемую форму. Когда мы выполняем серверный вызов с контекстом (&НаСервере), мы получаем полный доступ ко всем данным формы, и никакие преобразования не нужны.

Вам не нужно "вытаскивать" табличную часть из объекта. Достаточно просто обратиться к ней:


&НаСервере
Процедура ЗаполнитьТабЧастьНаСервере()

    // Получаем данные из любого источника, например, через запрос
    тз = ПолучитьДанныеДляЗаполнения();
  
    // Используем стандартный метод Загрузить() для табличной части формы
    // Это самый эффективный способ для массового заполнения
    Объект.тчДопУслуги.Загрузить(тз);
  
КонецПроцедуры

Если нужно не полностью перезаполнить, а изменить существующие данные или добавить несколько строк, можно работать с табличной частью как с обычной коллекцией:


&НаСервере
Процедура ДобавитьСтрокиНаСервере()

    // Можно очистить перед добавлением, если нужно
    // Объект.тчДопУслуги.Очистить(); 
    
    // Добавляем новые строки в цикле
    Для i = 1 По 5 Цикл
        НоваяСтрока = Объект.тчДопУслуги.Добавить();
        НоваяСтрока.Номенклатура = //... какое-то значение
        НоваяСтрока.Количество = i;
        НоваяСтрока.Цена = 100 * i;
    КонецЦикла;
  
КонецПроцедуры

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

Решение 2: Использование методов Выгрузить() / Загрузить()

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

Алгоритм действий следующий:

  1. Выгружаем данные из табличной части формы в ТаблицуЗначений.
  2. Производим все необходимые изменения с этой таблицей.
  3. Загружаем измененные данные обратно в табличную часть формы.

Посмотрим на пример:


&НаСервере
Процедура ИзменитьДанныеТЧНаСервере()

    // 1. Выгружаем данные
    ТаблицаДанных = Объект.тчДопУслуги.Выгрузить();
    
    // 2. Манипулируем данными в ТаблицеЗначений
    // Например, увеличим цену для всех строк
    Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
        СтрокаТЗ.Цена = СтрокаТЗ.Цена * 1.1; // Увеличиваем на 10%
    КонецЦикла;
    
    // 3. Загружаем измененные данные обратно
    Объект.тчДопУслуги.Загрузить(ТаблицаДанных);
    
КонецПроцедуры

Анализ производительности: "Метод экономиста" против стандарта

В обсуждении возник интересный вопрос: а что если, для "экономии трафика", не передавать всю форму на сервер, а сделать бесконтекстный вызов? Этот подход иногда называют "методом сильных экономистов", однако он часто противоречит приемам построения эффективных интерфейсов.

Сравним два подхода:

  1. Стандартный (контекстный) вызов &НаСервере:
    • На сервер передается контекст формы.
    • На сервере выполняются действия (например, Объект.ТЧ.Загрузить()).
    • На клиент возвращаются только изменения.
  2. "Метод экономиста" (бесконтекстный) вызов &НаСервереБезКонтекста:
    • С клиента вызывается серверная функция без передачи контекста.
    • На сервере выполняется запрос, данные выгружаются, например, в массив структур.
    • Этот массив передается с сервера на клиент.
    • На клиенте в цикле данные из массива добавляются в табличную часть формы.

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

Проанализируем шаги "экономиста":

  1. Выборка данных на сервере.
  2. Дополнительный обход данных для преобразования их в сериализуемый формат (например, МассивСтруктур).
  3. Потеря времени на передачу большого массива по сети.
  4. Обход массива на клиенте и добавление строк, что само по себе медленная операция, которая может вызывать неявные обращения к серверу для синхронизации.

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

Важнейший аспект: встроенная оптимизация платформы 1С

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

Как это работает:

Таким образом, стандартный контекстный вызов &НаСервере с прямым изменением данных формы — это не только самый простой в написании, но и самый оптимизированный с точки зрения платформы способ. Вы пишете простой код, а 1С сама эффективно управляет сетевым трафиком.

← На главную