Почему программно заполненный реквизит табличной части не отображается на форме в 1С?

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

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

Анализ исходной проблемы и кода

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

  1. Работа (ссылка на справочник Работы).
  2. Тариф (ссылка на справочник ТарифыРабот).
  3. Значение тарифа (числовой тип).

У элемента справочника Работы есть реквизит ТарифОсновной, из которого мы должны программно подтянуть сам тариф и его числовое значение при выборе работы в строке табличной части.

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


&НаСервере 
Функция РаботыРаботаПриИзмененииНаСервереВернутьТариф(Работа) 
    Возврат Работа.ТарифОсновной; 
КонецФункции 

&НаСервере 
Функция РаботыРаботаПриИзмененииНаСервереВернутьЗначениеТарифа(Тариф) 
    Возврат Тариф.Значение; 
КонецФункции 

&НаКлиенте 
Процедура РаботыРаботаПриИзменении(Элемент) 
    ТекущаяСтрока = Элементы.Работы.ТекущиеДанные; 
    Если НЕ ТекущаяСтрока.Работа.Пустая() Тогда 
        ТекущаяСтрока.Тариф = РаботыРаботаПриИзмененииНаСервереВернутьТариф(ТекущаяСтрока.Работа); 
        ТекущаяСтрока.ЗначениеТарифа = РаботыРаботаПриИзмененииНаСервереВернутьЗначениеТарифа(ТекущаяСтрока.Тариф); 
    КонецЕсли;
КонецПроцедуры

При выполнении этого кода значение тарифа (число) на форме отображается отлично, а вот ссылочный реквизит Тариф остается пустым. Почему так происходит? Выясним причину.

Оптимизация серверных вызовов: «Закон трех строк»

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

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

Оптимизированный вариант кода выглядит так:


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

&НаКлиенте
Процедура РаботыРаботаПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Работы.ТекущиеДанные;
    
    Если ТекущаяСтрока <> Неопределено И ЗначениеЗаполнено(ТекущаяСтрока.Работа) Тогда
        // Передаем строку на сервер одним вызовом
        ЗаполнитьДанныеТарифаНаСервере(ТекущаяСтрока);
    КонецЕсли;
КонецПроцедуры

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

Почему реквизит остается пустым на форме?

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

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

Альтернативный вариант: ОбработкаВыбора

В сложных сценариях, когда стандартное событие ПриИзменении перегружено типовой логикой или перекрывается расширениями, логику подстановки данных можно перенести в событие ОбработкаВыбора поля ввода Работа.

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

← На главную