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

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При организации обмена данными между базами 1С:Предприятие 7.7 разработчики часто сталкиваются с задачей: загрузить документы из текстового файла, но не сохранять их исходные номера, а присвоить новые по порядку текущей информационной базы. Рассмотрим практические нюансы реализации этого механизма, типичные ошибки при работе со встроенным методом УстановитьНовыйНомер, а также разберем алгоритм кастомной нумерации с учетом подразделений и условий.

Типичные ошибки при программном присвоении номера

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

  1. Попытка использовать процедуру как функцию. Метод УстановитьНовыйНомер() в 1С 7.7 является процедурой. Он ничего не возвращает, а напрямую меняет реквизит НомерДок у объекта. Конструкция вида ДокВН.НомерДок = ДокВН.УстановитьНовыйНомер("ЦСК"); приводит к синтаксической ошибке выполнения: «Обращение к процедуре объекта как к функции». Правильный синтаксис — отдельный вызов: ДокВН.УстановитьНовыйНомер("ЦСК");.
  2. Сравнение ссылки со строковым литералом. Если в коде ссылка на справочник присвоена переменной (например, через СпрМХ.ТекущийЭлемент), проверка условия Если Получатель = "Магазин" Тогда никогда не сработает. Происходит сравнение объекта типа «Справочник» со строкой. Необходимо сравнивать строковое поле (например, СокрЛП(Получатель.Наименование)) или выполнять проверку непосредственно по значению из файла до поиска в справочнике.
  3. Ошибка «Номер не уникальный!». Возникает из-за превышения длины номера или сбоя лексикографического порядка. Например, если длина номера документа ограничена 10 символами, а префикс занимает 3 символа, под числовую часть остается строго 7 позиций. Если в базе вручную введен номер без ведущих нулей или нарушена длина, штатный механизм не сможет рассчитать следующий корректный индекс.
  4. Порядок заполнения даты и номера. Метод УстановитьНовыйНомер() чувствителен к периодичности нумератора. Если периодичность установлена «В пределах года», вызывать генерацию номера следует строго после присвоения реквизита ДатаДок, иначе номер будет сформирован в периоде рабочей даты.

Решение 1. Использование штатного метода УстановитьНовыйНомер

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

Посмотрим на пример правильного кода:


// Сначала определяем реквизиты поиска
НомерДокИзФайла = СпРекв.ПолучитьЗначение(2);
ДатаДок = Дата(СпРекв.ПолучитьЗначение(3));

ИмяПолучателя = СокрЛП(СпРекв.ПолучитьЗначение(6));
Если СпрМХ.НайтиПоНаименованию(ИмяПолучателя, 0, 1) = 1 Тогда
    Получатель = СпрМХ.ТекущийЭлемент;
Иначе
    Получатель = "";
КонецЕсли;

ДокВН.Новый();
ДокВН.ДатаДок = ДатаДок;
ДокВН.МестоХранения = МестоХранения;
ДокВН.Получатель = Получатель;

// Проверяем строковое значение получателя для выбора схемы нумерации
Если ИмяПолучателя = "Магазин" Тогда
    // Сохраняем исходный номер документа из файла
    ДокВН.НомерДок = НомерДокИзФайла;
Иначе
    // Генерируем новый порядковый номер с заданным префиксом
    ДокВН.УстановитьНовыйНомер("ЦСК");
КонецЕсли;

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

Решение 2. Программный алгоритм нумерации по коду склада

В нетиповых конфигурациях логика нумерации часто привязана к реквизитам шапки — например, префиксом выступает код места хранения. Однако при программной загрузке через СоздатьОбъект("Документ...") процедуры из модуля экранной формы документа (например, ВыборНомераДокумента) не срабатывают. В таком случае алгоритм расчета номера переносят непосредственно в саму обработку загрузки.

Рассмотрим реализацию собственной процедуры формирования номера:


Функция ПолучитьСледующийНомер(ТекМестоХранения, ТекДатаДок)
    Перем ДокВыборка, ТекПрефикс, МаксНомер, ДлинаНомера;
    
    ТекПрефикс = СокрЛП(ТекМестоХранения.Код);
    МаксНомер = 0;
    ДлинаЧисла = 7; // Количество знаков под числовую часть
    
    ДокВыборка = СоздатьОбъект("Документ.РасходнаяНакладнаяВнутр");
    ДокВыборка.ОбратныйПорядок(1);
    ДокВыборка.ВыбратьДокументы(НачГода(ТекДатаДок), КонГода(ТекДатаДок));
    
    Пока ДокВыборка.ПолучитьДокумент() > 0 Цикл
        // Проверяем соответствие префикса документа коду склада
        Если Лев(ДокВыборка.НомерДок, СтрДлина(ТекПрефикс)) = ТекПрефикс Тогда
            НомерСтр = Сред(ДокВыборка.НомерДок, СтрДлина(ТекПрефикс) + 1);
            НомерЧисло = Число(НомерСтр);
            Если НомерЧисло > МаксНомер Тогда
                МаксНомер = НомерЧисло;
            КонецЕсли;
            // Так как включен обратный порядок, максимальный номер встретится в начале выборки
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    СледНомер = МаксНомер + 1;
    СтрСледНомер = Строка(СледНомер);
    
    // Дополняем лидирующими нулями
    НедостаетНулей = ДлинаЧисла - СтрДлина(СтрСледНомер);
    Если НедостаетНулей > 0 Тогда
        СтрСледНомер = Лев("0000000000", НедостаетНулей) + СтрСледНомер;
    КонецЕсли;
    
    Возврат ТекПрефикс + СтрСледНомер;
КонецФункции

Архитектурные риски при смене нумерации в загрузке

Выясним важный побочный эффект: если мы отказываемся от номеров из файла, стандартный поиск существующего документа через ДокВН.НайтиПоНомеру(НомерДок, ДатаДок) становится некорректным и опасным:

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

Рекомендация: Для надежной идентификации сохраняйте входящий номер файла в отдельный реквизит документа (например, НомерВхДок или Комментарий). Поиск документов перед обновлением следует выполнять по комбинации параметров: склад-отправитель, склад-получатель, дата и сохраненный исходный номер документа.

← На главную