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