Вычисляемое поле в СКД: от простой формулы до нарастающего итога

· 10 мин

Содержание

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

Подвох в том, что формула в запросе и формула в вычисляемом поле считаются по-разному. Первая выполняется на сервере СУБД до выборки, вторая — уже после, для каждой записи компоновки. Перепутать их — значит получить пустые ячейки, деление на ноль или отчёт, который заметно тормозит на большой выборке. Разберёмся, как настроить вычисляемое поле в СКД правильно и чем отличаются доступные способы его добавить.

Что делает вычисляемое поле и когда оно нужнее запроса

Поле запроса берётся из базы: ВЫБРАТЬ Цена * Количество КАК Сумма. СУБД считает его один раз, по нему можно группировать и отбирать быстро.

Вычисляемое поле СКД работает иначе. Его выражение применяется к уже полученному набору данных — к каждой детальной записи и к каждой группировке отдельно. Поэтому в нём доступны то, чего нет в запросе: функции компоновки вроде ВычислитьВыражение, обращение к ресурсам и к соседним группировкам.

Вывод простой:

  • 🧮 Значение можно получить прямо в запросе — считайте его в запросе. Это быстрее, и по такому полю доступны отбор и группировка на уровне СУБД.
  • 📊 Значение зависит от итогов, соседних строк или нарастающего результата — это вычисляемое поле СКД. В запросе такого не выразить.

Классические задачи именно для вычисляемого поля: процент строки от общего итога, нарастающий итог, ранг, «склейка» ФИО или адреса в одну строку на этапе вывода, подстановка текста по условию.

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

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

Способ зависит от того, кто и где правит отчёт.

1. На закладке «Вычисляемые поля» схемы. Открываете макет с типом «Схема компоновки данных», переходите на закладку Вычисляемые поля, добавляете строку. Заполняете:

  • Путь данных — имя поля латиницей или кириллицей без пробелов (например, Процент);
  • Заголовок — как колонка подпишется в отчёте;
  • Выражение — собственно формула на языке выражений СКД;
  • Тип значения — задайте явно, если планируете сортировку или особое форматирование по этому полю.

После этого поле нужно вынести в настройки: на закладке Настройки добавить его в Выбранные поля. Само по себе определение поля в схеме колонку в отчёте не показывает.

2. Пользовательское поле в настройках отчёта. Этот способ доступен конечному пользователю, без Конфигуратора. В форме настроек отчёта открываете Пользовательские поля (в типовых отчётах — через меню Ещё → Изменить вариант или Настройки), добавляете Новое поле выражение. У такого поля два выражения:

  • Выражение детальных записей — значение в строках-детализациях;
  • Выражение итоговых записей — значение в строках-итогах (группировках).

Если заполнить только первое, в итоговых строках поле останется пустым. Это частая причина «пропавших» значений в подвале группировки.

3. Поле-выбор (ВЫБОР … КОГДА). Там же, рядом с полем-выражением, есть Новое поле выбор — визуальный конструктор условий без ручного набора ВЫБОР КОГДА … ТОГДА … КОНЕЦ. Удобно, когда значение зависит от набора условий, а писать выражение вручную не хочется.

Где считать новое поле?

Язык выражений СКД: операторы и функции

Выражение пишется на языке выражений системы компоновки данных. Он близок к встроенному языку 1С, но это не он — часть привычных методов здесь недоступна.

Что точно работает:

  • арифметика + - * /, сравнения = <> > < >= <=;
  • логика И, ИЛИ, НЕ;
  • условие ВЫБОР КОГДА Условие ТОГДА Значение1 ИНАЧЕ Значение2 КОНЕЦ;
  • обработка пустых значений ЕСТЬNULL(Поле, 0);
  • агрегатные функции Сумма(), Количество(), Среднее(), Минимум(), Максимум();
  • строковые и датовые функции: Строка(), Формат(), Год(), Месяц(), НачалоПериода(), ПредставлениеПериода().

Простые примеры:

// Полное имя из трёх полей
Фамилия + " " + Имя + " " + Отчество

// Сумма строки без деления на ноль
ВЫБОР КОГДА Количество = 0 ТОГДА 0 ИНАЧЕ Выручка / Количество КОНЕЦ

// Текстовая метка по условию
ВЫБОР КОГДА ОстатокДолга > 0 ТОГДА "Должник" ИНАЧЕ "Оплачено" КОНЕЦ

К полю обращаются по имени так, как оно задано в наборе данных или в псевдониме запроса. Если поле вложено в таблицу (Товары.Номенклатура), путь пишется через точку.

Ещё пара моментов, на которых спотыкаются чаще всего:

  • Ссылочные поля. В таблицу попадает ссылка, а не её текст. Чтобы вывести наименование, берите реквизит через точку (Номенклатура.Наименование) либо получайте представление функцией Представление(Номенклатура). Складывать ссылку со строкой напрямую нельзя.
  • Типы в арифметике. Сложение строки и числа без приведения даёт ошибку. Число превращают в строку через Строка() или собирают текст шаблоном, а не «плюсом».
  • Дата как период. Для группировки по месяцу или кварталу удобно считать НачалоПериода(Дата, "Месяц"), а подписывать — ПредставлениеПериода(НачалоПериода(Дата, "Месяц"), КонецПериода(Дата, "Месяц")).

Отдельный приём — агрегат с условием. Он помогает посчитать «количество только оплаченных» без отдельного ресурса:

// Доля оплаченных заказов в группировке
Количество(ВЫБОР КОГДА Статус = "Оплачен" ТОГДА 1 КОНЕЦ)
  / Количество(Ссылка) * 100

Внутри ВЫБОР без ветки ИНАЧЕ неподходящие строки дают NULL и в счёт Количество не попадают — ровно то, что нужно.

Нарастающий итог и процент от общего: функция ВычислитьВыражение

Главный инструмент вычисляемых полей — функция ВычислитьВыражение. Она считает выражение в контексте другой группировки: общего итога, текущей группировки от первой записи до текущей и так далее.

Процент строки от общего итога. Делим значение записи на грандтотал:

Выручка / ВычислитьВыражение("Сумма(Выручка)", "ОбщийИтог") * 100

Второй параметр "ОбщийИтог" говорит СКД взять сумму по всему отчёту, а не по текущей группировке. Чтобы не словить деление на ноль на пустом отчёте, оберните знаменатель в ВЫБОР КОГДА … КОНЕЦ.

Нарастающий итог. Считаем сумму от первой записи группировки до текущей:

ВычислитьВыражение("Сумма(Выручка)", "", "Группировка", "Первая", "Текущая")

Здесь параметры — выражение, имя группировки (пусто = текущая), тип расчёта и границы Первая/Текущая. Полный список параметров и их значения смотрите в синтакс-помощнике Конфигуратора по функции ВычислитьВыражение — там же описаны Предыдущая, Следующая и числовые смещения для скользящих итогов.

Старую функцию Вычислить() с одним аргументом трогать не нужно: она оставлена для совместимости, в новых отчётах используют ВычислитьВыражение.

ВычислитьВыражение по большой группировке с сортировкой считается для каждой строки заново. На выборках в десятки тысяч строк это ощутимо замедляет вывод — см. раздел о производительности.

Практический пример: поле с условием, итогом и форматированием

Соберём колонку «Доля в обороте, %» с округлением и прочерком вместо нуля. Выражение вычисляемого поля:

ВЫБОР
  КОГДА ВычислитьВыражение("Сумма(СуммаПродаж)", "ОбщийИтог") = 0
    ТОГДА 0
  ИНАЧЕ СуммаПродаж / ВычислитьВыражение("Сумма(СуммаПродаж)", "ОбщийИтог") * 100
КОНЕЦ

Дальше настраиваем вывод:

  1. У поля в схеме задайте Тип значения → Число, длина и точность под проценты (например, 5 и 2).
  2. На закладке Настройки → Условное оформление добавьте оформление: при значении поля = 0 выводить текст —. Так ноль не загромождает таблицу.
  3. Вынесите поле в Выбранные поля и, если нужно, разрешите сортировку по нему.

Результат: колонка показывает долю каждой строки в общем обороте, итог по группировке считается автоматически, пустые доли заменяются прочерком. Всё это — без единой строки в модуле.

Второй частый запрос — отклонение от среднего. Покажем, насколько продажи строки выше или ниже среднего по всему отчёту:

СуммаПродаж - ВычислитьВыражение("Среднее(СуммаПродаж)", "ОбщийИтог")

Положительное число — строка выше среднего, отрицательное — ниже. Через условное оформление такие значения удобно подсветить: отрицательные — красным, положительные — зелёным. Оформление настраивается там же, на закладке Условное оформление, с отбором по самому вычисляемому полю.

Почему вычисляемое поле пустое или считает неверно

Чаще всего дело не в формуле, а в данных или в настройке вывода.

Диагностика: выберите симптом

Ещё одна ловушка — путаница между вычисляемым полем и ресурсом. Ресурс агрегирует (суммирует, считает) значение по группировкам автоматически. Вычисляемое поле само по себе ничего не агрегирует: в группировке оно пересчитывает своё выражение. Если нужна именно сумма по группе — заводите ресурс, а в вычисляемом поле уже используйте его результат.

Как не посадить производительность отчёта

Главное правило: всё, что можно посчитать в запросе, считайте в запросе. Поле запроса обрабатывается СУБД и индексами, вычисляемое поле — построчно уже на выводе.

Что замедляет отчёт:

  • 🐢 ВычислитьВыражение с сортировкой по большой группировке — для каждой строки идёт отдельный проход.
  • 🐢 Отбор по вычисляемому полю. В запросе отбор отсекает строки до выборки, а по вычисляемому полю фильтр применяется уже после получения всех данных — лишний объём гоняется зря.
  • 🐢 Тяжёлые строковые операции и вложенные ВЫБОР на каждой детальной записи при десятках тысяч строк.

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

Есть и обратная сторона. Простые выражения вроде склейки ФИО или метки по условию стоят почти ничего — их спокойно оставляют в вычисляемом поле, даже если формально их можно было бы завести и в запросе. Удаление лишних полей из Выбранные поля и отказ от неиспользуемых группировок дают больший выигрыш, чем перенос одной короткой формулы в запрос. Оптимизировать имеет смысл то, что реально тормозит на вашей выборке, а не каждую строку подряд.

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

Проверка перед сдачей отчёта
Выполнено: 0 / 6

Частые вопросы

Чем вычисляемое поле отличается от ресурса?
Ресурс агрегирует значение по группировкам (сумма, количество, среднее) автоматически. Вычисляемое поле считает произвольное выражение для каждой записи и каждой группировки, но само не суммирует. Их часто используют вместе: ресурс даёт итог, поле — например, его процент от общего.
Можно ли отобрать отчёт по вычисляемому полю?
Да, через Отбор в настройках. Но фильтр сработает уже после выборки, на стороне компоновки, а не СУБД. Если данных много, выгоднее получить значение в запросе и фильтровать там.
Почему функция из встроенного языка не работает в выражении?
Язык выражений СКД — отдельный от встроенного языка 1С. В нём доступен свой набор функций. Если нужного метода нет, либо считайте значение в запросе, либо выносите логику в поле набора данных через функцию общего модуля.
Чем пользовательское поле отличается от поля в схеме?
Поле в схеме задаёт разработчик в Конфигураторе, оно часть конфигурации. Пользовательское поле создаётся прямо в настройках варианта отчёта и доступно конечному пользователю без изменения конфигурации.
Как сделать нарастающий итог в отчёте?
Вычисляемым полем с функцией ВычислитьВыражение, где границы расчёта заданы как от первой записи до текущей. Точный набор параметров приведён в синтакс-помощнике по этой функции.