Как реализовать округление в запросе 1С с переменным количеством знаков после запятой

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

В процессе разработки на платформе 1С программисты часто сталкиваются с необходимостью округления вычисляемых значений непосредственно в тексте запроса. Типичная ситуация: при расчете остатков с учетом коэффициентов упаковок или при пересчете валют необходимо округлить результат до определенного количества знаков. Трудность возникает тогда, когда это количество знаков не является фиксированным, а хранится в справочнике (например, в поле Номенклатура.ЕдиницаХраненияОстатков.КоэффициентОкругления) или передается как параметр.

Разберем детально, почему стандартные методы могут не работать и какие существуют проверенные способы решения этой задачи для разных версий платформы 1С:Предприятие.

Причина ошибки при использовании ВЫРАЗИТЬ

Проанализируем попытку использования классической функции ВЫРАЗИТЬ. Многие начинающие разработчики пытаются написать код следующим образом:


ВЫРАЗИТЬ(Количество * Коэффициент / Номенклатура.ЕдиницаХраненияОстатков.Коэффициент 
    КАК ЧИСЛО(10, Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления))

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

Решение 1: Использование функции ОКР() (для платформы 8.3.20 и выше)

Рассмотрим самый современный способ. Начиная с версии платформы 8.3.20, в языке запросов появилась полноценная функция ОКР(). Это значительно упростило жизнь разработчикам, так как ранее округление приходилось имитировать сложными математическими выкладками.

Синтаксис функции выглядит так:

ОКР(Число, Разрядность)

Однако здесь есть важный нюанс, который мы должны учитывать: параметр Разрядность все равно должен быть целым числом-константой. Если ваша задача — округлить до заранее известного количества знаков, этот метод идеален:


ВЫБРАТЬ
    ОКР(Продажи.Сумма / Продажи.Курс, 2) КАК СуммаВВалюте
ИЗ
    РегистрНакопления.Продажи КАК Продажи

Важные особенности ОКР() в запросе:

  1. Округление всегда происходит по математическим правилам (0.5 округляется до 1).
  2. В отличие от встроенного языка, в запросе нельзя указать режим округления (например, "Окр15как20").
  3. Если разрядность не указана, округление происходит до целого числа.

Решение 2: Использование конструкции ВЫБОР для динамической точности

Если количество знаков после запятой может меняться в зависимости от условий (например, для одного товара это 0 знаков, для другого — 3), и мы работаем в рамках одного запроса, наиболее надежным методом будет использование оператора ВЫБОР. Проанализируем пример реализации:


ВЫБРАТЬ
    ВЫБОР
        КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 0
            ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 0))
        КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 1
            ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 1))
        КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 2
            ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 2))
        ИНАЧЕ ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 3))
    КОНЕЦ КАК РезультатОкругления
ИЗ
    ВременнаяТаблица КАК Таблица

Этот метод кажется громоздким, но он обладает максимальной производительностью, так как транслируется в эффективный SQL-код, понятный любому серверу баз данных (MS SQL, PostgreSQL). Рассмотрим его преимущества: мы явно управляем типами данных и избегаем ошибок переполнения.

Решение 3: Математический метод (универсальный "хак")

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

  1. Умножаем исходное число на 10 в степени N (где N — нужное количество знаков).
  2. Прибавляем 0.5 для обеспечения математического округления (чтобы дробная часть >= 0.5 перешла в следующий разряд).
  3. Приводим результат к целому числу с помощью ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 0)).
  4. Делим результат обратно на 10 в степени N.

Посмотрим на пример кода в запросе, где точность передается через параметр:


ВЫБРАТЬ
    // Предположим, нам нужно округлить до знаков, указанных в &КоэффициентМножитель (например, 100 для 2 знаков)
    ВЫРАЗИТЬ(Таблица.Цена * &КоэффициентМножитель + 0.5 КАК ЧИСЛО(15, 0)) / &КоэффициентМножитель КАК ОкругленнаяЦена
ИЗ
    Справочник.Номенклатура КАК Таблица

Внимание: Основная сложность этого метода в том, что в чистом языке запросов 1С нет функции возведения в степень (POW). Поэтому коэффициент (10, 100, 1000) нужно либо заранее подготовить в коде на встроенном языке и передать в параметр, либо хранить в базе данных.

Решение 4: Использование Системы компоновки данных (СКД)

Если ваш запрос является частью отчета на СКД, возможности округления расширяются. Проанализируем возможности компоновки:

  1. Выражения полей: В СКД в полях "Выражение" можно использовать функции встроенного языка 1С, включая Окр(), даже если версия платформы ниже 8.3.20.
  2. Оформление: Часто пользователю нужно видеть округленное число только в печатной форме, при этом расчеты (итоги) должны идти по точным данным. В этом случае используйте вкладку "Наборы данных", выберите поле и в колонке "Оформление" задайте формат ЧДЦ=2 (Число Десятичных Цифр).

Решение 5: Схема запроса (для продвинутых разработчиков)

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

Вместо того чтобы пытаться вставить переменную в текст запроса, мы программно формируем строку ВЫРАЗИТЬ(... КАК ЧИСЛО(15, " + НужнаяТочность + ")) и подставляем её в дерево запроса. Это позволяет избежать жестко заданных конструкций ВЫБОР, сохраняя типизацию данных.

Резюме и рекомендации

Выясним, какой метод лучше выбрать в зависимости от ситуации:

Используя предложенные методы, вы сможете гибко настраивать точность вычислений в ваших прикладных решениях на базе 1С, обеспечивая корректность данных и удобство для пользователей.

← На главную