Как правильно вызвать экспортную функцию модуля объекта из формы списка в 1С

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

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

Проблема контекста и доступа к методам модуля объекта

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

Разберем основные способы реализации этой задачи, двигаясь от простых к наиболее правильным с точки зрения производительности системы.

Способ 1. Использование метода ПолучитьОбъект()

Самый очевидный способ — это получение ссылки на текущую строку списка и преобразование её в объект. Рассмотрим, как это выглядит в коде серверной процедуры формы списка:


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

Важное предостережение: Метод ПолучитьОбъект() является крайне ресурсоемким. При его вызове система считывает из базы данных абсолютно все реквизиты объекта и все его табличные части. Если ваша экспортная функция использует только один-два реквизита, такая операция будет избыточной. Проанализируем ситуацию: если в списке 1000 строк и вы решите вызвать этот метод в цикле, производительность сервера резко упадет.

Способ 2. Ошибка использования РеквизитФормыВЗначение в списках

Часто начинающие разработчики пытаются применить метод РеквизитФормыВЗначение("Объект"), который отлично работает в форме элемента. Однако в форме списка этот метод вызовет исключение, так как реквизита Объект там просто не существует. Выясним причину: в форме списка основным реквизитом является Список (тип ДинамическийСписок), который не имеет прямого отображения в объект метаданных в оперативной памяти.

Способ 3. Оптимальное решение: Модуль менеджера

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

Посмотрим на пример реализации в модуле менеджера справочника или документа:


// В модуле менеджера
Функция РассчитатьПоказатель(СсылкаНаОбъект) Экспорт
    // Логика расчета без получения тяжелого объекта
    Возврат Результат;
КонецФункции

Теперь обратимся к этой функции из модуля формы списка:


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

Этот метод позволяет избежать лишних чтений табличных частей и экономит память сервера.

Специфика программного проведения из формы списка

Разберем ситуацию, когда из формы списка нужно провести документ. Попытка напрямую вызвать процедуру ОбработкаПроведения() из модуля объекта как обычную функцию — это грубая ошибка. Выясним, почему: при таком вызове не открывается транзакция записи, не блокируются данные, и движения документа не будут сформированы корректно.

Правильный алгоритм проведения выглядит так:

  1. Получаем объект документа через ссылку.
  2. Используем стандартный метод Записать() с параметром РежимЗаписиДокумента.Проведение.

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

Внутри модуля объекта в процедуре ОбработкаПроведения мы сможем проанализировать структуру ДополнительныеСвойства и изменить логику проведения соответствующим образом.

Групповая обработка строк списка

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


&НаКлиенте
Процедура КомандаГрупповаяОбработка(Команда)
    МассивСсылок = Элементы.Список.ВыделенныеСтроки;
    Если МассивСсылок.Количество() > 0 Тогда
        ВыполнитьДействиеДляМассиваНаСервере(МассивСсылок);
    КонецЕсли;
КонецПроцедуры

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

Итоги и рекомендации

Подведем итог нашему исследованию. При вызове экспортных функций из формы списка придерживайтесь следующих правил:

  1. Соблюдайте контекст: Обращение к модулю объекта возможно только на сервере. Всегда используйте связку &НаКлиенте -> &НаСервере.
  2. Экономьте ресурсы: Если функцию можно перенести в Модуль менеджера и передать туда только ссылку — сделайте это. Это золотой стандарт разработки на 1С.
  3. Работайте с транзакциями: Если ваша цель — проведение документа, используйте метод Записать(РежимЗаписиДокумента.Проведение), а не прямой вызов обработчиков событий.
  4. Используйте Общие модули: Если логика функции универсальна и требуется в разных местах системы, выносите её в общий модуль. Это упростит поддержку кода и предотвратит дублирование.

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

← На главную