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