Как программно запустить обработчик события формы в 1С 8.3?

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

При автоматизации бизнес-процессов в среде «1С:Предприятие 8.3» разработчики часто сталкиваются со следующей проблемой: необходимо программно создать или заполнить документ (например, из внешней обработки или API), однако вся важная логика автоматического пересчета строк (цены, скидки, суммы, ставки НДС) «зашита» в модуле управляемой формы документа, конкретно — в обработчиках интерактивных событий, таких как ТоварыНоменклатураПриИзменении.

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

Почему нельзя просто вызвать обработчик события формы?

Стандартная процедура-обработчик интерактивного действия, например ТоварыНоменклатураПриИзменении(Элемент), по умолчанию объявляется в модуле формы без ключевого слова Экспорт. Это делает её абсолютно невидимой для внешнего программного кода.

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

Решение 1. Прямой вызов экспортной процедуры формы с активацией строки

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


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент) Экспорт
    // Код пересчета реквизитов строки табличной части
КонецПроцедуры

Теперь эту процедуру можно вызвать из внешнего кода, предварительно получив форму документа. Рассмотрим пример реализации:


ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДокумент);
ФормаДокумента = ОткрытьФорму("Документ.ЗаказКлиента.Форма.ФормаДокумента", ПараметрыФормы);

// Вызываем обработчик события, передавая элемент управления номенклатурой
ФормаДокумента.ТоварыНоменклатураПриИзменении(ФормаДокумента.Элементы.ТоварыНоменклатура);

Важный нюанс: внутри типовых обработчиков 1С практически всегда присутствует обращение к активной строке таблицы через конструкцию Элементы.Товары.ТекущиеДанные. Если мы просто вызовем процедуру, система не поймет, к какой именно строке применить изменения. Чтобы исправить это, перед вызовом процедуры необходимо программно активизировать нужную строку.

Разберем по шагам, как правильно перебрать строки и запустить расчет для каждой из них:


Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    // Шаг 1. Получаем уникальный идентификатор строки в контексте данных формы
    ИдентификаторСтроки = СтрокаТЧ.ПолучитьИдентификатор();
    
    // Шаг 2. Делаем строку активной на форме документа
    ФормаДокумента.Элементы.Товары.ТекущаяСтрока = ИдентификаторСтроки;
    
    // Шаг 3. Теперь Элементы.Товары.ТекущиеДанные указывают на СтрокаТЧ. Вызываем расчет:
    ФормаДокумента.ТоварыНоменклатураПриИзменении(Неопределено);
КонецЦикла;

Решение 2. Трюк с методом «ОповеститьОВыборе» (симуляция выбора пользователя)

Что делать, если конфигурация находится на строгой поддержке, вносить изменения нельзя, а процедура в модуле формы не объявлена как экспортная? В этом случае на помощь приходит классический обходной путь платформы «1С» — симуляция интерактивного ввода через метод ОповеститьОВыборе.

Этот метод заставляет платформу поверить, что пользователь самостоятельно открыл форму выбора и нажал кнопку «Выбрать». При этом система автоматически записывает значение в реквизит и запускает связанный с ним неэкспортный обработчик ПриИзменении.

Проанализируем алгоритм работы этого трюка:

  1. Из вашей обработки открывается форма документа.
  2. Для вспомогательной формы-пустышки (или формы вашей собственной обработки) свойство ВладелецФормы временно переопределяется. Ему назначается целевой элемент управления основной формы (например, ФормаДокумента.Элементы.ТоварыНоменклатура).
  3. На вспомогательной форме вызывается метод ОповеститьОВыборе(ВыбранноеЗначениеНоменклатуры).
  4. Платформа перехватывает это оповещение, записывает переданное значение в строку и принудительно выполняет закрытую процедуру ТоварыНоменклатураПриИзменении.

Решение 3. Использование расширений конфигурации (современный стандарт)

В версиях платформы 8.3.6 и выше проблему закрытой конфигурации можно легко обойти без сомнительных трюков. Для этого используется механизм расширений конфигурации:

Решение 4. Архитектурно правильный перенос расчетов в Модуль объекта

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

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

Правильное решение проблемы по шагам:

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

Решение 5. Использование готового API БСП

Если разработка ведется в типовой конфигурации (например, 1С:ERP, 1С:Управление торговлей 11 или 1С:ЗУП 3), обратите внимание на функции общих модулей Библиотеки стандартных подсистем (БСП). В них уже реализованы все необходимые механизмы автоматических расчетов.

Изучите структуру типовых модулей, таких как ОбработкаТабличнойЧастиКлиентСервер или серверные процедуры заполнения цен и расчетов. Использование стандартного API БСП позволит вашему коду оставаться работоспособным даже после масштабных обновлений конфигурации.

← На главную