Как настроить автонумерацию документа только при записи в 1С

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

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

В чем разница между свойствами автонумерации объекта и формы

Разберем ключевую причину, из-за которой самодельный документ ведет себя иначе, чем типовой. В платформе 1С (при работе с обычными формами) существуют две совершенно разные настройки со схожими названиями:

  1. Свойство самого объекта метаданных «Документ»: флажок Автонумерация в палитре свойств документа в дереве метаданных. Он указывает платформе, что объекту в принципе разрешено автоматически генерировать следующий номер по порядку. Если отключить этот признак, автонумерация перестанет работать вовсе.
  2. Свойство обычной формы документа: реквизит Автонумерация в палитре свойств конкретной формы. По умолчанию при создании новой формы платформа выставляет ему значение Авто, что приводит к немедленному расчету номера при инициализации окна.

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

  1. Оставим включенным флажок Автонумерация в свойствах самого объекта метаданных в дереве конфигурации.
  2. Откроем редактор нужной формы документа. Щелкнем правой кнопкой мыши по свободному фону формы (за пределами элементов управления) и откроем окно Свойства.
  3. Найдем свойство Автонумерация и изменим его значение с Авто на Не использовать.

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

Управление доступностью поля «Номер» и ручное редактирование

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

В типовых конфигурациях (таких как ЗУП 2.0, УПП 1.3, УТ 10.3) эта задача решается централизованно. В командную панель формы выводится специальная кнопка «Редактировать номер», которая по умолчанию блокирует поле ввода, но позволяет снять блокировку по требованию пользователя.

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


Процедура ПриОткрытии()
    // Добавляем типовую команду в подменю действий формы
    МеханизмНумерацииОбъектов.ДобавитьВМенюДействияКнопкуРедактированияНомера(ЭлементыФормы.ДействияФормы.Кнопки.Подменю1);
    
    // Блокируем прямое редактирование поля до явного нажатия кнопки пользователем
    МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера(
        Метаданные, 
        ЭтаФорма, 
        ЭлементыФормы.ДействияФормы.Кнопки.Подменю1, 
        ЭлементыФормы.Номер
    );
КонецПроцедуры

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

Почему номер растет при каждом нажатии «Записать» и как этого избежать

Иногда разработчики пытаются реализовать отложенную нумерацию вручную, вызывая метод УстановитьНовыйНомер() в обработчике события ПередЗаписью модуля документа. Это приводит к серьезной ошибке: при каждом нажатии кнопки «Записать» номер увеличивается на единицу, а любые ручные правки пользователя затираются.

Проанализируем правила безопасной работы со счетчиком номеров:

  1. Если в метаданных включена Автонумерация, а в свойствах формы выставлено значение Не использовать, вызывать метод УстановитьНовыйНомер() вручную вообще не требуется. Платформа самостоятельно присвоит номер при первой записи объекта.
  2. Если логика конфигурации требует явного вызова метода УстановитьНовыйНомер() в коде, его обязательно нужно экранировать проверкой на заполненность реквизита:
    
    Если Не ЗначениеЗаполнено(ЭтотОбъект.Номер) Тогда
        ЭтотОбъект.УстановитьНовыйНомер();
    КонецЕсли;
    
  3. Если пользователь ввел номер вручную до момента записи, платформа не перезаписывает введенную строку, сохраняя пользовательское значение.

Подписки на события и формирование префиксов

В типовых решениях для управления номерами активно применяется событие ПриУстановкеНовогоНомера (через общие подписки на события). Обработчик вызывается платформой непосредственно перед генерацией значения и принимает параметры СтандартнаяОбработка и Префикс.

Если новый документ должен иметь префикс узла распределенной информационной базы (РИБ) или префикс организации, достаточно включить новый документ в состав объектов подписки (например, ПриУстановкеНовогоНомераДокумента). В этом случае обработчик передаст нужный префикс в платформенный генератор, и платформа сформирует номер с сохранением заданной разрядности нулей.

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

Рассмотрим, чем поведение платформы в управляемом приложении отличается от обычных форм:

  1. Отсутствие свойства у управляемой формы: В интерфейсе управляемых форм свойства формы Автонумерация нет. Платформа по умолчанию использует механизм отложенного присвоения: на стороне тонкого клиента поле номера гарантированно остается пустым вплоть до успешного завершения серверной транзакции записи.
  2. Сбои последовательности и кэширование: Если из-за некорректных ручных правок или сбоев транзакций платформа начинает сообщать о неуникальности номера, в оперативной памяти сервера мог закешироваться неверный индекс. Для принудительного пересчета максимального номера в рамках текущего периода без перезапуска кластера применяется метод глобального контекста: ОбновитьНумерациюОбъектов(Метаданные.Документы.ИмяДокумента);
← На главную