При разработке на управляемых формах 1С мы часто сталкиваемся с задачей: при изменении одного реквизита в табличной части документа необходимо автоматически заполнить связанные зависимые реквизиты в этой же строке. На первый взгляд задача кажется тривиальной, но иногда возникает интересная аномалия — в отладчике мы видим, что значение присвоено корректно, а на форме поле остается абсолютно пустым. Давайте подробно разберем такую ситуацию, проанализируем частые ошибки и найдем правильные пути решения.
Рассмотрим конкретный пример. У нас есть документ с табличной частью Работы. В ней содержатся три реквизита:
Работы).ТарифыРабот).У элемента справочника Работы есть реквизит ТарифОсновной, из которого мы должны программно подтянуть сам тариф и его числовое значение при выборе работы в строке табличной части.
Посмотрим на исходный код, который часто пишут начинающие разработчики:
&НаСервере
Функция РаботыРаботаПриИзмененииНаСервереВернутьТариф(Работа)
Возврат Работа.ТарифОсновной;
КонецФункции
&НаСервере
Функция РаботыРаботаПриИзмененииНаСервереВернутьЗначениеТарифа(Тариф)
Возврат Тариф.Значение;
КонецФункции
&НаКлиенте
Процедура РаботыРаботаПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Работы.ТекущиеДанные;
Если НЕ ТекущаяСтрока.Работа.Пустая() Тогда
ТекущаяСтрока.Тариф = РаботыРаботаПриИзмененииНаСервереВернутьТариф(ТекущаяСтрока.Работа);
ТекущаяСтрока.ЗначениеТарифа = РаботыРаботаПриИзмененииНаСервереВернутьЗначениеТарифа(ТекущаяСтрока.Тариф);
КонецЕсли;
КонецПроцедуры
При выполнении этого кода значение тарифа (число) на форме отображается отлично, а вот ссылочный реквизит Тариф остается пустым. Почему так происходит? Выясним причину.
Первое, что бросается в глаза в приведенном выше коде — это неэффективное использование клиент-серверного взаимодействия. Из клиентской процедуры ПриИзменении совершается два последовательных вызова сервера для получения данных. Это нарушает правила оптимизации, так как каждый серверный вызов несет накладные расходы на передачу контекста и сетевой трафик.
Давайте перепишем код более профессионально. Нам нужно передать всю структуру текущей строки на сервер один раз, там модифицировать ее и вернуть на клиент. В управляемых формах объекты типа ДанныеФормыСтруктура (которым является текущая строка табличной части) можно изменять прямо внутри серверной процедуры.
Оптимизированный вариант кода выглядит так:
&НаСервере
Процедура ЗаполнитьДанныеТарифаНаСервере(СтрокаТаблицы)
// Получаем связанные данные через точку на сервере
СтрокаТаблицы.Тариф = СтрокаТаблицы.Работа.ТарифОсновной;
СтрокаТаблицы.ЗначениеТарифа = СтрокаТаблицы.Тариф.Значение;
КонецПроцедуры
&НаКлиенте
Процедура РаботыРаботаПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Работы.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено И ЗначениеЗаполнено(ТекущаяСтрока.Работа) Тогда
// Передаем строку на сервер одним вызовом
ЗаполнитьДанныеТарифаНаСервере(ТекущаяСтрока);
КонецЕсли;
КонецПроцедуры
Такой подход не только ускоряет работу программы, но и снижает риск рассинхронизации данных между клиентом и сервером.
Даже после оптимизации кода реквизит может упорно не появляться на форме. Если в отладчике в переменной ТекущаяСтрока.Тариф находится корректная ссылка, а пользователь видит пустое поле, проанализируем следующие настройки платформы:
Тариф (или элемента формы) настроена связь параметров выбора (например, тариф фильтруется по определенному владельцу или организации), платформа 1С строго проверяет программно присваиваемое значение на соответствие этим условиям. Если программно подтянутый тариф не удовлетворяет условию связи параметров выбора, платформа визуально очищает это поле. Проверьте свойства элемента формы и реквизита объекта!Очищать значение при изменении связанных полей. Если оно активировано, платформа может принудительно стирать ваш тариф в процессе отработки стандартных обработчиков.&После, сначала отрабатывает типовой код конфигурации, а затем ваш. Возможно, в типовом коде есть алгоритмы, которые конфликтуют с вашим заполнением или переопределяют поведение формы.В сложных сценариях, когда стандартное событие ПриИзменении перегружено типовой логикой или перекрывается расширениями, логику подстановки данных можно перенести в событие ОбработкаВыбора поля ввода Работа.
Событие ОбработкаВыбора срабатывает на клиенте в момент, когда пользователь выбрал значение из выпадающего списка или формы выбора, но данные еще не были окончательно помещены в реквизит. Это позволяет нам перехватить выбранное значение, обратиться к серверу и сформировать нужный пакет данных для заполнения строки, избегая многих коллизий с внутренними проверками управляемой формы.