Почему условие сравнения строк в цикле не срабатывает и возвращает значение по умолчанию в 1С?

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

При разработке алгоритмов сопоставления кодов, сценариев или выгрузок в форматы XML/XBRL разработчики часто сталкиваются с ситуацией, когда визуально идентичные строки не проходят проверку равенства в операторах Если ... Тогда. В результате функция возвращает значение ветки Иначе (например, "0" или пустое значение), хотя в коде передаются ожидаемые параметры.

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

Анализ проблемы: почему одинаковые на вид строки не равны

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


Функция fnc_scenario_418(s_id)
    Перем res_func;
    Если s_id = "A1" Тогда
        res_func = " explicitMember dimension=""dim-int:FL_YULAxis"" ";
    ИначеЕсли s_id = "A2" Тогда
        res_func = " typedMember dimension=""dim-int:ID_strokiTaxis"" ";
    ИначеЕсли s_id = "A3" Тогда
        res_func = " explicitMember dimension=""dim-int:Rezident_nerezident"" ";
    Иначе
        res_func = "0";
    КонецЕсли;
    Возврат res_func;
КонецФункции

МассивID = Новый Массив(3);
МассивID[0] = "А1";
МассивID[1] = "А2";
МассивID[2] = "А3";

Для Каждого ЭлементМассива Из МассивID Цикл
    Текст.ЗаписатьСтроку(fnc_scenario_418(ЭлементМассива) + "");
КонецЦикла;

В результате выполнения данного кода в текстовый файл записываются нули: "0", "0", "0". При этом, если передать литерал напрямую в вызов функции — fnc_scenario_418("A1") — условие успешно срабатывает.

Главная причина: использование букв из разных алфавитов (омоглифов). Оператор = в платформе 1С выполняет строгое посимвольное сопоставление по кодам символов Unicode. Русская заглавная буква «А» имеет код 1040, а латинская заглавная «A» — код 65. Визуально в редакторе кода они выглядят абсолютно одинаково, но для платформы это два совершенно разных символа, поэтому проверка равенства возвращает Ложь.

Способы диагностики скрытых различий в строках

Когда условия сравнения ведут себя неожиданно, разберем по шагам, как выявить расхождения в символах:

  1. Проверка кодов символов: используем встроенную функцию КодСимвола(), чтобы точно узнать, из каких знаков состоят сравниваемые строки.
    
    КодСимвола("А", 1); // Русская "А" вернет 1040
    КодСимвола("A", 1); // Латинская "A" вернет 65
    
  2. Временная замена на визуально отличимые символы: если есть подозрение на конфликт раскладок, заменим проблемный символ на букву, не имеющую латинского аналога (например, "Ж", "Ф") или явно латинскую букву ("F", "Z"). Если после замены логика начинает работать корректно — проблема однозначно в раскладке.
  3. Проверка скрытых и неразрывных пробелов: несовпадение также может возникать из-за концевых пробелов, переводов строк (Символы.ПС, Символы.ВК) или неразрывных пробелов (Символы.НПП, код 160). Для очистки базовых пробелов применяем СокрЛП().
  4. Корректная работа с отладчиком: при вычислении выражений в окне отладки (Shift+F9) нельзя передавать имя функции без круглых скобок. Попытка вычислить fnc_scenario_418 вызовет ошибку «Переменная не определена», так как отладчик ищет переменную с таким именем. Необходимо передавать полный вызов с параметрами: fnc_scenario_418(ЭлементМассива).

Решение 1. Унификация алфавита строковых литералов

Самое быстрое исправление — привести все строковые литералы в модуле к единой раскладке (например, только к латинице или только к кириллице):


МассивID = Новый Массив;
МассивID.Добавить("A1"); // Латинская "A"
МассивID.Добавить("A2"); // Латинская "A"
МассивID.Добавить("A3"); // Латинская "A"

Для Каждого ЭлементМассива Из МассивID Цикл
    Текст.ЗаписатьСтроку(fnc_scenario_418(ЭлементМассива));
КонецЦикла;

Решение 2. Использование коллекции «Соответствие» вместо цепочки условий

Длинные конструкции Если ... ИначеЕсли неудобны для масштабирования и подвержены ошибкам опечаток. Рассмотрим более производительный и лаконичный подход с использованием объекта Соответствие:


Функция ПолучитьСценарийПоИдентификатору(Идентификатор)
    
    // Инициализируем таблицу сопоставления
    КартаСценариев = Новый Соответствие;
    КартаСценариев.Вставить("A1", " explicitMember dimension=""dim-int:FL_YULAxis"" ");
    КартаСценариев.Вставить("A2", " typedMember dimension=""dim-int:ID_strokiTaxis"" ");
    КартаСценариев.Вставить("A3", " explicitMember dimension=""dim-int:Rezident_nerezident"" ");
    
    Результат = КартаСценариев.Получить(СокрЛП(Идентификатор));
    
    // Если ключ не найден, возвращаем значение по умолчанию
    Если Результат = Неопределено Тогда
        Возврат "0";
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Использование объекта Соответствие позволяет производить поиск значения по ключу за фиксированное время O(1) и делает добавление новых сценариев значительно проще и безопаснее.

Решение 3. Программная нормализация входных данных

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


Функция НормализоватьКод(ВходнаяСтрока)
    
    СтрокаОбработки = ВРег(СокрЛП(ВходнаяСтрока));
    
    // Заменяем распространенные русские буквы на латинские аналоги
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "А", "A");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "В", "B");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "С", "C");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "Е", "E");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "Н", "H");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "К", "K");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "М", "M");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "О", "O");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "Р", "P");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "Т", "T");
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, "Х", "X");
    
    Возврат СтрокаОбработки;
    
КонецФункции

Применение функции предварительной нормализации гарантирует, что вне зависимости от того, на какой раскладке был введен символ "А", алгоритм получит единообразное значение для сопоставления.

← На главную