Как в 1С 7.7 выборочно присваивать номер документа при загрузке из файла?

Программист 1С v7.7 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Анализ проблемы: сравнение ссылочного реквизита и строки

Типичная ошибка при попытке прописать условие вручную выглядит следующим образом:


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

Выясним причину, по которой данная конструкция не срабатывает и документ всегда получает системный порядковый номер по ветке Иначе. Переменная Получатель в коде обработки заполняется путем поиска элемента в справочнике:


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

В результате успешного поиска переменная Получатель содержит ссылку на объект справочника (тип данных Справочник), а в условии выполняется прямое сравнение со строковым литералом "Магазин". В платформе 1С:Предприятие 7.7 сравнение ссылки со строкой всегда возвращает Ложь, так как типы операндов не совпадают.

Варианты реализации корректного условия

Рассмотрим несколько способов исправления этой ошибки в зависимости от архитектурных требований к обработке.

Вариант 1. Сравнение исходной строки из файла

Если известно точное текстовое наименование получателя в структуре файла импорта, простейшим решением будет проверка значения напрямую из списка реквизитов строки файла с очисткой от пробелов через СокрЛП():


Если СокрЛП(СпРекв.ПолучитьЗначение(6)) = "Магазин" Тогда
    ДокВН.НомерДок = НомерДок;
Иначе
    ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;

Этот вариант не зависит от того, был ли найден элемент в справочнике или нет, и проверяет только входящие строковые данные.

Вариант 2. Проверка реквизитов найденного элемента справочника

Если мы хотим проверять фактические свойства уже найденного в базе объекта, сравнивать необходимо строковое наименование элемента Получатель.Наименование, предварительно убедившись, что ссылка выбрана:


Если ПустоеЗначение(Получатель) = 0 Тогда
    Если СокрЛП(Получатель.Наименование) = "Магазин" Тогда
        ДокВН.НомерДок = НомерДок;
    Иначе
        ДокВН.УстановитьНовыйНомер("Цск");
    КонецЕсли;
Иначе
    ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;

Вариант 3. Использование реквизита на форме обработки (рекомендуемый)

Жесткое прописывание названий объектов («хардкод») в программном коде считается плохой практикой: если пользователь базы изменит наименование склада или контрагента (например, переименует в «Магазин №1»), загрузка перестанет работать. Правильнее вынести выбор контролируемого места хранения на диалоговую форму обработки (тип данных реквизита диалога — Справочник.МестаХранения) или использовать соответствующую константу:


Если (ПустоеЗначение(Получатель) = 0) И (Получатель = ВыбПолучательДляСвоегоНомера) Тогда
    ДокВН.НомерДок = НомерДок;
Иначе
    ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;

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

При модификации фрагмента инициализации документа критически важно соблюдать правильную последовательность установки реквизитов:

  1. Установка даты до генерации номера: метод УстановитьНовыйНомер() платформы 1С 7.7 рассчитывает очередной номер строго с учетом заданной в метаданных периодичности (год, месяц, день или без периодичности) и текущего значения даты документа ДатаДок. Если вызвать УстановитьНовыйНомер() до заполнения поля даты, платформа определит номер для текущей рабочей даты системы, а не для даты из загружаемого документа. Сначала всегда заполняется ДатаДок, и лишь затем вызывается нумератор.
  2. Формат номера из файла: если тип номера текстовый и в базе-приемнике приняты лидирующие нули (например, 8 знаков вида «00000123»), номер из файла должен строго соответствовать этой разрядности. Запись номера без лидирующих нулей (например, «123») может нарушить строковый лексикографический порядок автонумератора 7.7, из-за чего последующие штатные документы начнут получать некорректные номера.
  3. Контроль уникальности: если для документа включен контроль уникальности номеров, попытка записать документ с номером из файла, который уже существует в том же расчетном периоде, вызовет системную ошибку.

Итоговый блок кода инициализации документа

С учетом всех правил корректный фрагмент создания и нумерации шапки документа в процедуре Загрузить() будет выглядеть следующим образом:


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

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