СКД в 1С

Вычисляемые поля в СКД 1С: синтаксис выражений, функции и группировки

Коротко

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

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

Где задаются вычисляемые поля СКД

В конструкторе схемы компоновки данных есть отдельная закладка «Вычисляемые поля». Каждая строка — один объект ВычисляемоеПолеСхемыКомпоновкиДанных со свойствами:

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

Ключевое отличие от полей запроса: вычисляемое поле СКД рассчитывает процессор компоновки уже после выборки данных. В SQL-запрос оно не попадает, индексы по нему не работают, но зато в нём доступны функции СКД, которых в языке запросов нет.

Синтаксис выражений СКД в вычисляемом поле

Язык выражений СКД синтаксически близок к языку запросов: те же операторы сравнения, И/ИЛИ/НЕ, конструкция ВЫБОР … КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ, литералы ЗНАЧЕНИЕ(Справочник.Валюты.Рубль) и ДАТАВРЕМЯ(2024, 1, 1).

// Категория заказа по сумме
ВЫБОР
    КОГДА СуммаДокумента >= 1000000 ТОГДА "A"
    КОГДА СуммаДокумента >= 100000 ТОГДА "B"
    ИНАЧЕ "C"
КОНЕЦ

В выражении можно разыменовывать реквизиты через точку от поля-ссылки набора данных (Номенклатура.ЕдиницаИзмерения.Наименование) и обращаться к параметрам схемы через &ИмяПараметра:

// Просрочка на дату отчёта
ВЫБОР
    КОГДА СрокОплаты < &ДатаОтчёта ТОГДА РАЗНОСТЬДАТ(СрокОплаты, &ДатаОтчёта, ДЕНЬ)
    ИНАЧЕ 0
КОНЕЦ

Чего в выражении вычисляемого поля нет: соединений, вложенных запросов, временных таблиц и обращения к другим вычисляемым полям как к «уже посчитанным колонкам таблицы». Если нужна вторая таблица — это уровень набора данных или связи наборов, а не вычисляемого поля.

Не уверены, что выражение вообще отработает на ваших данных? В Консоли кода можно попросить агента собрать схему компоновки с нужным вычисляемым полем, выполнить её на реальной базе и показать результат — вместо цикла «поправил в конфигураторе → перезапустил отчёт».

Какие функции доступны в выражениях СКД

В выражениях СКД доступны три группы функций, и различать их важно.

  • Функции языка запросов — работают в вычисляемом поле как обычно: ЕСТЬNULL, ПОДСТРОКА, ГОД, МЕСЯЦ, НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, РАЗНОСТЬДАТ, ВЫРАЗИТЬ, ПРЕДСТАВЛЕНИЕ, ССЫЛКА.
  • Агрегатные функцииСумма, Количество, Максимум, Минимум, Среднее. В вычисляемом поле они осмысленны только внутри ВычислитьВыражение(): само вычисляемое поле считается построчно, агрегировать ему нечего.
  • Функции компоновки данныхВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений, Уровень, НомерПоПорядку, ПорядковыйНомерВГруппировке. В языке запросов их нет.

Функции общих модулей конфигурации в выражениях СКД тоже вызываются, но только когда компоновка инициализирована с разрешением внешних функций: у метода ПроцессорКомпоновкиДанных.Инициализировать() за это отвечает параметр <ВозможностьИспользованияВнешнихФункций>.

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , , Истина);

Результат = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Инициализировать
Макетмакет компоновки данных
ВнешниеНаборыДанныхструктура внешних наборов
ДанныеРасшифровкиобъект данных расшифровки
ВозможностьИспользованияВнешнихФункцийразрешает вызов функций общих модулей в выражениях
МенеджерВременныхТаблицменеджер временных таблиц
ПроцессорКомпоновкиДанных

Вычисление по группировкам: ВычислитьВыражение

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

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

Вторым параметром вместо "ОбщийИтог" указывают имя конкретной группировки настроек — тогда доля считается внутри неё. Пустая строка означает текущую группировку:

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

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

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

Вычисляемое поле или ресурс: чем отличаются

Вычисляемое поле считается по каждой записи. Ресурс (в схеме — коллекция ПоляИтога) считается по группировкам агрегатной функцией. Классическая ошибка — посчитать среднюю цену вычисляемым полем Сумма / Количество, а потом сделать его ресурсом с формулой Сумма(СредняяЦена): в итоге получится сумма средних, а не средняя.

// Правильно: средняя цена как ресурс по агрегатам,
// а не как сумма построчных вычисляемых полей
ПолеИтога = Схема.ПоляИтога.Добавить();
ПолеИтога.ПутьКДанным = "СредняяЦена";
ПолеИтога.Выражение   = "Сумма(СуммаОборот) / Сумма(КоличествоОборот)";
ПолеИтога.Группировки.Добавить("Номенклатура");
ПоляИтога.Добавить
ПутьКДаннымпуть к данным поля, для которого описывается формула итога
Выражениеформула расчёта итога, например «Сумма(КоличествоКонечныйОстаток)»
Группировкимассив имён полей, для которых поле вычисляется в итогах
ПолеИтогаСхемыКомпоновкиДанных

Практическое правило выбора: если формула складывается из агрегатов (Сумма(A) / Сумма(B)) — это ресурс. Если формула считается по одной строке (категория, флаг, разница дат, форматированное представление) — это вычисляемое поле. Если нужен построчный расчёт с оглядкой на итог группировки — вычисляемое поле плюс ВычислитьВыражение().

Программное создание вычисляемого поля в схеме

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

Схема = Отчеты.АнализПродаж.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

Поле = Схема.ВычисляемыеПоля.Добавить();
Поле.ПутьКДанным = "ДоляВИтоге";
Поле.Заголовок   = "Доля в итоге, %";
Поле.Выражение   =
    "ВЫБОР
    |   КОГДА ВычислитьВыражение(""Сумма(СуммаОборот)"", ""ОбщийИтог"") = 0 ТОГДА 0
    |   ИНАЧЕ 100 * СуммаОборот / ВычислитьВыражение(""Сумма(СуммаОборот)"", ""ОбщийИтог"")
    |КОНЕЦ";
Поле.ТипЗначения = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
ВычисляемыеПоля.Добавить
без параметров, добавляет новый элемент коллекции
Вставить(Индекс)добавление в заданную позицию
Количество()число полей в коллекции
ВычисляемоеПолеСхемыКомпоновкиДанных

Существующее поле правится через Найти() по имени — метод возвращает Неопределено, если поля с таким именем в схеме нет:

Поле = Схема.ВычисляемыеПоля.Найти("ДоляВИтоге");
Если Поле = Неопределено Тогда
    Поле = Схема.ВычисляемыеПоля.Добавить();
    Поле.ПутьКДанным = "ДоляВИтоге";
КонецЕсли;
// Истина = использование запрещено
Поле.ОграничениеИспользования.Условие = Истина;
Поле.ОграничениеИспользования.Группировка = Истина;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);
ВычисляемыеПоля.Найти
Имяимя искомого поля (ПутьКДанным)
ВычисляемоеПолеСхемыКомпоновкиДанных либо Неопределено

После правки схемы обязательно перекомпоновать макет: КомпоновщикМакетаКомпоновкиДанных.Выполнить() принимает схему и настройки и возвращает МакетКомпоновкиДанных. Изменение схемы уже после получения макета на результат не влияет.

Параметры схемы и выражения СКД

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

Параметр = Схема.Параметры.Найти("ДатаОкончания");
Если Параметр <> Неопределено Тогда
    Параметр.Выражение = "КонецПериода(&Период, ""День"")";
    Параметр.Использование = ИспользованиеПараметраКомпоновкиДанных.Всегда;
КонецЕсли;
Параметры.Найти
Имяимя параметра схемы
Выражениеформула, по которой вычисляется значение параметра
ВключатьВДоступныеПолявиден ли параметр в списке полей
ПараметрСхемыКомпоновкиДанных либо Неопределено

В самом вычисляемом поле параметр читается как &ИмяПараметра. Если параметр передаётся ещё и в текст запроса набора данных, следите за совпадением имён: в схеме параметр один, а вот значение к моменту расчёта вычисляемого поля уже подставлено, и «пустая» дата даст неожиданное сравнение.

NULL, деление на ноль и тип значения

Три типовые причины, по которым корректное на вид выражение даёт пустую колонку.

NULL заражает всё выражение. Любая арифметика с NULL даёт NULL, а он приходит из левых соединений и остатков без движений. Оборачивайте поля в ЕСТЬNULL до вычислений, а не после:

// Неверно: NULL внутри скобок обнулит весь результат
ЕСТЬNULL(СуммаОборот - СуммаВозврата, 0)

// Верно: страхуем каждое слагаемое
ЕСТЬNULL(СуммаОборот, 0) - ЕСТЬNULL(СуммаВозврата, 0)

Деление на ноль. Отдельной защиты в СКД нет — знаменатель проверяется явно через ВЫБОР. Проверять нужно именно то выражение, на которое делите, включая результат ВычислитьВыражение().

ВЫБОР
    КОГДА ЕСТЬNULL(КоличествоОборот, 0) = 0 ТОГДА 0
    ИНАЧЕ СуммаОборот / КоличествоОборот
КОНЕЦ

Тип значения не определён. Если ТипЗначения у вычисляемого поля пустой, платформа выводит тип из выражения — и для ВЫБОР с разнотипными ветками получает составной тип. Итог: не работает сортировка, отбор предлагает не те значения, число выводится как строка. Задавайте ОписаниеТипов явно и приводите ветки к одному типу через ВЫРАЗИТЬ.

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

Частые ошибки при работе с вычисляемыми полями СКД

  • Ссылка на другое вычисляемое поле или на ресурс. В выражении вычисляемого поля допустимы только поля наборов данных, параметры и функции СКД. Повторите формулу или перенесите расчёт в набор данных.
  • Агрегатная функция прямо в вычисляемом поле. Сумма(СуммаОборот) без ВычислитьВыражение() не даст итога по группировке — поле считается построчно.
  • Вычисляемое поле, назначенное ресурсом «в лоб». Сумма(Процент) по построчным процентам даёт бессмысленное число. Ресурс должен быть выражен через агрегаты исходных полей.
  • Пробелы и точки в ПутьКДанным. Имя поля используется в других выражениях и настройках, поэтому должно быть идентификатором. Человеческое название — в Заголовок.
  • Отбор по вычисляемому полю на больших выборках. Условие не уходит в СУБД: сначала выбираются все записи, потом отсеиваются. Фильтровать лучше в запросе набора данных.
  • Правка схемы после компоновки макета. Изменения в Схема.ВычисляемыеПоля учитываются только при повторном вызове КомпоновщикМакетаКомпоновкиДанных.Выполнить().
  • Кавычки в программно заданном выражении. Внутри строки 1С кавычки удваиваются: "ВычислитьВыражение(""Сумма(Сумма)"", ""ОбщийИтог"")".

Частые вопросы о вычисляемых полях СКД

Чем вычисляемое поле СКД отличается от ресурса?

Вычисляемое поле рассчитывается для каждой детальной записи, ресурс — агрегатной функцией по группировкам. Формула из агрегатов вида Сумма(A) / Сумма(B) должна быть ресурсом; построчная формула — вычисляемым полем.

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

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

Как посчитать процент от итога группировки в СКД?

Через функцию ВычислитьВыражение(): первым аргументом — агрегат ("Сумма(СуммаОборот)"), вторым — имя группировки или "ОбщийИтог". Знаменатель обязательно проверяйте на ноль конструкцией ВЫБОР.

Тарифы

ИИ Консоль запросов 1С

Лайт

Бесплатно

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты
Начать бесплатно

Старт

Популярный выбор
990 руб. в месяц
≈ 5 млн токенов

Для индивидуального использования

Выбрать тариф

Продвинутый

3900 руб. в месяц
≈ 19,5 млн токенов

Для интенсивного использования или команд

Выбрать тариф