Как программно вызвать действие кнопки документа из внешней обработки в 1С

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

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

Ограничения платформы и распространенные заблуждения

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

Кроме того, код формы обычно выполняется в контексте клиентского сеанса (директивы &НаКлиенте и &НаКлиентеНаСервереБезКонтекста). Если форма документа не открыта, ее визуального контекста просто не существует. Пытаться открыть сотни форм документов в цикле ради нажатия экранной кнопки неэффективно и приводит к зависанию интерфейса.

Вариант 1. Вынос логики в Модуль объекта или Модуль менеджера (архитектурный стандарт)

Рассмотрим самое правильное и надежное решение с точки зрения стандартов разработки 1С. Бизнес-логика выполнения операций не должна быть заперта внутри модуля формы. Модуль формы предназначен только для взаимодействия с пользователем, а вся прикладная работа с данными должна находиться на сервере.

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

  1. Открываем конфигуратор и переходим в модуль формы документа, где расположен обработчик нужной кнопки.
  2. Анализируем код обработчика: исключаем из него чисто интерфейсные вызовы, такие как Предупреждение, ПоказатьВопрос или Вопрос.
  3. Переносим чистый алгоритм обработки данных в Модуль объекта документа и объявляем процедуру с ключевым словом Экспорт.

Посмотрим на пример экспортной процедуры в модуле объекта документа:


// В модуле объекта Документ.ЗаказКлиента
Процедура ВыполнитьРасчетИЗаполнение() Экспорт
    
    // Алгоритм пересчета табличной части или заполнения реквизитов
    Для Каждого СтрТЧ Из Товары Цикл
        СтрТЧ.Сумма = СтрТЧ.Количество * СтрТЧ.Цена;
    КонецЦикла;
    
КонецПроцедуры

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


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

Если для выполнения действия модификация реквизитов объекта целиком не требуется (например, отправляется запрос во внешнюю систему или рассчитываются служебные движения), процедуру можно вынести в Модуль менеджера документа, передавая ссылку параметром. Это избавит платформу от необходимости создавать тяжелый объект в памяти.

Вариант 2. Вызов экспортной процедуры открытой формы через параметры

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

Рассмотрим подробнее сценарий с передачей параметра при открытии:

  1. В обработчике нажатия кнопки на форме нашей обработки получаем ссылку на документ из текущей строки табличной части.
  2. Формируем структуру параметров, куда передаем ключ документа и флаг необходимости автовыполнения действия.
  3. В модуле формы целевого документа перехватываем этот параметр в событии ПриОткрытии или ПриСозданииНаСервере.

Посмотрим на код вызова формы из внешней обработки:


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

В модуле формы самого документа (например, через расширение конфигурации) обрабатываем переданный параметр:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    Если Параметры.Свойство("АвтоВыполнениеКнопки") И Параметры.АвтоВыполнениеКнопки Тогда
        // Вызываем штатную процедуру нажатия нужной кнопки
        НажатиеКнопкиВыполнить();
    КонецЕсли;
    
КонецПроцедуры

Вариант 3. Использование механизма оповещений

Разберем еще один подход, когда форма документа уже может быть открыта пользователем на рабочем столе. Чтобы запустить на ней действие без повторного переоткрытия, используется штатный механизм оповещений платформы 1С.

Из внешней обработки отправляется оповещение с помощью клиентского метода Оповестить:


&НаКлиенте
Процедура ОповеститьФормуДокумента(СсылкаНаДокумент)
    
    ПараметрыОповещения = Новый Структура("Ссылка", СсылкаНаДокумент);
    Оповестить("ВыполнитьДействиеКнопки", ПараметрыОповещения, "ОбработкаСписка");
    
КонецПроцедуры

А в форме документа задействуется обработчик ОбработкаОповещения:


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

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

← На главную