Разработка и Конфигурация · 9 мин
Как в 1С посчитать количество слов в строке
Как в 1С посчитать количество слов в строке: функция СтрРазделить, цикл по пробелам, обработка лишних пробелов и переносов. Готовый код, примеры и частые ошибки.
Подсчёт слов в строке — типовая задача при разработке на встроенном языке 1С: она встречается при проверке длины комментариев, разборе ФИО, валидации наименований и подготовке данных для обмена. Встроенной функции «посчитай слова» в языке нет, поэтому задачу решают комбинацией строковых функций: СтрРазделить, СтрЧислоВхождений или классическим перебором символов.
Выбор способа зависит от того, что считать словом. Если слова разделены одиночными пробелами — достаточно одной строки кода. Если в тексте возможны двойные пробелы, табуляции и переносы строк, нужна предварительная нормализация или более аккуратный алгоритм. Ниже разобраны рабочие варианты с готовым кодом, их ограничения и способы проверки результата.
Способ 1: подсчёт через СтрРазделить
Функция СтрРазделить разбивает строку на массив подстрок по указанному разделителю. Если разделитель — пробел, то количество элементов массива и будет количеством слов. Это самый короткий и читаемый вариант, доступный во всех актуальных версиях платформы.
Функция КоличествоСлов(Текст)
МассивСлов = СтрРазделить(СокрЛП(Текст), " ", Ложь);
Возврат МассивСлов.Количество();
КонецФункции
Третий параметр Ложь указывает не включать пустые подстроки в результат: тогда двойные пробелы не создадут «пустых слов». Вызов СокрЛП убирает пробелы в начале и конце строки, которые иначе тоже могли бы исказить подсчёт.
Ограничение способа: разделителем считается только обычный пробел. Табуляция, неразрывный пробел (символ 160) и перенос строки склеят соседние слова в одно. Если текст приходит из внешних источников — из Excel, веб-форм, буфера обмена — там такие символы встречаются часто.
Способ 2: подсчёт через число вхождений разделителя
Если строка гарантированно «чистая» — слова разделены ровно одним пробелом, без лишних символов, — количество слов равно количеству пробелов плюс один. Для этого подходит функция СтрЧислоВхождений.
Функция КоличествоСловПоПробелам(Текст)
Текст = СокрЛП(Текст);
Если ПустаяСтрока(Текст) Тогда
Возврат 0;
КонецЕсли;
Возврат СтрЧислоВхождений(Текст, " ") + 1;
КонецФункции
Обязательна проверка на пустую строку: иначе для пустого текста функция вернёт 1 вместо 0. Этот способ быстрее перебора на очень длинных строках, но он самый чувствительный к качеству данных — один двойной пробел даёт завышенный результат.
Способ 3: универсальный перебор символов
Когда разделители могут быть любыми — пробелы любого вида, табуляции, переносы строк, знаки препинания, — надёжнее всего идти по строке посимвольно и фиксировать переходы «разделитель → не разделитель». Каждый такой переход означает начало нового слова.
Функция КоличествоСловУниверсально(Текст)
Разделители = " " + Символ(9) + Символ(10) + Символ(13) + Символ(160);
Счетчик = 0;
ВнутриСлова = Ложь;
Для Позиция = 1 По СтрДлина(Текст) Цикл
Символ = Сред(Текст, Позиция, 1);
ЭтоРазделитель = СтрНайти(Разделители, Символ) > 0;
Если Не ЭтоРазделитель И Не ВнутриСлова Тогда
Счетчик = Счетчик + 1;
ВнутриСлова = Истина;
ИначеЕсли ЭтоРазделитель Тогда
ВнутриСлова = Ложь;
КонецЕсли;
КонецЦикла;
Возврат Счетчик;
КонецФункции
Алгоритм не создаёт промежуточных массивов и корректно обрабатывает любые комбинации разделителей подряд. При необходимости набор разделителей легко расширить, добавив в строку Разделители запятые, точки с запятой или другие символы.
Сравнение способов
Самый короткий код. Подходит для текстов с обычными пробелами, требует СокрЛП и флага Ложь для пустых подстрок.
Быстрый на длинных строках, но ошибается при двойных пробелах и нестандартных разделителях. Только для нормализованных данных.
Универсальный и самый надёжный, обрабатывает любые разделители. Код длиннее, на очень больших строках медленнее встроенных функций.
Нормализация строки перед подсчётом
Большинство ошибок подсчёта связано не с алгоритмом, а с «грязными» данными. Перед подсчётом имеет смысл привести строку к единому виду: заменить неразрывные пробелы и табуляции обычными пробелами, убрать переносы строк и схлопнуть повторные пробелы.
Функция Нормализовать(Текст)
Результат = СтрЗаменить(Текст, Символ(160), " ");
Результат = СтрЗаменить(Результат, Символ(9), " ");
Результат = СтрЗаменить(Результат, Символы.ПС, " ");
Результат = СтрЗаменить(Результат, Символы.ВК, " ");
Пока СтрНайти(Результат, " ") > 0 Цикл
Результат = СтрЗаменить(Результат, " ", " ");
КонецЦикла;
Возврат СокрЛП(Результат);
КонецФункции
После такой подготовки любой из простых способов — СтрРазделить или СтрЧислоВхождений — даст корректный результат. Цикл схлопывания двойных пробелов работает, потому что каждая итерация уменьшает число повторов, пока их не останется вовсе.
- 1Определите, какие символы в ваших данных разделяют слова: только пробел или также табуляции и переносы.
- 2Нормализуйте строку: замените спецсимволы пробелами, схлопните двойные пробелы, примените СокрЛП.
- 3Посчитайте слова через СтрРазделить с параметром Ложь или универсальным перебором.
- 4Проверьте крайние случаи: пустая строка, строка из одних пробелов, одно слово без пробелов.
Проверка результата и типичные ошибки
Проверять функцию стоит на контрольном наборе: пустая строка должна дать 0, строка из пробелов — 0, одно слово — 1, «два слова» — 2, текст с двойными пробелами и переносом строки — фактическое число слов. Если какой-то из этих тестов даёт неожиданное число, причина почти всегда в необработанных разделителях или отсутствии проверки на пустоту.
Как проверить результат
Функция возвращает 0
Возвращает 1 или падает с ошибкой
Возвращает 0
Возвращает число больше нуля
Считаются только реальные слова
Счётчик завышен на число лишних разделителей
Слова разделены и посчитаны верно
Несколько слов склеиваются в одно
Где размещать функцию и ограничения
Если подсчёт нужен в нескольких местах конфигурации, функцию размещают в общем модуле с установленным признаком «Сервер» (и «Клиент», если она нужна на клиенте) и экспортируют ключевым словом Экспорт. Для разового использования достаточно локальной функции в модуле формы или объекта.
Учитывайте контекст исполнения: в клиент-серверном режиме вызов серверной функции из цикла на клиенте порождает лишние серверные вызовы. Если подсчёт выполняется для множества строк (например, при обработке табличной части), передавайте данные на сервер одним пакетом и считайте там.
На управляемых формах помните про директивы компиляции: функция в разделе &НаКлиенте не видна из &НаСервере и наоборот. Для тонкого клиента и веб-клиента все перечисленные функции работают одинаково, платформенных ограничений здесь нет.
Если подсчёт слов нужен для проверки «не более N слов», не обязательно считать все слова до конца: в универсальном переборе можно прервать цикл сразу после превышения лимита. На длинных текстах это заметно экономит время.
Частые вопросы
Можно ли посчитать слова в запросе 1С без кода?
Прямой функции подсчёта слов в языке запросов нет. Можно косвенно оценить через разность длин: СтрДлина(Строка) минус СтрДлина(Строка без пробелов) даст число пробелов, но функции замены подстроки в запросе тоже нет, поэтому на практике проще выгрузить результат и посчитать кодом.
Как посчитать слова в многострочном тексте?
Перед подсчётом замените переносы строк (Символы.ПС и Символы.ВК) на пробелы и схлопните повторные пробелы, либо используйте универсальный перебор, где переносы уже включены в список разделителей.
Считаются ли дефис и апостроф разделителями слов?
В приведённых алгоритмах — нет: «северо-восток» считается одним словом. Если по логике задачи дефис должен разделять слова, добавьте его в строку разделителей универсального варианта или в список замен при нормализации.
Что быстрее: СтрРазделить или перебор символов?
На коротких и средних строках разница незаметна. На очень длинных текстах встроенные функции (СтрРазделить, СтрЧислоВхождений) обычно быстрее посимвольного цикла на встроенном языке, поэтому при больших объёмах предпочтительнее нормализация плюс СтрРазделить.
Как учесть слова, разделённые запятыми или точками с запятой?
Функция СтрРазделить принимает строку из нескольких разделителей, например СтрРазделить(Текст, " ,;", Ложь) разобьёт текст по пробелам, запятым и точкам с запятой одновременно. Либо добавьте эти символы в набор разделителей универсального перебора.
Работают ли эти функции на мобильной платформе 1С?
Да, СтрРазделить, СтрЧислоВхождений, СокрЛП и посимвольный перебор доступны в мобильной платформе так же, как и в обычной, ограничений по строковым функциям там нет.
Что важно запомнить
Для чистых данных достаточно СтрРазделить с СокрЛП и флагом Ложь. Для реальных текстов из внешних источников сначала нормализуйте строку (неразрывные пробелы, табуляции, переносы, двойные пробелы) или используйте универсальный перебор с флагом «внутри слова». Всегда проверяйте функцию на пустой строке и строке из одних разделителей.