Почему пустеет Универсальный отчет при отборе по типу регистратора и как это исправить

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При работе в старых редакциях конфигураций, таких как 1С:Управление производственным предприятием 1.3 или Комплексная автоматизация 1.1, программисты часто сталкиваются с необходимостью доработки стандартного «Универсального отчета». Одна из типичных задач — ограничить данные отчета конкретным типом документа (например, только «Требованиями-накладными»). Однако простая вставка условия ССЫЛКА в текст запроса часто приводит к тому, что отчет становится абсолютно пустым, как только пользователь пытается добавить группировку или дополнительный отбор в интерфейсе. Рассмотрим, почему это происходит и как правильно решить задачу.

Анализ проблемы: ловушка жесткого условия ГДЕ

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


ГДЕ
    ИсточникДанных.Регистратор ССЫЛКА Документ.ТребованиеНакладная

На первый взгляд, это логичное решение. Однако «Универсальный отчет» построен на базе механизма ПостроительОтчета. Этот механизм динамически перестраивает текст запроса в зависимости от настроек, выбранных пользователем (группировки, поля, отборы). Когда мы используем виртуальную таблицу ОстаткиИОбороты, система ожидает определенную структуру данных для корректного расчета итогов.

Главная причина «пустого отчета» заключается в том, что в виртуальной таблице ОстаткиИОбороты записи, отвечающие за начальные и конечные остатки, не имеют конкретного регистратора (поле Регистратор для них может быть неопределено или содержать пустую ссылку в контексте итоговых записей). Накладывая жесткое условие ССЫЛКА Документ.ТребованиеНакладная в секции ГДЕ, мы буквально заставляем систему выкинуть из результата все записи, которые не являются этим документом. В итоге записи с остатками исчезают, а если по выбранной номенклатуре не было движений именно этим типом документа в выбранном периоде, результат запроса будет полностью пустым.

Шаг 1: Диагностика через получение текста запроса

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

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

УниверсальныйОтчет.ПостроительОтчета.ПолучитьЗапрос().Текст

Именно этот метод позволяет увидеть, куда построитель вставил ваши условия и как он преобразовал секции ИТОГИ и СГРУППИРОВАТЬ ПО. Часто после такого анализа становится очевидно, что жесткое условие ГДЕ конфликтует с вложенными запросами, которые генерирует построитель для расчета остатков.

Шаг 2: Правильное использование необязательных условий

Чтобы отчет работал корректно и не «ломался» при добавлении группировок, условия нужно выносить в специальные блоки фигурных скобок {}. Это дает понять Построителю, что данные условия являются необязательными и должны применяться гибко.

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


ИЗ
    РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(&ДатаНач, &ДатаКон, Регистратор, , ) КАК ИсточникДанных
{ГДЕ
    ИсточникДанных.Регистратор.* КАК Регистратор,
    ИсточникДанных.Номенклатура.* КАК Номенклатура}

Если мы хотим, чтобы тип регистратора был ограничен программно, но при этом отчет не пустел, у нас есть два пути:

  1. Использование параметров виртуальной таблицы. Это наиболее производительный метод. Однако для таблицы ОстаткиИОбороты нельзя напрямую отфильтровать регистратор в параметрах самой таблицы (в отличие от таблицы Обороты).
  2. Использование условий в секции построителя. Вместо жесткого ГДЕ в основном теле запроса, мы убеждаемся, что поле Регистратор доступно в блоке {ГДЕ ...}.

Шаг 3: Настройка отбора без добавления в группировки

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

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

При такой настройке Построитель отчета сам добавит в SQL-запрос условие проверки типа, но при этом корректно обработает итоги. Поскольку поле «Регистратор» добавлено только в отбор, но не выбрано в списке «Группировки строк», в самом отчете детальных записей по документам не будет — вы увидите только агрегированные данные по номенклатуре или складам, но только те, которые были сформированы выбранным типом документа.

Программная установка фильтра по типу

Если вам нужно «намертво» зашить этот отбор в коде, чтобы пользователь не мог его снять, проанализируем пример кода, который можно вставить в процедуру УстановитьНачальныеНастройки:


// Находим поле Регистратор в доступных полях отбора
НовыйОтбор = УниверсальныйОтчет.ПостроительОтчета.Отбор.Добавить("Регистратор");
НовыйОтбор.Использование = Истина;
НовыйОтбор.ВидСравнения = ВидСравнения.ТипЗначания;
НовыйОтбор.Значение = Тип("ДокументСсылка.ТребованиеНакладная");

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

Резюме

Подводя итоги, отметим основные правила работы с Универсальным отчетом в УПП:

← На главную