Как добавить вычисляемое поле в СКД, запросе и на управляемой форме
Содержание
Вычисляемое поле в 1С — это столбец, значение которого программа считает по формуле прямо при выводе, а не берёт из базы. Создают его в трёх местах: на вкладке Вычисляемые поля в схеме компоновки данных (СКД), в самом тексте запроса и как реквизит на управляемой форме. Где именно — зависит от того, где результат должен появиться: в отчёте, в произвольном списке или в карточке объекта.
Быстрый ориентир. Нужна колонка в отчёте — делайте поле в СКД, там же работают итоги и группировки. Значение нужно внутри выборки данных, чтобы потом по нему фильтровать или сортировать, — считайте в запросе. Поле показывается в форме документа и пересчитывается при вводе — это реквизит формы, который заполняется кодом.
Везде работает один принцип: вы описываете выражение на понятном 1С языке, а платформа подставляет его в нужный момент. Отличается только синтаксис и момент вычисления.
Что такое вычисляемое поле и когда без него не обойтись
Поле реальной таблицы хранит то, что ввёл пользователь: цену, количество, дату. Вычисляемое поле хранить нечего — его значение выводится из других полей. Классические примеры: сумма строки как Цена * Количество, остаток как разность прихода и расхода, признак «просрочено» по сравнению даты с текущей.
Держать такие значения в базе вредно: при изменении исходных данных они разъезжаются. Поэтому их считают на лету.
Вычисляемое поле пригодится, когда:
- 🧮 нужен результат арифметики над несколькими колонками (сумма, процент, разница);
- 🔀 значение зависит от условия —
ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ; - 🧩 надо собрать строку из нескольких реквизитов (ФИО, адрес, артикул с наименованием);
- 📅 требуется привести тип или формат — дату к началу месяца, число к строке с разделителями;
- 📊 в отчёте нужна доля или ранг относительно итога группировки.
Вычисляемое поле в отчёте на системе компоновки данных
Самый частый случай — отчёт на СКД. Откройте схему компоновки данных (в отчёте это макет типа «Схема компоновки данных»), перейдите на вкладку Вычисляемые поля и нажмите Добавить.
Заполните три колонки:
- Путь к данным — технический идентификатор поля. Без пробелов и точек, латиница или кириллица слитно:
СуммаСтроки,ДоляВИтоге. По этому имени вы потом добавите поле в выбранные. - Заголовок — как колонка подпишется в отчёте для пользователя: «Сумма строки».
- Выражение — формула на языке выражений компоновки данных.
Выражение похоже на язык запросов, но считается уже после выборки, на этапе компоновки. Пример простого поля:
Цена * Количество
Пример с условием, чтобы не делить на ноль:
ВЫБОР
КОГДА Количество = 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), тогда вместо пустоты выведется ноль.