Как в СКД настроить вычисляемое поле с данными из разных наборов данных и рассчитать разность дат

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

При разработке отчетов на базе Системы компоновки данных (СКД) в 1С часто возникает необходимость объединения информации из разных источников. Например, когда у нас есть два набора данных (два отдельных запроса), и нам требуется создать вычисляемое поле, в котором будут одновременно участвовать поля как из первого, так и из второго набора.

На первый взгляд задача кажется простой: достаточно добавить новое поле на вкладку «Вычисляемые поля» и прописать нужную формулу. Однако на практике разработчики часто сталкиваются с тем, что отчет «ломается», выдает ошибки компоновки или просто выводит пустые значения. В этой статье мы подробно разберем, почему возникают эти ошибки, проанализируем внутренние механизмы работы СКД и рассмотрим два практических способа решения этой задачи. Для изучения других вариантов построения формул можно посмотреть примеры отчетов со сложными выражениями в СКД.

---

Почему отчет «ломается» или не выводит данные? Выясняем причины

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

  1. Отсутствие связей между наборами данных. СКД выполняет каждый набор данных (запрос) изолированно друг от друга. Если мы просто объявим два набора и попытаемся обратиться к их полям в одном выражении, система не поймет, какую строку первого набора сопоставить со строкой второго. Без явного указания связи результатом вычисления всегда будет NULL или пустая строка.
  2. Попытка прямого вычитания дат через оператор «минус». В обычном коде 1С мы можем написать Дата1 - Дата2 и получить разницу в секундах. Однако язык выражений СКД имеет другой синтаксис. Конструкция типа ПериодСнятияСУчета - ДатаСнятияПравНаОбъектНедвижимости вызовет ошибку компоновки: «Неверные параметры "-"». В вычисляемых полях СКД математические операции над датами напрямую не поддерживаются.
  3. Неправильный синтаксис функции получения разности дат. Для расчета интервалов времени в СКД предусмотрена функция РазностьДат. Но здесь кроется важный нюанс: синтаксис этой функции в языке запросов и в языке выражений СКД отличается. Если в запросе мы пишем РАЗНОСТЬДАТ(Дата1, Дата2, МЕСЯЦ), то в вычисляемом поле СКД третий параметр (периодичность) обязательно должен передаваться в виде строки в кавычках: РазностьДат(Дата1, Дата2, "МЕСЯЦ"). Ошибка в кавычках приведет к сбою формирования отчета.
  4. Проблема расчета итогов в группировках (Ресурсы против Вычисляемых полей). Когда мы связываем наборы данных и делаем сложные вычисления на уровне детальных записей вычисляемого поля, СКД некорректно рассчитывает общие итоги по группировкам. Для правильного расчета итоговых показателей формулу обязательно нужно дублировать или переносить на вкладку «Ресурсы» с использованием агрегатных функций (например, Сумма()).

---

Вариант А. Правильная настройка через интерфейс СКД (с двумя наборами данных)

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

Шаг 1. Настройка связи наборов данных

Переходим на вкладку «Связи наборов данных». Нам необходимо связать наш НаборДанных1 (источник) и НаборДанных2 (приемник).

Шаг 2. Создание вычисляемого поля

Переходим на вкладку «Вычисляемые поля». Добавляем новую строку со следующими параметрами:

Проанализируем выражение, которое решит задачу автора темы:


Выбор 
    Когда ДатаСнятияПравНаОбъектНедвижимости = ДатаВремя(1, 1, 1) Или ДатаСнятияПравНаОбъектНедвижимости Есть Null
    Тогда КоличествоМесяцевВладения 
    Иначе КоличествоМесяцевВладения - РазностьДат(ДатаСнятияПравНаОбъектНедвижимости, ПериодСнятияСУчета, "МЕСЯЦ") 
Конец

Обратите внимание: мы использовали функцию ДатаВремя(1, 1, 1) для проверки на пустую дату (вместо некорректного ДАТА(1,1,1) из первого сообщения автора) и обернули параметр "МЕСЯЦ" в кавычки.

Шаг 3. Настройка ресурсов для расчета итогов

Чтобы в группировках и общих итогах отчета выводились корректные математические суммы, переходим на вкладку «Ресурсы». Добавляем наше поле МесяцыВладенияКорректные и в колонке «Выражение» пишем формулу расчета агрегатных данных:


Сумма(КоличествоМесяцевВладения) - Сумма(Выбор 
    Когда ДатаСнятияПравНаОбъектНедвижимости = ДатаВремя(1, 1, 1) Или ДатаСнятияПравНаОбъектНедвижимости Есть Null 
    Тогда 0 
    Иначе РазностьДат(ДатаСнятияПравНаОбъектНедвижимости, ПериодСнятияСУчета, "МЕСЯЦ") 
Конец)

---

Вариант Б. Перенос логики в один запрос (Рекомендуемый способ)

Связывание наборов данных на уровне платформы 1С аналогично левому соединению таблиц (LEFT JOIN), но выполняется программно после того, как СУБД вернула результаты отдельных запросов. На больших объемах данных это может приводить к существенному снижению производительности отчета.

Поэтому наиболее эффективным и профессиональным решением является объединение двух наборов данных в **один Набор данных - запрос** на уровне СУБД.

Посмотрим на пример структуры такого запроса:


ВЫБРАТЬ
    ПервыйНабор.ОбъектНедвижимости КАК ОбъектНедвижимости,
    ПервыйНабор.КоличествоМесяцевВладения КАК КоличествоМесяцевВладения,
    ВторойНабор.ПериодСнятияСУчета КАК ПериодСнятияСУчета,
    ВторойНабор.ДатаСнятияПравНаОбъектНедвижимости КАК ДатаСнятияПравНаОбъектНедвижимости,
    
    // Вычисляем значение прямо в запросе
    ВЫБОР
        КОГДА ВторойНабор.ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1, 1, 1) 
            ИЛИ ВторойНабор.ДатаСнятияПравНаОбъектНедвижимости ЕСТЬ NULL
        ТОГДА ПервыйНабор.КоличествоМесяцевВладения
        ИНАЧЕ ПервыйНабор.КоличествоМесяцевВладения - РАЗНОСТЬДАТ(ВторойНабор.ДатаСнятияПравНаОбъектНедвижимости, ВторойНабор.ПериодСнятияСУчета, МЕСЯЦ)
    КОНЕЦ КАК МесяцыВладенияКорректные
ИЗ
    Справочник.ОбъектыНедвижимости КАК ПервыйНабор
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОбОбъектах КАК ВторойНабор
        ПО ПервыйНабор.ОбъектНедвижимости = ВторойНабор.ОбъектНедвижимости

Преимущества данного подхода очевидны:

← На главную