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