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