Почему двоятся строки в отчете СКД при добавлении реквизитов и как это исправить?

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

При доработке типовых отчетов в 1С:Управление торговлей 11 (например, отчета по задолженности поставщикам или взаиморасчетам) разработчики часто сталкиваются с неприятным эффектом: пока отчет работает в базовом виде, группировки выводятся корректно, но стоит добавить через схему компоновки данных (СКД) пару дополнительных реквизитов (например, Поставщик и Поставщик.SWIFT из документа Заказ поставщику), как строки начинают задваиваться. В отчете на один и тот же документ система выводит две раздельные строки: в одной заполнены одни показатели, во второй — другие.

Разберем детально механизм возникновения этой проблемы и рассмотрим все способы ее решения.

Проанализируем причину появления дублей

В большинстве типовых отчетов по учету расчетов и взаиморасчетов итоговая выборка формируется не единым простым запросом, а конструкцией с несколькими объединениями — ОБЪЕДИНИТЬ ВСЕ, либо при помощи нескольких связанных наборов данных. Например, одна ветка запроса выбирает текущие остатки расчетов, а вторая — просроченную задолженность с разбивкой по интервалам времени.

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

  1. Поля добавлены не во все ветки объединения. Если добавить реквизиты только в первую таблицу запроса, то во второй таблице на их месте будет автоматически сформировано значение NULL. В результате СКД получает две независимые записи: в одной есть сумма остатка и заполненный реквизит, а во второй — сумма просрочки и NULL в новом реквизите. Свернуть такие строки отчет не может.
  2. Несовпадение псевдонимов полей. Достаточно допустить минимальную опечатку в имени поля в одной из веток (например, ПоставщикSWIFT в первой части и ПоставщикSwift или SWIFT во второй), чтобы платформа посчитала их абсолютно разными колонками. В этом случае в выборку попадают два разных поля, каждое из которых содержит NULL в противоположной ветке.
  3. Несовпадение типов пустых значений. Если поле отсутствует в одной из таблиц и подставляется как NULL без явного приведения типа, компоновщик данных может некорректно сопоставить типы колонок.

Способ 1. Синхронизация полей во всех ветках объединения запроса

Разберем по шагам, как правильно внести изменения, если требуется скорректировать сам текст запроса в наборе данных СКД:

  1. Открываем схему компоновки данных и переходим на вкладку Наборы данных к редактированию запроса.
  2. Находим все части запроса, соединенные операторами ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ.
  3. Проверяем, чтобы новые поля присутствовали в списке выборки каждой ветки запроса с абсолютно идентичными псевдонимами (с учетом регистра).
  4. Если в какой-то из таблиц требуемого реквизита физически нет, обязательно добавляем типизированную заглушку.

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


ВЫБРАТЬ
    Расчеты.ЗаказПоставщику КАК ОбъектРасчетов,
    Расчеты.ЗаказПоставщику.Контрагент КАК Поставщик,
    Расчеты.ЗаказПоставщику.Контрагент.КодПоSWIFT КАК ПоставщикSWIFT,
    Расчеты.СуммаОстаток КАК СуммаОстаток,
    0 КАК СуммаПросрочено
ИЗ
    РегистрНакопления.РасчетыСПоставщиками.Остатки(&Период, ) КАК Расчеты

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Просрочка.ЗаказПоставщику КАК ОбъектРасчетов,
    Просрочка.ЗаказПоставщику.Контрагент КАК Поставщик,
    Просрочка.ЗаказПоставщику.Контрагент.КодПоSWIFT КАК ПоставщикSWIFT,
    0 КАК СуммаОстаток,
    Просрочка.СуммаПросрочено КАК СуммаПросрочено
ИЗ
    РегистрСведений.РасписаниеПогашенияЗадолженности КАК Просрочка

Если же во второй таблице ссылка на документ отсутствует вовсе, используем явное приведение типа для пустого значения с помощью функции ВЫРАЗИТЬ или конструкцию ЗНАЧЕНИЕ:


ВЫБРАТЬ
    ВЫРАЗИТЬ(NULL КАК Справочник.Контрагенты) КАК Поставщик,
    "" КАК ПоставщикSWIFT,
    ТаблицаБезЗаказа.Сумма КАК СуммаОстаток
ИЗ
    РегистрНакопления.ПрочиеРасчеты КАК ТаблицаБезЗаказа

Способ 2. Получение реквизитов через точку без изменения текста запроса

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

Разберем по шагам, как вывести нужные поля через интерфейс СКД:

  1. Возвращаем типовой текст запроса в исходное состояние, удалив ручные вставки полей.
  2. Переходим на вкладку Настройки схемы компоновки данных (или открываем форму настройки варианта отчета в режиме предприятия).
  3. В списке доступных полей находим поле документа-основания (например, Объект расчетов или Заказ поставщику).
  4. Нажимаем на значок «+» рядом с полем, раскрывая его структуру реквизитов.
  5. Находим реквизит Поставщик, раскрываем его и выбираем реквизит SWIFT.
  6. Перетаскиваем найденные поля в структуру группировок или в список выбранных полей отчета.

При таком подходе платформа 1С автоматически сформирует необходимые левые соединения при выполнении компоновки данных. Это полностью исключает риск задвоения строк из-за расхождения структур в объединяемых запросах.

Способ 3. Использование вычисляемых полей

Если реквизит нужно вывести под удобным пользовательским именем или составить составное выражение, отличным решением будет создание вычисляемого поля:

  1. Открываем вкладку Вычисляемые поля в схеме СКД.
  2. Добавляем новую строку. В колонке «Путь к данным» указываем имя поля (например, ПоставщикSWIFT).
  3. В колонке «Выражение» прописываем обращение через точку к уже существующему полю выборки: ОбъектРасчетов.Контрагент.КодПоSWIFT.
  4. На вкладке «Настройки» добавляем созданное вычисляемое поле в список выбранных полей варианта отчета.

Вычисляемые поля рассчитываются компоновщиком данных уже после того, как все ветки запроса объединены и свернуты, поэтому они не приводят к появлению пустых строк с NULL.

Способ 4. Настройка ролей полей в схеме компоновки

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

  1. В списке полей набора данных находим добавленные реквизиты и переходим в колонку Роль.
  2. Убеждаемся, что для добавленных полей не установлен флаг Измерение. Поля-измерения принудительно расщепляют группировки при любых несовпадениях.
  3. В параметрах роли поля указываем Родительское поле — ссылку на документ, реквизитом которого оно является (например, ОбъектРасчетов). Это подскажет компоновщику данных, что поле является дополнительным свойством объекта и не должно образовывать отдельную независимую строку.
  4. При необходимости устанавливаем флаг Игнорировать значение NULL, чтобы пустые строки отсекались на этапе компоновки и не формировали отдельных групп.
← На главную