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

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

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

Однако стандартный подход «записать в реквизит объекта» не всегда срабатывает: в момент формирования отчета реквизит в модуле объекта оказывается пустым, хотя на форме он был заполнен. В этой статье мы подробно разберем, почему так происходит и как правильно настроить отчет, чтобы данные передавались без потерь.

Разбор проблемы: почему данные «теряются»?

Проанализируем механизм работы управляемых форм в 1С. Когда вы открываете форму отчета, платформа создает в памяти экземпляр объекта. Однако при нажатии кнопки «Сформировать» во многих случаях происходит создание нового экземпляра объекта отчета на сервере. Если данные в форме не были должным образом синхронизированы с реквизитами этого нового объекта, процедура ПриКомпоновкеРезультата увидит только значения по умолчанию.

Рассмотрим типичную ошибку. Программист создает реквизит в модуле отчета (например, АдресХранилища) и пытается заполнить его через серверную процедуру формы:


&НаСервере
Процедура УстановитьРеквизитОтчета(Адрес)
    ОтчетОбъект = РеквизитФормыВЗначение("Отчет");       
    ОтчетОбъект.АдресХранилища = Адрес;     
    // Ошибка: здесь мы изменили локальную копию объекта, но не вернули ее в форму
КонецПроцедуры

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

Решение 1: Правильная типизация основного реквизита формы

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

Пошаговое решение:

  1. Откроем форму отчета в конфигураторе.
  2. Перейдем на закладку «Реквизиты».
  3. Найдем реквизит Отчет (он выделен жирным шрифтом).
  4. В поле «Тип» нажмем кнопку выбора и выберем конкретный отчет из списка (например, ВнешнийОтчет.МойОтчет или Отчет.НазваниеОтчета).

После этого действия в дереве реквизитов формы у объекта Отчет появятся все ваши дополнительные реквизиты. Теперь платформа знает, что при каждом серверном вызове и при нажатии кнопки формирования необходимо «пробрасывать» значения этих реквизитов из формы в объект.

Решение 2: Передача данных через параметры СКД

Рассмотрим более «профессиональный» с точки зрения архитектуры СКД способ. Вместо создания реквизитов в самом объекте отчета, мы можем использовать параметры схемы компоновки данных. Это избавляет от проблем с типизацией формы и синхронизацией объектов.

Алгоритм действий:

  1. В схеме компоновки данных (СКД) на закладке «Параметры» добавим новый параметр, например, пАдресХранилища.
  2. Снимем у него галочку «Включать в доступные поля», чтобы пользователь не видел его в настройках.
  3. В форме отчета перед формированием установим значение этого параметра:

&НаСервере
Процедура УстановитьПараметрСКД(Адрес)
    Параметр = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("пАдресХранилища");
    Если Параметр <> Неопределено Тогда
        Параметр.Значение = Адрес;
        Параметр.Использование = Истина;
    КонецЕсли;
КонецПроцедуры

В процедуре ПриКомпоновкеРезультата в модуле объекта мы сможем легко прочитать это значение:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    АдресФайла = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("пАдресХранилища").Значение;
    Если ЗначениеЗаполнено(АдресФайла) Тогда
        // Обрабатываем данные из хранилища
    КонецЕсли;
КонецПроцедуры

Важные нюансы работы с временным хранилищем

Проанализируем ситуацию, когда отчет формируется в фоновом задании (что является стандартом для современных конфигураций на базе БСП). Если вы поместили файл во временное хранилище в модуле формы, адрес этого хранилища «живет» до тех пор, пока живет форма. Однако фоновое задание — это другой сеанс на сервере.

Чтобы адрес хранилища был доступен в модуле объекта (особенно при фоновом формировании), при вызове метода ПоместитьВоВременноеХранилище обязательно передавайте вторым параметром уникальный идентификатор формы: ЭтаФорма.УникальныйИдентификатор. Это гарантирует, что данные не будут удалены преждевременно и будут доступны серверному коду модуля объекта.

Использование ДополнительныхСвойств

Иногда возникает соблазн использовать структуру ДополнительныеСвойства объекта. Стоит помнить, что это свойство не сериализуется автоматически между формой и объектом при стандартном формировании отчета платформой. Если вы запишете туда данные в процедуре ПриСозданииНаСервере, то в ПриКомпоновкеРезультата при нажатии кнопки «Сформировать» они, скорее всего, будут утеряны, так как объект будет пересоздан на основе данных формы, а форма «знает» только о реквизитах, но не о ДополнительныхСвойствах.

Резюмируем: для стабильной передачи данных из формы в модуль отчета всегда проверяйте Тип основного реквизита формы Отчет. Он должен указывать на конкретный объект метаданных. Если же вы хотите следовать лучшим практикам 1С, используйте передачу значений через параметры КомпоновщикаНастроек, так как это штатный механизм СКД, работающий максимально предсказуемо.

← На главную