К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как заменить строку в 1С: функции и примеры кода

Как заменить строку в 1С: функция СтрЗаменить, поиск подстроки через СтрНайти, замена в многострочном тексте, типичные ошибки и примеры кода на встроенном языке.

Замена подстроки — одна из самых частых операций при работе с текстом в 1С: очистка номеров документов от префиксов, подстановка значений в шаблоны печатных форм, нормализация данных при обмене. Во встроенном языке за это отвечает функция СтрЗаменить, а для контроля результата используются функции поиска — СтрНайти и СтрЧислоВхождений.

Главная особенность, о которой часто забывают: строки в 1С неизменяемы. СтрЗаменить не меняет исходную переменную, а возвращает новую строку. Если не присвоить результат обратно, замена «потеряется» без всякой ошибки — код отработает, но данные останутся прежними.

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

Функция СтрЗаменить: синтаксис и базовый пример

Функция имеет три обязательных параметра: исходная строка, искомая подстрока и строка замены. Все вхождения искомого фрагмента заменяются за один вызов — перебирать вхождения вручную не требуется.

НомерДокумента = "ПР-000123";

НомерБезПрефикса = СтрЗаменить(НомерДокумента, "ПР-", "");

// Результат: "000123"

Текст = "Уважаемый [Клиент]!";

Приветствие = СтрЗаменить(Текст, "[Клиент]", "Иван Петров");

// Результат: "Уважаемый Иван Петров!"

Если искомая подстрока не найдена, функция просто возвращает исходную строку без изменений — исключения не возникает. Это удобно для шаблонов: можно последовательно «прогонять» текст через серию замен, не проверяя наличие каждого маркера.

Обратите внимание: пустая строка в качестве третьего параметра — легальный способ удалить фрагмент. А вот пустая строка в качестве искомого значения недопустима и приведёт к ошибке выполнения.

Поиск перед заменой: СтрНайти и СтрЧислоВхождений

Часто замену нужно выполнять условно — только если фрагмент действительно присутствует. Для этого используется СтрНайти, которая возвращает позицию первого вхождения (начиная с 1) или 0, если подстрока не найдена.

Строка = "Заказ № АБВ-456 от клиента";

Если СтрНайти(Строка, "АБВ-") > 0 Тогда

Строка = СтрЗаменить(Строка, "АБВ-", "XYZ-");

КонецЕсли;

Функция СтрЧислоВхождений возвращает количество вхождений подстроки. Она полезна для проверки результата: после замены число вхождений старого фрагмента должно стать нулевым, а нового — соответствовать ожиданию.

Замена без учёта регистра

СтрЗаменить всегда регистрозависима, и это одна из самых частых причин «неработающей» замены. Если регистр символов в данных непредсказуем (например, пользовательский ввод), надёжный приём — работать через копию строки в одном регистре, вычисляя позиции в ней, а вырезать фрагменты из оригинала.

Функция ЗаменитьБезРегистра(Исходная, ЧтоИскать, НаЧтоЗаменить)

Результат = Исходная;

НижнийРезультат = НРег(Результат);

ИскомоеНижний = НРег(ЧтоИскать);

Позиция = СтрНайти(НижнийРезультат, ИскомоеНижний);

Пока Позиция > 0 Цикл

Результат = Лев(Результат, Позиция - 1) + НаЧтоЗаменить

+ Сред(Результат, Позиция + СтрДлина(ЧтоИскать));

НижнийРезультат = НРег(Результат);

Позиция = СтрНайти(НижнийРезультат, ИскомоеНижний);

КонецЦикла;

Возврат Результат;

КонецФункции

Такой подход сохраняет исходный регистр остального текста и корректно обрабатывает смешанные варианты написания. Для разовых простых случаев, где регистр заведомо известен, достаточно обычной СтрЗаменить.

Последовательная замена в шаблонах

Типовой сценарий — подстановка нескольких значений в шаблон письма, СМС или печатной формы. Замены выполняются цепочкой: результат каждой операции передаётся в следующую.

Порядок действий
  1. 1
    Подготовьте шаблон с уникальными маркерами, например [ФИО], [Дата], [Сумма]
  2. 2
    Последовательно вызовите СтрЗаменить для каждого маркера, присваивая результат той же переменной
  3. 3
    Проверьте через СтрНайти(Текст, "["), что незаменённых маркеров не осталось
  4. 4
    Передайте готовый текст в печатную форму, письмо или сообщение
Текст = Шаблон;

Текст = СтрЗаменить(Текст, "[ФИО]", Данные.ФИО);

Текст = СтрЗаменить(Текст, "[Дата]", Формат(Данные.Дата, "ДЛФ=D"));

Текст = СтрЗаменить(Текст, "[Сумма]", Формат(Данные.Сумма, "ЧДЦ=2"));

Если СтрНайти(Текст, "[") > 0 Тогда

Сообщить("В шаблоне остались незаполненные маркеры");

КонецЕсли;

Порядок замен имеет значение, если маркеры пересекаются: например, замена «[Дата]» до «[ДатаОплаты]» может повредить второй маркер. Используйте маркеры, которые не являются началом друг друга, или заменяйте более длинные маркеры первыми.

Замена в многострочном тексте и спецсимволы

СтрЗаменить корректно работает с переносами строк, табуляцией и другими служебными символами — их можно указывать через объект Символы. Это удобно для нормализации текста, пришедшего из файлов или внешних систем.

// Убрать символы возврата каретки после загрузки из файла Unix-формата

Текст = СтрЗаменить(Текст, Символы.ВК, "");

// Заменить табуляции на точку с запятой для выгрузки

Строка = СтрЗаменить(Строка, Символы.Таб, ";");

// Убрать неразрывные пробелы из чисел, скопированных из Excel

ЧислоСтрокой = СтрЗаменить(ЧислоСтрокой, Символ(160), "");

ЧислоСтрокой = СтрЗаменить(ЧислоСтрокой, " ", "");

Неразрывный пробел (код 160) — классическая ловушка при разборе чисел и сумм: визуально он неотличим от обычного пробела, но СтрЗаменить с обычным пробелом его не находит, а преобразование к числу завершается ошибкой. Если данные приходят из внешних источников, удаляйте оба варианта.

Типичные ошибки
01
Вызов СтрЗаменить без присваивания результата — строка не меняется, ошибки нет
02
Поиск и замена с разным регистром — фрагмент визуально есть, но не заменяется
03
Замена обычного пробела там, где стоит неразрывный пробел (код 160)
04
Пересекающиеся маркеры шаблона — замена короткого маркера портит длинный
05
Передача пустой строки как искомой подстроки — ошибка выполнения

Альтернативные способы: Лев, Сред, Прав и разбор строки

Иногда замену удобнее выполнить не поиском, а конструированием строки из частей. Функции Лев, Сред, Прав и СтрДлина позволяют собрать новое значение по известным позициям — например, заменить символ в фиксированной позиции кода или артикула.

// Заменить третий символ в коде фиксированной длины

Код = "АБВ123";

НовыйКод = Лев(Код, 2) + "Х" + Сред(Код, 4);

// Результат: "АБХ123"

Для сложных сценариев — замена по маске, обработка разделителей, работа со списками — полезны СтрРазделить и СтрСоединить: строка разбивается в массив, элементы обрабатываются по отдельности, затем собираются обратно. В толстом клиенте и на сервере доступны также регулярные выражения через COM-объект VBScript.RegExp, но это решение зависит от платформы и операционной системы, поэтому в кроссплатформенных решениях его избегают.

Сравнение вариантов

СтрЗаменить

Универсальный способ для точной замены всех вхождений; не подходит для поиска без учёта регистра и масок

Лев/Сред/Прав

Замена по известным позициям в строках фиксированной структуры; требует точного знания длины

СтрРазделить + СтрСоединить

Обработка списков и разделителей; избыточно для простой одиночной замены

Регулярные выражения (COM)

Замена по маске; зависит от ОС и недоступна в веб-клиенте и мобильной платформе

Проверка результата и отладка

После замены полезно убедиться, что она действительно произошла и не затронула лишнего. Минимальный набор проверок: искомый фрагмент отсутствует, длина строки изменилась ожидаемо, количество вхождений нового фрагмента совпадает с расчётным.

Контрольные точки

Как проверить результат

СтрНайти(Результат, СтарыйФрагмент)
Норма

Возвращает 0 — старых вхождений не осталось

Тревожный признак

Возвращает позицию > 0 — замена не сработала или сработала частично

СтрЧислоВхождений(Результат, НовыйФрагмент)
Норма

Равно ожидаемому числу замен

Тревожный признак

Больше ожидаемого — новый фрагмент уже встречался в тексте

СтрДлина исходной и итоговой строки
Норма

Разница соответствует разнице длин фрагментов, умноженной на число замен

Тревожный признак

Неожиданная длина — заменено лишнее или ничего не заменено

При отладке в конфигураторе используйте табло (Shift+F9), чтобы увидеть реальное содержимое строки, включая непечатаемые символы. Если строка длинная, выведите её в сообщение или сохраните в текстовый документ и откройте в редакторе с отображением служебных символов.

Итог

Что важно запомнить

СтрЗаменить возвращает новую строку и заменяет все вхождения с учётом регистра. Результат всегда присваивайте переменной, проверяйте через СтрНайти и СтрЧислоВхождений, а при данных из внешних источников очищайте неразрывные пробелы и служебные символы.

Частые вопросы

Почему СтрЗаменить не меняет мою строку?

Функция не изменяет исходную переменную, а возвращает новое значение. Запись вида СтрЗаменить(Текст, "а", "б") без присваивания ничего не делает. Правильно: Текст = СтрЗаменить(Текст, "а", "б").

Как заменить только первое вхождение подстроки?

Найдите позицию через СтрНайти, затем соберите строку: Лев(Строка, Позиция - 1) + Замена + Сред(Строка, Позиция + СтрДлина(Искомое)). СтрЗаменить такой режим не поддерживает — она всегда заменяет все вхождения.

Как удалить фрагмент из строки?

Передайте пустую строку третьим параметром: СтрЗаменить(Текст, "удаляемое", ""). Это стандартный и безопасный способ удаления подстроки.

Работает ли СтрЗаменить на клиенте в управляемых формах?

Да, функция доступна на тонком, толстом и веб-клиенте, а также на сервере. Никакой передачи данных на сервер для строковых операций не требуется — выполняйте их там, где удобнее по логике кода.

Как заменить текст в неограниченной строке или многострочном поле?

Точно так же — ограничений по длине у СтрЗаменить нет. Переносы строк указывайте через Символы.ПС и Символы.ВК, если нужно работать с построчной структурой. Для очень больших текстов учитывайте, что каждая замена создаёт новую строку в памяти.

Можно ли заменить значение в реквизите объекта напрямую?

СтрЗаменить работает только со значением строки. Для реквизита объекта нужно получить объект методом ПолучитьОбъект(), присвоить реквизиту результат замены и вызвать Записать(). В запросе замену строки выполнить нельзя — там доступны только функции выборки и сравнения.