Почему не сохраняется значение реквизита внешнего отчета при формировании и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Разберем причину: жизненный цикл внешнего объекта

Основная причина проблемы заключается в специфике работы с внешними файлами (.erf для отчетов и .epf для обработок). Когда мы вызываем команду открытия внешнего отчета, система выполняет следующие действия:

  1. Создает экземпляр объекта из двоичных данных файла.
  2. Инициализирует форму.
  3. При вызове метода ОткрытьФорму или программном обращении к внешней форме через МенеджерВнешнихОтчетов, система может создать новый экземпляр объекта.

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

Способ 1: Передача параметров через структуру при открытии формы

Это наиболее корректный путь, если мы хотим передать данные (например, ссылку на документ-основание) в открываемый отчет. Рассмотрим по шагам, как это реализовать в коде команды.

Вместо того чтобы просто присваивать значение реквизиту Отчет.Документ на клиенте, мы упаковываем все необходимые данные в структуру параметров и передаем их при открытии. Посмотрим на пример правильной реализации:


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    
    // Подготавливаем параметры для открытия формы
    ПараметрыОткрытия = Новый Структура;
    
    // Передаем ссылку на выбранный документ (например, первый из массива)
    ПараметрыОткрытия.Вставить("ДокументСсылка", ОбъектыНазначенияМассив[0]);
    
    // Можно сразу дать команду на формирование отчета
    ПараметрыОткрытия.Вставить("СформироватьПриОткрытии", Истина);
    
    // Указываем путь к форме внешнего отчета
    // Используем ЭтаФорма.ИмяФормы или явный путь
    ОткрытьФорму("ВнешнийОтчет.ИмяВашегоОтчета.Форма.ФормаОтчета", ПараметрыОткрытия);
    
КонецПроцедуры

После этого в модуле формы отчета в процедуре ПриСозданииНаСервере нам необходимо принять этот параметр и записать его в реквизит отчета, чтобы он стал доступен серверному контексту модуля объекта:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("ДокументСсылка") Тогда
        Отчет.СсылкаНаДок = Параметры.ДокументСсылка;
    КонецЕсли;
    
КонецПроцедуры

Способ 2: Использование параметров СКД (рекомендуемый)

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

Выясним, как сделать это профессионально:

  1. Откройте схему компоновки данных (Макет СКД).
  2. На закладке Параметры создайте новый параметр, например, П_ДокументСсылка с типом нужного документа.
  3. В запросе на закладке Наборы данных используйте этот параметр: ГДЕ Ссылка = &П_ДокументСсылка.
  4. В модуле формы передайте значение в настройки компоновщика.

Пример программной установки параметра в компоновщике настроек:


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

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

Способ 3: Работа через Временное хранилище

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

  1. На стороне формы (откуда вызываем отчет) помещаем данные в хранилище: Адрес = ПоместитьВоВременноеХранилище(МояТаблица, ЭтаФорма.УникальныйИдентификатор);
  2. Передаем Адрес как параметр при открытии формы отчета.
  3. В модуле объекта отчета (в процедуре ПриКомпоновкеРезультата) извлекаем данные: Данные = ПолучитьИзВременногоХранилища(АдресПараметра);

Важные нюансы и типичные ошибки

Разберем еще несколько моментов, которые часто путают разработчиков:

Ошибка синхронизации: Помните, что Отчет в модуле формы — это ДанныеФормыСтруктура. А ЭтотОбъект в модуле объекта — это сам программный объект. В типовых конфигурациях при нажатии кнопки «Сформировать» на форме, платформа автоматически сериализует данные формы в объект. Но если вы программно создаете объект в коде (например, через ВнешниеОтчеты.Создать(...)), это будет совершенно другой экземпляр с пустыми реквизитами.

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

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

← На главную