При написании обработок для изменения нумерации документов начинающие разработчики часто сталкиваются со странным поведением платформы: вместо ожидаемого увеличения номера на единицу (например, из УТ-01333 получить УТ-01334) программа просто дописывает единицу в конец строки, превращая её в УТ-013331. Кроме того, часто измененные на форме номера никак не сохраняются в самой базе данных.
В этой статье мы подробно разберем, почему так происходит, как правильно работать со строковыми типами данных в 1С, изучим безопасные способы программного изменения номеров документов и научимся обновлять системный кэш нумерации, чтобы избежать конфликтов в будущем.
Основная ошибка кроется в фундаментальном понимании типов данных. Реквизит Номер у любого документа в системе 1С:Предприятие имеет тип Строка. Это сделано для того, чтобы система могла поддерживать сложные префиксы организаций, касс, складов или информационных баз (например, МСК-000125 или УТ-000001).
Когда мы пытаемся выполнить выражение вида Стр.Номер = Номер + 1, где переменная Номер является строкой (например, полученной из поля ввода на форме), платформа 1С выполняет не арифметическое сложение, а конкатенацию (склеивание строк). При этом число 1 автоматически и неявно приводится к строковому типу. В результате получается склеенная строка.
Для корректного изменения номера нам необходимо разделять префиксную (буквенную) и числовую части, увеличивать числовую часть математически, а затем собирать номер обратно в строку, сохраняя при этом исходную длину и лидирующие нули.
Даже если мы напишем идеальный алгоритм преобразования строки, код автора из сообщения форума по-прежнему не изменит номера документов в самой системе. Автор производит цикл по табличной части обработки:
Для Каждого Стр Из Объект.Результат Цикл
Стр.Номер = Номер + 1; // Изменение происходит только в оперативной памяти формы!
КонецЦикла;
Этот код меняет значения только внутри временной таблицы на форме обработки (в реквизите Объект.Результат). Чтобы изменения зафиксировались в базе данных 1С, необходимо для каждой строки таблицы получить реальный объект документа, присвоить ему новое значение номера и принудительно вызвать метод записи.
Давайте посмотрим на правильный шаблон обхода документов:
Для Каждого Стр Из Объект.Результат Цикл
// Получаем реальный объект документа из ссылки для редактирования
ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
// Рассчитываем новый номер (различные варианты рассмотрим ниже)
НовыйНомер = "УТ-01334";
ДокОбъект.Номер = НовыйНомер;
// Записываем изменения в базу данных в режиме записи (без перепроведения)
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;
Использование режима РежимЗаписиДокумента.Запись критически важно: это позволяет просто перезаписать реквизит номера, не запуская тяжелые механизмы проведения документа и не меняя движения по регистрам учета.
---
Если нам нужно просто перенумеровать документы по порядку, используя стандартный префикс нашей информационной базы или организации, лучшим решением будет использование встроенного метода платформы УстановитьНовыйНомер(). Платформа сама найдет последний существующий в базе номер с указанным префиксом, увеличит его числовую часть на единицу и автоматически сформирует красивую строку с сохранением разрядности.
Разберем готовый код этого решения:
Для Каждого Стр Из Объект.Результат Цикл
ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
// Передаем в метод префикс организации или базы данных
// Платформа сама рассчитает следующий свободный номер, например, "УТ-00001334"
ДокОбъект.УстановитьНовыйНомер("УТ-");
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;
Этот способ минимизирует вероятность ошибок уникальности номера, так как платформа сама контролирует процесс генерации.
---
Если перед нами стоит задача жестко задать начальный номер (например, начать строго с номера УТ-01333 и далее увеличивать его по порядку на единицу в рамках цикла), нам придется формировать строку номера самостоятельно.
При этом важно помнить про лидирующие нули. Если мы просто сложим префикс и число (например, "УТ-" + 1333), мы получим номер УТ-1333. Из-за уменьшения длины номера (разрядности) в будущем автонумерация 1С может сбиться. Поэтому мы обязаны использовать функцию Формат() для выравнивания числовой части.
Разберем по шагам, как это реализовать:
Префикс = "УТ-";
ТекущийСчетчик = 1333; // Начальное число, которое мы указали в поле ввода на форме
Для Каждого Стр Из Объект.Результат Цикл
ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
// Преобразуем число в строку фиксированной длины с лидирующими нулями
// Параметры форматирования:
// ЧЦ=5 — общая длина числовой части номера (5 символов)
// ЧВН= — указывает платформе выводить лидирующие (левые) нули
// ЧГ=0 — отключает группировку разрядов пробелами (чтобы не получилось "01 333")
СтрокаЧисла = Формат(ТекущийСчетчик, "ЧЦ=5; ЧВН=; ЧГ=0");
// Собираем готовый номер: префикс + отформатированное число
ДокОбъект.Номер = Префикс + СтрокаЧисла;
// Фиксируем изменения в информационной базе
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
// Увеличиваем счетчик для следующего по порядку документа
ТекущийСчетчик = ТекущийСчетчик + 1;
КонецЦикла;
---
Если вы работаете в современных типовых конфигурациях (таких как Управление торговлей 11, Бухгалтерия предприятия 3.0, ERP или Комплексная автоматизация), в них интегрирована Библиотека Стандартных Подсистем (БСП). В составе БСП есть удобные готовые программные интерфейсы для работы со строками номеров документов.
Например, мы можем использовать функции общего модуля ПрефиксацияОбъектовКлиентСервер и ПрефиксацияОбъектов для автоматического разбора номера на префиксную и числовую части, что избавляет нас от ручного написания регулярных выражений или поиска символов дефиса в строке номера.
---
Многие программисты, выполнив программное перенумерование документов, сталкиваются со следующей проблемой: при попытке пользователя создать новый документ вручную, система выдает ошибку «Значение поля "Номер" не уникально» или подставляет старый, уже неактуальный номер.
Происходит это потому, что платформа 1С в целях повышения производительности кэширует в оперативной памяти сервера последние выданные номера документов. Когда мы принудительно и массово меняем номера через код «в обход» стандартного интерактивного создания документов, системный кэш не знает об этих изменениях.
Чтобы решить эту проблему, в самом конце нашей обработки (сразу после завершения цикла записи документов) обязательно нужно выполнить принудительный сброс и обновление кэша для нашего типа метаданных. Делается это с помощью встроенного метода:
// Очищаем кэш номеров для документов "Поступление товаров и услуг"
ОбновитьНумерациюОбъектов(Метаданные.Документы.ПоступлениеТоваровУслуг);
После выполнения этой команды платформа мгновенно пересчитает максимальный номер в базе данных, и пользователи смогут продолжить работу в штатном режиме без ошибок уникальности.
---
Поскольку автор темы упомянул, что он не является профессиональным программистом 1С, для него может быть безопаснее воспользоваться стандартными инструментами, которые уже встроены в программу или доступны бесплатно.
Важное предупреждение: Перед запуском любых обработок, изменяющих номера документов в работающей базе данных, обязательно сделайте резервную копию вашей информационной базы!