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