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