При разработке или модификации внешних обработок и отчетов в среде «1С:Предприятие» программисты часто сталкиваются с ситуацией, когда код, успешно работающий в одной базе, выдает критическую ошибку в другой. Одной из самых распространенных проблем при работе со строками является ошибка: «Процедура или функция с указанным именем не определена (СтрНайти)». Рассмотрим подробно, почему это происходит, как режим совместимости влияет на доступность встроенных функций и какими способами можно решить эту задачу, сохранив работоспособность системы.
Для начала разберем ситуацию, в которой оказался автор вопроса. Несмотря на то, что используется современная версия платформы (например, 8.3.12 или выше), система при синтаксической проверке или выполнении кода сообщает, что функция СтрНайти ей неизвестна. Проанализируем техническую подоплеку этой проблемы.
Функция СтрНайти была добавлена в платформу «1С:Предприятие» только в версии 8.3.6.1977. До этого момента основным инструментом поиска подстроки была функция Найти. Однако ключевым фактором здесь является не версия установленной платформы, а режим совместимости конфигурации. Если в свойствах вашей конфигурации установлен режим совместимости «Версия 8.2.16» (как в случае с Бухгалтерией предприятия 2.0 или УПП), платформа намеренно блокирует доступ ко всем новым методам встроенного языка, которые появились в версиях выше 8.2.
Выясним, почему 1С ведет себя именно так. Режим совместимости гарантирует, что конфигурация будет работать на старом ядре без изменений в логике запросов, поведении интерфейса и работе системных функций. Поэтому использование СтрНайти в таких базах невозможно без изменения глобальных настроек конфигурации, что зачастую недопустимо для рабочих систем.
Самый простой и правильный путь решения проблемы в режиме совместимости ниже 8.3.6 — это возврат к классической функции Найти. Рассмотрим, как изменить код, чтобы он стал универсальным. Проанализируем различия в синтаксисе:
Старый синтаксис функции Найти принимает всего два параметра: исходную строку и искомую подстроку. Рассмотрим пример адаптации кода:
// Вместо нового варианта:
// НомерВхождения = СтрНайти(СтрокаТЗ.Комментарий, "#");
// Используем классический вариант:
НомерВхождения = Найти(СтрокаТЗ.Комментарий, "#");
Нужно учитывать, что функция Найти всегда возвращает позицию первого вхождения подстроки и ищет только с начала строки. Если ваша задача ограничивается простым поиском символа (как в примере автора с символом «#»), этого будет вполне достаточно.
Рассмотрим более сложную ситуацию. Новая функция СтрНайти удобна тем, что позволяет указать параметр НомерВхождения. Если нам нужно найти, например, вторую или третью решетку в строке комментария, простая замена на Найти не сработает. Разберем алгоритм, который позволяет эмулировать это поведение в старых версиях платформы.
Для поиска второго вхождения нам потребуется выполнить поиск первого, «отрезать» найденную часть строки и повторить поиск. Посмотрим на пример кода, реализующий эту логику:
// Пример поиска второго вхождения символа "#" в строку
ИсходнаяСтрока = СтрокаТЗ.Комментарий;
ИскомыйСимвол = "#";
НомерНужногоВхождения = 2;
ТекущаяПозиция = 0;
НайденоВхождений = 0;
Для Итератор = 1 По НомерНужногоВхождения Цикл
ПозицияВхолостую = Найти(Сред(ИсходнаяСтрока, ТекущаяПозиция + 1), ИскомыйСимвол);
Если ПозицияВхолостую > 0 Тогда
ТекущаяПозиция = ТекущаяПозиция + ПозицияВхолостую;
НайденоВхождений = НайденоВхождений + 1;
Иначе
ТекущаяПозиция = 0;
Прервать;
КонецЕсли;
КонецЦикла;
// В переменной ТекущаяПозиция теперь находится индекс нужного вхождения
Если ТекущаяПозиция > 0 Тогда
// Продолжаем логику обработки
КонецЕсли;
Если вы часто используете расширенный поиск строк во внешней обработке, разберем, как написать собственную функцию СтрНайти, которая будет доступна внутри вашего модуля даже в режиме совместимости 8.2. Посмотрим на программную реализацию, которую можно разместить в разделе «Процедуры и функции» вашей обработки:
Функция МояСтрНайти(Знач Строка, ПодстрокаПоиска, НачальнаяПозиция = 1, НомерВхождения = 1)
Результат = 0;
ТекущаяСтрока = Сред(Строка, НачальнаяПозиция);
Смещение = НачальнаяПозиция - 1;
Для Индекс = 1 По НомерВхождения Цикл
Поз = Найти(ТекущаяСтрока, ПодстрокаПоиска);
Если Поз = 0 Тогда
Возврат 0;
КонецЕсли;
Результат = Смещение + Поз;
// Готовим строку для следующего поиска
ТекущаяСтрока = Сред(ТекущаяСтрока, Поз + 1);
Смещение = Результат;
КонецЦикла;
Возврат Результат;
КонецФункции
Проанализируем преимущества такого подхода: вы сохраняете логику кода, близкую к современному стандарту 1С, и при этом обеспечиваете полную совместимость со старыми конфигурациями (УПП, БП 2.0). Вам достаточно заменить в тексте модуля вызовы встроенной СтрНайти на вашу МояСтрНайти.
Рассмотрим вопрос, который часто задают начинающие разработчики: «Почему бы просто не изменить версию совместимости в свойствах конфигурации на 8.3.6?». Выясним, чем это грозит крупной корпоративной системе:
Важный совет: Если вы разрабатываете внешнюю обработку, которая должна работать у разных клиентов, всегда ориентируйтесь на минимально возможные функции платформы. Использование Найти вместо СтрНайти делает ваш инструмент более универсальным и надежным.
Посмотрим, как должен выглядеть исправленный фрагмент кода из исходного сообщения автора, чтобы он успешно прошел проверку в «Толстом клиенте (обычное приложение)»:
// Очищаем переменную для результата
НомерВхождения = 0;
// Используем классическую функцию Найти()
// В режиме совместимости 8.2.16 доступна только она
НомерВхождения = Найти(СокрЛП(СтрокаТЗОтчетПроизводстваЗаСмену.Комментрарий), "#");
Если НомерВхождения > 0 Тогда
// Извлекаем часть строки начиная с символа #
ОтчетКоммент = СокрЛП(Сред(СтрокаТЗОтчетПроизводстваЗаСмену.Комментрарий, НомерВхождения));
Если ОтчетКоммент = РеализацияКомментарий Тогда
СтрРеалицации.СформированОтчет = "Сформирован";
КонецЕсли;
КонецЕсли;
В данном примере мы проанализировали ситуацию и выяснили, что для решения задачи достаточно первого вхождения символа «#». Следовательно, переход на Найти является оптимальным решением, не требующим написания сложных циклов или изменения метаданных конфигурации.
Подводя итог, отметим: работа в экосистеме 1С требует понимания того, что платформа постоянно развивается, но прикладные решения могут годами оставаться на старых технологических рельсах. Всегда проверяйте доступность методов в синтакс-помощнике (раздел «Доступность»), обращая внимание на примечания о режиме совместимости.