Часто в практике разработки на платформе 1С возникает задача, когда стандартного реквизита «Номер» не хватает, и требуется создать дополнительное текстовое поле, которое будет нумероваться автоматически по определенным правилам. Например, нам нужно формировать номер в формате «22-575», где общая длина строки строго ограничена 11 символами, а нумерация является непериодической. Разберем по шагам, как можно реализовать подобный механизм, избежав при этом конфликтов и дублирования номеров.
Стандартная автонумерация платформы «зашита» в ее ядро и работает исключительно для системного реквизита. Если мы создаем свой собственный реквизит (например, ДополнительныйНомер), платформа не будет автоматически генерировать для него значения. Нам придется реализовать эту магию самостоятельно. Рассмотрим два основных подхода к решению этой задачи.
Если мы не хотим писать сложный код парсинга и контроля уникальности, мы можем делегировать эту задачу самой платформе. Проанализируем этот нестандартный, но рабочий метод.
СлужебныйНумератор).Этот способ прост в реализации, но оставляет в базе множество «мусорных» служебных документов. Поэтому перейдем к более профессиональному и правильному подходу.
Для надежной работы системы без «дырок» в нумерации мы создадим собственный алгоритм. Рассмотрим подробнее, как это сделать правильно.
Шаг 1. Хранение последнего номера
Чтобы быстро получать следующий номер, не стоит искать его по всей таблице документов (особенно если их много). Лучше всего создать отдельный Регистр сведений, в котором будет храниться последнее выданное значение (числовая часть). Если нумерация идет в пределах года, добавляем в регистр измерение Год.
Шаг 2. Блокировка данных
Если два бухгалтера одновременно нажмут кнопку «Записать», они могут получить одинаковый номер. Чтобы избежать этого, перед получением номера мы устанавливаем исключительную блокировку на наш регистр сведений.
Шаг 3. Событие генерации
Генерировать номер следует в модуле объекта (или в Подписке на событие), в обработчике ПередЗаписью. Обязательно проверяем, что документ новый, чтобы не менять номер при каждом редактировании.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() И ПустаяСтрока(ДополнительныйНомер) Тогда
ДополнительныйНомер = СгенерироватьНовыйНомер();
КонецЕсли;
КонецПроцедуры
Шаг 4. Алгоритм инкрементирования
Разберем функцию генерации. Если мы не используем регистр сведений, а ищем номер прямо в документах, нам потребуется запрос с использованием оператора ПОДОБНО.
Функция СгенерироватьНовыйНомер()
// Пример алгоритма без блокировок для простоты понимания
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(ТаблицаДокумента.ДополнительныйНомер) КАК МаксНомер
|ИЗ
| Документ.НашДокумент КАК ТаблицаДокумента
|ГДЕ
| ТаблицаДокумента.ДополнительныйНомер ПОДОБНО ""22-%""";
Результат = Запрос.Выполнить().Выгрузить();
СтрокаНомера = Результат[0].МаксНомер;
Если ЗначениеЗаполнено(СтрокаНомера) Тогда
// Отделяем префикс и получаем число
МассивЧастей = СтрРазделить(СтрокаНомера, "-");
ЧисловаяЧасть = Число(МассивЧастей[1]);
НовоеЧисло = ЧисловаяЧасть + 1;
Иначе
НовоеЧисло = 1;
КонецЕсли;
// Форматируем обратно в строку нужной длины
ТекстовыйНомер = "22-" + Формат(НовоеЧисло, "ЧГ=0; ЧВН=; ЧЦ=8");
Возврат ТекстовыйНомер;
КонецФункции
Обратите внимание на функцию Формат. В ней мы используем параметры ЧЦ (общая длина числа) и ЧВН (выводить лидирующие нули), чтобы сохранить нужную структуру номера.
Если ваша база синхронизируется с филиалами, простого счетчика будет недостаточно. Вам обязательно нужно добавлять префикс информационной базы (узла). Например, номер должен выглядеть как МСК-22-575. Если вы используете программную генерацию, не забудьте получить префикс текущего узла и добавить его к строке при формировании результата.
Таким образом, комбинируя обработчик ПередЗаписью, запросы на поиск максимального значения и функции работы со строками, вы можете реализовать автонумерацию текстовых полей любой сложности, не завися от стандартных ограничений платформы.