Работа со строками в 1С:Предприятие — одна из самых частых задач при разработке отчётов, обработок и интеграций. Обрезка строк требуется для очистки данных, извлечения подстрок, форматирования вывода или подготовки данных к обмену. Однако в 1С нет универсальной функции вроде SUBSTRING из SQL или slice() из JavaScript — вместо этого используется набор инструментов с нюансами работы в разных контекстах: встроенный язык, запросы, регулярные выражения.
Эта статья покрывает все актуальные способы обрезки строк в 1С 8.3 и 1С 8.2, включая редко документированные приёмы. Мы разберём не только базовые функции Лев(), Прав() и Сред(), но и обрезку с учётом многобайтовых кодировок (UTF-8), работу с пробелами, а также оптимизацию производительности при обработке больших массивов данных. Особое внимание уделено обрезке строк прямо в запросах 1С — задаче, с которой сталкиваются при формировании отчётов или выгрузке данных.
Базовые функции обрезки: Лев(), Прав(), Сред()
Три основные функции встроенного языка 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 байт (например, эмодзи 😊). Платформа 1С обычно корректно обрабатывает это на уровне встроенного языка, но проблемы возникают:
- 🔺 При обмене данными с внешними системами (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 (в зависимости от СУБД). Важно помнить, что:
- 🖥️ В 1С SQL-запросы к внешним базам выполняются через
Запрос.УстановитьПараметр(). - 🖥️ Результаты обрезки в SQL могут отличаться от встроенного языка из-за разных правил обработки кодировок.
Убедиться в поддержке функции SUBSTRING|Проверить кодировку соединения (UTF-8/Windows-1251)|Тестировать на данных с многобайтовыми символами|Обработать возможные NULL-значения-->
Оптимизация производительности при обрезке больших данных
Обрезка строк в циклах или массовых операциях может значительно тормозить выполнение кода. Оптимизируйте процесс следующими способами:
1. Избегайте обрезки в циклах — если нужно обрезать строки в выборке, сделайте это в одном запросе:
// Плохо (обрезка в цикле)
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Лев(Выборка.Наименование, 20));
КонецЦикла;
// Хорошо (обрезка в запросе)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ЛЕВ(Наименование, 20) КАК КороткоеНаименование ИЗ Справочник.Номенклатура";
Результат = Запрос.Выполнить();
2. Кэшируйте длину строки — если вам нужно многократно обрезать одну и ту же строку, сохраните её длину в переменную:
ДлинаСтроки = СтрДлина(БольшаяСтрока);
ОбрезаннаяЧасть = Лев(БольшаяСтрока, МинимальноеЗначение(ДлинаСтроки, 100));
3. Используйте временные таблицы для промежуточных результатов при сложной обработке.
Обрезка строк в запросе 1С вместо цикла ускоряет выполнение в 10-100 раз при работе с большими выборками (10 000+ строк).
Типичные ошибки и как их избежать
Даже опытные разработчики 1С допускают ошибки при обрезке строк. Вот наиболее распространённые:
- Игнорирование пустых строк. Функции
Лев()/Прав()не выдают ошибку на пустой строке, но могут вернуть неожиданный результат в логике программы. Всегда проверяйте:Если НЕ ПустаяСтрока(ИсходнаяСтрока) Тогда// Обрезка
КонецЕсли;
- Неучёт регистра. Если вы ищете подстроку для обрезки (например,
НАЙТИ()), помните, что поиск регистрозависимый. ИспользуйтеНРег()для приведения к нижнему регистру. - Обрезка по байтам вместо символов. В строках с эмодзи или иероглифами обрезка по байтам приведёт к "битым" символам (��). Всегда используйте
СтрДлина()для определения реальной длины в символах.
Ещё одна типичная проблема — обрезка строк с переносами (\r\n). Если вы сохраняете обрезанную строку в файл, переносы могут "обрезаться" некорректно, что приведёт к слипшимся строкам в выходном файле. Решение:
// Заменить переносы на пробелы перед обрезкой
БезопаснаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символы.ПС, " ");
ОбрезаннаяСтрока = Лев(БезопаснаяСтрока, 100);
⚠️ Внимание: При обмене данными черезXMLилиJSONобрезанные строки могут содержать неэкранированные символы (например,&или"), что приведёт к ошибкам парсинга. Всегда экранируйте результат с помощьюСтрШаблон()или специализированных функций для JSON/XML.
FAQ: Частые вопросы по обрезке строк в 1С
Как обрезать строку до первого пробела?
Используйте комбинацию НАЙТИ() и ЛЕВ():
ПозицияПробела = НАЙТИ(ИсходнаяСтрока, " ");
Если ПозицияПробела = 0 Тогда
Результат = ИсходнаяСтрока; // Пробелов нет
Иначе
Результат = ЛЕВ(ИсходнаяСтрока, ПозицияПробела - 1);
КонецЕсли;
Можно ли обрезать строку в отчёте без изменения исходных данных?
Да, используйте вычисляемое поле в схеме компоновки данных. В настройках поля укажите выражение:
ЛЕВ(Поле, 30)
Это не изменит исходные данные, но отобразит в отчёте только первые 30 символов.
Почему Сред() возвращает пустую строку, хотя позиция корректна?
Проверьте два момента:
- Нумерация символов в
Сред()начинается с 1, а не с 0. - Если указанная позиция превышает длину строки, результат будет пустым. Используйте
МинимальноеЗначение()для защиты:
Начало = 5;
ДлинаСтроки = СтрДлина(Текст);
Результат = Сред(Текст, МинимальноеЗначение(Начало, ДлинаСтроки + 1), 10);
Как обрезать строку в 1С:Документооборот или 1С:ERP?
В типовых конфигурациях (например, 1С:ERP 2.5 или 1С:Документооборот 3.0) для обрезки строк в печатных формах или отчётах используйте:
- 📄 В СКД (схема компоновки данных) — вычисляемые поля с функциями
ЛЕВ()/ПРАВ(). - 📄 В макетах печатных форм — параметры с предварительной обрезкой в модуле.
- 📄 Для полей ввода — обработчики событий
ПриИзменениис обрезкой значения.
В 1С:Документооборот при обрезке названий документов учитывайте, что они могут содержать служебные символы (например, # для версий). Используйте:
НазваниеБезВерсии = СтрЗаменить(Документ.Название, "#" + Сред(Документ.Название, НАЙТИ(Документ.Название, "#")), "");
Как обрезать строку по слову (не разрывая слова)?
Для обрезки строки с сохранением целых слов используйте следующий алгоритм:
- Обрежьте строку до нужной длины + запас (например, 100 + 20 символов).
- Найдите позицию последнего пробела в обрезанной строке.
- Обрежьте строку по этому пробелу.
Функция ОбрезатьПоСлову(Строка, МаксДлина)
Если СтрДлина(Строка) <= МаксДлина Тогда
Возврат Строка;
КонецЕсли;
Обрезанная = Лев(Строка, МаксДлина + 20); // Запас для последнего слова
ПозицияПробела = НАЙТИ(Обрезанная, " ", СтрДлина(Обрезанная));
Если ПозицияПробела = 0 Тогда
Возврат Обрезанная; // Пробелов нет, возвращаем как есть
Иначе
Возврат Лев(Обрезанная, ПозицияПробела) + "...";
КонецЕсли;
КонецФункции