Почему после обновления объекта через ЗначениеВРеквизитФормы очищаются колонки в табличной части?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Причина проблемы: разница между данными объекта и данными формы

Чтобы понять корень проблемы, нужно четко различать два вида данных, с которыми мы работаем в управляемой форме:

  1. Данные объекта. Это информация, которая непосредственно хранится в базе данных. Например, в табличной части документа «Заказ клиента» хранятся ссылки на номенклатуру и характеристику, а также числа — количество и цена. В объекте нет поля «Артикул».
  2. Данные формы. Это то, что видит пользователь на экране. Данные формы включают в себя данные объекта, а также дополнительные, вычисляемые или «служебные» реквизиты. Колонка «Артикул» — классический пример. Ее значение не хранится в документе, а подтягивается на форме из связанного справочника «Номенклатура» по пути Объект.Товары.Номенклатура.Артикул.

Когда мы выполняем последовательность действий для программного изменения объекта, происходит следующий процесс:

  1. РеквизитФормыВЗначение("Объект", ...)
    На этом шаге мы преобразуем данные формы в серверный объект типа ДокументОбъект.ЗаказКлиента. Платформа берет все реквизиты, которые соответствуют структуре объекта в базе данных, и "упаковывает" их. При этом все служебные и вычисляемые колонки формы, которых нет в структуре самого объекта (как наш «Артикул»), просто игнорируются. На сервер уезжает «чистый» объект.
  2. Программное изменение объекта на сервере
    Мы вносим свои изменения в этот «чистый» серверный объект.
  3. ЗначениеВРеквизитФормы(ОбъектЗначение, "Объект")
    Здесь происходит обратный процесс. Измененный серверный объект «возвращается» на форму и полностью заменяет ее данные. Поскольку в вернувшемся объекте не было никакой информации об артикулах, соответствующие колонки на форме очищаются.

Таким образом, это не ошибка, а штатное поведение платформы. Мы сами заменяем полные данные формы урезанными данными из объекта, теряя при этом всю вспомогательную информацию.

Правильное решение: повторное заполнение служебных реквизитов

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

Шаг 1. Находим процедуру заполнения

В большинстве типовых конфигураций логика заполнения зависимых полей (артикулов, единиц измерения, характеристик и т.д.) вынесена в отдельную серверную процедуру в модуле формы. Ее часто вызывают в обработчиках ПриСозданииНаСервере и ПриИзменении для полей вроде Номенклатура.

В нашем случае, как подсказали на форуме, это может быть процедура ЗаполнитьСлужебныеРеквизитыПоНоменклатуре(). Название может отличаться в вашей конфигурации. Ищите в модуле формы процедуры с похожими по смыслу названиями, которые вызываются в ключевых событиях.

Шаг 2. Вызываем процедуру после обновления объекта

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

Посмотрим на пример, который решает исходную задачу автора:


&НаСервере
Процедура ПрисвоитьНовоеЗначениеИСохранить()

    // 1. Получаем текущие данные формы в виде серверного объекта
    ОбъектЗначение = РеквизитФормыВЗначение("Объект");

    // 2. Вносим необходимые изменения в объект
    // Например, автор хотел присвоить значение реквизиту "Серии номенклатуры"
    // ОбъектЗначение.Товары[ТекущаяСтрока].Серия = ВыбранноеЗначениеСерии;

    // 3. Возвращаем измененный объект обратно в реквизит формы "Объект"
    // На этом шаге колонки "Артикул" и другие служебные поля очистятся
    ЗначениеВРеквизитФормы(ОбъектЗначение, "Объект");

    // 4. КЛЮЧЕВОЙ ШАГ: принудительно перезаполняем служебные данные
    // Название процедуры может отличаться в вашей конфигурации!
    // Эта процедура должна обойти строки табличной части и по номенклатуре
    // заполнить все связанные реквизиты: артикул, единицу измерения и т.д.
    ЗаполнитьСлужебныеРеквизитыПоНоменклатуре();

КонецПроцедуры

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

Что не поможет и почему?

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

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

← На главную