Почему метод КритерииОтбора.СвязанныеДокументы.Найти() находит не все документы и как это исправить?

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

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

Выясним причину: почему стандартный поиск «видит» не всё

Для начала разберем внутреннюю механику работы критериев отбора. Когда мы вызываем метод Найти(), платформа обращается к заранее построенному индексу. Этот индекс формируется строго на основании настроек, заданных в Конфигураторе в объекте КритерийОтбора.СвязанныеДокументы на вкладке Состав.

Рассмотрим основные причины «пропусков» документов:

  1. Отсутствие реквизита в составе критерия. Если в конфигурацию был добавлен новый документ или новый реквизит в существующий документ (например, через расширение), но он не был включен в состав критерия отбора СвязанныеДокументы, платформа его проигнорирует. Метод Найти() просто «не знает», что по этому полю нужно искать связь.
  2. Связи через табличные части. В таких конфигурациях, как УНФ, УТ 11 или ERP, связь между оплатой (Поступление на счет) и заказом часто хранится не в шапке документа, а в строках табличной части (например, РасшифровкаПлатежа). Если реквизит табличной части не отмечен в составе критерия, поиск по ссылке на документ-основание не даст результатов.
  3. Многоуровневая иерархия (косвенные связи). Стандартный метод Найти() выполняет «плоский» поиск — он находит только те документы, которые напрямую ссылаются на искомый объект. Однако в структуре подчиненности мы можем видеть цепочку: Заказ покупателя -> Счет на оплату -> Поступление на счет. В этом случае Поступление на счет связано напрямую со Счетом, а не с Заказом. Обычный поиск по Заказу не найдет оплату, если она не имеет прямой ссылки на него.

Способ 1: Прямой поиск в табличных частях (на примере УНФ)

Если нам известно, что нужный документ (например, Поступление на счет) связан с родительским объектом через специфическую таблицу, мы можем обойти ограничение критерия отбора, обратившись к данным напрямую. Проанализируем пример логики для конфигурации «Управление нашей фирмой».

В этом случае вместо использования только критерия отбора, мы можем выполнить запрос к документам оплаты, проверяя их табличную часть РасшифровкаПлатежа. Посмотрим на алгоритм действий:

1. Выбираем все потенциальные документы оплаты за период.
2. В цикле или (что более правильно) через запрос проверяем содержимое колонки Документ (или Заказ) в табличной части РасшифровкаПлатежа.
3. Если ссылка совпадает с нашим исходным документом, добавляем его в список найденных.

Такой подход гарантирует результат, даже если разработчик типового решения не включил реквизиты табличной части в индекс критерия отбора.

Способ 2: Реализация рекурсивного поиска

Для того чтобы построить дерево документов, аналогичное стандартному интерфейсному, нам необходимо реализовать рекурсивный обход. Рассмотрим пример кода, который позволяет найти не только «ближайшие» связанные документы, но и те, что связаны с ними далее по цепочке:


// Получаем первичный список связанных документов
СвязанныеДокументы = КритерииОтбора.СвязанныеДокументы.Найти(СтрокаЗапроса.Ссылка);

Для Каждого ТекДок из СвязанныеДокументы Цикл
    // Для каждого найденного документа ищем его собственные связи
    ВторичныеСвязи = КритерииОтбора.СвязанныеДокументы.Найти(ТекДок.Ссылка);
    
    Для Каждого ДокВторогоУровня из ВторичныеСвязи Цикл
        // Здесь мы получаем документы, связанные через посредника
        // Например: Заказ -> Счет -> Поступление (находим Поступление через Счет)
        Сообщить("Найден документ следующего уровня: " + ДокВторогоУровня);
    КонецЦикла;
КонецЦикла;

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

Способ 3: Использование механизмов БСП

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), рекомендуется отказаться от прямого использования КритерииОтбора.Найти() в пользу программного интерфейса подсистемы «Связанные документы».

Типовое «Дерево подчиненности» строится сложным запросом, который объединяет данные из:

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

Подведем итоги

Для решения проблемы «невидимых» документов при программном поиске связей следует придерживаться следующего чек-листа:

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

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

← На главную