Часто при разработке, особенно в задачах интеграции или синхронизации данных между несколькими базами 1С (для чего часто применяется универсальная выгрузка и загрузка данных), возникает нестандартная потребность. Нам нужно не просто создать документ и позволить системе присвоить ему следующий по порядку номер, а сформировать номер на основе уже известного числового значения. Например, перенести документ с числовым номером 123 из одной базы в другую (в том числе при использовании адаптивной выгрузки XML для разных конфигураций), но в целевой базе он должен получить номер в стандартном формате, например, "УТОР-000123".
В этой статье мы подробно разберем, как решить эту задачу. Проанализируем, почему в 1С нет одной "волшебной" функции для этого, и рассмотрим несколько надежных способов, как собрать правильный номер документа, используя типовые механизмы платформы и конфигурации.
Основная логика платформы 1С и типовых конфигураций рассчитана на последовательную и автоматическую нумерацию. Когда вы создаете новый документ и вызываете метод УстановитьНовыйНомер(), система сама определяет последний использованный номер в пределах заданного префикса и периода и присваивает следующий. Это гарантирует уникальность номеров и порядок в учете.
Задача "встроить" свой, заранее известный номер в эту последовательность является нетиповой. Система не предоставляет готового инструмента вида СформироватьПолныйНомер(МоеЧисло). Поэтому решение заключается в том, чтобы "сымитировать" работу стандартного механизма: самостоятельно получить все составные части номера и правильно их объединить.
Полный номер документа в типовых конфигурациях обычно состоит из трех частей:
Наша цель — собрать эти части в единую строку. Рассмотрим несколько подходов.
Если вы точно знаете, какие префиксы должны быть, и они не меняются, можно собрать номер простой конкатенацией (сложением) строк.
Допустим, нам известен числовой номер ХХ, префикс информационной базы "ИИ" и префикс организации "ОО".
Самый простой, но не очень надежный вариант — "зашить" нули в код:
ЧислоНомера = 123;
// Предполагаем, что номер всегда шестизначный
НомерСтрокой = "ИИОО-000" + Строка(ЧислоНомера);
ДокОбъект.Номер = НомерСтрокой; // Получим "ИИОО-000123"
Этот код сломается, если число будет четырехзначным (например, 1234), так как количество нулей жестко задано. Более правильный подход — использовать форматирование.
Для форматирования числовой части с добавлением лидирующих нулей идеально подходит функция Формат().
ЧислоНомера = 123;
ДлинаЧисловойЧасти = 6; // Длину можно получить из метаданных: Метаданные.Документы.МойДокумент.ДлинаНомера
// Форматная строка "ЧГ=0" означает, что группировка разрядов отключена (ЧГ), а пустые позиции слева будут заменены нулями (0).
ФорматнаяСтрока = "ЧЦ=" + ДлинаЧисловойЧасти + "; ЧВН=; ЧГ=0";
ЧисловаяЧастьСтрокой = Формат(ЧислоНомера, ФорматнаяСтрока); // Получим "000123"
ДокОбъект.Номер = "ИИОО-" + ЧисловаяЧастьСтрокой;
Еще один популярный и компактный способ форматирования — использовать конкатенацию со строкой нулей и функцию Прав(). Этот метод очень нагляден:
ЧислоНомера = 123;
ДлинаЧисловойЧасти = 6;
// К строке нулей добавляем наше число и берем справа нужное количество символов
ЧисловаяЧастьСтрокой = Прав("00000000000" + Формат(ЧислоНомера, "ЧГ="), ДлинаЧисловойЧасти);
ДокОбъект.Номер = "ИИОО-" + ЧисловаяЧастьСтрокой;
Недостаток этого подхода в том, что префиксы "ИИ" и "ОО" жестко прописаны в коде. Если администратор изменит их в настройках программы, ваш код перестанет работать корректно. Поэтому перейдем к более универсальному решению.
Этот метод является самым правильным и надежным, так как он не зависит от конкретных значений префиксов, а получает их напрямую из настроек системы. Алгоритм состоит из трех шагов: получить префиксы, отформатировать число и собрать итоговую строку.
Шаг 1. Получаем префиксы программно
В типовых конфигурациях, особенно использующих Библиотеку стандартных подсистем (БСП), логика формирования префиксов вынесена в общие модули. Чтобы быстрее ориентироваться в них, можно использовать справочник по методам БСП с примерами кода. Наша задача — найти и вызвать нужные функции из этих модулей.
Как правило, за нумерацию отвечает общий модуль НумерацияОбъектов или похожий по названию. В нем есть функции для получения готового префикса для объекта.
Чтобы получить префикс для нашего документа, нам нужно передать в эту функцию объект документа с заполненным реквизитом Организация, так как префикс организации зависит от этого реквизита.
Посмотрим на пример. Предположим, мы создаем документ РеализацияТоваровУслуг.
// Создаем объект документа в памяти, но пока не записываем его
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// Обязательно заполняем реквизиты, от которых зависит префиксация!
// В первую очередь - Организация.
НовыйДокумент.Организация = Справочники.Организации.НайтиПоНаименованию("Наша организация");
НовыйДокумент.Дата = ТекущаяДата();
// ... заполняем другие необходимые реквизиты ...
// Вызываем типовую функцию для получения полного префикса.
// Путь к функции может отличаться в разных конфигурациях!
// Ищите в общем модуле, отвечающем за нумерацию (например, НумерацияОбъектовКлиентСервер).
ПолныйПрефикс = "";
УправлениеПрефиксациейОбъектов.ПолучитьПрефиксОбъекта(НовыйДокумент, ПолныйПрефикс);
// После вызова этой процедуры переменная "ПолныйПрефикс" будет содержать строку вида "ИИОО"
Важно: Название модуля и функции может отличаться в вашей конфигурации (например, УправлениеПрефиксациейОбъектов.ПриПолученииПрефиксаНомера или НумерацияОбъектовПереопределяемый.УстановитьПрефикс). Чтобы найти нужную, откройте подписку на событие ПриУстановкеНовогоНомера для вашего вида документа и посмотрите, какая процедура там вызывается. Это самый надежный способ найти актуальную логику.
Шаг 2. Форматируем числовую часть
Этот шаг не отличается от того, что мы делали в первом решении. Мы берем наше известное число и дополняем его нулями до нужной длины.
ИзвестноеЧисло = 456;
ДлинаНомера = НовыйДокумент.Метаданные().ДлинаНомера; // Получаем длину из метаданных
ФорматнаяСтрока = "ЧЦ=" + ДлинаНомера + "; ЧВН=; ЧГ=0";
ЧисловаяЧасть = Формат(ИзвестноеЧисло, ФорматнаяСтрока); // Результат: "000456" (если длина 6)
Шаг 3. Собираем итоговый номер и присваиваем его документу
Теперь у нас есть все компоненты: полученный через типовую функцию префикс и отформатированная числовая часть. Осталось их объединить.
// ПолныйПрефикс мы получили на Шаге 1, например, "УТОР"
// ЧисловаяЧасть - на Шаге 2, например, "000456"
// Собираем итоговый номер
ИтоговыйНомер = ПолныйПрефикс + "-" + ЧисловаяЧасть; // Результат: "УТОР-000456"
// Присваиваем номер нашему объекту
НовыйДокумент.Номер = ИтоговыйНомер;
// Теперь документ можно записывать
НовыйДокумент.Записать();
Задача формирования номера по известному числу чаще всего возникает при переносе данных между базами. В этом контексте важно помнить о нескольких вещах:
ВходящийНомерОбмена. Если требуется сохранить всю историю изменений, может быть выполнен перенос версий объектов (БСП) из исходной базы. Это позволяет:
Тем не менее, если бизнес-требования жестко предписывают сохранять числовую часть номера, то описанный выше "Рекомендуемый способ" является наилучшим решением.