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