В процессе разработки в среде 1С:Предприятие часто возникает задача автоматического пересчета значений в строках табличной части. Типичный пример: расчет средней стоимости, цены за единицу или, как в нашем случае, суммы за день. Однако при реализации такой логики начинающие разработчики часто сталкиваются с двумя критическими ошибками: «Деление на ноль» и «Переменная не определена». В этой статье мы подробно разберем причины возникновения этих ситуаций и изучим правильные методы их решения.
Разберем ситуацию, когда разработчик пытается обратиться к реквизиту колонки напрямую, например: Если Число(ЗатраченнаяСумма) <> 0 Тогда.... Система выдает ошибку, так как в контексте модуля формы ЗатраченнаяСумма не является глобальной переменной. Это реквизит конкретной строки табличной части.
Для правильного обращения к данным нам необходимо сначала получить контекст текущей строки, с которой работает пользователь. Проанализируем, как это сделать правильно:
// Для обычных форм
ТекДок = ЭлементыФормы.Долги.ТекущиеДанные;
// Для управляемых форм
ТекДок = Элементы.Долги.ТекущиеДанные;
После того как мы получили объект ТекДок (который представляет собой структуру данных текущей строки), обращение к полям должно происходить строго через этот объект: ТекДок.ЗатраченнаяСумма или ТекДок.День.
Математически деление на ноль невозможно, и платформа 1С строго следует этому правилу, прерывая выполнение кода критической ошибкой. Ошибка возникает в тот момент, когда в знаменателе (в нашем случае это колонка День) оказывается значение 0 или пустое значение, которое приводится к нулю.
Рассмотрим несколько способов предотвращения этой ситуации.
Это самый надежный и читаемый способ. Мы проверяем значение делителя перед выполнением арифметической операции. Обратите внимание, что проверять нужно именно знаменатель (количество дней), а не числитель.
ТекДок = ЭлементыФормы.Долги.ТекущиеДанные;
// Проверяем, что в строке есть данные и делитель не равен нулю
Если ТекДок <> Неопределено Тогда
Если ТекДок.День <> 0 Тогда
ТекДок.СуммаЗаДень = ТекДок.ЗатраченнаяСумма / ТекДок.День;
Иначе
// Если дней 0, устанавливаем результат в 0 или выводим предупреждение
ТекДок.СуммаЗаДень = 0;
КонецЕсли;
КонецЕсли;
В данном примере мы используем явную проверку. Это позволяет избежать ошибки даже в том случае, если пользователь еще не успел заполнить колонку День.
Если вы хотите сделать код более лаконичным, можно воспользоваться встроенным тернарным оператором ?(). Он позволяет вычислить условие в одну строку.
ТекДок = ЭлементыФормы.Долги.ТекущиеДанные;
ТекДок.СуммаЗаДень = ?(ТекДок.День = 0, 0, ТекДок.ЗатраченнаяСумма / ТекДок.День);
Здесь система сначала проверяет условие ТекДок.День = 0. Если оно истинно, возвращается 0. Если ложно — выполняется деление. Это оптимальный вариант для простых расчетов в обработчиках событий ПриИзменении.
Некоторые разработчики предлагают использовать перехват исключений. Посмотрим, как это выглядит в коде:
Попытка
ТекДок.СуммаЗаДень = ТекДок.ЗатраченнаяСумма / ТекДок.День;
Исключение
ТекДок.СуммаЗаДень = 0;
КонецПопытки;
Важное замечание: Несмотря на работоспособность, использование Попытки для обработки деления на ноль считается плохим тоном в программировании 1С. Это снижает производительность системы и может «проглотить» другие важные ошибки кода, затрудняя отладку. Рекомендуется всегда использовать явную проверку условия.
Для создания действительно надежной системы недостаточно просто избежать деления на ноль. Рассмотрим важные дополнения, которые помогут сделать ваш код профессиональным.
1. Округление результата. При делении сумм часто возникают бесконечные дроби. Для денежных полей обязательно используйте функцию Окр().
Результат = ТекДок.ЗатраченнаяСумма / ТекДок.День;
ТекДок.СуммаЗаДень = Окр(Результат, 2); // Округляем до 2 знаков (копеек)
2. Обработка NULL в запросах. Если подобные расчеты производятся не в форме, а в запросе (например, в отчете), то используется конструкция ВЫБОР. В запросах нет блоков Попытка, поэтому проверка обязательна:
ВЫБОР
КОГДА Таблица.День = 0
ТОГДА 0
ИНАЧЕ Таблица.ЗатраченнаяСумма / Таблица.День
КОНЕЦ
3. Проверка типов. Если существует вероятность, что в поле День попадет значение типа Неопределено или NULL, рекомендуется использовать функцию Число() для гарантированного приведения к числовому типу перед проверкой.
ТекущиеДанные табличной части.?() для компактности или Если для сложной логики.Соблюдение этих правил позволит вам писать стабильный код, устойчивый к ошибкам ввода пользователя и обеспечивающий точность финансовых расчетов в системе 1С.