Как правильно увеличить номер документа на единицу в 1С с сохранением префикса и нулей

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

В процессе разработки или доработки конфигураций 1С часто возникает задача программной генерации следующего номера документа. Казалось бы, задача проста: взять текущий номер, прибавить единицу и записать обратно. Однако, поскольку номер в 1С — это строка (например, У00000000011), при обычном преобразовании в число и обратно мы теряем и префикс, и ведущие нули, получая на выходе просто число 12. В этой статье мы подробно разберем, как корректно инкрементировать номер, сохраняя его структуру.

Почему стандартное преобразование не работает?

Рассмотрим ситуацию: у нас есть номер У00000000011. Если мы используем функцию Число(), платформа отсечет префикс и все ведущие нули. При обратном преобразовании Строка(11 + 1) результат будет "12". Нам же необходимо получить У00000000012. Для этого нужно отдельно обработать текстовый префикс и цифровую часть, обеспечив правильное форматирование последней.

Способ 1. Использование встроенной функции Формат()

Это наиболее надежный и быстрый способ управления внешним видом числа. Функция Формат() позволяет жестко задать количество знаков и заставить систему заполнять пустые разряды нулями. Проанализируем пример кода, который решает задачу наиболее лаконично:


// Предположим, ТекущийНомер = "У00000000011"
Префикс = "У";
ДлинаЧисловойЧасти = 11; // Общая длина числовой части после префикса
ТолькоЦифры = Число(Прав(ТекущийНомер, ДлинаЧисловойЧасти));
НовоеЧисло = ТолькоЦифры + 1;

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

Важный нюанс: Обратите внимание на параметр ЧГ=0. Если его не указать, 1С может вставить неразрывный пробел в качестве разделителя групп разрядов (например, "1 001"), что недопустимо в номере документа и приведет к ошибкам при записи или поиске.

Способ 2. Автоматическая установка номера методом платформы

Прежде чем писать сложный код по замене строк, проанализируем возможности самой платформы. У объектов (Документов, Справочников) существует встроенный метод УстановитьНовыйНомер(). Это "правильный" путь, так как система сама находит последний номер в базе и увеличивает его, соблюдая уникальность.


ДокОбъект = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// Устанавливает номер с учетом заданного префикса
ДокОбъект.УстановитьНовыйНомер("У"); 

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

Способ 3. Динамическое разделение префикса и числа

В некоторых случаях мы не знаем заранее длину префикса — он может быть как "У", так и "УУ" или "АБ-". Разберем алгоритм, который автоматически определяет, где заканчивается текст и начинается число:


ПоследнийНомер = "УУ0000000045";
Инд = 1;
ДлинаЧисловойЧасти = 0;

// Идем с конца строки, пока находим цифры
Пока Инд < СтрДлина(ПоследнийНомер) Цикл
    Символ = Сред(ПоследнийНомер, СтрДлина(ПоследнийНомер) - Инд + 1, 1);
    Если Найти("0123456789", Символ) = 0 Тогда
        ДлинаЧисловойЧасти = Инд - 1;
        Прервать;
    КонецЕсли;
    Инд = Инд + 1;
КонецЦикла;

ПрефиксЧасть = Лев(ПоследнийНомер, СтрДлина(ПоследнийНомер) - ДлинаЧисловойЧасти);
ЧислоЧасть = Число(Прав(ПоследнийНомер, ДлинаЧисловойЧасти)) + 1;

// Собираем обратно
НовыйНомер = ПрефиксЧасть + Формат(ЧислоЧасть, "ЧЦ=" + ДлинаЧисловойЧасти + "; ЧВН=; ЧГ=0");

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

Способ 4. Работа через запрос (для массовой обработки)

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |   Реализация.Номер КАК Номер
    |ИЗ
    |   Документ.РеализацияТоваровУслуг КАК Реализация
    |УПОРЯДОЧИТЬ ПО
    |   Номер УБЫВ";

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Если Выборка.Следующий() Тогда
    // Здесь применяем логику инкремента из способов выше
    ТекНомер = Выборка.Номер;
    // ... обработка номера ...
КонецЕсли;

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

Типичные ошибки при ручной нумерации

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

  1. Лишние пробелы: Функция Строка(Число) по умолчанию добавляет разделитель групп разрядов. Если число 1000 превратится в "1 000", это сломает всю дальнейшую логику работы с кодом. Всегда используйте Формат(..., "ЧГ=0").
  2. Неразрывные пробелы: В региональных настройках системы в качестве разделителя может быть установлен специальный символ (Unicode 160). Обычная функция СтрЗаменить(Строка, " ", "") его не удалит.
  3. Переполнение разрядности: Если длина номера ограничена (например, 11 символов), и вы достигли номера "9999999999", прибавить единицу без увеличения длины строки не получится. Программа либо выдаст ошибку, либо "зациклит" номер.
  4. Региональные настройки: Поведение функций преобразования может меняться в зависимости от настроек операционной системы на сервере или клиенте. Использование форматной строки — единственный способ гарантировать одинаковый результат везде.

Рекомендации для современных конфигураций (БСП)

Если вы работаете в современной базе (УТ 11, БП 3.0, ERP), мы рекомендуем не изобретать велосипед, а заглянуть в общий модуль ПрефиксацияОбъектовКлиентСервер. Там реализованы мощные инструменты для работы с номерами, которые учитывают префиксы организаций, префиксы информационных баз в РИБ и корректно разделяют их. Использование стандартов БСП (Библиотеки стандартных подсистем) сделает ваш код более устойчивым к обновлениям платформы.

Выясним причину, по которой ручная нумерация иногда считается плохим тоном. 1С хранит номера в индексированном поле. Как только пользователь "ломает" нумерацию (например, вводит номер 999 вместо 001), автонумерация начинает предлагать 1000. Если же ввести номер максимальной длины из букв, автонумерация может и вовсе остановиться. Поэтому, прежде чем программно увеличивать номер, убедитесь, что это действительно необходимо и нельзя обойтись стандартным функционалом УстановитьНовыйНомер().

← На главную