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

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

Как посчитать количество пробелов в строке в 1С

Как посчитать количество пробелов в строке в 1С: СтрЧислоВхождений, СтрЗаменить, цикл с Найти, подсчёт пробелов в начале и конце строки. Примеры кода и типичные ошибки.

Подсчёт пробелов в строке — типовая задача при разработке на встроенном языке 1С: она возникает при разборе ФИО, проверке формата адресов и артикулов, валидации данных из файлов обмена и очистке пользовательского ввода. В платформе «1С:Предприятие 8.3» есть несколько способов решить эту задачу, и выбор зависит от версии платформы, требований к производительности и того, какие именно пробелы нужно учитывать.

Самый короткий путь — функция СтрЧислоВхождений(), появившаяся в платформе 8.3.6. Если конфигурация должна работать на более старых релизах, придётся использовать приём с заменой символов через СтрЗаменить() или классический цикл с Найти(). Каждый вариант имеет свои ограничения, которые важно понимать до внедрения кода в рабочую базу.

Отдельная ситуация — подсчёт пробелов только в начале или в конце строки. Здесь удобнее всего сравнить длину исходной строки с длиной результата функций СокрЛ(), СокрП() или СокрЛП(). Ниже разобраны все подходы с готовыми примерами кода, проверкой результата и разбором типичных ошибок.

Способ 1. Функция СтрЧислоВхождений — самый простой вариант

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

Строка = "Иванов  Иван   Иванович";

КоличествоПробелов = СтрЧислоВхождений(Строка, " ");

// Результат: 5

Функция считает именно вхождения символа пробела (код 32). Неразрывный пробел (код 160) и символ табуляции она не учтёт — об этом подробнее в разделе про особые символы. Учтите также, что несколько пробелов подряд считаются по одному: «два пробела» дадут результат 2, а не одно вхождение пары.

Главное ограничение — доступность: СтрЧислоВхождений() появилась в платформе 8.3.6. Если конфигурация запускается на более ранних версиях или режим совместимости этого требует, код вызовет ошибку «Процедура или функция с указанным именем не определена». Перед использованием проверьте минимальную версию платформы, на которой работают ваши пользователи.

Способ 2. Подсчёт через СтрЗаменить — работает на любой версии

Универсальный приём, известный ещё со времён платформы 8.0: сравнивается длина исходной строки с длиной строки, из которой удалены все пробелы. Разность и есть количество пробелов:

Строка = "Артикул ТОВ 001 25";

КоличествоПробелов = СтрДлина(Строка) - СтрДлина(СтрЗаменить(Строка, " ", ""));

// Результат: 3

Метод работает на любой версии платформы 1С:Предприятие 8 и не требует циклов. По скорости он сопоставим со СтрЧислоВхождений() для строк разумной длины, поэтому его часто выбирают как вариант «по умолчанию», когда нужна совместимость с разными релизами.

Недостаток тот же, что и у первого способа: учитывается только обычный пробел. Кроме того, приём создаёт промежуточную строку без пробелов, что на очень длинных текстах (десятки тысяч символов) даёт дополнительный расход памяти. Для типовых задач вроде проверки ФИО или номенклатурного кода это несущественно.

Способ 3. Цикл с функцией Найти

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

Строка = "Раз два три четыре";

КоличествоПробелов = 0;

Позиция = Найти(Строка, " ");

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

КоличествоПробелов = КоличествоПробелов + 1;

Позиция = Найти(Сред(Строка, Позиция + 1), " ");

Если Позиция > 0 Тогда

Строка = Сред(Строка, Позиция + 1);

Позиция = Найти(Строка, " ");

КонецЕсли;

КонецЦикла;

Более аккуратный вариант — без изменения исходной строки, с накоплением смещения:

Функция КоличествоПробелов(Знач Строка) Экспорт

Результат = 0;

Смещение = 0;

Позиция = Найти(Строка, " ");

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

Результат = Результат + 1;

Смещение = Смещение + Позиция;

Позиция = Найти(Сред(Строка, Смещение + 1), " ");

КонецЦикла;

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

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

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

Сравнение способов

СтрЧислоВхождений

Самый читаемый код, но требует платформу 8.3.6 или новее

СтрДлина минус СтрЗаменить

Работает на любой версии 8.x, подходит как универсальное решение

Цикл с Найти

Нужен, когда важны позиции пробелов или ранний выход по условию; для простого подсчёта избыточен

Как посчитать пробелы в начале и в конце строки

Частая практическая задача — определить, есть ли лишние пробелы по краям строки, например при загрузке данных из Excel или при сравнении наименований, введённых пользователем вручную. Здесь помогает разность длин до и после обрезки:

Строка = "  Наименование товара ";

ПробеловСлева = СтрДлина(Строка) - СтрДлина(СокрЛ(Строка)); // 2

ПробеловСправа = СтрДлина(Строка) - СтрДлина(СокрП(Строка)); // 1

ПробеловПоКраям = СтрДлина(Строка) - СтрДлина(СокрЛП(Строка)); // 3

Важно понимать, что СокрЛП() удаляет не только пробелы, но и другие незначащие символы: табуляцию, перевод строки, возврат каретки, неразрывный пробел. Поэтому результат разности длин — это количество именно незначащих символов по краям, а не строго пробелов. Если нужен подсчёт только символов с кодом 32, придётся перебирать строку посимвольно через Сред() и КодСимвола().

Типовой сценарий использования — валидация перед записью в базу: если СтрДлина(Строка) <> СтрДлина(СокрЛП(Строка)), значит, по краям есть лишние символы, и стоит либо автоматически очистить значение, либо предупредить пользователя.

Проверка лишних пробелов по краям строки
  1. 1
    Сохраните исходную строку в переменную
  2. 2
    Вычислите СтрДлина(Строка) и СтрДлина(СокрЛП(Строка))
  3. 3
    Если длины различаются — по краям есть незначащие символы
  4. 4
    Запишите в базу значение СокрЛП(Строка) или сообщите пользователю об ошибке

Особые символы: неразрывный пробел и табуляция

Данные, скопированные из Excel, Word или веб-страниц, часто содержат неразрывный пробел (код 160) вместо обычного. Визуально символы неотличимы, но СтрЧислоВхождений(Строка, " ") такие символы не посчитает, а сравнение строк с обычным пробелом даст ложное неравенство. Это одна из самых коварных причин «необъяснимых» расхождений при обработке строк.

Чтобы учесть оба вида пробелов, предварительно замените неразрывный пробел на обычный:

НПП = Символ(160); // неразрывный пробел

Нормализованная = СтрЗаменить(Строка, НПП, " ");

КоличествоПробелов = СтрЧислоВхождений(Нормализованная, " ");

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

Типичные ошибки
01
Считать только обычный пробел и игнорировать неразрывный (код 160) — данные из Excel дают заниженный результат
02
Использовать СтрЧислоВхождений на платформе ниже 8.3.6 — код падает с ошибкой о неопределённой функции
03
Путать СокрЛП с удалением пробелов внутри строки — СокрЛП обрезает только края
04
Передавать в Найти пустую подстроку поиска — результат будет некорректным
05
Забыть обработать пустую строку или Неопределено — функции работы со строками ожидают строковое значение

Производительность и оформление кода

Для строк типичной длины (наименования, ФИО, адреса) разница в скорости между способами практически незаметна. Существенной она становится при пакетной обработке: например, при проверке сотен тысяч строк табличной части или при разборе большого текстового файла в цикле.

В таких сценариях предпочтительны встроенные строковые функции (СтрЧислоВхождений, СтрЗаменить), поскольку они выполняются на уровне платформы и работают быстрее интерпретируемого цикла с Найти(). Цикл оставляйте для случаев, где нужна логика, недоступная встроенным функциям.

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

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

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

Тест на строке с известным числом пробелов
Норма

Функция возвращает ожидаемое число

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

Результат меньше — вероятно, в строке неразрывные пробелы

Пустая строка и строка без пробелов
Норма

Возвращается 0 без ошибок

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

Ошибка выполнения или неверное значение

Строка с пробелами по краям
Норма

Краевые пробелы учтены в общем подсчёте

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

Результат отличается — проверьте, не применён ли СокрЛП до подсчёта

Практические сценарии применения

Подсчёт пробелов редко является самоцелью — обычно он часть более крупной проверки. Вот типовые ситуации, где он применяется:

  • Проверка ФИО. Если в строке меньше двух пробелов, вероятно, пользователь ввёл неполные данные: только фамилию и имя без отчества или всё одним словом.
  • Контроль формата артикула или кода. Наличие пробелов там, где их быть не должно, — признак ошибки ввода или некорректной выгрузки.
  • Разбор составных строк. Перед разделением строки через СтрРазделить() подсчёт разделителей помогает оценить ожидаемое число элементов.
  • Очистка загружаемых данных. Обнаружение двойных пробелов и пробелов по краям перед записью в справочники.

Для проверки двойных пробелов подсчёт не нужен — достаточно условия Найти(Строка, " ") > 0. А устранить повторные пробелы можно циклом замены двойного пробела на одинарный, пока Найти() продолжает находить вхождения.

Итог

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

Для платформы 8.3.6+ используйте СтрЧислоВхождений, для любых версий — разность длин через СтрЗаменить. Пробелы по краям считайте через СокрЛ/СокрП/СокрЛП, а данные из внешних источников предварительно очищайте от неразрывного пробела (Символ(160)).

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

Как посчитать пробелы в строке на управляемой форме без обращения к серверу?

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

Чем отличается СтрЧислоВхождений от Найти?

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

Почему функция не считает пробелы в строке, скопированной из Excel?

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

Как проверить, что в строке есть хотя бы один пробел, без полного подсчёта?

Используйте условие Найти(Строка, " ") > 0. Это быстрее и нагляднее, чем сравнение результата СтрЧислоВхождений с нулём, особенно если фактическое количество не имеет значения.

Можно ли посчитать пробелы в запросе 1С, а не в коде?

В языке запросов нет прямой функции подсчёта вхождений символа. Стандартная практика — выбрать данные запросом, а подсчёт выполнить в коде при обходе результата. Для фильтрации строк с пробелами в самом запросе можно использовать ПОДОБНО с шаблоном "% %".

Как удалить все пробелы из строки, а не только посчитать их?

Примените СтрЗаменить(Строка, " ", "") — функция вернёт строку без пробелов. Если нужно убрать только лишние пробелы между словами, заменяйте в цикле двойной пробел на одинарный, пока Найти(Строка, " ") возвращает ненулевую позицию.