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