Как найти и исправить ошибку в сложной формуле расчета типа цен в 1С?

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

При настройке автоматического расчета цен в программах «1С:Предприятие 8» (таких как «Управление торговлей», «ERP» или «Комплексная автоматизация») пользователи и разработчики часто сталкиваются с необходимостью создания сложных многоуровневых условий. Типичный инструмент для этого — тернарный оператор или встроенная функция ?(). Однако при большом количестве вложений легко допустить ошибку, которую система прокомментирует лаконичным сообщением: «В формуле обнаружены ошибки».

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

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

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


?([Розничные]*100/[Закупочные]-100 < 25,[Розничные]*97/100,
?([Розничные]*100/[Закупочные]-100 >= 25 и [Розничные]*100/[Закупочные]-100 < 30,[Розничные]*96/100,
?([Розничные]*100/[Закупочные]-100 >= 30 и [Розничные]*100/[Закупочные]-100 < 35,[Розничные]*95/100,
?([Розничные]*100/[Закупочные]-100 >= 35 и [Розничные]*100/[Закупочные]-100 < 45,[Розничные]*94/100,
?([Розничные]*100/[Закупочные]-100 >= 45 и [Розничные]*100/[Закупочные]-100 < 60,[Розничные]*93/100,
?([Розничные]*100/[Закупочные]-100 >= 60 и [Розничные]*100/[Закупочные]-100 < 65,[Розничные]*90/100,
?([Розничные]*100/[Закупочные]-100 >= 65 ,[Розничные]*88/100)))))))

Проанализируем, почему эта формула не работает. Основная причина кроется в синтаксисе функции ?(). В языке 1С эта функция является аналогом конструкции Если...Тогда...Иначе и всегда требует три параметра:

  1. Условие (выражение, возвращающее Истину или Ложь).
  2. Значение, если условие Истинно.
  3. Значение, если условие Ложно.

Посмотрим на самую внутреннюю часть формулы автора: ?([Розничные]*100/[Закупочные]-100 >= 65 ,[Розничные]*88/100). Здесь указано условие и значение «Тогда», но отсутствует обязательное значение «Иначе». Программа не понимает, что делать, если наценка окажется меньше 65 (в контексте последнего вложения), и выдает ошибку синтаксиса.

Решение №1: Исправление синтаксиса

Чтобы формула заработала, нам необходимо «закрыть» каждое вложение значением, которое будет возвращено, если ни одно из предыдущих условий не выполнилось. Рассмотрим исправленный вариант, где в последнем условии добавлено значение по умолчанию (например, сама розничная цена или ноль):


?([Розничные]*100/[Закупочные]-100 < 25,[Розничные]*97/100,
?([Розничные]*100/[Закупочные]-100 >= 25 и [Розничные]*100/[Закупочные]-100 < 30,[Розничные]*96/100,
?([Розничные]*100/[Закупочные]-100 >= 30 и [Розничные]*100/[Закупочные]-100 < 35,[Розничные]*95/100,
?([Розничные]*100/[Закупочные]-100 >= 35 и [Розничные]*100/[Закупочные]-100 < 45,[Розничные]*94/100,
?([Розничные]*100/[Закупочные]-100 >= 45 и [Розничные]*100/[Закупочные]-100 < 60,[Розничные]*93/100,
?([Розничные]*100/[Закупочные]-100 >= 60 и [Розничные]*100/[Закупочные]-100 < 65,[Розничные]*90/100,
?([Розничные]*100/[Закупочные]-100 >= 65 ,[Розничные]*88/100, [Розничные])))))))

Здесь в самом конце добавлена переменная [Розничные]. Теперь функция имеет все три аргумента и будет корректно интерпретирована системой.

Решение №2: Оптимизация логики (Упрощение)

Проанализируем структуру условий. Заметим, что мы проверяем диапазоны последовательно. Если первое условие наценка < 25 не выполнилось, это автоматически означает, что наценка >= 25. Следовательно, во второй строке повторная проверка [Розничные]*100/[Закупочные]-100 >= 25 является избыточной.

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


?([Розничные]*100/[Закупочные]-100 < 25, [Розничные]*0.97,
?([Розничные]*100/[Закупочные]-100 < 30, [Розничные]*0.96,
?([Розничные]*100/[Закупочные]-100 < 35, [Розничные]*0.95,
?([Розничные]*100/[Закупочные]-100 < 45, [Розничные]*0.94,
?([Розничные]*100/[Закупочные]-100 < 60, [Розничные]*0.93,
?([Розничные]*100/[Закупочные]-100 < 65, [Розничные]*0.90, [Розничные]*0.88))))))

Преимущества такого подхода:

Важные рекомендации по работе с ценами

Проанализируем еще несколько критических моментов, которые часто упускаются при написании формул в типах цен.

1. Защита от деления на ноль

В формуле используется делитель [Закупочные]. Если для какого-то товара закупочная цена не будет установлена (равна 0), расчет всей колонки цен прервется с ошибкой. Рекомендуем всегда добавлять проверку делителя с помощью функции ?() или Макс(). Например:

[Розничные]*100 / ?([Закупочные] = 0, 1, [Закупочные])

2. Округление результата

При умножении на коэффициенты вроде 0.97 или 97/100 часто получаются дробные числа с большим количеством знаков после запятой (например, 150.33333). Для корректной работы кассового ПО и эстетичного вида ценников следует использовать функцию округления:

Окр(ВашаФормула, 2) — для округления до копеек.

3. Читаемость кода

Хотя редактор 1С позволяет писать формулу в одну строку, мы советуем использовать переносы строк и отступы («лесенку»), как показано в примерах выше. Это никак не влияет на производительность системы, но позволяет визуально сопоставить открывающие и закрывающие скобки, количество которых должно строго совпадать.

Альтернативные методы реализации

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

Подводя итог, помните: любая функция ?() должна иметь три составляющих, а последовательная проверка диапазонов позволяет значительно упростить логику, убрав лишние сравнения И.

← На главную