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