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