Почему возникает ошибка «Несоответствие типов» при использовании критериев отбора во внешней печатной форме?

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

При разработке внешних обработок и печатных форм в среде 1С программисты часто сталкиваются с ситуацией, когда код, идеально работающий при ручном запуске через Файл — Открыть, внезапно выдает ошибку после регистрации в справочнике Дополнительные отчеты и обработки. Одной из наиболее коварных ошибок является «Ошибка обработки представления» при работе с виртуальными таблицами критериев отбора.

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

Анализ исходной проблемы и причины ошибки

Рассмотрим ситуацию: разработчик создал запрос для получения списка перемещений, связанных с конкретным документом Заказ-наряд. В консоли запросов или при открытии обработки как файла всё работает корректно. Однако при вызове из механизма печати система выдает сообщение:

Ошибка при вызове метода контекста (Выполнить): {(5, 2)}: Ошибка обработки представления "КритерийОтбора.ПодчиненныеДокументы:Несоответствие типов (Параметр номер ""1"")"

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

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

Решение 1: Явное преобразование в Ссылку

Самый быстрый и эффективный способ исправить ситуацию — гарантировать передачу ссылки в параметр запроса. Даже если в вашу функцию пришел объект, у него всегда есть свойство Ссылка, которое содержит нужный тип данных.

Давайте посмотрим на исправленный фрагмент кода:


Функция ПолучитьАртикулы(ЗаказНаряд)
    
    Запрос = Новый Запрос;
    // Используем Ссылка, чтобы гарантировать правильный тип для критерия отбора
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    ВЫРАЗИТЬ(ПодчиненныеДокументы.Ссылка КАК Документ.ПеремещениеТоваровВПроизводство) КАК Перемещение
    |ПОМЕСТИТЬ Перемещения
    |ИЗ
    |    КритерийОтбора.ПодчиненныеДокументы(&ЗаказНаряд) КАК ПодчиненныеДокументы
    |ГДЕ
    |    ПодчиненныеДокументы.Ссылка ССЫЛКА Документ.ПеремещениеТоваровВПроизводство
    |;
    |
    |ВЫБРАТЬ
    |    ПеремещениеТоваровВПроизводствоТовары.Номенклатура.Артикул КАК НоменклатураАртикул
    |ИЗ
    |    Перемещения КАК Перемещения
    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПеремещениеТоваровВПроизводство.Товары КАК ПеремещениеТоваровВПроизводствоТовары
    |        ПО Перемещения.Перемещение = ПеремещениеТоваровВПроизводствоТовары.Ссылка";
    
    // Вместо просто ЗаказНаряд передаем ЗаказНаряд.Ссылка
    Если Справочники.ТипЗнч(ЗаказНаряд) = Тип("ДокументСсылка.ЗаказНаряд") Тогда
        Запрос.УстановитьПараметр("ЗаказНаряд", ЗаказНаряд);
    Иначе
        Запрос.УстановитьПараметр("ЗаказНаряд", ЗаказНаряд.Ссылка);
    КонецЕсли;
    
    РезультатЗапроса = Запрос.Выполнить();
    // Дальнейшая обработка результата...
КонецФункции

Важный нюанс: если вы используете типовую БСП (Библиотеку стандартных подсистем), в метод Печать обычно приходит массив объектов. В этом случае необходимо перебирать массив и извлекать ссылку из каждого элемента.

Решение 2: Проверка состава критерия отбора в метаданных

Если после исправления типа данных запрос всё равно возвращает пустой результат (но уже без ошибки), нам необходимо проанализировать структуру метаданных. Критерий отбора работает только с теми документами, которые явно включены в его «Состав».

Разберем шаги для проверки в Конфигураторе:

  1. Найдите в дереве метаданных ветку Общие -> Критерии отбора.
  2. Откройте критерий ПодчиненныеДокументы.
  3. Перейдите на вкладку Данные и проверьте поле Тип. Там должен быть указан ваш тип документа (например, ДокументСсылка.ЗаказНаряд).
  4. Перейдите на вкладку Состав. Убедитесь, что там отмечены те документы (например, ПеремещениеТоваровВПроизводство), которые должны «видеть» ваш заказ-наряд. Обычно выбирается реквизит ДокументОснование или аналогичный.

Если связь в метаданных не настроена, виртуальная таблица КритерийОтбора.ПодчиненныеДокументы просто не будет знать о существовании цепочки документов.

Решение 3: Универсальный подход к типизации параметров

Чтобы ваша печатная форма была максимально надежной, мы рекомендуем использовать универсальную проверку типа при установке параметров. Это защитит код от изменений в контексте вызова (например, если завтра вы решите вызывать эту функцию из формы списка, а не из формы объекта).

Рассмотрим пример универсальной функции-помощника:


Функция ПолучитьСсылкуИзЛюбогоТипа(Данные)
    
    ТипДанных = ТипЗнч(Данные);
    
    // Если это уже ссылка - возвращаем как есть
    Если Справочники.ТипЗнч(Данные) = Тип("ДокументСсылка.ЗаказНаряд") Тогда
        Возврат Данные;
    // Если это объект - берем его ссылку
    ИначеЕсли ТипДанных = Тип("ДокументОбъект.ЗаказНаряд") Тогда
        Возврат Данные.Ссылка;
    КонецЕсли;
    
    Возврат Данные; // Или вызвать исключение, если тип недопустим
    
КонецФункции

Использование такой проверки перед вызовом Запрос.УстановитьПараметр гарантирует, что в виртуальную таблицу КритерийОтбора попадет валидное значение.

Альтернативный программный метод обращения к критериям

Выясним причину, по которой иногда стоит отказаться от запроса в пользу объектной модели. Если вам нужно просто получить список ссылок без сложных соединений с табличными частями, можно использовать метод Выбрать() самого объекта метаданных.

Рассмотрим пример:


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

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

Этот метод более «лоялен» к типам данных и работает быстрее, если ваша цель — простое получение списка ссылок. Однако в исходной задаче требовалось получить Артикул из табличной части, поэтому использование запроса с временной таблицей ПОМЕСТИТЬ Перемещения остается лучшим решением с точки зрения производительности.

Резюме и рекомендации

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

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

← На главную