При формировании печатных форм, отчетов или отображении данных пользователям часто требуется скрыть технические ведущие нули номера, оставив только его значащую часть (например, превратить 00001540 в 1540). Разберем причины присутствия нулей в номерах, выясним, почему нельзя удалять их непосредственно в реквизите объекта, и подробно рассмотрим все способы очистки номера от незначащих нулей.
В платформе 1С:Предприятие номера документов и коды справочников являются строками фиксированной длины. Платформа автоматически дополняет номер нулями слева для обеспечения правильной алфавитно-цифровой (лексикографической) сортировки. Если убрать лидирующие нули, строка 10 при стандартной сортировке окажется раньше строки 2.
Важное архитектурное правило: модифицировать реквизит ЭтотОбъект.Номер при записи документа категорически не рекомендуется. Механизм автонумерации платформы жестко завязан на длину строки и шаблон нумератора. Если записать номер разной длины, нумератор начнет сбоить или выдавать дубликаты. Очищать номер от нулей необходимо исключительно на этапе вывода информации: в макетах печати, отчетах или строковых представлениях.
Посмотрим на популярный прием, позволяющий очистить чисто цифровой номер в одну строку без циклов и регулярных выражений. Идея заключается в замене нулей на пробелы, вызове функции СокрЛ(), которая штатно убирает пробелы только слева, и обратной замене пробелов на нули:
НомерБезНулей = СтрЗаменить(СокрЛ(СтрЗаменить(ИсходныйНомер, "0", " ")), " ", "0");
Разберем работу этого выражения поэтапно:
СтрЗаменить(..., "0", " ") превращает "00001540" в " 1540".СокрЛ() удаляет пробелы только с левой стороны строки, получая "1540". Пробел в конце или середине (если бы там был ноль) сохранился бы.СтрЗаменить(..., " ", "0") восстанавливает оставшиеся пробелы обратно в нули. Например, из "00001040" получится "1040".Нюанс использования: этот алгоритм идеально подходит для строго цифровых номеров. Однако если в номере изначально присутствовали пробелы (например, в префиксе), они также превратятся в нули. Для предотвращения такой коллизии пробелы можно предварительно временно экранировать неразрывным пробелом:
СтрокаБезПробелов = СтрЗаменить(ИсходныйНомер, " ", Символы.НПП);
Результат = СтрЗаменить(СокрЛ(СтрЗаменить(СтрокаБезПробелов, "0", " ")), " ", "0");
Результат = СтрЗаменить(Результат, Символы.НПП, " ");
Проанализируем классический подход, который часто встречается в процедурах общего назначения. Мы последовательно отсекаем первый символ строки до тех пор, пока он равен нулю:
Функция УбратьЛидирующиеНули(Знач Номер) Экспорт
Номер = СокрЛП(Номер);
Пока Лев(Номер, 1) = "0" Цикл
Номер = Сред(Номер, 2);
КонецЦикла;
Возврат Номер;
КонецФункции
Этот метод прост, нагляден и не искажает пробелы внутри строки. Однако обратим внимание на граничный случай: если номер целиком состоит из нулей ("000000"), цикл вернет пустую строку. Чтобы вернуть хотя бы одну значащую цифру "0", добавим условие:
Функция УбратьЛидирующиеНулиБезопасно(Знач Номер) Экспорт
Номер = СокрЛП(Номер);
Пока СтрДлина(Номер) > 1 И Лев(Номер, 1) = "0" Цикл
Номер = Сред(Номер, 2);
КонецЦикла;
Возврат Номер;
КонецФункции
Если номер гарантированно не содержит буквенных префиксов и дефисов, его можно преобразовать в числовой тип с последующим форматированием:
НомерНаПечать = Формат(Число(Номер), "ЧГ=0");
Параметр "ЧГ=0" отключает группировку разрядов, чтобы в номере не появились пробелы-разделители тысяч (например, 1 540). Аналогичное преобразование можно выполнить через ОписаниеТипов:
Описание = Новый ОписаниеТипов("Число");
ЧисловойНомер = Описание.ПривестиЗначение(Номер);
НомерНаПечать = Формат(ЧисловойНомер, "ЧГ=0");
Предупреждение: вызов функции Число() вызовет аварийную ошибку выполнения программы, если в строке встретится префикс организации, буква или дефис (например, "ОФ-000012"). Метод через ОписаниеТипов не вызовет падения, но при наличии нечисловых символов вернет 0.
В современных версиях платформы 1С:Предприятие (начиная с релиза 8.3.23) появилась нативная поддержка регулярных выражений, работающая кроссплатформенно как на Windows, так и на Linux:
// Удаление всех нулей в начале строки
НомерНаПечать = СтрЗаменитьПоРегулярномуВыражению(Номер, "^0+", "");
// Удаление нулей с сохранением последнего нуля, если строка состоит только из нулей
НомерНаПечать = СтрЗаменитьПоРегулярномуВыражению(Номер, "^0+(?=\d)", "");
Для более старых версий платформы под управлением Windows разработчики нередко применяли COM-объект VBScript.RegExp:
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Pattern = "^0*([1-9][0-9]*)$";
НомерНаПечать = RegExp.Replace(Номер, "$1");
Ограничение: использование COMОбъект не поддерживается на серверах и клиентах под управлением Linux, macOS, а также в веб-клиенте. В промышленном коде такой способ использовать не рекомендуется.
В реальных конфигурациях номер часто содержит префикс организации или узла РИБ, разделенный дефисом (например, ПРФ-000102030). Если требуется удалить нули только из числовой части после префикса, можно воспользоваться разбором строки:
Функция ОчиститьНомерСПрефиксом(Знач ИсходныйНомер) Экспорт
Номер = СокрЛП(ИсходныйНомер);
// Пропускаем символы префикса и дефис
Пока НЕ ((КодСимвола(Лев(Номер, 1)) >= 48 И КодСимвола(Лев(Номер, 1)) <= 57) ИЛИ Номер = "")
ИЛИ Лев(Номер, 1) = "-" Цикл
Номер = Сред(Номер, 2);
КонецЦикла;
// Убираем лидирующие нули из оставшейся цифровой части
Пока Лев(Номер, 1) = "0" Цикл
Номер = Сред(Номер, 2);
КонецЦикла;
Возврат Номер;
КонецФункции
Если разработка ведется в типовой или нетиповой конфигурации на базе БСП (1С:ERP, 1C:Комплексная автоматизация, 1C:Управление торговлей, 1С:Бухгалтерия и др.), не требуется писать собственные велосипеды. В составе библиотеки есть готовые функции общего модуля ПрефиксацияОбъектовКлиентСервер:
// Удаление всех префиксов и лидирующих нулей (типовой номер на печать):
НомерДляПечати = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(ДокументСсылка.Номер, Истина, Истина);
// Удаление нулей с сохранением префикса информационной базы:
НомерСПрефиксом = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(ДокументСсылка.Номер, Ложь, Истина);
// Удаление лидирующих нулей только из цифровой части (например, "ООГГ-0000123" станет "ООГГ-123"):
НомерПреобразованный = ПрефиксацияОбъектовКлиентСервер.УдалитьЛидирующиеНулиИзНомераОбъекта(ДокументСсылка.Номер);
Методы БСП учитывают все стандарты нумерации 1С: префиксы узлов распределенных баз, префиксы организаций, дефисы и пользовательские литеры, формируя корректный номер для вывода в печатные формы согласно требованиям делопроизводства.