Как передать параметры из формы настроек в модуль объекта отчета в 1С 8.3?

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

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

В этой статье мы подробно разберем, почему возникает популярная ошибка «Ожидается выражение "ВЫБРАТЬ"», почему реквизиты формы настроек «теряются» при обращении к ним из модуля объекта, и рассмотрим два надежных способа решения этой задачи.

Проанализируем сначала проблемную ситуацию, с которой столкнулся автор темы на форуме.

Анализ ошибки: почему возникает исключение «Ожидается выражение "ВЫБРАТЬ"»?

Разработчик написал в модуле объекта отчета следующий код:


Если ЭтотОбъект.Касса Тогда
    Запрос = Новый Запрос("ВЫБРАТЬ
                          |   ДенежныеСредстваНаличныеОбороты.Регистратор КАК ДокументПродажи,
                          |   ДенежныеСредстваНаличныеОбороты.СуммаПриход + ДенежныеСредстваНаличныеОбороты.СуммаРасход КАК СуммаОборотРЗ
                          |ИЗ
                          |   РегистрНакопления.ДенежныеСредстваНаличные.Обороты(&НП, &КП, Регистратор, Организация = &Организация) КАК ДенежныеСредстваНаличныеОбороты");
КонецЕсли;

Когда реквизит Касса располагался на основной форме отчета, этот код отрабатывал без нареканий. Но как только его перенесли на Форму настроек, система начала генерировать исключение: Произошла исключительная ошибка. Ожидается выражение "ВЫБРАТЬ".

Выясним причину этой ошибки по шагам:

  1. Форма настроек в управляемом приложении (особенно в типовых конфигурациях вроде «Управление торговлей 11», построенных на базе БСП) работает в собственном, изолированном контексте. Она напрямую не связана с экземпляром объекта отчета ЭтотОбъект, который создается на сервере в момент формирования данных.
  2. Когда пользователь устанавливает флажок на форме настроек, это значение записывается в Компоновщик настроек (в коллекцию пользовательских настроек), а не в физический реквизит объекта отчета.
  3. В результате в модуле объекта при обращении к свойству ЭтотОбъект.Касса платформа возвращает значение по умолчанию для типа Булево — Ложь.
  4. Условие Если ЭтотОбъект.Касса Тогда не выполняется, и инициализация переменной Запрос.Текст полностью пропускается. Свойство Текст остается пустой строкой.
  5. При последующем вызове метода Запрос.Выполнить() парсер платформы анализирует пустую строку и выдает синтаксическую ошибку, сообщая, что ожидалось ключевое слово ВЫБРАТЬ.

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

Способ 1. Использование параметров схемы компоновки данных (СКД)

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

Рассмотрим пошагово процесс настройки:

  1. Откроем основную схему компоновки данных (макет СКД) нашего отчета.
  2. Перейдем на вкладку Параметры.
  3. Добавим новый параметр с именем Касса и установим для него тип Булево.
  4. Снимем флажок в колонке Ограничение доступности, чтобы пользователь мог интерактивно управлять этим параметром.
  5. В нижней части окна настроек параметров найдем свойства элемента пользовательских настроек (значок «шестеренка») и установим флажок Включать в пользовательские настройки. Это автоматически выведет наш флажок на стандартную форму настроек отчета.

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

Применим следующий шаблон кода в модуле объекта:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Инициализируем значение по умолчанию
    ЗначениеКассы = Ложь;
    ИмяПараметра = "Касса";
    
    // 1. Сначала ищем значение в Пользовательских настройках (то, что изменил пользователь на форме)
    Для Каждого Элемент Из КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЗначениеПараметраКомпоновкиДанных") 
           И Элемент.Параметр = Новый ПараметрКомпоновкиДанных(ИмяПараметра) Тогда
            Если Элемент.Использование Тогда
                ЗначениеКассы = Элемент.Значение;
            КонецЕсли;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // 2. Если в пользовательских настройках параметр не найден, берем значение из основных настроек схемы
    Если Не ЗначениеЗаполнено(ЗначениеКассы) Тогда
        ПараметрНастройки = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяПараметра));
        Если ПараметрНастройки <> Неопределено И ПараметрНастройки.Использование Тогда
            ЗначениеКассы = ПараметрНастройки.Value; // Или .Значение в зависимости от контекста
        КонецЕсли;
    КонецЕсли;
    
    // 3. Используем полученное значение в логике построения запроса
    Если ЗначениеКассы Тогда
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   ДенежныеСредстваНаличныеОбороты.Регистратор КАК ДокументПродажи,
            |   ДенежныеСредстваНаличныеОбороты.СуммаПриход + ДенежныеСредстваНаличныеОбороты.СуммаРасход КАК СуммаОборотРЗ
            |ИЗ
            |   РегистрНакопления.ДенежныеСредстваНаличные.Обороты(&НП, &КП, Регистратор, Организация = &Организация) КАК ДенежныеСредстваНаличныеОбороты";
            
        // Здесь выполняется дальнейшая работа с запросом и вывод данных...
    КонецЕсли;

КонецПроцедуры

Преимущество этого метода: Полная совместимость со стандартными механизмами БСП и СКД. Нам не нужно программировать поведение элементов управления на форме, платформа берет эти задачи на себя.

Способ 2. Программная передача из кастомной формы настроек

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

Разберем этот процесс по шагам:

Шаг 1. Передача значения при закрытии формы настроек

В модуле кастомной формы настроек в обработчике закрытия или при нажатии кнопки «ОК / Применить» мы должны передать структуру с измененными параметрами обратно в вызывающую форму (основную форму отчета):


&НаКлиенте
Процедура КомандаОК(Команда)
    
    СтруктураПараметров = Новый Структура;
    СтруктураПараметров.Вставить("Касса", Отчет.Касса);
    
    // Закрываем форму настроек и передаем структуру параметров в качестве результата
    Закрыть(СтруктураПараметров);
    
КонецПроцедуры

Шаг 2. Принятие параметров в основной форме отчета

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


&НаКлиенте
Процедура ОткрытьНастройки(Команда)
    
    // Указываем обработчик, который примет возвращаемые параметры
    Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормыНастроек", ЭтотОбъект);
    ОткрытьФорму("Отчет.МойОтчет.Форма.ФормаНастроек", , ЭтотОбъект, , , , Оповещение);
    
КонецПроцедуры

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

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

Рекомендации разработчикам

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

← На главную