В практике разработчика 1С иногда возникают ситуации, которые кажутся паранормальными: стандартная системная функция начинает вести себя вопреки описанию в синтакс-помощнике. Типичный пример — функция СтрНайти(), которая должна возвращать позицию символа (число), но внезапно возвращает Истина или Ложь. Давайте детально разберем, почему это происходит, как провести диагностику и какими способами можно решить эту проблему.
Разберем исторический контекст. Функция СтрНайти() появилась в платформе 1С:Предприятие далеко не сразу (начиная с версии 8.3.6). До этого разработчики использовали функцию Найти(). Однако во многих старых конфигурациях, работающих в режиме совместимости (например, 8.2.13 или 8.3.3), программисты создавали свои собственные "обертки" с названием СтрНайти() в общих модулях с установленным признаком Глобальный.
Проблема заключается в приоритетах вызова имен в 1С. Проанализируем ситуацию: если в конфигурации существует экспортная функция СтрНайти() в глобальном общем модуле, то при определенных настройках режима совместимости платформа будет вызывать именно её, а не встроенный системный метод. Если автор этой "самописной" функции решил, что ему достаточно знать только сам факт наличия подстроки, он мог написать внутри Возврат Результат > 0;. В итоге во всей базе системный механизм оказывается "отравлен" этим костылем.
Посмотрим на ситуацию со стороны типов данных. Если переменная Поз, в которую вы записываете результат функции, является не просто локальной переменной, а реквизитом объекта или формы с жестко заданным типом Булево, платформа выполнит неявное приведение типов. В 1С действует правило: любое число, не равное нулю, при приведении к булеву превращается в Истина, а ноль — в Ложь.
Проверим это на примере кода:
// Предположим, Объект.ПозицияСимвола имеет тип Булево в метаданных
Объект.ПозицияСимвола = СтрНайти("Мама мыла раму", "мыла");
// Системная функция вернет 6, но в реквизит запишется Истина
Если вы столкнулись с тем, что СтрНайти() возвращает булево значение, выполним следующие шаги для поиска "самозванца":
F12. Если платформа перейдет в общий модуль, значит, системная функция перекрыта. Если переход не срабатывает с первого раза (как упоминалось в обсуждении), попробуйте обновить индекс поиска или перезапустить конфигуратор.СтрНайти().Ctrl + Shift + F и введите запрос Функция СтрНайти. Обязательно ищите по всей конфигурации, включая свойства общих модулей.Рассмотрим несколько способов исправления ситуации в зависимости от ваших прав доступа к коду и требований стабильности системы.
Если вы нашли ту самую "самописную" функцию, проанализируем её код. Скорее всего, она выглядит так:
Функция СтрНайти(Строка, Подстрока) Экспорт
Результат = Найти(Строка, Подстрока);
Возврат Результат > 0; // Ошибка здесь! Должно возвращаться число.
КонецФункции
Необходимо исправить возврат значения на числовой тип, чтобы эмулировать поведение стандартной функции платформы:
Функция СтрНайти(Строка, Подстрока, Направление = Неопределено, НачальнаяПозиция = Неопределено, НомерВхождения = Неопределено) Экспорт
// Если режим совместимости низкий, используем старую функцию Найти()
Возврат Найти(Строка, Подстрока);
КонецФункции
Если вам нужно просто найти первое вхождение подстроки и вы не хотите воевать с глобальными модулями, используйте классическую функцию Найти(). Она является более старой, но стабильной и редко перекрывается разработчиками, так как существует в платформе "изначально".
// Вместо Поз = СтрНайти(Текст, "23");
Поз = Найти(Текст, "23");
В некоторых случаях (если режим совместимости позволяет) можно попробовать вызвать англоязычный синоним StrFind(). Однако, как показывает практика, если глобальный модуль перекрыл русское имя, платформа в старых режимах совместимости может блокировать и англоязычный вариант. Тем не менее, это стоит проверить, если у вас нет возможности править общий модуль.
Выясним причину, почему такие ситуации вообще возникают. Это происходит из-за плохой практики именования пользовательских функций именами, которые могут совпасть с будущими именами функций платформы. Проанализируем профессиональный подход:
СтрНайти, СтрШаблон, Округлить. Используйте уникальные имена, например РаботаСоСтрокамиЛокальная.СтрНайти().ТипЗнч(Поз) в отладчике, чтобы убедиться, что проблема именно в функции, а не в переменной-приемнике.Таким образом, мы выяснили, что странное поведение СтрНайти() — это не баг платформы, а следствие особенностей архитектуры 1С, связанное с наследованием старого кода и приоритетами глобальных модулей. Будьте внимательны при работе в старых конфигурациях и всегда используйте замер производительности для локализации подобных проблем.