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