Почему функция СтрНайти() возвращает Булево вместо числа и как это исправить

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

В практике разработчика 1С иногда возникают ситуации, которые кажутся паранормальными: стандартная системная функция начинает вести себя вопреки описанию в синтакс-помощнике. Типичный пример — функция СтрНайти(), которая должна возвращать позицию символа (число), но внезапно возвращает Истина или Ложь. Давайте детально разберем, почему это происходит, как провести диагностику и какими способами можно решить эту проблему.

Причина №1: Наличие одноименной функции в глобальном модуле

Разберем исторический контекст. Функция СтрНайти() появилась в платформе 1С:Предприятие далеко не сразу (начиная с версии 8.3.6). До этого разработчики использовали функцию Найти(). Однако во многих старых конфигурациях, работающих в режиме совместимости (например, 8.2.13 или 8.3.3), программисты создавали свои собственные "обертки" с названием СтрНайти() в общих модулях с установленным признаком Глобальный.

Проблема заключается в приоритетах вызова имен в 1С. Проанализируем ситуацию: если в конфигурации существует экспортная функция СтрНайти() в глобальном общем модуле, то при определенных настройках режима совместимости платформа будет вызывать именно её, а не встроенный системный метод. Если автор этой "самописной" функции решил, что ему достаточно знать только сам факт наличия подстроки, он мог написать внутри Возврат Результат > 0;. В итоге во всей базе системный механизм оказывается "отравлен" этим костылем.

Причина №2: Неявное преобразование типов при присваивании

Посмотрим на ситуацию со стороны типов данных. Если переменная Поз, в которую вы записываете результат функции, является не просто локальной переменной, а реквизитом объекта или формы с жестко заданным типом Булево, платформа выполнит неявное приведение типов. В 1С действует правило: любое число, не равное нулю, при приведении к булеву превращается в Истина, а ноль — в Ложь.

Проверим это на примере кода:


// Предположим, Объект.ПозицияСимвола имеет тип Булево в метаданных
Объект.ПозицияСимвола = СтрНайти("Мама мыла раму", "мыла"); 
// Системная функция вернет 6, но в реквизит запишется Истина

Как провести диагностику и найти виновника

Если вы столкнулись с тем, что СтрНайти() возвращает булево значение, выполним следующие шаги для поиска "самозванца":

  1. Использование перехода к определению (F12): Выделите имя функции в коде и нажмите F12. Если платформа перейдет в общий модуль, значит, системная функция перекрыта. Если переход не срабатывает с первого раза (как упоминалось в обсуждении), попробуйте обновить индекс поиска или перезапустить конфигуратор.
  2. Замер производительности: Это самый надежный способ. Запустите отладку, откройте меню "Отладка" — "Замер производительности", выполните проблемный участок кода и остановите замер. В появившейся таблице вы увидите точный путь к программному модулю и номер строки, где физически отработал алгоритм СтрНайти().
  3. Глобальный поиск: Нажмите Ctrl + Shift + F и введите запрос Функция СтрНайти. Обязательно ищите по всей конфигурации, включая свойства общих модулей.

Варианты решения проблемы

Рассмотрим несколько способов исправления ситуации в зависимости от ваших прав доступа к коду и требований стабильности системы.

Способ 1: Исправление глобальной функции

Если вы нашли ту самую "самописную" функцию, проанализируем её код. Скорее всего, она выглядит так:


Функция СтрНайти(Строка, Подстрока) Экспорт
    Результат = Найти(Строка, Подстрока);
    Возврат Результат > 0; // Ошибка здесь! Должно возвращаться число.
КонецФункции

Необходимо исправить возврат значения на числовой тип, чтобы эмулировать поведение стандартной функции платформы:


Функция СтрНайти(Строка, Подстрока, Направление = Неопределено, НачальнаяПозиция = Неопределено, НомерВхождения = Неопределено) Экспорт
    // Если режим совместимости низкий, используем старую функцию Найти()
    Возврат Найти(Строка, Подстрока);
КонецФункции

Способ 2: Использование функции Найти()

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


// Вместо Поз = СтрНайти(Текст, "23");
Поз = Найти(Текст, "23"); 

Способ 3: Обход через англоязычный синоним

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

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

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

Таким образом, мы выяснили, что странное поведение СтрНайти() — это не баг платформы, а следствие особенностей архитектуры 1С, связанное с наследованием старого кода и приоритетами глобальных модулей. Будьте внимательны при работе в старых конфигурациях и всегда используйте замер производительности для локализации подобных проблем.

← На главную