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