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