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

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

При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты часто сталкиваются с необходимостью проводить сложные арифметические расчеты непосредственно на уровне схемы компоновки. Для этого используются вычисляемые поля. Однако написание формул в СКД имеет свои специфические особенности и подводные камни, которые могут приводить к неверным результатам или даже к «исчезновению» данных в ячейках отчета.

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

Постановка задачи: логика расчета налоговых показателей

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

Сформулируем базовые правила расчета, которыми руководствовался разработчик:

  1. Если колонка 11* (Дата снятия прав на объект недвижимости) не заполнена:
    • Если заполнена колонка 6* (коэффициент ЗначениеК), то итоговый результат равен: СуммаНалога * ЗначениеК.
    • Если колонка 6* не заполнена, результатом является просто СуммаНалога.
  2. Если колонка 11* заполнена:
    • Если заполнена колонка 6*, то итоговый результат равен: СуммаНалога * ЗначениеК * (Коэффициент владения).
    • Если колонка 6* не заполнена, результатом является: СуммаНалога * (Коэффициент владения).

Коэффициент владения рассчитывается как отношение оставшихся месяцев владения к общему количеству месяцев в периоде: (КоличествоМесяцевВладения - ПериодОтсутствия) / КоличествоМесяцевВладения.

Анализ исходной формулы и первые проблемы

Для реализации этой логики в вычисляемом поле СКД разработчик написал следующую формулу выражения:


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      ВЫБОР
         КОГДА ЕСТЬNULL(ЗначениеК, 0) = 0 ТОГДА
            СуммаНалога
         ИНАЧЕ
            СуммаНалога * ЕСТЬNULL(ЗначениеК, 1)
      КОНЕЦ
   ИНАЧЕ 
      ВЫБОР
         КОГДА ЕСТЬNULL(ЗначениеК, 0) = 0 ТОГДА
            СуммаНалога * (КоличествоМесяцевВладения - (МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости))/КоличествоМесяцевВладения)
         ИНАЧЕ
            СуммаНалога * ЕСТЬNULL(ЗначениеК, 1) * (КоличествоМесяцевВладения - (МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости))/КоличествоМесяцевВладения)
      КОНЕЦ
КОНЕЦ

При тестировании этой формулы на контрольном примере ожидалось получить значение 9, однако система выводила в ячейку число 63. Давайте разберемся, как локализовать подобную ошибку и почему расчет пошел не по плану.

Пошаговая методика локализации и отладки ошибки в СКД

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

Шаг 1. Проверяем правильность ветвления условий

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


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      55
   ИНАЧЕ 
      77
КОНЕЦ

Запустив отчет с этой формулой, мы увидим, какие строки пошли по ветке незаполненной даты (вывелось 55), а какие — по ветке заполненной (вывелось 77). Если результаты на тестовых данных совпали с реальностью, значит, само логическое условие проверки даты на пустые значения работает абсолютно корректно.

Шаг 2. Изолируем расчетную часть формулы

После подтверждения корректности ветвления перейдем к проверке математической формулы внутри ветки ИНАЧЕ. Попробуем вывести промежуточный результат вычисления коэффициента месяцев:


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      55
   ИНАЧЕ 
      (КоличествоМесяцевВладения - (МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости))) / 3
КОНЕЦ

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

Шаг 3. Локализация проблемы с делением

Проверим, как СКД реагирует на другие математические операции. Попробуем выполнить сложение констант в той же ветке:


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      55
   ИНАЧЕ 
      1 + 3
КОНЕЦ

Результат сложения успешно выводится на экран и равен 4. Но как только мы меняем операцию на деление:


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      55
   ИНАЧЕ 
      1 / 3
КОНЕЦ

Ячейка снова отображается пустой! Почему это происходит?

Выясняем причину: влияние формата оформления СКД

Причина «исчезновения» данных при делении кроется не в ошибке компилятора 1С и не в делении на ноль. Все дело в форматных настройках оформления поля в СКД.

Если для вычисляемого числового поля в настройках набора данных или в оформлении конкретного элемента отчета задан формат с параметром ЧДЦ=0 (Число десятичных знаков = 0), система будет округлять все выводимые значения до целого числа.

При делении 1 / 3 получается бесконечная дробь 0.33333333.... При попытке вывести ее с форматом «0 знаков после запятой», СКД округляет 0.33 до ближайшего целого, то есть до 0. В зависимости от настроек скрытия нулевых значений в отчете, этот ноль может отображаться либо как пустое место, либо вводить в заблуждение программиста.

Решение проблемы: Обязательно проверьте свойства вычисляемого поля в СКД. На вкладке «Наборы данных» найдите ваше поле, откройте колонку «Оформление», выберите параметр «Формат» и убедитесь, что там указана корректная точность (например, ЧДЦ=2 или ЧДЦ=4), либо полностью очистите этот параметр, чтобы система выводила число с его естественной точностью.

Исправив формат отображения чисел и расставив скобки для соблюдения математического приоритета операций, мы получим работоспособную формулу:


ВЫБОР
   КОГДА ДатаСнятияПравНаОбъектНедвижимости = ДАТАВРЕМЯ(1,1,1) ТОГДА 
      ВЫБОР
         КОГДА ЕСТЬNULL(ЗначениеК, 0) = 0 ТОГДА
            СуммаНалога
         ИНАЧЕ
            СуммаНалога * ЕСТЬNULL(ЗначениеК, 1)
      КОНЕЦ
   ИНАЧЕ 
      ВЫБОР
         КОГДА ЕСТЬNULL(ЗначениеК, 0) = 0 ТОГДА
            СуммаНалога * ((КоличествоМесяцевВладения - (МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости))) / КоличествоМесяцевВладения)
         ИНАЧЕ
            (СуммаНалога * ЕСТЬNULL(ЗначениеК, 1)) * ((КоличествоМесяцевВладения - (МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости))) / КоличествоМесяцевВладения)
      КОНЕЦ
КОНЕЦ

Критические скрытые ошибки в формуле (работа над ошибками)

Хотя вышеописанная формула формально решает сиюминутную проблему отображения данных, с точки зрения промышленной разработки в ней содержится несколько критических уязвимостей, которые неизбежно приведут к неверным расчетам в реальной базе данных.

1. Ошибка перехода через границу года при расчете разности месяцев

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

МЕСЯЦ(ПериодСнятияСУчета) - МЕСЯЦ(ДатаСнятияПравНаОбъектНедвижимости)

Давайте проанализируем ситуацию, когда ПериодСнятияСУчета равен 01.01.2024, а ДатаСнятияПравНаОбъектНедвижимости равна 01.12.2023. Подставим значения месяцев в формулу:

1 - 12 = -11

Если подставить это значение в общую формулу, коэффициент владения примет вид:

(12 - (-11)) / 12 = 23 / 12 = 1.916

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

2. Игнорирование «Правила 15-го числа» налогового законодательства

Судя по названиям полей, рассчитывается налог на имущество или земельный налог. Согласно НК РФ (ст. 382, 396 НК РФ), при изменении прав на имущество в течение налогового периода применяется законодательно утвержденное «правило 15-го числа»:

Простое вычитание дат без анализа дня месяца приведет к грубейшему нарушению налогового учета и штрафам от ФНС.

3. Риск деления на ноль

В формуле присутствует деление на переменную КоличествоМесяцевВладения. Если при соединении наборов данных или из-за отсутствия сведений это поле примет значение 0 или NULL, построение отчета завершится аварийной остановкой системы.

Как сделать расчет абсолютно надежным и правильным

Чтобы исправить все вышеперечисленные недостатки, рассмотрим более надежные технические подходы.

Вариант 1. Использование встроенной функции РАЗНОСТЬДАТ в СКД

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

РазностьДат(ДатаСнятияПравНаОбъектНедвижимости, ПериодСнятияСУчета, "МЕСЯЦ")

Эта функция вернет корректное количество месяцев вне зависимости от года.

Для предотвращения деления на ноль обернем деление в проверку безопасности:


ВЫБОР 
   КОГДА КоличествоМесяцевВладения = 0 ИЛИ КоличествоМесяцевВладения ЕСТЬ NULL 
   ТОГДА 0 
   ИНАЧЕ ... // Ваша формула расчета
КОНЕЦ

Вариант 2. Перенос расчетов на уровень запроса (Архитектурно верный путь)

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

Вычисляемые поля СКД рассчитываются на самом последнем этапе компоновки данных. Это существенно усложняет оптимизацию производительности базы данных, мешает СУБД использовать индексы и лишает вас возможности быстро протестировать расчеты в консоли запросов.

Рекомендуем придерживаться следующего алгоритма проектирования отчета:

  1. Создайте временную таблицу (ВТ), в которой соберите все необходимые даты.
  2. На уровне запроса, используя операторы языка запросов ВЫБОР и функции работы с датами (включая правила анализа 15-го числа), рассчитайте точное числовое значение коэффициента владения.
  3. Передайте в СКД уже полностью готовое, предрассчитанное числовое поле коэффициента.
  4. В вычисляемом поле СКД оставьте лишь простейшее перемножение итоговых колонок: СуммаНалога * КоэффициентВладения * КоэффициентК.

Этот подход не только защитит отчет от непредвиденных ошибок деления или округления, но и значительно ускорит его формирование на больших объемах данных.

← На главную