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