При интеграции систем, переносе данных и настройке правил обмена разработчики часто сталкиваются с задачей приведения номеров документов к единой длине путем добавления ведущих нулей. Нередко стандартные попытки применить функцию Формат() не дают результата или вызывают ошибки компиляции. Разберем по шагам, почему это происходит и как правильно решить задачу в различных сценариях.
Проанализируем распространенную ошибку, когда разработчик пытается отформатировать номер следующим образом:
Номер = Источник.Номер;
Результат = Формат(Номер, "ЧЦ=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");
Результат = Префикс + ЧисловаяЧасть + Суффикс;
Также для разделения префиксов и номеров в типовых решениях рекомендуется задействовать специализированный модуль ПрефиксацияОбъектовКлиентСервер.
Проанализируем типичные ошибки при настройке выгрузки данных через «Конвертацию данных» в обработчике ПередВыгрузкойСвойства реквизита Номер:
Сообщить() не возвращает значения. Конструкции вида Результат = Сообщить(...) приводят к фатальной ошибке выполнения: «Обращение к процедуре как к функции (Сообщить)».Значение. Если записать результат в Результат = ..., платформа проигнорирует эту строку и выгрузит исходный Источник.Номер без нулей.ОбменДанными.Загрузка = Истина. При этом событие ПриУстановкеНовогоНомера не вызывается, а номер записывается в базу-приемник ровно в том виде, в котором он был выгружен.Таким образом, правильный фрагмент кода для обработчика ПередВыгрузкой свойства Номер должен выглядеть следующим образом:
ДлинаНомера = 11;
НомерСтрокой = СокрЛП(Источник.Номер);
// Обязательно присваиваем предопределенной переменной Значение:
Значение = Прав("00000000000000000" + НомерСтрокой, ДлинаНомера);