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