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

· 9 мин

Содержание

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

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

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

Что такое вычисляемое поле и когда без него не обойтись

Поле реальной таблицы хранит то, что ввёл пользователь: цену, количество, дату. Вычисляемое поле хранить нечего — его значение выводится из других полей. Классические примеры: сумма строки как Цена * Количество, остаток как разность прихода и расхода, признак «просрочено» по сравнению даты с текущей.

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

Вычисляемое поле пригодится, когда:

  • 🧮 нужен результат арифметики над несколькими колонками (сумма, процент, разница);
  • 🔀 значение зависит от условия — ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ;
  • 🧩 надо собрать строку из нескольких реквизитов (ФИО, адрес, артикул с наименованием);
  • 📅 требуется привести тип или формат — дату к началу месяца, число к строке с разделителями;
  • 📊 в отчёте нужна доля или ранг относительно итога группировки.

Вычисляемое поле в отчёте на системе компоновки данных

Самый частый случай — отчёт на СКД. Откройте схему компоновки данных (в отчёте это макет типа «Схема компоновки данных»), перейдите на вкладку Вычисляемые поля и нажмите Добавить.

Заполните три колонки:

  1. Путь к данным — технический идентификатор поля. Без пробелов и точек, латиница или кириллица слитно: СуммаСтроки, ДоляВИтоге. По этому имени вы потом добавите поле в выбранные.
  2. Заголовок — как колонка подпишется в отчёте для пользователя: «Сумма строки».
  3. Выражение — формула на языке выражений компоновки данных.

Выражение похоже на язык запросов, но считается уже после выборки, на этапе компоновки. Пример простого поля:

Цена * Количество

Пример с условием, чтобы не делить на ноль:

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

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

Не путайте вычисляемое поле с ресурсом. Ресурс — это итог по числовому полю, который схема считает по группировкам и строке «Итого»: выручка по менеджеру, количество по складу. Вычисляемое поле описывает произвольное выражение для каждой записи. Часто их используют вместе: вычисляемое поле Цена * Количество задаёт сумму строки, а ресурс Сумма(СуммаСтроки) сворачивает её в итог по группировке.

Итоги, доли и ранги по группировкам

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

Сумма / ВычислитьВыражениеСГруппировкойМассив("Сумма(Сумма)", "ОбщийИтог")[0]

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

Собственные функции в выражении СКД доступны только из общего модуля с флагом «Глобальный». Если модуль не глобальный, функция в выражении не найдётся. Когда логика сложная, проще посчитать её в запросе набора данных, а в вычисляемом поле лишь отформатировать результат.

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

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

ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Цена * Товары.Количество КАК Сумма,
    ВЫБОР
        КОГДА Товары.Количество = 0
            ТОГДА 0
        ИНАЧЕ Товары.Цена
    КОНЕЦ КАК ЦенаЗаЕдиницу
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Товары

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

Полученное вычисляемое поле ведёт себя как обычная колонка: по нему можно наложить условие в ГДЕ, упорядочить в УПОРЯДОЧИТЬ ПО, сгруппировать.

Несколько приёмов, которые закрывают большинство задач в запросе:

  • Логический флаг — выражение сравнения возвращает булево: Товары.Количество > Товары.Резерв КАК ЕстьСвободный.
  • Категория по диапазону — вложенные ВЫБОР КОГДА: разбить сумму на «до 10 000», «от 10 000 до 100 000», «свыше».
  • Признак просрочки — сравнение с параметром: ВЫБОР КОГДА Заказ.СрокОплаты < &ТекущаяДата ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ.

Агрегатную функцию (СУММА, КОЛИЧЕСТВО) нельзя класть в обычное вычисляемое поле без группировки — запрос выдаст ошибку. Для агрегатов обязателен раздел СГРУППИРОВАТЬ ПО.

Вычисляемые поля при работе с виртуальными таблицами

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

Типичный пример — остаток, который может оказаться NULL, если движений по номенклатуре не было. Его обязательно оборачивают в ЕСТЬNULL:

ВЫБРАТЬ
    Остатки.Номенклатура КАК Номенклатура,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток,
    ЕСТЬNULL(Остатки.СуммаОстаток, 0) КАК Сумма
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки

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

У таблицы ОстаткиИОбороты поля прихода и расхода уже разнесены, поэтому вычисляемое поле часто строят прямо над ней — например, оборачиваемость как отношение оборота к среднему остатку:

ВЫБРАТЬ
    Данные.Номенклатура КАК Номенклатура,
    ЕСТЬNULL(Данные.КоличествоРасход, 0) КАК Расход,
    ЕСТЬNULL(Данные.КоличествоКонечныйОстаток, 0) КАК Остаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(
        &НачалоПериода, &КонецПериода, , ) КАК Данные

Само отношение Расход / Остаток безопаснее посчитать во внешнем запросе через ВЫБОР КОГДА, чтобы нулевой остаток не уронил выборку делением на ноль.

Преобразование типов и формата значения

Отдельная группа задач — не посчитать, а привести значение к нужному виду. Это тоже делается вычисляемым полем.

Приведение составного типа. Если поле хранит ссылку разных типов (например, Регистратор движения), к конкретному реквизиту доберётесь только через ВЫРАЗИТЬ:

ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент

Для строк других типов ВЫРАЗИТЬ вернёт NULL — это нормально, его отсекают условием.

Формат вывода. В СКД и во встроенном языке есть функция Формат. Число с разделителями групп и двумя знаками:

Формат(Сумма, "ЧДЦ=2; ЧРГ=' '")

Дата без времени:

Формат(Дата, "ДЛФ=D")

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

Сборка строки. Склеить несколько полей в одну надпись помогает оператор + для строк или функция СтрШаблон во встроенном языке:

Представление = СтрШаблон("%1 — %2 шт.", Номенклатура, Формат(Количество, "ЧГ=0"));

Число перед склейкой со строкой приводите через Формат, иначе получите ошибку преобразования типов. Лидирующие нули (номер документа «00012») задаёт признак ЧЦ в форматной строке: Формат(Номер, "ЧЦ=5; ЧВН=").

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

Вычисляемое поле на управляемой форме

На форме «вычисляемое поле» реализуют двумя разными способами — выбор зависит от того, форма это списка или объекта.

Колонка в динамическом списке

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

Реквизит формы с пересчётом в коде

Для формы документа или обработки добавьте Реквизит формы (а не реквизит объекта), поставьте его на форму и считайте значение кодом. Минимальный пример — показать итог по строкам:

&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
    ПересчитатьИтог();
КонецПроцедуры

&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
    ПересчитатьИтог();
КонецПроцедуры

&НаКлиенте
Процедура ПересчитатьИтог()
    Итого = Объект.Количество * Объект.Цена;
КонецПроцедуры

Здесь Итого — реквизит формы. Обработчики ПриИзменении вешаются на поля, от которых зависит результат, плюс вызов в ПриСозданииНаСервере, чтобы значение появилось сразу при открытии.

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

Почему вычисляемое поле не считается: разбор ошибок

Большинство проблем сводится к нескольким типовым причинам. Прогоните свой случай по списку.

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

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

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

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