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

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет
← На главную

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

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

Использование Построителя отчета для создания отборов

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

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


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

ПостроительОтчета.Текст = ТекстЗапроса;
ПостроительОтчета.ЗаполнитьНастройки();

Обратите внимание на использование фигурных скобок {} в тексте запроса. Это специальный синтаксис ПостроителяОтчета. Конструкция {ГДЕ ...} указывает построителю, в какое место запроса нужно подставить условия, выбранные пользователем в табличном поле на форме. Если пользователь не выберет ни одного фильтра, построитель просто проигнорирует эту секцию, и запрос выполнится целиком.

Решение проблемы с объединением строк неограниченной длины

Часто в отчетах требуется выводить комментарии или текстовые описания объектов. В языке запросов 1С существует ограничение: нельзя использовать поля с типом Строка (неограниченной длины) в операциях ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ. Если мы попытаемся объединить выборку из регистра бухгалтерии с чем-то еще, и в обеих частях будет поле Комментарий, система выдаст ошибку.

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


ВЫБРАТЬ
    ХозрасчетныйОстатки.Субконто2 КАК Документ,
    ПОДСТРОКА(ХозрасчетныйОстатки.Субконто2.Комментарий, 1, 1000) КАК Комментарий
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(...) КАК ХозрасчетныйОстатки
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    ДругаяТаблица.Ссылка,
    ПОДСТРОКА(ДругаяТаблица.Комментарий, 1, 1000)
ИЗ
    Документ.РеализацияТоваровУслуг КАК ДругаяТаблица

Использование ПОДСТРОКА(Поле, 1, 1000) превращает неограниченную строку в строку длиной 1000 символов, что позволяет успешно выполнить ОБЪЕДИНИТЬ.

Корректная работа с ЛЕВОЕ СОЕДИНЕНИЕ и дополнительными реквизитами

Типичная ошибка при получении данных из регистра сведений ЗначенияСвойствОбъектов — неправильное наложение фильтра по свойству. Рассмотрим пример, когда мы хотим получить значение конкретного доп. реквизита (например, "Контрагент") для документа.

Если мы напишем условие по свойству в секции ГДЕ, то документы, у которых этот реквизит не заполнен, просто исчезнут из результата отчета. Это происходит потому, что условие ГДЕ ЗначенияСвойствОбъектов.Свойство = &Свойство фактически превращает ЛЕВОЕ СОЕДИНЕНИЕ во ВНУТРЕННЕЕ, так как для отсутствующих записей значение свойства будет NULL, а NULL не равен нашему параметру.

Разберем, как сделать правильно. Условие по конкретному свойству нужно переносить непосредственно в условие связи ПО:


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

В этом случае система сначала найдет записи в регистре сведений, соответствующие нужному объекту и нужному свойству, а затем «приклеит» их к основной таблице. Если записи нет — в поле Значение будет NULL, который мы красиво обработаем функцией ЕСТЬNULL.

Вывод данных в фиксированный макет вручную

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


// 1. Выполняем построитель с учетом установленных пользователем отборов
ПостроительОтчета.Выполнить();
РезультатЗапроса = ПостроительОтчета.Результат;

// 2. Получаем выборку
Выборка = РезультатЗапроса.Выбрать();

// 3. Работаем с макетом
Макет = ПолучитьМакет("МойМакет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

ТабДок = Новый ТабличныйДокумент;
ТабДок.Вывести(ОбластьШапка);

Пока Выборка.Следующий() Цикл
    // Заполняем параметры области из полей выборки
    ОбластьСтрока.Параметры.Заполнить(Выборка);
    
    // Здесь можно добавить доп. логику, которую сложно реализовать в запросе
    Если Выборка.Остаток < 0 Тогда
        ОбластьСтрока.Параметры.Комментарий = "Внимание: Отрицательный остаток!";
    КонецЕсли;
    
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

ТабДок.Показать("Отчет по остаткам");

Использование метода ПостроительОтчета.Выполнить() возвращает объект РезультатЗапроса, в котором уже учтены все фильтры, наложенные пользователем через форму. Это позволяет нам пользоваться всеми преимуществами динамических отборов, сохраняя полный контроль над внешним видом печатной формы.

Передача параметров в построитель

Важно помнить, что если в тексте запроса используются параметры (например, &НаДату или &Счета), их нужно передать в построитель до начала выполнения. Рассмотрим подробнее способ управления параметрами:


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

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

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

← На главную