Как отфильтровать строки табличной части документа при выгрузке в 1С:Конвертация данных 2.1

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

При работе с инструментом «1С:Конвертация данных 2.1» (КД 2.1) часто возникают задачи частичной выгрузки данных. Типичный сценарий: необходимо перегрузить документ, но не целиком, а только те строки его табличной части, которые соответствуют определенному критерию (например, номенклатура с определенным артикулом). В этой статье мы подробно разберем, как реализовать такую фильтрацию, не прибегая к модификации данных в базе-источнике.

Анализ проблемы и выбор стратегии

Рассмотрим ситуацию: у нас есть документ, содержащий список товаров. Нам нужно выгрузить только те позиции, артикул которых начинается на определенную цифру. Первое, что приходит в голову начинающему разработчику — это программно удалить «лишние» строки из табличной части объекта Источник прямо перед выгрузкой. Однако это плохая практика по нескольким причинам:

  1. Мы можем случайно зафиксировать изменения в базе данных источника, если код сработает некорректно.
  2. Удаление строк может нарушить логику итогов документа в памяти.
  3. Это избыточная операция, так как КД предоставляет штатные механизмы пропуска объектов.

Разберем правильные способы решения этой задачи, начиная от самого простого и заканчивая наиболее производительным.

Способ 1. Использование события «Перед выгрузкой» в ПКГС

Самый гибкий и простой в реализации способ — использование обработчика события в Правиле конвертации группы свойств (ПКГС). Группа свойств в контексте документа — это и есть его табличная часть.

Для реализации фильтрации выполним следующие шаги:

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

Важный нюанс: Нам нужно событие «Перед выгрузкой» не для всего свойства (ТЧ), а для каждого объекта коллекции (строки ТЧ). В КД 2.1 этот обработчик вызывается для каждой строки перед тем, как она будет преобразована в XML-узел.

Рассмотрим пример кода, который нужно разместить в этом обработчике:


// Проверяем, заполнена ли номенклатура в текущей строке
Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура) Тогда
    
    // Получаем артикул. Важно помнить, что Артикул — это реквизит справочника Номенклатура,
    // а не самой строки табличной части (чаще всего).
    АртикулНоменклатуры = ОбъектКоллекции.Номенклатура.Артикул;
    
    // Проверяем условие: например, артикул должен начинаться на "1"
    Если Лев(СокрЛП(АртикулНоменклатуры), 1) <> "1" Тогда
        // Если условие не выполняется, устанавливаем Отказ = Истина.
        // Это отменит выгрузку ТЕКУЩЕЙ строки, но не всего документа.
        Отказ = Истина;
    КонецЕсли;
    
Иначе
    // Если номенклатура не заполнена, возможно, стоит пропустить такую строку
    Отказ = Истина;
КонецЕсли;

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

Способ 2. Подмена коллекции в ПКО (Событие «Перед выгрузкой» объекта)

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

Для этого в ПКО документа в обработчике «Перед выгрузкой» (самого объекта) мы пишем следующий код:


// Создаем временную таблицу, структуру которой копируем из ТЧ источника
ТЗ_Отфильтрованная = Источник.Товары.ВыгрузитьКолонки();

// Наполняем таблицу только нужными данными
Для Каждого СтрокаТЧ Из Источник.Товары Цикл
    Если Лев(СтрокаТЧ.Номенклатура.Артикул, 1) = "1" Тогда
        ЗаполнитьЗначенияСвойств(ТЗ_Отфильтрованная.Добавить(), СтрокаТЧ);
    КонецЕсли;
КонецЦикла;

// Передаем нашу таблицу в параметр КоллекцияОбъектов.
// Теперь для ПКГС "Товары" источником будет не Источник.Товары, а эта ТЗ.
КоллекцияОбъектов = ТЗ_Отфильтрованная;

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

Способ 3. Фильтрация на уровне запроса в ПВД

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

В ПВД мы можем написать запрос, который выберет только те данные, которые нам нужны. Проанализируем пример логики в ПВД:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   РеализацияТоваровУслуг.Ссылка КАК Ссылка
    |ИЗ
    |   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
    |ГДЕ
    |   РеализацияТоваровУслуг.Товары.Номенклатура.Артикул ПОДОБНО ""1%""";

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

Пока Выборка.Следующий() Цикл
    // Выгружаем объект по правилу, но фильтрация строк ТЧ все равно 
    // должна быть настроена в ПКО (способами 1 или 2), 
    // так как ВыгрузитьПоПравилу выгружает объект целиком.
    ВыгрузитьПоПравилу(Выборка.Ссылка);
КонецЦикла;

Важно понимать: ПВД лишь определяет, какие документы попадут в выгрузку. Чтобы внутри этих документов отфильтровались строки, вам все равно придется использовать Способ 1 или Способ 2 в правилах конвертации объектов.

Важные технические нюансы

Проанализируем несколько критических моментов, которые часто упускают из виду:

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

Итоги

Мы рассмотрели три основных подхода к фильтрации данных внутри документа при использовании «1С:Конвертация данных 2.1». Наиболее рекомендуемым для большинства задач является Способ 1 (использование параметра Отказ в ПКГС), так как он требует минимум кода и наиболее органично вписывается в архитектуру правил обмена. Помните о необходимости проверки заполненности данных и не забывайте про пересчет итоговых сумм в базе-приемнике, чтобы избежать логических ошибок в учете.

← На главную