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