Как исправить ошибку «Не установлен отбор по регистратору» при обмене данными в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При настройке обмена данными между конфигурациями (например, при переносе между базами «Управление производственным предприятием», «Зарплата и управление персоналом» или самописными решениями) с помощью конфигурации «Конвертация данных 2.1» разработчики нередко сталкиваются со сбоем на этапе загрузки в приемник:

Ошибка при вызове метода контекста (Записать): Ошибка записи! Не установлен отбор по регистратору

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

Причины возникновения ошибки

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

  1. Независимый — записи могут добавляться, изменяться и удаляться напрямую, без привязки к документам. Отбор по регистратору отсутствует.
  2. Подчинение регистратору — каждая запись регистра жестко связана с конкретным документом-регистратором. Изменение таких записей возможно только через объект РегистрСведенийНаборЗаписей с обязательной установкой отбора по ссылке на документ в поле Отбор.Регистратор.

На уровне платформы действует жесткое системное ограничение: если у регистра сведений включен режим ПодчинениеРегистратору, метод набора записей Записать() вызовет исключение, если отбор по регистратору не включен (Использование = Ложь) или значение ссылки регистратора не заполнено (равно Неопределено или пустой ссылке). Записать такой набор записей «вслепую» или целиком по всему регистру технически невозможно.

В процессе обмена по правилам XML ошибка обычно возникает в следующих ситуациях:

  1. Нарушен порядок загрузки объектов. Правило выгрузки регистра (ПКО) выполняется раньше, чем правило для документа-регистратора. В момент чтения файла приемник пытается записать набор движений, но соответствующий документ в базе еще не создан, ссылка на него пуста, и отбор сформировать не удается.
  2. Регистр выгружается отдельно от документа как самостоятельный объект. Создано отдельное Правило выгрузки данных (ПВД) для подчиненного регистра сведений, при этом стандартный реквизит Регистратор либо не выгружен, либо не сопоставлен с правилом конвертации документов.
  3. Несовпадение метаданных в базах. В источнике регистр независимый, а в приемнике — подчиненный регистратору (или наоборот). Выгрузка набора формируется без реквизита регистратора, а приемник требует его наличия.
  4. Повреждение ссылочной целостности в источнике. В базе-источнике в регистре присутствуют некорректные («битые») записи без валидного документа-регистратора, которые выгружаются в файл обмена с пустым узлом фильтра.

Способ 1. Перенос движений в составе документа (штатный подход в КД 2)

Самый надежный и правильный с точки зрения архитектуры 1С способ — отказаться от выгрузки подчиненного регистра как самостоятельной сущности через отдельное ПВД. Движения должны переноситься вместе с документом, который их породил.

Выполним следующие шаги в конфигурации «Конвертация данных»:

  1. Перейдем в список «Правила выгрузки данных» (ПВД) и отключим или удалим отдельное правило для подчиненного регистра сведений.
  2. Откроем «Правила конвертации объектов» (ПКО) для документа, являющегося регистратором для данного регистра.
  3. Перейдем на вкладку «Движения».
  4. Найдем в списке нужный подчиненный регистр сведений и установим напротив него флаг выгрузки.
  5. Сохраним правила и обновим файл выгрузки.

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

Способ 2. Корректировка порядка выполнения правил

Если специфика обмена требует выгружать регистр сведений через отдельное ПКО, необходимо строго контролировать очередность загрузки данных. Документ-регистратор обязан загружаться раньше, чем подчиненный ему регистр.

Посмотрим на настройки порядка в «Конвертации данных»:

  1. Откроем список «Правила конвертации объектов».
  2. Обратим внимание на колонку «Порядок выполнения». Чем меньше числовое значение порядка, тем раньше объект будет записан в файл выгрузки и прочитан в приемнике.
  3. Установим для документов-регистраторов приоритет выше (число меньше), чем для подчиненных регистров сведений. Например, документам зададим порядок 100, а зависимому регистру — 2000.
  4. Проверим в ПКО регистра сведений наличие реквизита Регистратор в таблице «Свойства» и убедимся, что для него указано соответствующее правило конвертации (ПКО документа).

Способ 3. Программная установка отбора при загрузке данных

Если ссылка на регистратор присутствует в строках набора записей, но сам блок фильтра в XML оказался незаполненным, установим отбор принудительно перед записью набора в приемнике.

Для этого в ПКО проблемного регистра сведений откроем вкладку «Обработчики событий» и в событии «ПередЗаписьюПолученныхДанных» добавим программный код:


Если Не ЗначениеЗаполнено(Объект.Отбор.Регистратор.Значение) Тогда
    
    // Если в наборе есть записи, возьмем регистратор из первой строки
    Если Объект.Количество() > 0 Тогда
        Если ЗначениеЗаполнено(Объект[0].Регистратор) Тогда
            Объект.Отбор.Регистратор.Установить(Объект[0].Регистратор);
        Иначе
            // Записи без регистратора записывать нельзя
            Отказ = Истина;
        КонецЕсли;
    Иначе
        // Попытка записать пустой набор без отбора приведет к ошибке платформы
        Отказ = Истина;
    КонецЕсли;
    
КонецЕсли;

Такой обработчик перехватывает попытку записи некорректного набора: если регистратор удается извлечь из самих строк, отбор выставляется программно, а если набор пуст или регистратор поврежден — операция безопасно отменяется через Отказ = Истина, не прерывая весь обмен целиком.

Способ 4. Программное проведение документов в базе-приемнике

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

Реализуем автоматическое проведение загруженных документов:

  1. В обработчике правил обмена «ПослеЗагрузкиПараметров» инициализируем список документов для проведения: Параметры.Вставить("СписокДокументовДляПроведения", Новый Массив);
  2. В ПКО каждого необходимого документа в обработчике «ПослеЗагрузкиОбъекта» добавим созданный документ в массив:
    
    Если Не Отказ И Объект.Проведен Тогда
        Параметры.СписокДокументовДляПроведения.Добавить(Ссылка);
    КонецЕсли;
    
  3. В обработчике конвертации «ПослеЗагрузкиДанных» выполним пакетное проведение накопленного массива:
    
    Для Каждого СсылкаДок Из Параметры.СписокДокументовДляПроведения Цикл
        Попытка
            ДокОбъект = СсылкаДок.ПолучитьОбъект();
            Если ДокОбъект <> Неопределено Тогда
                ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
            КонецЕсли;
        Исключение
            ЗаписьЖурналаРегистрации("ОбменДанными.ОшибкаПроведения",
                УровеньЖурналаРегистрации.Ошибка, , СсылкаДок, ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;
    

Способ 5. Корректная выгрузка набора записей в ПВД кодом

Если выгрузка подчиненного регистра настраивается произвольным алгоритмом в обработчике ПВД «ПередОбработкойПравила», нельзя выгружать отдельные строки через выборку запроса напрямую в ПКО. Выгружать необходимо именно объект набора записей с предварительно установленным фильтром:


ВыборкаРегистраторов = Запрос.Выполнить().Выбрать();

Пока ВыборкаРегистраторов.Следующий() Цикл
    
    // Создаем набор с обязательным отбором по конкретному регистратору
    Набор = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();
    Набор.Отбор.Регистратор.Установить(ВыборкаРегистраторов.Регистратор);
    Набор.Прочитать();
    
    // Выгружаем прочитанный набор с корректным фильтром
    ВыгрузитьПоПравилу(Набор, , , , "ИмяПКОПодчиненногоРегистра");
    
КонецЦикла;

При таком подходе обработка ОбменДаннымиXML сформирует валидный XML-узел <Filter>, содержащий информацию об отборе, и при чтении данных в базе-приемнике исключение вызвано не будет.

← На главную