Почему при суммировании в цикле возникает ошибка или отладчик возвращает значение Ложь в 1С?

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

При выгрузке данных в форматы обмена (например, в XML или JSON) разработчики часто сталкиваются с необходимостью параллельного подсчета итоговых сумм и количеств. В процессе отладки таких алгоритмов нередко возникают две взаимосвязанные проблемы: аварийное завершение с ошибкой «Преобразование значения к типу Число не может быть выполнено» или неожиданный результат Ложь вместо рассчитанного числа при проверке строки в табло отладчика. Разберем подробно, почему это происходит и как правильно организовать структуры данных и циклы в 1С.

Особенность работы отладчика: почему выражение возвращает Ложь

Проанализируем ситуацию, когда разработчик в окне «Вычислить выражение» (Shift+F9) или в «Табло» вводит строку целиком из модуля, например:

Количество = Количество + Массив[Счетчик][4]

В кодовой базе платформы 1С символ = выполняет две функции в зависимости от контекста:

  1. Оператор присваивания: используется в текстах процедур и функций для записи нового значения в переменную.
  2. Оператор сравнения: используется в логических выражениях (например, в условиях Если ... Тогда).

В окне отладчика знак = всегда воспринимается исключительно как операция сравнения. Отладчик не выполняет присваивание, а проверяет, равно ли текущее значение переменной Количество (допустим, 0) сумме этой же переменной и элемента массива (0 + 1 = 1). Так как 0 не равен 1, отладчик возвращает булево значение Ложь. Это создает ложное впечатление, будто в саму переменную записывается логический тип вместо числа.

Чтобы корректно проверить результат вычисления в отладчике, необходимо передавать только правую часть выражения без присваивания: Количество + Массив[Счетчик][4].

Причины ошибки преобразования к типу Число

Если в процессе выполнения кода платформа выдает исключение «Преобразование значения к типу Число не может быть выполнено» на строке сложения, выясним возможные источники проблемы:

  1. Нечисловой тип данных в ячейке: операция сложения (+) завершается критической ошибкой, если один из операндов имеет тип Null, Неопределено, пустую ссылку или нечисловую строку. Если массив заполняется результатами запроса, в котором использовались левые соединения, ненайденные значения вернут Null. Для предотвращения таких ситуаций в запросе следует обязательно использовать функцию ЕСТЬNULL(Поле, 0).
  2. Выход за границы массива: обращение по жестко заданным индексам вида Массив[299][9] в условии цикла Пока Счетчик <> Массив[299][9] Цикл приводит к тому, что при изменении размерности данных или опечатке в индексе считывается некорректная ячейка либо возникает ошибка «Индекс находится за границами массива».
  3. Именование переменных: использование имени переменной Количество крайне нежелательно, так как оно совпадает с именем встроенного метода коллекций платформы 1С (.Количество()). Это ухудшает читаемость кода и провоцирует скрытые ошибки. Для итоговых показателей безопаснее использовать имена ИтогоКоличество или ВсегоКоличество.

Рефакторинг: переход от многомерных массивов к безопасным структурам данных

Хранение табличных данных в многомерных массивах с цифровыми индексами (Массив[Счетчик][0], Массив[Счетчик][4]) делает код уязвимым к любым изменениям структуры запроса. Оптимальным решением является использование объекта ТаблицаЗначений или массива структур с явными именами колонок.

Рассмотрим, как преобразовать исходный алгоритм формирования XML в надежный и читаемый вид:


// Инициализация записи XML
ЗаписьXML.ЗаписатьНачалоЭлемента("DocumentLines");

// Получаем таблицу значений с типизированными колонками из запроса
ТаблицаТоваров = ЗапросТоваров(Элемент.Значение);

// Безопасный обход строк с помощью цикла Для Каждого
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Line");
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("GroupName");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.GroupName));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("LineNumber");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.LineNumber));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("LotNumber");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.LotNumber));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("GoodCode");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.GoodCode));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("NameGoods");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.NameGoods));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("NumberGoods");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.Количество));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("UnitName");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТовара.UnitName));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("UnitPrice");
    ЗаписьXML.ЗаписатьТекст(Формат(СтрокаТовара.Цена, "ЧРД=.; ЧГ=0"));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Currency");
    ЗаписьXML.ЗаписатьТекст(СтрЗаменить(СтрокаТовара.Currency, "*", ""));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Line
    
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // DocumentLines

// Подсчет общего количества без ручного сложения в цикле
ИтогоКоличество = ТаблицаТоваров.Итог("Количество");

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

  1. Исключение ошибок индексации: цикл Для Каждого автоматически обходит все строки коллекции от первой до последней, исключая выход за границы массива или бесконечное зацикливание при сбое условий.
  2. Быстрый расчет итогов: метод ТаблицаЗначений.Итог("ИмяКолонки") выполняет суммирование платформенными средствами на уровне C++, что работает быстрее ручного сложения в цикле и защищает от ошибок несовпадения типов.
  3. Корректная сериализация: применение функции XMLСтрока() обеспечивает правильное приведение встроенных типов 1С к стандартам XML без необходимости вручную вызывать Строка().
← На главную