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