Как в 1С убрать дробную часть числа без округления в большую сторону?

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

При разработке отчетов и обработок в 1С часто возникает задача отобразить число без дробной части (актуально, когда вы проходите тестирование на вакансию). Стандартный механизм форматной строки ЧДЦ=0 выполняет математическое округление: например, число 15 114,7 превратится в 15 115. Однако во многих бизнес-задачах требуется просто "отсечь" хвост, чтобы получить 15 114. В этой статье мы подробно разберем, как добиться такого результата в программном коде, в запросах и при расчете итогов в отчетах.

Проблема использования форматной строки

Рассмотрим ситуацию, когда мы пытаемся настроить свойства ячейки в конструкторе форматной строки. Установив параметр "Число разрядов дробной части" в 0 (ЧДЦ=0), мы даем платформе команду округлить число до целого по правилам математики. Если в ячейке находится значение 15 114,7, платформа увидит, что дробная часть больше или равна 0,5, и прибавит единицу к целому разряду.

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

Решение задачи в программном коде 1С

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

Проанализируем пример кода (такая практика для новичков поможет быстрее освоить синтаксис):


// Допустим, в выборке пришло значение 15114.7
ЧислоСХвостом = Выборка.Сумма; 
// Используем функцию Цел()
Результат = Цел(ЧислоСХвостом); 
// Теперь в переменной Результат хранится 15114
Область.Параметры.Сумма = Результат;

Также в обсуждениях часто встречается "математический лайфхак" (хотя в планировании лучше использовать точные методы) с вычитанием 0.5 перед использованием формата. Рассмотрим его подробнее, чтобы понять риски:


// Попытка обмануть стандартное округление
Результат = Формат(15114.7 - 0.5, "ЧДЦ=0"); // Получим "15114"

Этот метод работает для положительных чисел с дробной частью >= 0.5, но он крайне ненадежен. Если число изначально было целым (15114.0), то после вычитания мы получим 15113.5, что форматная строка округлит до 15114 (если используется банковское округление) или 15114. Однако при значениях типа 15114.2 результат может быть непредсказуемым. Рекомендуем всегда использовать Цел() вместо подобных манипуляций.

Реализация в языке запросов (для платформ ниже 8.3.20)

В языке запросов 1С долгое время отсутствовала прямая функция Цел(). Основным инструментом была функция ВЫРАЗИТЬ(), которая ведет себя специфически. Рассмотрим пример:

ВЫРАЗИТЬ(Сумма КАК ЧИСЛО(15, 0))

Эта конструкция также выполняет округление. Более того, в 1С используется так называемое "банковское округление": если дробная часть равна ровно 0,5, число округляется до ближайшего четного. То есть 1.5 станет 2, а 2.5 тоже станет 2.

Чтобы отсечь дробную часть в запросе на старых версиях платформы, нам придется использовать логическую конструкцию ВЫБОР. Разберем алгоритм: мы сравниваем число с его округленным вариантом. Если округленное число оказалось больше исходного, значит, произошло округление в большую сторону, и нам нужно вычесть единицу.

Пример реализации в запросе:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ВЫРАЗИТЬ(Итоговая.Оплата КАК ЧИСЛО(15, 0)) > Итоговая.Оплата
            ТОГДА ВЫРАЗИТЬ(Итоговая.Оплата КАК ЧИСЛО(15, 0)) - 1
        ИНАЧЕ ВЫРАЗИТЬ(Итоговая.Оплата КАК ЧИСЛО(15, 0))
    КОНЕЦ КАК ОплатаЦелая
ИЗ
    ...

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

Современный подход: функции запросов в 8.3.20+

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

  1. Цел(Число) — вычисляет целую часть, отсекая дробную.
  2. Окр(Число, Разрядность, Способ) — полноценное округление.

Теперь запрос выглядит максимально просто и понятно:


ВЫБРАТЬ
    Цел(Итоговая.Оплата) КАК ОплатаБезДробнойЧасти
ИЗ
    Документ.Оплата КАК Итоговая

Проблема суммирования итогов

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

  1. Суммировать точные данные, а потом отсечь дробную часть у итога. В этом случае сумма по колонке визуально может не совпасть с суммой строк (так как копейки из каждой строки накопятся и дадут целый рубль).
  2. Суммировать уже "отсеченные" значения. Это обеспечит визуальное совпадение итогов со строками, но приведет к потере данных в общей сумме документа.

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


ВЫБРАТЬ
    СУММА(ВЫБОР
        КОГДА ВЫРАЗИТЬ(Оплата КАК ЧИСЛО(15, 0)) > Оплата
            ТОГДА ВЫРАЗИТЬ(Оплата КАК ЧИСЛО(15, 0)) - 1
        ИНАЧЕ ВЫРАЗИТЬ(Оплата КАК ЧИСЛО(15, 0))
    КОНЕЦ) КАК СуммаЦелых
ИЗ
    ...

Работа в Системе компоновки данных (СКД)

Если вы делаете отчет на СКД, задачу решить еще проще. В СКД на закладке "Вычисляемые поля" вы можете добавить поле и в выражении написать обычную функцию Цел(МоеПоле). Система компоновки поддерживает большинство функций встроенного языка 1С, включая работу с числами. Это позволит вам хранить в наборе данных точное число (для правильных расчетов), а пользователю показывать только целую часть через вычисляемое поле.

Подведем итог: выбор метода зависит от вашей версии платформы и того, где именно нужно преобразовать число. Для кода используйте Цел(), для современных запросов — встроенную функцию Цел() в языке запросов, а для старых систем — конструкцию ВЫБОР с функцией ВЫРАЗИТЬ().

← На главную