При разработке и доработке конфигураций на платформе 1С:Предприятие 7.7 часто возникает необходимость найти определенный документ, опираясь на значение его реквизита — например, найти документ АктРазногласий, созданный на основании конкретной ТТН. Разработчики нередко пытаются применить привычный метод НайтиПоРеквизиту, однако при выполнении кода платформа выдает ошибку: Поле Агрегатного объекта не обнаружено (НайтиПоРеквизиту). Разберем, почему возникает эта ошибка, и рассмотрим правильные варианты поиска документов.
Проанализируем контекст вызова метода. В платформе 1С 7.7 метод НайтиПоРеквизиту() реализован исключительно для объекта Справочник (при условии, что у реквизита в метаданных включен признак сортировки/отбора). У объекта Документ такого метода в синтаксисе нет в принципе. Более того, для документов нельзя настроить произвольную индексацию отдельных реквизитов так же легко, как в справочниках.
Стоит отметить, что и в платформе 1С 8.x у менеджеров документов метод НайтиПоРеквизиту также отсутствует — там поиск по реквизитам выполняется через запросы или критерии отбора.
Выясним, какими способами можно быстро и корректно найти подчиненный документ в 1С 7.7, зная ссылку на документ-основание.
Самый распространенный и штатный способ найти документ, созданный на основании другого — использовать платформенный механизм подчиненности. Для этого у объекта Документ существует метод ВыбратьПодчиненныеДокументы(Дата1, Дата2, Докум).
Рассмотрим по шагам, как устроен этот алгоритм:
ПолучитьПустоеЗначение("Документ").Документ.ВыбратьПодчиненныеДокументы, передавая в качестве третьего параметра наш документ-основание.Вид().ТекущийДокумент() и прерываем цикл.Посмотрим на пример программной реализации:
Акт = ПолучитьПустоеЗначение("Документ");
Док = СоздатьОбъект("Документ");
// Выбираем все подчиненные документы по известному основанию ДокОснование
Док.ВыбратьПодчиненныеДокументы(,, ДокОснование);
Пока Док.ПолучитьДокумент() = 1 Цикл
Если Док.Вид() = "АктРазногласий" Тогда
Акт = Док.ТекущийДокумент();
Прервать; // Нужный документ найден, выходим из цикла
КонецЕсли;
КонецЦикла;
Если Акт.Выбран() = 1 Тогда
Сообщить("Найден акт: " + Строка(Акт));
// Выполняем дальнейшие действия с найденным документом
Иначе
Сообщить("Подчиненный акт разногласий не обнаружен!");
КонецЕсли;
Важные нюансы метода:
Документ или конкретный вид документа). Если реквизит имеет тип Неопределенный, автоматическая фиксация подчиненности может не сработать.,, ДокОснование), выборка будет производиться по всей глубине базы. Для ускорения работы рекомендуется ограничивать интервал: в качестве начальной даты указывать дату документа-основания (ДокОснование.ДатаДок), а в качестве конечной — актуальную дату или дату запрета редактирования.Если требуется выполнять частый и быстрый поиск документов по определенному реквизиту (в том числе по реквизиту ДокументОснование), можно задействовать Графу отбора.
Разберем последовательность настройки и программного вызова:
Основание).ВыбратьПоЗначению().Посмотрим на пример кода выборки по графе отбора:
Док = СоздатьОбъект("Документ.АктРазногласий");
ДатаНач = ТТН.ДатаДок;
ДатаКон = ТекущаяДата();
// Выборка документов по зарегистрированной графе отбора
Док.ВыбратьПоЗначению(ДатаНач, ДатаКон, "Основание", ТТН);
Если Док.ПолучитьДокумент() = 1 Тогда
Сообщить("Найден документ: " + Строка(Док.ТекущийДокумент()));
Иначе
Сообщить("Документ по указанному основанию не найден.");
КонецЕсли;
Этот метод работает быстрее полного перебора, так как использует платформенные индексы графы отбора в базе данных.
Если реквизит основания не является типизированным для системного журнала подчиненности или граф отбора в конфигурации нет, надежным решением является стандартный объект Запрос.
Рассмотрим пример формирования запроса:
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ПоискАкта)
|Период С ТТН.ДатаДок По ТекущаяДата();
|Акт = Документ.АктРазногласий.ТекущийДокумент;
|Основание = Документ.АктРазногласий.ДокументОснование;
|Группировка Акт;
|Условие(Основание = ТТН);
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Пока Запрос.Группировка(1) = 1 Цикл
НайденныйАкт = Запрос.Акт;
Сообщить("Найден акт через запрос: " + Строка(НайденныйАкт));
КонецЦикла;
КонецЕсли;
Запрос позволяет строго ограничить выборку конкретным видом документа и условием на реквизит шапки, что избавляет от необходимости вручную фильтровать подчиненные документы в цикле.