При разработке отчетов на обычных формах в 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С (Обычные формы) объекты передаются по ссылке, поэтому изменения настроек на второй форме сразу отразятся в основном объекте.
Подведем итог: Работа с ПостроителемОтчета — это отличный компромисс между жестким кодом и гибкостью СКД. Мы рассмотрели, как выводить фильтры, как бороться с ограничениями типов данных в запросах и как правильно выводить результат в произвольный макет. Следуя этим инструкциям, вы сможете создавать профессиональные и удобные отчеты даже в старых конфигурациях на обычных формах.