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

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

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

Почему не работает функция Формат для номера документа

Проанализируем распространенную ошибку, когда разработчик пытается отформатировать номер следующим образом:


Номер = Источник.Номер;
Результат = Формат(Номер, "ЧЦ=6; ЧВН=; ЧГ=0");

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

Для того чтобы функция форматирования сработала, строку необходимо сначала явно преобразовать в число. Рассмотрим, как это выглядит на практике:


// Вариант с явным преобразованием строки в число
Результат = Формат(Число(СокрЛП(Номер)), "ЧЦ=6; ЧВН=; ЧГ=0");

// Либо с неявным приведением через сложение с нулем
Результат = Формат(0 + Номер, "ЧЦ=6; ЧВН=; ЧГ=0");

Однако данный подход допустим только в том случае, если номер состоит исключительно из цифр. Если в номере содержатся буквенные префиксы, тире или разделители (например, «к3» или «ОФ-0012»), попытка преобразования в число вызовет критическую ошибку выполнения: «Преобразование значения к типу Число не может быть выполнено».

Дополнение строки нулями с помощью строковых функций

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


ДлинаНомера = 11; // Требуемая длина номера приемника
НомерСтрокой = СокрЛП(Источник.Номер);
Результат = Прав("00000000000000000" + НомерСтрокой, ДлинаНомера);

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

Использование функций Библиотеки стандартных подсистем (БСП)

Если в конфигурации внедрена БСП, мы можем не формировать конкатенации строк вручную, а воспользоваться готовыми типовыми методами. Вызовем функцию общего модуля:


ЧисловаяЧасть = "3";
ДлинаНомера = 6;
Результат = СтроковыеФункцииКлиентСервер.ДополнитьСтроку(ЧисловаяЧасть, ДлинаНомера, "0", "Слева");
// Результат вернет "000003"

Этот метод исключает ошибки ручного вычисления длины и делает программный код более понятным.

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

В реальных базах номера почти всегда содержат префиксы организации или узла распределенной информационной базы (например, «к3», «ЦБ-00045»). Если мы просто дополним всю строку нулями слева, то получим значение вида «0000000000к3». В платформе 1С такой номер считается поврежденным, так как префикс обязан стоять в начале строки. Из-за этого встроенный механизм автонумерации перестанет понимать порядок следования документов и начнет выдавать ошибки неуникальности номера.

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


Номер = СокрЛП(Источник.Номер);
Цифры = ""; 
Префикс = ""; 
Суффикс = "";

Для х = 1 По СтрДлина(Номер) Цикл
    Символ = Сред(Номер, х, 1); 
    КодСимвола = КодСимвола(Символ);
    
    // Проверяем, является ли символ цифрой (коды ASCII от 48 до 57)
    Если НЕ (КодСимвола >= 48 И КодСимвола <= 57) Тогда
        Если СтрДлина(Цифры) > 0 Тогда
            Суффикс = Суффикс + Символ;
        Иначе
            Префикс = Префикс + Символ;
        КонецЕсли;
    Иначе
        Цифры = Цифры + Символ;
    КонецЕсли;
КонецЦикла;

// Дополняем только числовую часть до нужной разрядности
ЧисловаяЧасть = Формат(Число(Цифры), "ЧВН=; ЧЦ=6; ЧГ=0");
Результат = Префикс + ЧисловаяЧасть + Суффикс;

Также для разделения префиксов и номеров в типовых решениях рекомендуется задействовать специализированный модуль ПрефиксацияОбъектовКлиентСервер.

Особенности передачи номера в правилах конвертации данных (КД 2.x)

Проанализируем типичные ошибки при настройке выгрузки данных через «Конвертацию данных» в обработчике ПередВыгрузкойСвойства реквизита Номер:

  1. Вызов Сообщить() в выражении: процедура Сообщить() не возвращает значения. Конструкции вида Результат = Сообщить(...) приводят к фатальной ошибке выполнения: «Обращение к процедуре как к функции (Сообщить)».
  2. Присвоение переменной Результат: в КД обработчик ожидает результат в предопределенной переменной Значение. Если записать результат в Результат = ..., платформа проигнорирует эту строку и выгрузит исходный Источник.Номер без нулей.
  3. Флаг «Автоматически приводить к длине приемника»: этот флаг предназначен для фиксации длины строк пробелами справа, поэтому для формирования лидирующих нулей он не подходит.
  4. Режим загрузки данных: при загрузке объектов через обмен выставляется режим ОбменДанными.Загрузка = Истина. При этом событие ПриУстановкеНовогоНомера не вызывается, а номер записывается в базу-приемник ровно в том виде, в котором он был выгружен.

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


ДлинаНомера = 11;
НомерСтрокой = СокрЛП(Источник.Номер);
// Обязательно присваиваем предопределенной переменной Значение:
Значение = Прав("00000000000000000" + НомерСтрокой, ДлинаНомера);
← На главную