Как правильно открыть форму выбора с отбором и добавить значение в табличную часть 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке логики заполнения табличной части документа разработчики часто сталкиваются с необходимостью организовать выбор подчиненных элементов (например, единиц измерения или характеристик с отбором по выбранной номенклатуре). Попытка переопределить стандартное поведение через СтандартнаяОбработка = Ложь нередко приводит к нагромождению избыточного и некорректного кода: попыткам открыть форму на сервере, использованию устаревших модальных окон или неправильному обращению к элементам интерфейса вместо коллекции данных. Рассмотрим подробнее типичные ошибки и разберем правильные варианты реализации этой задачи в управляемых формах 1С.

Анализ типичных ошибок при программном выборе

Выясним причину, почему код с переопределением обработчиков выбора часто перестает работать или ведет себя непредсказуемо:

  1. Попытка открытия формы на сервере. Вызовы методов ПолучитьФорму, Открыть или ОткрытьМодально в серверном контексте (директивы &НаСервере) технически недопустимы. В управляемом приложении все визуальные действия, показ диалогов и окон выбора должны выполняться строго на клиенте (&НаКлиенте).
  2. Использование устаревшего модального режима. В современных конфигурациях свойство конфигурации «Режим использования модальности» отключено (установлено в значение «Не использовать»). Попытка вызвать метод ОткрытьМодально() приводит к аварийному завершению сеанса с ошибкой времени выполнения.
  3. Ошибочное использование метода ДобавитьСтроку(). Метод элемента интерфейса Элементы.ИмяТаблицы.ДобавитьСтроку() служит исключительно для интерактивного создания новой строки пользователем и возвращает Неопределено. Конструкции вида НоваяСтрока = Элементы.Таблица.ДобавитьСтроку(); НоваяСтрока.Реквизит = Значение; не работают, так как переменная НоваяСтрока не содержит ссылки на объект данных.
  4. Сброс контекста при установке СтандартнаяОбработка = Ложь. Отключая стандартную обработку в событии ОбработкаВыбора, разработчик берет на себя ручную подстановку значения. Если при этом происходят хаотичные вызовы добавления строк или смещается фокус, свойство Элементы.Таблица.ТекущиеДанные возвращает не ту строку либо Неопределено.

Вариант 1. Настройка связей параметров выбора без написания кода (рекомендуемый)

Проанализируем самый лаконичный и надежный способ платформы 1С:Предприятие 8. Если реквизит подчинен владельцу (например, справочник ЕдиницыИзмерения подчинен справочнику Номенклатура), отбор можно настроить в дереве метаданных конфигуратора:

  1. Откроем свойства реквизита табличной части (или реквизита документа).
  2. Найдем свойство Связи параметров выбора.
  3. Добавим связь: укажем имя параметра отбора Отбор.Владелец и выберем реквизит-источник (например, реквизит шапки Объект.Номенклатура или колонку текущей строки Объект.Товары.Номенклатура).

В этом случае платформа автоматически откроет форму выбора с установленным отбором по владельцу и самостоятельно запишет выбранный элемент в строку табличной части. Программный код не требуется вовсе.

Вариант 2. Программная передача параметров выбора в событии НачалоВыбора

Если отбор должен формироваться динамически в зависимости от условий, но мы хотим сохранить стандартный механизм открытия окна и помещения значения в строку, разберем событие НачалоВыбора у элемента поля ввода. При этом не следует устанавливать СтандартнаяОбработка = Ложь.

Посмотрим на пример обработчика:


&НаКлиенте
Процедура ПолучателиЕдиницаИзмеренияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	// Создаем параметр отбора по владельцу
	ПараметрОтбора = Новый ПараметрВыбора("Отбор.Владелец", Объект.Номенклатура);
	
	// Помещаем его в массив параметров выбора элемента
	МассивПараметров = Новый Массив;
	МассивПараметров.Добавить(ПараметрОтбора);
	
	Элемент.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
	
КонецПроцедуры

В данном сценарии платформа применит сформированные параметры выбора, откроет стандартное окно справочника и сама заполнит реквизит текущей строки после выбора пользователем.

Вариант 3. Асинхронное открытие формы выбора через ОписаниеОповещения

Если требуется полностью перехватить выбор значения, открыть форму программно, выполнить дополнительные проверки и добавить данные в коллекцию формы, применим асинхронный паттерн с объектом ОписаниеОповещения.

Разберем по шагам реализацию клиентского кода:


&НаКлиенте
Процедура ОткрытьВыборЕдиницыИзмерения()
	
	// Формируем структуру параметров с нужными отборами
	СтруктураОтбора = Новый Структура;
	СтруктураОтбора.Вставить("Владелец", Объект.Номенклатура);
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("Отбор", СтруктураОтбора);
	ПараметрыФормы.Вставить("РежимВыбора", Истина);
	ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
	
	// Создаем описание оповещения для обработки результата
	ОповещениеОЗавершении = Новый ОписаниеОповещения("ПослеВыбораЕдиницы", ЭтотОбъект);
	
	// Открываем форму выбора без использования модальности
	ОткрытьФорму("Справочник.ЕдиницыИзмерения.ФормаВыбора", ПараметрыФормы, ЭтаФорма,,,, ОповещениеОЗавершении);
	
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЕдиницы(РезультатВыбора, ДополнительныеПараметры) Экспорт
	
	// Проверяем, выбрал ли пользователь значение или закрыл окно
	Если РезультатВыбора = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	// Добавляем строку напрямую в данные формы (коллекцию), а не через интерфейсный элемент
	НоваяСтрока = Объект.Получатели.Добавить();
	НоваяСтрока.ЕдиницаИзмерения = РезультатВыбора;
	
КонецПроцедуры

Обратим внимание: для программного манипулирования строками таблицы используется метод Добавить() у свойства данных Объект.ИмяТабличнойЧасти. Он возвращает объект типа ДанныеФормыЭлементКоллекции, чьи реквизиты можно сразу заполнять полученными данными.

Вариант 4. Автоматическое заполнение строк при изменении номенклатуры

Когда бизнес-требование заключается в том, чтобы после выбора номенклатуры строки формировались автоматически (например, подставлялись базовая единица измерения, характеристики или список контрагентов по умолчанию), интерактивные окна выбора единицы вообще не нужны.

Рассмотрим реализацию через серверную процедуру заполнения в обработчике ПриИзменении поля номенклатуры:


&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
	ЗаполнитьПолучателейНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПолучателейНаСервере()
	
	Если Не ЗначениеЗаполнено(Объект.Номенклатура) Тогда
		Возврат;
	КонецЕсли;
	
	// Очищаем предыдущие данные при смене номенклатуры
	Объект.Получатели.Очистить();
	
	// Добавляем новую строку и заполняем значениями по умолчанию
	НоваяСтрока = Объект.Получатели.Добавить();
	НоваяСтрока.ЕдиницаИзмерения = Объект.Номенклатура.БазоваяЕдиницаИзмерения;
	
КонецПроцедуры

Такой подход избавляет пользователя от лишних всплывающих диалоговых окон, исключает ошибки контекста выполнения и обеспечивает высокую скорость работы документа.

← На главную