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