При разработке интеграций, например, при загрузке прайс-листов из Excel, мы часто создаем документы программно. Однако в момент записи объекта может возникнуть неприятная ситуация: система отказывается сохранять документ, прерывая работу критической ошибкой «Значение поля "Номер" не уникально». Давайте подробно проанализируем эту ситуацию, разберем причины сбоя платформы 1С и рассмотрим надежные способы решения проблемы.
Рассмотрим классический пример. У нас есть обработка загрузки, которая читает файл Excel и создает документы установки цен. Код выглядит примерно следующим образом:
Функция УстановитьЦеныНоменклатуры(ТипЦены, ЦеныНоменклатуры, Комментарий = Неопределено) Экспорт
Док = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
Док.Дата = ТекущаяДата();
Док.Ответственный = ПараметрыСеанса.ТекущийПользователь;
Док.НеПроводитьНулевыеЗначения = Истина;
Док.Комментарий = Комментарий;
ЗаполнитьЗначенияСвойств(Док.ТипыЦен.Добавить(), Новый Структура("ТипЦен", ТипЦены));
Для Каждого Стр Из ЦеныНоменклатуры Цикл
Нов = Док.Товары.Добавить();
Нов.Валюта = Константы.ВалютаРегламентированногоУчета.Получить();
Нов.ЕдиницаИзмерения = Стр.Номенклатура.ЕдиницаХраненияОстатков;
Нов.ТипЦен = ТипЦены;
Нов.СпособРасчетаЦены = Перечисления.СпособыРасчетаЦены.ПоПроцентнойНаценкеНаБазовыйТип;
ЗаполнитьЗначенияСвойств(Нов, Стр);
КонецЦикла;
Док.Записать(РежимЗаписиДокумента.Проведение); // На этой строке возникает ошибка!
Возврат Док.Ссылка;
КонецФункции
При выполнении метода Записать платформа пытается присвоить новому документу следующий по порядку номер, но обнаруживает, что документ с таким номером в базе уже существует. Возникает закономерный вопрос: почему механизм автонумерации 1С дал сбой?
Система автонумерации в 1С работает по принципу инкремента: она ищет в базе документ с максимальным номером, отбрасывает буквенные префиксы, берет числовую часть и прибавляет к ней единицу. Если алгоритм ломается, причин может быть несколько. Разберем их по шагам:
15 вместо 00000000015) или добавил спецсимволы (дроби, дефисы), строковый расчет платформы выходит из строя.УТ000099999), платформа физически не сможет сгенерировать следующее значение без увеличения длины строки, попытается начать цикл заново и наткнется на уже занятые номера.Посмотрим на практические решения данной ситуации. Мы пойдем от самых простых и правильных подходов к программным "заглушкам".
Самый корректный и быстрый способ, рекомендуемый самой платформой — принудительно обновить кэш выданных номеров в базе данных. Для этого в 1С существует специальный глобальный метод ОбновитьНумерациюОбъектов.
Создадим простую внешнюю обработку и поместим в ее модуль следующий код:
&НаСервере
Процедура ВосстановитьНумерациюНаСервере()
ОбновитьНумерациюОбъектов(Метаданные.Документы.УстановкаЦенНоменклатуры);
// Метод перечитает максимальные номера из БД и синхронизирует кэш платформы
КонецПроцедуры
Важно: метод аннулирует все выданные, но еще не записанные в базу номера у других пользователей. Этот код должен выполнять администратор системы.
Если обновление нумерации не помогло, проанализируем список документов визуально. Скорее всего, где-то затесался документ с неправильным форматом номера.
Откройте список документов (в нашем случае «Установка цен номенклатуры»), отсортируйте колонку «Номер» по убыванию и внимательно изучите верхние строки. Найдите документ, у которого номер имеет нестандартную длину или содержит лишние символы (например, без нулей спереди). Зайдите в этот документ и вручную приведите его номер к стандартному платформенному виду.
Для массового исправления можно воспользоваться типовой обработкой «Универсальные подбор и обработка объектов» и выполнить перенумерацию всех документов за текущий год в хронологическом порядке.
Чтобы обезопасить нашу обработку загрузки из Excel от подобных падений в будущем, мы можем модифицировать наш исходный код. Если платформа попытается записать объект с неуникальным номером, мы перехватим ошибку и заставим систему принудительно сгенерировать новый, свободный номер с помощью метода УстановитьНовыйНомер.
Модернизируем код записи из исходного примера:
Попытка
// Пытаемся записать документ штатным образом
Док.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Если получаем ошибку не уникальности номера,
// заставляем 1С пересчитать номер заново
Док.УстановитьНовыйНомер();
Попытка
Док.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Если и тут ошибка, выводим подробности пользователю
Сообщить("Не удалось записать документ: " + ОписаниеОшибки());
КонецПопытки;
КонецПопытки;
Этот подход гарантирует, что даже при временных сбоях автонумерации ваша интеграция не сломается и продолжит успешно загружать данные в систему.
Иногда (если проблема плавающая и возникает только у одного пользователя) достаточно выполнить базовую операцию по очистке кэша 1С. Закройте базу, удалите ее из списка баз в стартере 1С и добавьте заново. Это очистит локальные временные файлы, которые могли вызывать конфликт генерации номеров на клиенте.
Применяя эти инструкции, вы сможете не только быстро устранить ошибку «Значение поля Номер не уникально», но и обеспечить отказоустойчивость ваших алгоритмов программного создания документов в 1С.