Работа со строками в 1С:Предприятие — одна из самых частых задач при разработке отчётов, обработок и интеграций. Обрезка строк требуется для очистки данных, извлечения подстрок, форматирования вывода или подготовки данных к обмену. Однако в нет универсальной функции вроде SUBSTRING из SQL или slice() из JavaScript — вместо этого используется набор инструментов с нюансами работы в разных контекстах: встроенный язык, запросы, регулярные выражения.

Эта статья покрывает все актуальные способы обрезки строк в 1С 8.3 и 1С 8.2, включая редко документированные приёмы. Мы разберём не только базовые функции Лев(), Прав() и Сред(), но и обрезку с учётом многобайтовых кодировок (UTF-8), работу с пробелами, а также оптимизацию производительности при обработке больших массивов данных. Особое внимание уделено обрезке строк прямо в запросах 1С — задаче, с которой сталкиваются при формировании отчётов или выгрузке данных.

Базовые функции обрезки: Лев(), Прав(), Сред()

Три основные функции встроенного языка для работы с подстроками — это Лев(), Прав() и Сред(). Они работают с любыми строками, включая пустые, и возвращают новую строку без изменения оригинала.

Функция Лев(Строка, Количество) возвращает указанное количество символов с начала строки. Если количество символов превышает длину строки, функция вернёт строку целиком без ошибок. Например:

Сообщение = "Привет, мир!";

ЛеваяЧасть = Лев(Сообщение, 6); // Результат: "Привет"

Функция Прав(Строка, Количество) аналогична, но работает с конца строки. Важный нюанс: если строка содержит многобайтовые символы (например, кириллицу в UTF-8), функция корректно обработает их как единый символ, а не как набор байтов.

Функция Сред(Строка, Начало, Длина) извлекает подстроку, начиная с указанной позиции (нумерация с 1!). Третий параметр — количество символов — можно опустить, чтобы получить подстроку до конца исходной строки:

Текст = "1С:Предприятие 8.3";

Подстрока = Сред(Текст, 4, 10); // Результат: "Предприяти"

  • 🔹 Лев(Строка, 0) вернёт пустую строку, а не ошибку.
  • 🔹 Если в Сред() указать начало за пределами строки, результат будет пустым.
  • 🔹 Эти функции не изменяют регистр и не удаляют пробелы автоматически.
💡

Для обрезки пробелов по краям строки используйте СокрЛП() (удалит пробелы слева и справа) или СокрЛ(Строка)/СокрП(Строка) для односторонней обрезки.

Обрезка строк в запросах 1С (язык запросов)

В отличие от встроенного языка, язык запросов 1С имеет ограниченный набор функций для работы со строками. Здесь нет Лев() или Прав(), но есть альтернативы:

Для извлечения подстроки используется функция ВЫРАЗИТЬ(Строка КАК СТРОКА(Длина)) в комбинации с ПОДСТРОКА (в новых версиях платформы). Однако чаще применяют конструкцию с ПОЗИЦИЯ и ЛЕВ/ПРАВ через выражения:

ВЫБРАТЬ

ЛЕВ(Наименование, 10) КАК КороткоеНаименование,

ПРАВ(Артикул, 5) КАК КодТовара

ИЗ

Справочник.Номенклатура

Для обрезки по символу-разделителю (например, извлечь домен из email) в запросе можно использовать комбинацию НАЙТИ и ЛЕВ:

ВЫБРАТЬ

ЛЕВ(КонтактнаяИнформация.АдресЭлектроннойПочты,

НАЙТИ(КонтактнаяИнформация.АдресЭлектроннойПочты, "@") - 1)

КАК ЛогинПочты

ИЗ

Справочник.Контрагенты КАК Контрагенты

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация

ПО Контрагенты.Ссылка = КонтактнаяИнформация.Объект

⚠️ Внимание: В старых версиях платформы (до 8.3.10) функция ПОДСТРОКА в запросах могла работать некорректно с многобайтовыми символами. Проверяйте результат на тестовых данных с кириллицей или эмодзи.
Задача Функция встроенного языка Аналог в языке запросов
Первые N символов Лев(Строка, N) ЛЕВ(Поле, N)
Последние N символов Прав(Строка, N) ПРАВ(Поле, N)
Подстрока с позиции M длиной N Сред(Строка, M, N) ПОДСТРОКА(Поле С M ПО M+N-1)
Удаление пробелов СокрЛП(Строка) ЗАМЕНИТЬ(Поле, " ", "") или СОКРЛП(Поле) (в новых версиях)

Обрезка с учётом многобайтовых кодировок (UTF-8)

При работе с текстами на кириллице, иероглифах или эмодзи стандартные функции Лев()/Прав() могут давать неожиданные результаты. Дело в том, что один "символ" в UTF-8 может занимать до 4 байт (например, эмодзи 😊). Платформа обычно корректно обрабатывает это на уровне встроенного языка, но проблемы возникают:

  • 🔺 При обмене данными с внешними системами (JSON, XML), где строка может быть обрезана по байтам, а не по символам.
  • 🔺 В старых версиях платформы (до 8.3.8) при работе с ДвоичныеДанные.
  • 🔺 При использовании низкоуровневых функций вроде ПолучениеДвоичныхДанныхИзСтроки().

Для безопасной обрезки многобайтовых строк используйте следующий приём:

Функция БезопаснаяОбрезка(Строка, Длина)

Возврат Лев(Строка, МинимальноеЗначение(Длина, СтрДлина(Строка)));

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

Если вам нужно обрезать строку по байтам (например, для записи в файл фиксированного размера), используйте ПолучениеДвоичныхДанныхИзСтроки() с последующим усечением и обратным преобразованием:

ДвоичныеДанные = ПолучениеДвоичныхДанныхИзСтроки(Текст, КодировкаТекста.UTF8);

ОбрезанныеДанные = Лев(ДвоичныеДанные, 100); // Обрезаем первые 100 байт

Результат = ПолучениеСтрокиИзДвоичныхДанных(ОбрезанныеДанные, КодировкаТекста.UTF8);

⚠️ Внимание: При обрезке по байтам многобайтовый символ может быть "разорван", что приведёт к появлению в строке непечатаемых символов (��). Всегда проверяйте результат на корректность.
📊 Какой способ обрезки строк вы используете чаще?
Встроенные функции (Лев/Прав/Сред)
Запросы 1С
Регулярные выражения
Ручная обработка по символам

Обрезка с использованием регулярных выражений

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

Пример: обрезать строку до первого вхождения запятой:

РегВыр = Новый РегулярноеВыражение("^,+");

Результат = РегВыр.Заменить(ИсходнаяСтрока, "");

Более сложный случай — извлечение подстроки между двумя маркерами:

РегВыр = Новый РегулярноеВыражение("\[(.*?)\]");

Находки = РегВыр.Найти(ИсходнаяСтрока);

Если Находки.Нашено Тогда

Результат = Находки.ПолучитьТекст(1); // Текст между скобками [ ]

КонецЕсли;

Регулярные выражения полезны для:

  • 📌 Очистки строк от служебных символов (\r\n, табуляции).
  • 📌 Извлечения email, телефонов или других шаблонных данных.
  • 📌 Обрезки строк с учётом контекста (например, удалить всё после первого двоеточия).
Пример

удаление всех тегов из HTML-строки:Скрытый код: РегВыр = Новый РегулярноеВыражение("<[^>]+>", РежимПоиска.Многострочный);

ЧистыйТекст = РегВыр.Заменить(HTMLСтрока, "");

Обрезка строк в SQL-запросах (внешние источники)

Если вы работаете с внешними базами данных через ODBC или ADO, обрезка строк выполняется средствами SQL. Синтаксис зависит от СУБД:

Для Microsoft SQL Server и PostgreSQL используется функция SUBSTRING:

ВЫБРАТЬ

Поле1,

SUBSTRING(Поле2, 1, 10) КАК ОбрезанноеПоле

ИЗ ВнешняяТаблица

В Oracle аналогичная функция называется SUBSTR:

ВЫБРАТЬ

SUBSTR(DESCRIPTION, 1, 20) КАК SHORT_DESC

ИЗ EXTERNAL_TABLE

Для обрезки пробелов в SQL используйте TRIM, LTRIM или RTRIM (в зависимости от СУБД). Важно помнить, что:

  • 🖥️ В SQL-запросы к внешним базам выполняются через Запрос.УстановитьПараметр().
  • 🖥️ Результаты обрезки в SQL могут отличаться от встроенного языка из-за разных правил обработки кодировок.

Убедиться в поддержке функции SUBSTRING|Проверить кодировку соединения (UTF-8/Windows-1251)|Тестировать на данных с многобайтовыми символами|Обработать возможные NULL-значения-->

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

Обрезка строк в циклах или массовых операциях может значительно тормозить выполнение кода. Оптимизируйте процесс следующими способами:

1. Избегайте обрезки в циклах — если нужно обрезать строки в выборке, сделайте это в одном запросе:

// Плохо (обрезка в цикле)

Выборка = Справочники.Номенклатура.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Лев(Выборка.Наименование, 20));

КонецЦикла;

// Хорошо (обрезка в запросе)

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ЛЕВ(Наименование, 20) КАК КороткоеНаименование ИЗ Справочник.Номенклатура";

Результат = Запрос.Выполнить();

2. Кэшируйте длину строки — если вам нужно многократно обрезать одну и ту же строку, сохраните её длину в переменную:

ДлинаСтроки = СтрДлина(БольшаяСтрока);

ОбрезаннаяЧасть = Лев(БольшаяСтрока, МинимальноеЗначение(ДлинаСтроки, 100));

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

💡

Обрезка строк в запросе 1С вместо цикла ускоряет выполнение в 10-100 раз при работе с большими выборками (10 000+ строк).

Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при обрезке строк. Вот наиболее распространённые:

  1. Игнорирование пустых строк. Функции Лев()/Прав() не выдают ошибку на пустой строке, но могут вернуть неожиданный результат в логике программы. Всегда проверяйте:
    Если НЕ ПустаяСтрока(ИсходнаяСтрока) Тогда
    

    // Обрезка

    КонецЕсли;

  2. Неучёт регистра. Если вы ищете подстроку для обрезки (например, НАЙТИ()), помните, что поиск регистрозависимый. Используйте НРег() для приведения к нижнему регистру.
  3. Обрезка по байтам вместо символов. В строках с эмодзи или иероглифами обрезка по байтам приведёт к "битым" символам (��). Всегда используйте СтрДлина() для определения реальной длины в символах.

Ещё одна типичная проблема — обрезка строк с переносами (\r\n). Если вы сохраняете обрезанную строку в файл, переносы могут "обрезаться" некорректно, что приведёт к слипшимся строкам в выходном файле. Решение:

// Заменить переносы на пробелы перед обрезкой

БезопаснаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символы.ПС, " ");

ОбрезаннаяСтрока = Лев(БезопаснаяСтрока, 100);

⚠️ Внимание: При обмене данными через XML или JSON обрезанные строки могут содержать неэкранированные символы (например, & или "), что приведёт к ошибкам парсинга. Всегда экранируйте результат с помощью СтрШаблон() или специализированных функций для JSON/XML.

FAQ: Частые вопросы по обрезке строк в 1С

Как обрезать строку до первого пробела?

Используйте комбинацию НАЙТИ() и ЛЕВ():

ПозицияПробела = НАЙТИ(ИсходнаяСтрока, " ");

Если ПозицияПробела = 0 Тогда

Результат = ИсходнаяСтрока; // Пробелов нет

Иначе

Результат = ЛЕВ(ИсходнаяСтрока, ПозицияПробела - 1);

КонецЕсли;

Можно ли обрезать строку в отчёте без изменения исходных данных?

Да, используйте вычисляемое поле в схеме компоновки данных. В настройках поля укажите выражение:

ЛЕВ(Поле, 30)

Это не изменит исходные данные, но отобразит в отчёте только первые 30 символов.

Почему Сред() возвращает пустую строку, хотя позиция корректна?

Проверьте два момента:

  1. Нумерация символов в Сред() начинается с 1, а не с 0.
  2. Если указанная позиция превышает длину строки, результат будет пустым. Используйте МинимальноеЗначение() для защиты:
Начало = 5;

ДлинаСтроки = СтрДлина(Текст);

Результат = Сред(Текст, МинимальноеЗначение(Начало, ДлинаСтроки + 1), 10);

Как обрезать строку в 1С:Документооборот или 1С:ERP?

В типовых конфигурациях (например, 1С:ERP 2.5 или 1С:Документооборот 3.0) для обрезки строк в печатных формах или отчётах используйте:

  • 📄 В СКД (схема компоновки данных) — вычисляемые поля с функциями ЛЕВ()/ПРАВ().
  • 📄 В макетах печатных форм — параметры с предварительной обрезкой в модуле.
  • 📄 Для полей ввода — обработчики событий ПриИзменении с обрезкой значения.

В 1С:Документооборот при обрезке названий документов учитывайте, что они могут содержать служебные символы (например, # для версий). Используйте:

НазваниеБезВерсии = СтрЗаменить(Документ.Название, "#" + Сред(Документ.Название, НАЙТИ(Документ.Название, "#")), "");
Как обрезать строку по слову (не разрывая слова)?

Для обрезки строки с сохранением целых слов используйте следующий алгоритм:

  1. Обрежьте строку до нужной длины + запас (например, 100 + 20 символов).
  2. Найдите позицию последнего пробела в обрезанной строке.
  3. Обрежьте строку по этому пробелу.
Функция ОбрезатьПоСлову(Строка, МаксДлина)

Если СтрДлина(Строка) <= МаксДлина Тогда

Возврат Строка;

КонецЕсли;

Обрезанная = Лев(Строка, МаксДлина + 20); // Запас для последнего слова

ПозицияПробела = НАЙТИ(Обрезанная, " ", СтрДлина(Обрезанная));

Если ПозицияПробела = 0 Тогда

Возврат Обрезанная; // Пробелов нет, возвращаем как есть

Иначе

Возврат Лев(Обрезанная, ПозицияПробела) + "...";

КонецЕсли;

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