В процессе разработки в среде 1С часто возникает задача манипуляции строками. Стандартная функция СтрЗаменить (или StrReplace) отлично справляется с заменой всех вхождений подстроки, но она бессильна, когда нам нужно заменить только второе, четвертое или конкретно выделенное пользователем слово. В этой статье мы подробно разберем, как реализовать «точечную» замену, сохраняя остальную структуру текста нетронутой.
Представим ситуацию: у нас есть шаблонный текст, где слово «тут» встречается несколько раз, и нам нужно заменить только второе вхождение. Для этого мы воспользуемся функцией СтрНайти, которая в платформе 1С:Предприятие 8.3 имеет крайне полезный четвертый параметр — НомерВхождения.
Рассмотрим алгоритм действий:
Проанализируем пример кода:
// Исходные данные
ИсходныйТекст = "Фото тут. Фото тут. Фото тут.";
ИскомоеСлово = "тут";
НовоеСлово = "здесь";
НомерНужногоВхождения = 2;
// Находим позицию 2-го вхождения слова "тут"
Позиция = СтрНайти(ИсходныйТекст, ИскомоеСлово, НаправлениеПоиска.СНачала, , НомерНужногоВхождения);
Если Позиция > 0 Тогда
// Вычисляем длину слова, чтобы знать, сколько символов "вырезать"
ДлинаСтарого = СтрДлина(ИскомоеСлово);
// Собираем результат
ТекстДо = Лев(ИсходныйТекст, Позиция - 1);
ТекстПосле = Сред(ИсходныйТекст, Позиция + ДлинаСтарого);
Результат = ТекстДо + НовоеСлово + ТекстПосле;
Сообщить(Результат); // Результат: "Фото тут. Фото здесь. Фото тут."
КонецЕсли;
Если ваша задача состоит в том, чтобы заменить слово, которое пользователь физически выделил курсором в поле ввода, нам не нужно ничего искать. Платформа 1С предоставляет доступ к метаданным выделения через свойства элементов формы.
Для обычного текстового поля (строкового реквизита) на управляемой форме мы можем использовать следующие свойства:
ВыделенныйТекст — возвращает строку, которая сейчас подсвечена курсором.НачалоВыделения — индекс первого символа выделения.ДлинаВыделения — количество выделенных символов.Разберем, как это работает на практике. Допустим, у нас есть поле ТекстПисьма на форме:
// Процедура вызывается по нажатию кнопки "Заменить выделенное"
&НаКлиенте
Процедура ЗаменитьВыделенное(Команда)
ЭлементТекст = ЭтаФорма.Элементы.ТекстПисьма;
// Получаем текущие границы выделения
Старт = ЭлементТекст.НачалоВыделения;
Длина = ЭлементТекст.ДлинаВыделения;
Если Длина > 0 Тогда
ПолныйТекст = Объект.ТекстПисьма;
НовоеСлово = "Замена";
// Формируем новую строку на основе позиций
ТекстДо = Лев(ПолныйТекст, Старт - 1);
ТекстПосле = Сред(ПолныйТекст, Старт + Длина);
Объект.ТекстПисьма = ТекстДо + НовоеСлово + ТекстПосле;
КонецЕсли;
КонецПроцедуры
Для более сложных случаев, когда нужно учитывать границы слов (чтобы не заменить «тут» внутри слова «институт»), идеально подходят регулярные выражения. В современных версиях платформы (8.3.24+) появилась встроенная поддержка объекта РегулярноеВыражение. Для более старых версий мы используем COM-объект VBScript.RegExp.
Рассмотрим пример использования регулярных выражений для точной замены слова:
// Пример для новых версий 1С
РегЭксп = Новый РегулярноеВыражение("\b" + ИскомоеСлово + "\b");
// Метод Заменить может заменить все, но RegExp позволяет
// строить более гибкие условия поиска (например, только слово целиком)
Результат = РегЭксп.Заменить(ИсходныйТекст, НовоеСлово);
Выясним причину, почему регулярные выражения лучше обычного поиска: они позволяют игнорировать знаки препинания вокруг слова. Шаблон \b обозначает границу слова, что гарантирует замену именно отдельной лексемы.
Проанализируем ситуацию, когда нам нужно заменить несколько вхождений, но не все, и при этом новые слова могут содержать в себе старые (что вызвало бы бесконечный цикл или повторную замену). В таких случаях опытные разработчики используют метод уникальных маркеров.
Алгоритм действий следующий:
{#МАРКЕР_1#}.СтрЗаменить, заменяя маркер на целевое значение.Если ваш текст находится не в обычной строке, а в Поле форматированного документа, обычные строковые функции могут повредить HTML-разметку (теги оформления жирным, цветом и т.д.). В этом случае следует использовать метод ПолучитьГраницыВыделения().
Рассмотрим шаги для безопасной замены:
ОписаниеВыделения.ЗаменитьТекст() к объекту текстового документа, указывая полученные границы. Это позволит вставить текст, сохранив окружающее оформление.Важный нюанс: При работе с массивами (через СтрРазделить) всегда помните, что вы теряете разделители (пробелы, переносы строк, знаки препинания). Если ваша задача требует сохранения исходной пунктуации, всегда отдавайте предпочтение методам на основе СтрНайти и функций Лев()/Сред()/Прав(), так как они работают с абсолютными индексами символов, не затрагивая структуру текста.