При настройке обмена данными между конфигурациями (например, при переносе между базами «Управление производственным предприятием», «Зарплата и управление персоналом» или самописными решениями) с помощью конфигурации «Конвертация данных 2.1» разработчики нередко сталкиваются со сбоем на этапе загрузки в приемник:
Ошибка при вызове метода контекста (Записать): Ошибка записи! Не установлен отбор по регистратору
Выгрузка из базы-источника при этом проходит штатно и без предупреждений, однако процесс чтения и сохранения данных в базе-приемнике аварийно прерывается. Разберем по шагам природу этой ошибки, выясним технические ограничения платформы 1С и изучим проверенные варианты корректной настройки правил обмена.
Чтобы понять, почему возникает ошибка, проанализируем внутреннее устройство регистров сведений в платформе «1С:Предприятие». Регистры сведений могут работать в двух режимах записи:
РегистрСведенийНаборЗаписей с обязательной установкой отбора по ссылке на документ в поле Отбор.Регистратор.На уровне платформы действует жесткое системное ограничение: если у регистра сведений включен режим ПодчинениеРегистратору, метод набора записей Записать() вызовет исключение, если отбор по регистратору не включен (Использование = Ложь) или значение ссылки регистратора не заполнено (равно Неопределено или пустой ссылке). Записать такой набор записей «вслепую» или целиком по всему регистру технически невозможно.
В процессе обмена по правилам XML ошибка обычно возникает в следующих ситуациях:
Регистратор либо не выгружен, либо не сопоставлен с правилом конвертации документов.Самый надежный и правильный с точки зрения архитектуры 1С способ — отказаться от выгрузки подчиненного регистра как самостоятельной сущности через отдельное ПВД. Движения должны переноситься вместе с документом, который их породил.
Выполним следующие шаги в конфигурации «Конвертация данных»:
При таком подходе платформа формирует набор записей в тесной связке с объектом документа. При загрузке сначала создается и записывается документ, после чего его готовая ссылка автоматически подставляется в отбор набора записей регистра, исключая ошибку отсутствия отбора.
Если специфика обмена требует выгружать регистр сведений через отдельное ПКО, необходимо строго контролировать очередность загрузки данных. Документ-регистратор обязан загружаться раньше, чем подчиненный ему регистр.
Посмотрим на настройки порядка в «Конвертации данных»:
100, а зависимому регистру — 2000.Регистратор в таблице «Свойства» и убедимся, что для него указано соответствующее правило конвертации (ПКО документа).Если ссылка на регистратор присутствует в строках набора записей, но сам блок фильтра в XML оказался незаполненным, установим отбор принудительно перед записью набора в приемнике.
Для этого в ПКО проблемного регистра сведений откроем вкладку «Обработчики событий» и в событии «ПередЗаписьюПолученныхДанных» добавим программный код:
Если Не ЗначениеЗаполнено(Объект.Отбор.Регистратор.Значение) Тогда
// Если в наборе есть записи, возьмем регистратор из первой строки
Если Объект.Количество() > 0 Тогда
Если ЗначениеЗаполнено(Объект[0].Регистратор) Тогда
Объект.Отбор.Регистратор.Установить(Объект[0].Регистратор);
Иначе
// Записи без регистратора записывать нельзя
Отказ = Истина;
КонецЕсли;
Иначе
// Попытка записать пустой набор без отбора приведет к ошибке платформы
Отказ = Истина;
КонецЕсли;
КонецЕсли;
Такой обработчик перехватывает попытку записи некорректного набора: если регистратор удается извлечь из самих строк, отбор выставляется программно, а если набор пуст или регистратор поврежден — операция безопасно отменяется через Отказ = Истина, не прерывая весь обмен целиком.
В некоторых случаях (особенно при переносе сложных учетных документов) переносить движения подчиненных регистров вовсе не требуется. Достаточно перенести сам документ и провести его в базе-приемнике, чтобы движения сформировались по алгоритмам целевой конфигурации.
Реализуем автоматическое проведение загруженных документов:
Параметры.Вставить("СписокДокументовДляПроведения", Новый Массив);
Если Не Отказ И Объект.Проведен Тогда
Параметры.СписокДокументовДляПроведения.Добавить(Ссылка);
КонецЕсли;
Для Каждого СсылкаДок Из Параметры.СписокДокументовДляПроведения Цикл
Попытка
ДокОбъект = СсылкаДок.ПолучитьОбъект();
Если ДокОбъект <> Неопределено Тогда
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("ОбменДанными.ОшибкаПроведения",
УровеньЖурналаРегистрации.Ошибка, , СсылкаДок, ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Если выгрузка подчиненного регистра настраивается произвольным алгоритмом в обработчике ПВД «ПередОбработкойПравила», нельзя выгружать отдельные строки через выборку запроса напрямую в ПКО. Выгружать необходимо именно объект набора записей с предварительно установленным фильтром:
ВыборкаРегистраторов = Запрос.Выполнить().Выбрать();
Пока ВыборкаРегистраторов.Следующий() Цикл
// Создаем набор с обязательным отбором по конкретному регистратору
Набор = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(ВыборкаРегистраторов.Регистратор);
Набор.Прочитать();
// Выгружаем прочитанный набор с корректным фильтром
ВыгрузитьПоПравилу(Набор, , , , "ИмяПКОПодчиненногоРегистра");
КонецЦикла;
При таком подходе обработка ОбменДаннымиXML сформирует валидный XML-узел <Filter>, содержащий информацию об отборе, и при чтении данных в базе-приемнике исключение вызвано не будет.