Почему функция ВЫРАЗИТЬ в запросе 1С округляет некорректно и расходятся итоги в СКД?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда визуальная сумма строк не совпадает с итогом по группировке, а попытка округлить значение прямо в запросе с помощью конструкции ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)) приводит к непредсказуемым результатам: например, близкие по значению числа округляются по-разному или отображается один знак после запятой вместо двух. Разберем по шагам, почему это происходит и как правильно настроить расчет данных.

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

Рассмотрим типичный пример. В отчете выводятся количество и цена, а поле стоимости рассчитывается как их произведение. Предположим, что мы видим следующие строки:

  1. Количество 33,873 умножается на цену 75. Математический результат равен 2 540,475, но отчет после применения ВЫРАЗИТЬ показывает 2 540,5.
  2. Количество 35,113 умножается на цену 75. Результат перемножения отображаемых чисел равен 2 633,475, однако после округления получается 2 633,49.

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


ВЫБРАТЬ
    ВЫРАЗИТЬ(35.113 * 75 КАК ЧИСЛО(15, 2)) КАК Результат1,
    ВЫРАЗИТЬ(33.873 * 75 КАК ЧИСЛО(15, 2)) КАК Результат2

Прямой запрос к СУБД возвращает значения 2 633,48 и 2 540,48. Это доказывает, что механизм приведения типов платформы 1С работает предсказуемо, а корень проблемы кроется в структуре входных данных и особенностях отображения чисел.

Причина 1. Скрытая точность операндов (невидимые разряды)

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

Посмотрим на пример вычислений с полными разрядами:

35,1132 * 75 = 2 633,4900

При усечении или скрытии разрядов форматом пользователю кажется, что программа ошиблась при умножении 35,113 * 75, тогда как запрос честно перемножил и округлил исходные неокругленные операнды.

Причина 2. Отображение незначащих нулей в дробной части

Результат 2 540,5 вместо 2 540,50 обусловлен тем, что числовой тип данных в 1С сам по себе не хранит незначащие нули справа. Если в результате округления сотые доли обращаются в ноль, платформа по умолчанию отсекает его при стандартном представлении числа. Чтобы сотые доли всегда присутствовали на экране, числовое округление обязательно должно дополняться строковым форматированием.

Причина 3. Разница между форматированием ячеек и округлением в запросе

Проанализируем частую ошибку: попытку решить проблему расхождения итогов исключительно настройкой свойства Формат (параметр ЧДЦ=2) в полях набора данных. Форматирование меняет только визуальное представление ячейки в отчете. СКД при подсчете итоговых сумм агрегирует полные числовые значения из базы данных, из-за чего сумма визуально округленных строк гарантированно разойдется с итоговой строкой группировки.

Решения для корректного округления и сходимости итогов

Разберем по шагам надежные способы устранения проблемы в зависимости от места расчета показателей.

Способ 1. Предварительное округление операндов и произведений в запросе

Если данные рассчитываются в наборе данных типа «Запрос», необходимо явно зафиксировать точность каждого множителя перед перемножением либо ограничить разрядность самого результата:


ВЫБРАТЬ
    Таблица.Номенклатура КАК Номенклатура,
    ВЫРАЗИТЬ(Таблица.Количество КАК ЧИСЛО(15, 3)) КАК Количество,
    ВЫРАЗИТЬ(Таблица.Цена КАК ЧИСЛО(15, 2)) КАК Цена,
    ВЫРАЗИТЬ(Таблица.Количество * Таблица.Цена КАК ЧИСЛО(15, 2)) КАК Стоимость
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Таблица

Чтобы исключить потерю нулей при выводе, для поля Стоимость на вкладке Наборы данных в колонке Оформление зададим формат:

ЧДЦ=2; ЧРД=,; ЧГ=3,0

Способ 2. Расчет через вычисляемые поля СКД

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

  1. Перейдем на вкладку Вычисляемые поля и добавим поле Стоимость.
  2. В колонке Выражение укажем:

    Выразить(Количество * Цена, "Число(15, 2)")

  3. Перейдем на вкладку Ресурсы и для поля Стоимость укажем выражение агрегации:

    Сумма(Стоимость)

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

Способ 3. Использование функции общего модуля для строгого арифметического округления

Конструкция ВЫРАЗИТЬ на уровне СУБД транслируется в функцию CAST, которая в зависимости от СУБД (PostgreSQL или MS SQL Server) может применять банковское округление (к ближайшему четному). Если бизнес-логика требует строгого арифметического округления (где 0,005 всегда округляется до 0,01 вверх), вызовем функцию общего модуля в СКД.

Создадим в общем серверном модуле (с признаками «Сервер», «Внешнее соединение») экспортную функцию:


Функция ОкруглитьДоСотых(Значение) Экспорт
    Возврат Окр(Значение, 2, РежимОкругления.Окр15как20);
КонецФункции

Затем в схеме компоновки данных на вкладке Вычисляемые поля используем вызов функции:

ОбщийМодульСервер.ОкруглитьДоСотых(Количество * Цена)

Это гарантирует одинаковый результат округления независимо от используемой СУБД и обеспечит идеальную сходимость сумм в отчете.

← На главную