В практике разработчика 1С часто возникает задача управления нумерацией, которая не укладывается в стандартные механизмы платформы. Например, когда необходимо программно увеличить номер, содержащий префиксы, тире или другие символы (например, превратить "AG-239" в "AG-240"). На первый взгляд задача кажется простой, но она таит в себе подводные камни: обработку нецифровых символов, сохранение ведущих нулей и правильную работу со знаками, которые платформа может ошибочно принять за математические операторы.
В этой статье мы подробно разберем несколько подходов к решению этой задачи: от простых манипуляций со строками до использования регулярных выражений и системных функций.
Самый надежный и понятный способ — это пройтись по всей строке и отобрать только те символы, которые являются цифрами. Это позволяет избежать проблем, когда тире или дефис внутри строки (например, в "AG-239") воспринимается функцией Число() как знак минус, что приводит к некорректному результату (вместо сложения происходит вычитание).
Рассмотрим реализацию функции, которая очищает строку от всех символов, кроме цифр:
Функция ПолучитьТолькоЦифры(ВходящаяСтрока)
Результат = "";
ДоступныеСимволы = "0123456789";
Для Индекс = 1 По СтрДлина(ВходящаяСтрока) Цикл
Символ = Сред(ВходящаяСтрока, Индекс, 1);
Если СтрНайти(ДоступныеСимволы, Символ) > 0 Тогда
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
После того как мы получили чистую строку из цифр, мы можем преобразовать её в число, увеличить на единицу и вернуть обратно в контекст исходной строки. Проанализируем, как собрать это воедино:
ЧисловаяЧасть = ПолучитьТолькоЦифры(ИсходнаяСтрока);
НовоеЧисло = Число(ЧисловаяЧасть) + 1;
НоваяСтрока = СтрЗаменить(ИсходнаяСтрока, ЧисловаяЧасть, Формат(НовоеЧисло, "ЧГ=0"));
Важный нюанс: использование функции СтрЗаменить() эффективно, если числовая часть уникальна внутри строки. Если строка имеет вид "100-ABC-100", замена может сработать некорректно.
Существует более изящный способ «фильтрации» строки, который предложили участники сообщества. Мы можем использовать функции СтрРазделить() и СтрСоединить(), чтобы буквально «выдавить» все нецифровые символы. Посмотрим на этот алгоритм:
Пример реализации в одну строку (для любителей компактного кода):
ТолькоЦифры = СтрСоединить(СтрРазделить(ИсходнаяСтрока, СтрСоединить(СтрРазделить(ИсходнаяСтрока, "0123456789"), ""), Ложь), "");
Этот метод работает быстро, но требует осторожности, если цифры встречаются в разных частях строки (и в префиксе, и в номере).
Если мы заранее знаем, что наша строка всегда разделена дефисом (например, "Склад-001"), мы можем применить метод прямого парсинга. Разберем ситуацию, когда нам нужно отделить всё, что находится после первого найденного тире.
ПозицияТире = Найти(СтрНомер, "-");
Префикс = Лев(СтрНомер, ПозицияТире);
ЧисловаяЧастьСтрокой = Прав(СтрНомер, СтрДлина(СтрНомер) - ПозицияТире);
НовоеЧисло = Число(ЧисловаяЧастьСтрокой) + 1;
// Собираем обратно
Результат = Префикс + Формат(НовоеЧисло, "ЧГ=0");
Здесь крайне важно помнить про ведущие нули. Если исходный номер был "AG-009", то простая прибавка единицы даст "AG-10", что нарушит сортировку. Чтобы сохранить длину номера, проанализируем использование функции Формат().
Для того чтобы номер "009" превратился в "010", а не в "10", необходимо знать исходную длину числовой части. Выясним, как это реализовать:
ДлинаЧисла = СтрДлина(ЧисловаяЧастьСтрокой);
НовоеЧисло = Число(ЧисловаяЧастьСтрокой) + 1;
// Формируем строку формата, например "ЧЦ=3; ЧВН=; ЧГ=0"
СтрокаФормата = "ЧЦ=" + Формат(ДлинаЧисла, "ЧГ=0") + "; ЧВН=; ЧГ=0";
НоваяЧисловаяЧасть = Формат(НовоеЧисло, СтрокаФормата);
Параметр ЧВН= (Число Ведущих Нулей) в функции Формат() гарантирует, что система дополнит число нулями слева до указанной в ЧЦ (Число Цифр) длины.
Если задача усложняется (например, цифры могут быть в середине, в конце, или их несколько групп), наиболее профессиональным подходом будет использование регулярных выражений. В Windows-среде 1С может обращаться к объекту RegExp.
Рассмотрим пример поиска и замены именно последней группы цифр в строке:
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Pattern = "(\d+)$"; // Ищем цифры в конце строки
RegExp.Global = Истина;
Если RegExp.Test(ИсходнаяСтрока) Тогда
Matches = RegExp.Execute(ИсходнаяСтрока);
СтароеЧислоСтрокой = Matches.Item(0).SubMatches.Item(0);
НовоеЧисло = Число(СтароеЧислоСтрокой) + 1;
// Форматируем с сохранением длины
НовоеЧислоСтрокой = Формат(НовоеЧисло, "ЧЦ=" + СтрДлина(СтароеЧислоСтрокой) + "; ЧВН=; ЧГ=0");
Результат = RegExp.Replace(ИсходнаяСтрока, НовоеЧислоСтрокой);
КонецЕсли;
Этот способ самый гибкий, так как он игнорирует любые символы в префиксе (включая тире, точки и скобки) и работает только с целевым числом.
Проанализируем ситуации, в которых лучше применять тот или иной подход:
ПрефиксацияОбъектовКлиентСервер или СтроковыеФункцииКлиентСервер. Часто там уже есть готовые инструменты для работы с префиксами и номерами.Лев() и Прав(). Это работает быстрее всего.Таким образом, мы рассмотрели все основные способы увеличения числа в строке. Выбор конкретного метода зависит от сложности вашей строки и требований к производительности системы.