При обмене данными между различными конфигурациями 1С часто возникает необходимость контролировать, какие именно объекты и их составные части должны быть выгружены. Например, нам требуется выгружать только те документы "КадровыйПеревод", которые относятся к определенным подразделениям, или даже фильтровать строки табличных частей таких документов. Давайте подробно разберем, как мы можем решить эту задачу с помощью механизмов "Конвертации Данных 2.1" (КД 2.1).
В начале нашей задачи нам потребовалось отфильтровать документы "КадровыйПеревод" таким образом, чтобы выгружались только те, основное подразделение которых принадлежит к группе "Производственные подразделения". Первоначальная попытка использовать переменную Источник в обработчике события ПередВыгрузкойОбъекта привела к ошибке компиляции, так как переменная Источник в данном контексте не определена. Правильно для доступа к текущему объекту используется переменная Объект.
Решение для фильтрации основного объекта:
Мы используем обработчик события ПередВыгрузкойОбъекта в Правиле Конвертации Объектов (ПКО) для документа "КадровыйПеревод" или в Правиле Выгрузки Данных (ПВД). В этом обработчике у нас есть доступ к выгружаемому объекту через переменную Объект. Чтобы отказаться от выгрузки, мы устанавливаем служебную переменную Отказ в Истина.
Давайте посмотрим на пример кода:
// Обработчик события: ПередВыгрузкойОбъекта
// ПВД: КадровыйПеревод
// Объект: КадровыйПеревод
// Получаем ссылку на группу "Производственные подразделения"
// Важно убедиться, что такая группа существует и ее наименование точно совпадает.
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");
// Проверяем, удалось ли найти группу
Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
// Если группа не найдена, возможно, стоит выгружать все или не выгружать ничего,
// в зависимости от логики. Для примера, если группы нет, то не фильтруем.
// Или можно установить Отказ = Истина; для всех, если отсутствие группы - это ошибка.
// Сообщить("Внимание! Группа 'Производственные подразделения' не найдена.");
Возврат;
КонецЕсли;
// Проверяем, принадлежит ли подразделение документа к указанной группе
// Объект.Подразделение - это реквизит документа "КадровыйПеревод",
// который хранит ссылку на подразделение.
Если Не Объект.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
// Если подразделение документа НЕ принадлежит производственным подразделениям,
// устанавливаем Отказ = Истина, чтобы этот документ не был выгружен.
Отказ = Истина;
КонецЕсли;
В данном коде мы сначала находим ссылку на группу справочника "ПодразделенияОрганизаций" по её наименованию. Затем, используя метод ПринадлежитЭлементу(), мы проверяем, входит ли подразделение текущего документа в эту группу. Если не входит, то мы прерываем выгрузку данного объекта. Обратите внимание, что мы используем Объект.Подразделение для доступа к реквизиту документа, что является критически важным отличием от ошибочной переменной Источник.
После успешной фильтрации основных объектов, перед нами встала более сложная задача: что делать, если подразделение, по которому необходимо фильтровать, находится не в реквизите самого документа, а в его табличной части? Например, в документе "КадровыйПеревод списком" табличная часть "Сотрудники" содержит поле "Подразделение", и нам нужно выгружать только те строки этой табличной части, где сотрудники переводятся в "Производственные подразделения". При этом, в одном документе могут быть сотрудники как из "Производственных подразделений", так и из "Заводоуправления". Мы не хотим отменять выгрузку всего документа, но хотим отфильтровать отдельные строки табличной части.
Рассмотрим несколько подходов к решению этой проблемы.
Этот подход является наиболее распространенным и гибким для фильтрации строк табличных частей. Мы будем работать с Правилом Конвертации Объектов (ПКО), которое отвечает за выгрузку именно этой табличной части.
Шаги реализации:
Давайте разберем код для обработчика ПередВыгрузкой ПКО табличной части:
// Обработчик события: ПередВыгрузкой
// ПКО: КадровыйПереводСписком_Сотрудники (или аналогичное для табличной части Сотрудники)
// В этом обработчике переменная Источник является коллекцией строк табличной части.
// Нам нужно создать новую коллекцию, отфильтровать строки и передать ее дальше.
// 1. Получаем ссылку на группу "Производственные подразделения"
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");
Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
// Если группа не найдена, возможно, логика должна быть другой.
// Например, можно вывести предупреждение и выгрузить пустую табличную часть
// или вообще не фильтровать.
// В данном случае, если группы нет, то считаем, что никаких производственных подразделений нет.
// Создадим пустую коллекцию и выйдем.
КоллекцияОбъектов = Новый ТаблицаЗначений();
Возврат;
КонецЕсли;
// 2. Создаем новую временную коллекцию (например, ТаблицуЗначений) для отфильтрованных данных
// Важно, чтобы структура этой таблицы значений соответствовала структуре табличной части
// или ПКО, к которому она применяется.
// Если ПКО табличной части ожидает объект определенного типа,
// то можем создать КоллекциюОбъектов, наполненную нужными элементами.
// Для простоты, здесь используем ТаблицуЗначений и добавляем колонки по основным реквизитам строк ТЧ.
// Например, если в табличной части есть колонки Сотрудник, Подразделение, Должность, ДатаНачала...
ОтфильтрованныеСтроки = Новый ТаблицаЗначений();
ОтфильтрованныеСтроки.Колонки.Добавить("Сотрудник");
ОтфильтрованныеСтроки.Колонки.Добавить("Подразделение");
// Добавьте все остальные колонки, которые выгружаются из табличной части
// 3. Перебираем исходную коллекцию строк табличной части (переменная Источник)
Для Каждого СтрокаТЧ Из Источник Цикл
// Проверяем условие фильтрации для текущей строки табличной части
Если СтрокаТЧ.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
// Если строка соответствует условию, добавляем ее в новую коллекцию
НоваяСтрока = ОтфильтрованныеСтроки.Добавить();
НоваяСтрока.Сотрудник = СтрокаТЧ.Сотрудник;
НоваяСтрока.Подразделение = СтрокаТЧ.Подразделение;
// Заполните все остальные реквизиты, которые вам нужно выгрузить
// НоваяСтрока.Должность = СтрокаТЧ.Должность;
// ...
КонецЕсли;
КонецЦикла;
// 4. Присваиваем отфильтрованную коллекцию служебной переменной КоллекцияОбъектов
// Эта переменная будет передана дальше для выгрузки.
КоллекцияОбъектов = ОтфильтрованныеСтроки;
Важные моменты:
Источник в обработчике ПередВыгрузкой ПКО табличной части представляет собой коллекцию строк этой табличной части.ТаблицаЗначений или Массив объектов) и заполняем ее только теми строками, которые соответствуют нашему условию.КоллекцияОбъектов, которая затем используется КД для дальнейшей обработки и выгрузки.Этот подход дает нам максимальный контроль над исходной выборкой данных для выгрузки. Вместо того чтобы полагаться на стандартную выборку данных по ПВД, мы можем написать собственный запрос, который сразу выберет только те объекты или данные, которые нам нужны. Этот метод подходит, если вы хотите контролировать, какие именно документы (или их части) будут вообще рассматриваться для выгрузки, и может быть применен как к основному объекту, так и, с некоторыми нюансами, к получению данных для табличных частей.
Шаги реализации:
Рассмотрим пример кода, который формирует выборку для документа "КадровыйПеревод списком", учитывая подразделения из табличной части:
// Обработчик события: ПолучитьОбъектыДляВыгрузки
// ПВД: КадровыйПереводСписком
// В этом обработчике мы должны сформировать список ссылок на объекты,
// которые должны быть выгружены.
// 1. Получаем ссылку на группу "Производственные подразделения"
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");
Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
// Если группа не найдена, возможно, логика должна быть другой.
// Например, можно вернуть пустой массив, чтобы ничего не выгружалось.
Возврат Новый Массив();
КонецЕсли;
// 2. Формируем запрос для получения ссылок на документы
// Запрос должен учитывать, что хотя бы одна строка табличной части
// документа относится к производственным подразделениям.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| КадровыйПереводСпискомСотрудники.Ссылка
|ИЗ
| Документ.КадровыйПереводСписком.Сотрудники КАК КадровыйПереводСпискомСотрудники
|ГДЕ
| КадровыйПереводСпискомСотрудники.Подразделение В ИЕРАРХИИ(&ГруппаПроизводственныеПодразделения)"; // В ИЕРАРХИИ позволяет проверять принадлежность к группе и ее подгруппам
Запрос.УстановитьПараметр("ГруппаПроизводственныеПодразделения", ГруппаПроизводственныеПодразделения);
Выборка = Запрос.Выполнить().Выбрать();
СписокОбъектовДляВыгрузки = Новый Массив();
Пока Выборка.Следующий() Цикл
СписокОбъектовДляВыгрузки.Добавить(Выборка.Ссылка);
КонецЦикла;
// Возвращаем сформированный список ссылок
Возврат СписокОбъектовДляВыгрузки;
В этом примере мы получаем ссылки на те документы "КадровыйПеревод списком", у которых есть хотя бы одна строка в табличной части "Сотрудники", где подразделение входит в группу "Производственные подразделения". Дальнейшая фильтрация *внутри* табличной части (если нам нужно выгружать документ, но только часть его строк) все равно потребует использования подхода с КоллекциейОбъектов в ПКО табличной части, но уже для каждого из отобранных документов.
Если мы хотим сразу в запросе получить данные для табличной части, то запрос будет сложнее, и нам придется в обработчике ПередВыгрузкой ПКО табличной части формировать коллекцию из результатов запроса, передавая ее через параметры ПВД или используя специализированные параметры выгрузки.
Преимущества произвольного алгоритма:
Обсуждая контроль за выгрузкой данных, мы обязательно сталкиваемся с концепцией Правил Регистрации Объектов (ПРО). Это очень мощный инструмент для управления миграцией данных, который работает на этапе регистрации изменений объекта, а не только при его выгрузке. ПРО позволяют нам задавать условия фильтрации данных на узлах планов обмена.
Что такое ПРО и как они работают?
Правила регистрации объектов (ПРО) – это алгоритмы, которые выполняются при записи объекта (например, документа или элемента справочника) и определяют, должен ли этот объект быть зарегистрирован для обмена с конкретным узлом плана обмена. Если объект не проходит условия ПРО, он не регистрируется и, следовательно, не будет выгружен.
Преимущества использования ПРО:
УзелОбмена, что позволяет строить логику фильтрации в зависимости от того, с каким конкретным узлом происходит обмен. Это критически важно в сценариях, где разные узлы получают разные подмножества данных (например, каждое подразделение выгружается в свой узел).Как применить ПРО для нашей задачи:
Для нашей задачи фильтрации кадровых переводов по подразделениям, ПРОБ (Правила регистрации объектов по свойствам объекта) может быть использовано следующим образом:
// Пример кода для ПРОБ для документа "КадровыйПеревод"
// Предполагается, что это код в глобальном модуле или модуле менеджера объекта,
// который вызывается при записи объекта для определения его регистрации.
// Конкретная реализация зависит от конфигурации и механизма обмена,
// но общая логика будет такой.
// Параметры, передаваемые в функцию проверки ПРОБ:
// ОбъектДанных - ссылка на записываемый объект
// УзелОбмена - ссылка на узел плана обмена
// Отказ - булево, устанавливаем Истина, если объект не должен быть зарегистрирован
Функция ОпределитьРегистрациюКадровогоПеревода(ОбъектДанных, УзелОбмена, Отказ) Экспорт
// 1. Получаем ссылку на группу "Производственные подразделения"
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");
Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
// Если группы нет, то для безопасности не регистрируем или регистрируем все
// В зависимости от требования. Для примера, не регистрируем.
Отказ = Истина;
Возврат;
КонецЕсли;
// 2. Проверяем, является ли ОбъектДанных документом "КадровыйПеревод"
Если ОбъектДанных.Метаданные().Имя = "КадровыйПеревод" Или ОбъектДанных.Метаданные().Имя = "КадровыйПереводСписком" Тогда
// Проверяем основной реквизит Подразделение
Если ОбъектДанных.Метаданные().Реквизиты.Найти("Подразделение") <> Неопределено Тогда
Если Не ОбъектДанных.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЕсли;
// 3. Проверяем табличные части, если это "КадровыйПереводСписком"
Если ОбъектДанных.Метаданные().Имя = "КадровыйПереводСписком" Тогда
Если ОбъектДанных.Метаданные().ТабличныеЧасти.Найти("Сотрудники") <> Неопределено Тогда
ЕстьНужныеСтроки = Ложь;
Для Каждого СтрокаТЧ Из ОбъектДанных.Сотрудники Цикл
Если СтрокаТЧ.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
ЕстьНужныеСтроки = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ЕстьНужныеСтроки Тогда
// Если ни одна строка табличной части не соответствует условию,
// то не регистрируем весь документ.
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// Если дошли сюда, значит объект удовлетворяет условиям для регистрации
Отказ = Ложь;
КонецФункции
Важный нюанс: ПРО фильтруют *регистрацию всего объекта*. Если нам нужно выгрузить документ, но *отфильтровать его табличную часть* (т.е. часть строк выгрузить, часть нет), то ПРО не подходит для этой задачи напрямую. В таком случае ПРО может решить, регистрировать ли вообще документ, а для фильтрации строк табличной части все равно придется использовать подходы, описанные ранее (КоллекцияОбъектов или произвольный алгоритм в ПВД).
Однако, если задача стоит так: "выгружать только те документы КадровыйПереводСписком, в которых хотя бы один сотрудник переводится в Производственные подразделения, а если таких сотрудников нет, то документ не выгружать вообще", то ПРО является отличным инструментом для такой фильтрации.
Использование ПРО и обработчиков выгрузки не исключают, а дополняют друг друга. ПРО отвечают за то, *какие* объекты попадут в план обмена, а обработчики выгрузки – за то, *как* эти объекты будут представлены при выгрузке (например, с отфильтрованными табличными частями).
Мы рассмотрели несколько эффективных способов фильтрации документов "КадровыйПеревод" и их табличных частей в 1С КД 2.1. Выбор конкретного метода зависит от вашей специфической задачи:
ПередВыгрузкойОбъекта в ПКО или ПВД, обращаясь к переменной Объект и устанавливая Отказ = Истина.КоллекциюОбъектов в обработчике ПередВыгрузкой ПКО, которое отвечает за выгрузку этой табличной части. Это наиболее гибкий и рекомендуемый способ.ПолучитьОбъектыДляВыгрузки.Ключевой метод для фильтрации именно строк табличной части, сохраняя при этом основной документ, это работа с КоллекциейОбъектов в обработчике ПередВыгрузкой ПКО табличной части. Всегда помните о контексте обработчиков: Объект для основного объекта, Источник для коллекции вложенных объектов (как в табличных частях), и КоллекцияОбъектов для передачи отфильтрованных данных.
Применяя эти подходы, мы можем достигнуть высокой точности в управлении данными, передаваемыми между информационными базами 1С, обеспечивая выгрузку только необходимой и релевантной информации.