Как убрать ведущие нули в номере документа слева в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При формировании печатных форм, отчетов или отображении данных пользователям часто требуется скрыть технические ведущие нули номера, оставив только его значащую часть (например, превратить 00001540 в 1540). Разберем причины присутствия нулей в номерах, выясним, почему нельзя удалять их непосредственно в реквизите объекта, и подробно рассмотрим все способы очистки номера от незначащих нулей.

Зачем нужны лидирующие нули и почему их нельзя удалять в базе данных

В платформе 1С:Предприятие номера документов и коды справочников являются строками фиксированной длины. Платформа автоматически дополняет номер нулями слева для обеспечения правильной алфавитно-цифровой (лексикографической) сортировки. Если убрать лидирующие нули, строка 10 при стандартной сортировке окажется раньше строки 2.

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

Способ 1. Лаконичный строковый алгоритм с заменой на пробелы

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


НомерБезНулей = СтрЗаменить(СокрЛ(СтрЗаменить(ИсходныйНомер, "0", " ")), " ", "0");

Разберем работу этого выражения поэтапно:

  1. Внутренний вызов СтрЗаменить(..., "0", " ") превращает "00001540" в " 1540".
  2. Функция СокрЛ() удаляет пробелы только с левой стороны строки, получая "1540". Пробел в конце или середине (если бы там был ноль) сохранился бы.
  3. Внешний вызов СтрЗаменить(..., " ", "0") восстанавливает оставшиеся пробелы обратно в нули. Например, из "00001040" получится "1040".

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


СтрокаБезПробелов = СтрЗаменить(ИсходныйНомер, " ", Символы.НПП);
Результат = СтрЗаменить(СокрЛ(СтрЗаменить(СтрокаБезПробелов, "0", " ")), " ", "0");
Результат = СтрЗаменить(Результат, Символы.НПП, " ");

Способ 2. Классический цикл по символам слева

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


Функция УбратьЛидирующиеНули(Знач Номер) Экспорт
    Номер = СокрЛП(Номер);
    Пока Лев(Номер, 1) = "0" Цикл 
        Номер = Сред(Номер, 2);
    КонецЦикла;
    Возврат Номер;
КонецФункции

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


Функция УбратьЛидирующиеНулиБезопасно(Знач Номер) Экспорт
    Номер = СокрЛП(Номер);
    Пока СтрДлина(Номер) > 1 И Лев(Номер, 1) = "0" Цикл 
        Номер = Сред(Номер, 2);
    КонецЦикла;
    Возврат Номер;
КонецФункции

Способ 3. Преобразование в число

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

НомерНаПечать = Формат(Число(Номер), "ЧГ=0");

Параметр "ЧГ=0" отключает группировку разрядов, чтобы в номере не появились пробелы-разделители тысяч (например, 1 540). Аналогичное преобразование можно выполнить через ОписаниеТипов:


Описание = Новый ОписаниеТипов("Число");
ЧисловойНомер = Описание.ПривестиЗначение(Номер);
НомерНаПечать = Формат(ЧисловойНомер, "ЧГ=0");

Предупреждение: вызов функции Число() вызовет аварийную ошибку выполнения программы, если в строке встретится префикс организации, буква или дефис (например, "ОФ-000012"). Метод через ОписаниеТипов не вызовет падения, но при наличии нечисловых символов вернет 0.

Способ 4. Использование регулярных выражений

В современных версиях платформы 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, а также в веб-клиенте. В промышленном коде такой способ использовать не рекомендуется.

Способ 5. Обработка номеров с буквенными префиксами

В реальных конфигурациях номер часто содержит префикс организации или узла РИБ, разделенный дефисом (например, ПРФ-000102030). Если требуется удалить нули только из числовой части после префикса, можно воспользоваться разбором строки:


Функция ОчиститьНомерСПрефиксом(Знач ИсходныйНомер) Экспорт
    Номер = СокрЛП(ИсходныйНомер);
    
    // Пропускаем символы префикса и дефис
    Пока НЕ ((КодСимвола(Лев(Номер, 1)) >= 48 И КодСимвола(Лев(Номер, 1)) <= 57) ИЛИ Номер = "") 
        ИЛИ Лев(Номер, 1) = "-" Цикл
        Номер = Сред(Номер, 2);
    КонецЦикла;
    
    // Убираем лидирующие нули из оставшейся цифровой части
    Пока Лев(Номер, 1) = "0" Цикл
        Номер = Сред(Номер, 2);
    КонецЦикла;
    
    Возврат Номер;
КонецФункции

Способ 6. Стандартные механизмы Библиотеки стандартных подсистем (БСП)

Если разработка ведется в типовой или нетиповой конфигурации на базе БСП (1С:ERP, 1C:Комплексная автоматизация, 1C:Управление торговлей, 1С:Бухгалтерия и др.), не требуется писать собственные велосипеды. В составе библиотеки есть готовые функции общего модуля ПрефиксацияОбъектовКлиентСервер:


// Удаление всех префиксов и лидирующих нулей (типовой номер на печать):
НомерДляПечати = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(ДокументСсылка.Номер, Истина, Истина);

// Удаление нулей с сохранением префикса информационной базы:
НомерСПрефиксом = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(ДокументСсылка.Номер, Ложь, Истина);

// Удаление лидирующих нулей только из цифровой части (например, "ООГГ-0000123" станет "ООГГ-123"):
НомерПреобразованный = ПрефиксацияОбъектовКлиентСервер.УдалитьЛидирующиеНулиИзНомераОбъекта(ДокументСсылка.Номер);

Методы БСП учитывают все стандарты нумерации 1С: префиксы узлов распределенных баз, префиксы организаций, дефисы и пользовательские литеры, формируя корректный номер для вывода в печатные формы согласно требованиям делопроизводства.

← На главную