Как отфильтровать кадровые переводы и их табличные части по подразделению при выгрузке данных в 1С КД 2.1?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

При обмене данными между различными конфигурациями 1С часто возникает необходимость контролировать, какие именно объекты и их составные части должны быть выгружены. Например, нам требуется выгружать только те документы "КадровыйПеревод", которые относятся к определенным подразделениям, или даже фильтровать строки табличных частей таких документов. Давайте подробно разберем, как мы можем решить эту задачу с помощью механизмов "Конвертации Данных 2.1" (КД 2.1).

Начальная проблема: фильтрация основного объекта документа "КадровыйПеревод"

В начале нашей задачи нам потребовалось отфильтровать документы "КадровыйПеревод" таким образом, чтобы выгружались только те, основное подразделение которых принадлежит к группе "Производственные подразделения". Первоначальная попытка использовать переменную Источник в обработчике события ПередВыгрузкойОбъекта привела к ошибке компиляции, так как переменная Источник в данном контексте не определена. Правильно для доступа к текущему объекту используется переменная Объект.

Решение для фильтрации основного объекта:

Мы используем обработчик события ПередВыгрузкойОбъекта в Правиле Конвертации Объектов (ПКО) для документа "КадровыйПеревод" или в Правиле Выгрузки Данных (ПВД). В этом обработчике у нас есть доступ к выгружаемому объекту через переменную Объект. Чтобы отказаться от выгрузки, мы устанавливаем служебную переменную Отказ в Истина.

Давайте посмотрим на пример кода:


// Обработчик события: ПередВыгрузкойОбъекта
// ПВД: КадровыйПеревод
// Объект: КадровыйПеревод

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

// Проверяем, удалось ли найти группу
Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
    // Если группа не найдена, возможно, стоит выгружать все или не выгружать ничего,
    // в зависимости от логики. Для примера, если группы нет, то не фильтруем.
    // Или можно установить Отказ = Истина; для всех, если отсутствие группы - это ошибка.
    // Сообщить("Внимание! Группа 'Производственные подразделения' не найдена.");
    Возврат; 
КонецЕсли;

// Проверяем, принадлежит ли подразделение документа к указанной группе
// Объект.Подразделение - это реквизит документа "КадровыйПеревод", 
// который хранит ссылку на подразделение.
Если Не Объект.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
    // Если подразделение документа НЕ принадлежит производственным подразделениям,
    // устанавливаем Отказ = Истина, чтобы этот документ не был выгружен.
    Отказ = Истина;
КонецЕсли;

В данном коде мы сначала находим ссылку на группу справочника "ПодразделенияОрганизаций" по её наименованию. Затем, используя метод ПринадлежитЭлементу(), мы проверяем, входит ли подразделение текущего документа в эту группу. Если не входит, то мы прерываем выгрузку данного объекта. Обратите внимание, что мы используем Объект.Подразделение для доступа к реквизиту документа, что является критически важным отличием от ошибочной переменной Источник.

Расширенная задача: фильтрация строк табличной части "Сотрудники"

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

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

Решение 1: Фильтрация табличной части с использованием КоллекцииОбъектов

Этот подход является наиболее распространенным и гибким для фильтрации строк табличных частей. Мы будем работать с Правилом Конвертации Объектов (ПКО), которое отвечает за выгрузку именно этой табличной части.

Шаги реализации:

  1. Определяем ПКО для табличной части: В конфигурации КД 2.1 найдите или создайте ПКО для табличной части "Сотрудники" документа "КадровыйПеревод списком". Обычно оно имеет наименование, связанное с документом и табличной частью, например, "КадровыйПереводСписком_Сотрудники".
  2. Конфигурируем свойство табличной части: В ПКО родительского документа ("КадровыйПеревод списком") для свойства, которое соответствует табличной части "Сотрудники", установите способ выгрузки "Получать из входящих данных". Это ключевой момент, который позволяет нам программно передавать подготовленную коллекцию данных.
  3. Пишем код в обработчике `ПередВыгрузкой` ПКО табличной части: Именно здесь мы будем создавать новую коллекцию данных, содержащую только нужные нам строки.

Давайте разберем код для обработчика ПередВыгрузкой ПКО табличной части:


// Обработчик события: ПередВыгрузкой
// ПКО: КадровыйПереводСписком_Сотрудники (или аналогичное для табличной части Сотрудники)

// В этом обработчике переменная Источник является коллекцией строк табличной части.
// Нам нужно создать новую коллекцию, отфильтровать строки и передать ее дальше.

// 1. Получаем ссылку на группу "Производственные подразделения"
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");

Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
    // Если группа не найдена, возможно, логика должна быть другой.
    // Например, можно вывести предупреждение и выгрузить пустую табличную часть
    // или вообще не фильтровать.
    // В данном случае, если группы нет, то считаем, что никаких производственных подразделений нет.
    // Создадим пустую коллекцию и выйдем.
    КоллекцияОбъектов = Новый ТаблицаЗначений();
    Возврат; 
КонецЕсли;

// 2. Создаем новую временную коллекцию (например, ТаблицуЗначений) для отфильтрованных данных
// Важно, чтобы структура этой таблицы значений соответствовала структуре табличной части
// или ПКО, к которому она применяется.
// Если ПКО табличной части ожидает объект определенного типа, 
// то можем создать КоллекциюОбъектов, наполненную нужными элементами.
// Для простоты, здесь используем ТаблицуЗначений и добавляем колонки по основным реквизитам строк ТЧ.
// Например, если в табличной части есть колонки Сотрудник, Подразделение, Должность, ДатаНачала...
ОтфильтрованныеСтроки = Новый ТаблицаЗначений();
ОтфильтрованныеСтроки.Колонки.Добавить("Сотрудник");
ОтфильтрованныеСтроки.Колонки.Добавить("Подразделение");
// Добавьте все остальные колонки, которые выгружаются из табличной части

// 3. Перебираем исходную коллекцию строк табличной части (переменная Источник)
Для Каждого СтрокаТЧ Из Источник Цикл
    // Проверяем условие фильтрации для текущей строки табличной части
    Если СтрокаТЧ.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
        // Если строка соответствует условию, добавляем ее в новую коллекцию
        НоваяСтрока = ОтфильтрованныеСтроки.Добавить();
        НоваяСтрока.Сотрудник    = СтрокаТЧ.Сотрудник;
        НоваяСтрока.Подразделение = СтрокаТЧ.Подразделение;
        // Заполните все остальные реквизиты, которые вам нужно выгрузить
        // НоваяСтрока.Должность = СтрокаТЧ.Должность;
        // ...
    КонецЕсли;
КонецЦикла;

// 4. Присваиваем отфильтрованную коллекцию служебной переменной КоллекцияОбъектов
// Эта переменная будет передана дальше для выгрузки.
КоллекцияОбъектов = ОтфильтрованныеСтроки;

Важные моменты:

Решение 2: Фильтрация с помощью произвольного алгоритма в Правиле Выгрузки Данных (ПВД)

Этот подход дает нам максимальный контроль над исходной выборкой данных для выгрузки. Вместо того чтобы полагаться на стандартную выборку данных по ПВД, мы можем написать собственный запрос, который сразу выберет только те объекты или данные, которые нам нужны. Этот метод подходит, если вы хотите контролировать, какие именно документы (или их части) будут вообще рассматриваться для выгрузки, и может быть применен как к основному объекту, так и, с некоторыми нюансами, к получению данных для табличных частей.

Шаги реализации:

  1. Настраиваем ПВД: В Правиле Выгрузки Данных (ПВД) для документа "КадровыйПеревод" (или "КадровыйПеревод списком") в поле "Способ выгрузки" выбираем "Произвольный алгоритм".
  2. Пишем код в обработчике `ПолучитьОбъектыДляВыгрузки`: В этом обработчике мы будем формировать выборку данных.

Рассмотрим пример кода, который формирует выборку для документа "КадровыйПеревод списком", учитывая подразделения из табличной части:


// Обработчик события: ПолучитьОбъектыДляВыгрузки
// ПВД: КадровыйПереводСписком

// В этом обработчике мы должны сформировать список ссылок на объекты,
// которые должны быть выгружены.

// 1. Получаем ссылку на группу "Производственные подразделения"
ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");

Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
    // Если группа не найдена, возможно, логика должна быть другой.
    // Например, можно вернуть пустой массив, чтобы ничего не выгружалось.
    Возврат Новый Массив(); 
КонецЕсли;

// 2. Формируем запрос для получения ссылок на документы
// Запрос должен учитывать, что хотя бы одна строка табличной части
// документа относится к производственным подразделениям.
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    КадровыйПереводСпискомСотрудники.Ссылка
    |ИЗ
    |    Документ.КадровыйПереводСписком.Сотрудники КАК КадровыйПереводСпискомСотрудники
    |ГДЕ
    |    КадровыйПереводСпискомСотрудники.Подразделение В ИЕРАРХИИ(&ГруппаПроизводственныеПодразделения)"; // В ИЕРАРХИИ позволяет проверять принадлежность к группе и ее подгруппам

Запрос.УстановитьПараметр("ГруппаПроизводственныеПодразделения", ГруппаПроизводственныеПодразделения);

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

СписокОбъектовДляВыгрузки = Новый Массив();
Пока Выборка.Следующий() Цикл
    СписокОбъектовДляВыгрузки.Добавить(Выборка.Ссылка);
КонецЦикла;

// Возвращаем сформированный список ссылок
Возврат СписокОбъектовДляВыгрузки;

В этом примере мы получаем ссылки на те документы "КадровыйПеревод списком", у которых есть хотя бы одна строка в табличной части "Сотрудники", где подразделение входит в группу "Производственные подразделения". Дальнейшая фильтрация *внутри* табличной части (если нам нужно выгружать документ, но только часть его строк) все равно потребует использования подхода с КоллекциейОбъектов в ПКО табличной части, но уже для каждого из отобранных документов.

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

Преимущества произвольного алгоритма:

Альтернативный подход: Правила регистрации объектов (ПРО)

Обсуждая контроль за выгрузкой данных, мы обязательно сталкиваемся с концепцией Правил Регистрации Объектов (ПРО). Это очень мощный инструмент для управления миграцией данных, который работает на этапе регистрации изменений объекта, а не только при его выгрузке. ПРО позволяют нам задавать условия фильтрации данных на узлах планов обмена.

Что такое ПРО и как они работают?

Правила регистрации объектов (ПРО) – это алгоритмы, которые выполняются при записи объекта (например, документа или элемента справочника) и определяют, должен ли этот объект быть зарегистрирован для обмена с конкретным узлом плана обмена. Если объект не проходит условия ПРО, он не регистрируется и, следовательно, не будет выгружен.

Преимущества использования ПРО:

  1. Ранняя фильтрация: Решение о выгрузке принимается в момент записи объекта, что исключает попадание ненужных данных в очередь обмена.
  2. Доступность УзлаОбмена: В ПРО нам доступен объект УзелОбмена, что позволяет строить логику фильтрации в зависимости от того, с каким конкретным узлом происходит обмен. Это критически важно в сценариях, где разные узлы получают разные подмножества данных (например, каждое подразделение выгружается в свой узел).
  3. Централизованное управление: Мы можем управлять правилами регистрации для всех объектов в одном месте, что упрощает администрирование сложных схем обмена.
  4. Производительность: Фильтрация на этапе регистрации может быть более эффективной, чем на этапе выгрузки, так как она предотвращает обработку заведомо ненужных данных.

Как применить ПРО для нашей задачи:

Для нашей задачи фильтрации кадровых переводов по подразделениям, ПРОБ (Правила регистрации объектов по свойствам объекта) может быть использовано следующим образом:


// Пример кода для ПРОБ для документа "КадровыйПеревод"

// Предполагается, что это код в глобальном модуле или модуле менеджера объекта,
// который вызывается при записи объекта для определения его регистрации.
// Конкретная реализация зависит от конфигурации и механизма обмена,
// но общая логика будет такой.

// Параметры, передаваемые в функцию проверки ПРОБ:
// ОбъектДанных - ссылка на записываемый объект
// УзелОбмена - ссылка на узел плана обмена
// Отказ - булево, устанавливаем Истина, если объект не должен быть зарегистрирован

Функция ОпределитьРегистрациюКадровогоПеревода(ОбъектДанных, УзелОбмена, Отказ) Экспорт
    // 1. Получаем ссылку на группу "Производственные подразделения"
    ГруппаПроизводственныеПодразделения = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Производственные подразделения");

    Если ГруппаПроизводственныеПодразделения = Неопределено Тогда
        // Если группы нет, то для безопасности не регистрируем или регистрируем все
        // В зависимости от требования. Для примера, не регистрируем.
        Отказ = Истина;
        Возврат; 
    КонецЕсли;

    // 2. Проверяем, является ли ОбъектДанных документом "КадровыйПеревод"
    Если ОбъектДанных.Метаданные().Имя = "КадровыйПеревод" Или ОбъектДанных.Метаданные().Имя = "КадровыйПереводСписком" Тогда
        // Проверяем основной реквизит Подразделение
        Если ОбъектДанных.Метаданные().Реквизиты.Найти("Подразделение") <> Неопределено Тогда
            Если Не ОбъектДанных.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
                Отказ = Истина;
                Возврат;
            КонецЕсли;
        КонецЕсли;

        // 3. Проверяем табличные части, если это "КадровыйПереводСписком"
        Если ОбъектДанных.Метаданные().Имя = "КадровыйПереводСписком" Тогда
            Если ОбъектДанных.Метаданные().ТабличныеЧасти.Найти("Сотрудники") <> Неопределено Тогда
                ЕстьНужныеСтроки = Ложь;
                Для Каждого СтрокаТЧ Из ОбъектДанных.Сотрудники Цикл
                    Если СтрокаТЧ.Подразделение.ПринадлежитЭлементу(ГруппаПроизводственныеПодразделения) Тогда
                        ЕстьНужныеСтроки = Истина;
                        Прервать;
                    КонецЕсли;
                КонецЦикла;

                Если Не ЕстьНужныеСтроки Тогда
                    // Если ни одна строка табличной части не соответствует условию,
                    // то не регистрируем весь документ.
                    Отказ = Истина;
                    Возврат;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;

    // Если дошли сюда, значит объект удовлетворяет условиям для регистрации
    Отказ = Ложь;
КонецФункции

Важный нюанс: ПРО фильтруют *регистрацию всего объекта*. Если нам нужно выгрузить документ, но *отфильтровать его табличную часть* (т.е. часть строк выгрузить, часть нет), то ПРО не подходит для этой задачи напрямую. В таком случае ПРО может решить, регистрировать ли вообще документ, а для фильтрации строк табличной части все равно придется использовать подходы, описанные ранее (КоллекцияОбъектов или произвольный алгоритм в ПВД).

Однако, если задача стоит так: "выгружать только те документы КадровыйПереводСписком, в которых хотя бы один сотрудник переводится в Производственные подразделения, а если таких сотрудников нет, то документ не выгружать вообще", то ПРО является отличным инструментом для такой фильтрации.

Использование ПРО и обработчиков выгрузки не исключают, а дополняют друг друга. ПРО отвечают за то, *какие* объекты попадут в план обмена, а обработчики выгрузки – за то, *как* эти объекты будут представлены при выгрузке (например, с отфильтрованными табличными частями).

Итоги и рекомендации

Мы рассмотрели несколько эффективных способов фильтрации документов "КадровыйПеревод" и их табличных частей в 1С КД 2.1. Выбор конкретного метода зависит от вашей специфической задачи:

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

Ключевой метод для фильтрации именно строк табличной части, сохраняя при этом основной документ, это работа с КоллекциейОбъектов в обработчике ПередВыгрузкой ПКО табличной части. Всегда помните о контексте обработчиков: Объект для основного объекта, Источник для коллекции вложенных объектов (как в табличных частях), и КоллекцияОбъектов для передачи отфильтрованных данных.

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

← На главную