Почему возникает ошибка «Несоответствие типов» при программном открытии формы выбора в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

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

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

Анализ проблемного кода

Рассмотрим ситуацию, с которой столкнулся автор вопроса. Задача состояла в том, чтобы при начале выбора в поле документа перехватить стандартную обработку и открыть форму выбора этапа производства с отбором по заказу клиента.

Исходный код, вызывающий ошибку, выглядел следующим образом:


&НаКлиенте
Процедура ЭтапПроизводства1НачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Если Не ТипЗнч(Объект.ЗаказКлиента) = Тип("Строка") Тогда
        СтандартнаяОбработка = Ложь;
        ЗначениеОтбора = Новый Структура("ЗаказКлиента", Объект.ЗаказКлиента);
        // Ошибка возникает на следующей строке:
        ПараметрыВыбора = Новый Структура("Отбор", ЗначениеОтбора); 
        ОткрытьФорму("Документ.ЭтапПроизводства2_2.ФормаВыбора", ПараметрыВыбора);      
    КонецЕсли;
КонецПроцедуры

Платформа выдает ошибку «Несоответствие типов» на строке присвоения значения переменной ПараметрыВыбора. На первый взгляд код кажется верным: мы создаем новую структуру. Почему же система ругается на тип?

Истинная причина ошибки: Конфликт имен

Давайте разберемся, что происходит в контексте выполнения кода. Процедура НачалоВыбора является обработчиком события элемента формы.

Главная ошибка здесь кроется не в логике, а в именовании переменной. Идентификатор ПараметрыВыбора в контексте расширения поля формы (и самой управляемой формы) является зарезервированным системным свойством.

  1. У элемента формы (поля ввода) есть свойство ПараметрыВыбора. Это свойство имеет тип ФиксированныйМассив (или СписокЗначений в некоторых контекстах), в котором хранятся параметры выбора, заданные декларативно в конфигураторе.
  2. Когда вы пишете ПараметрыВыбора = Новый Структура(...), платформа воспринимает это не как создание новой локальной переменной, а как попытку присвоить системному свойству элемента формы значение типа Структура.
  3. Так как свойство элемента формы ожидает ФиксированныйМассив (или доступно только для чтения в данном контексте), а вы передаете Структура, возникает исключение «Несоответствие типов».

Это классическая ошибка затенения (shadowing) или конфликта имен в области видимости переменных.

Решение проблемы

Чтобы исправить ошибку, достаточно изменить имя переменной на любое другое, которое не пересекается со свойствами формы или элемента управления. Например, используем имя ПараметрыОткрытия или СтруктураПараметров.

Исправленный код будет выглядеть так:


&НаКлиенте
Процедура ЭтапПроизводства1НачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
    
    // Проверяем, заполнен ли заказ, чтобы не делать пустой отбор
    Если Не ЗначениеЗаполнено(Объект.ЗаказКлиента) Тогда
        Возврат;
    КонецЕсли;

    СтандартнаяОбработка = Ложь;
    
    // Формируем отбор для списка
    ЗначениеОтбора = Новый Структура("ЗаказКлиента", Объект.ЗаказКлиента);
    
    // Используем безопасное имя переменной
    ПараметрыОткрытия = Новый Структура("Отбор", ЗначениеОтбора);
    
    // Открываем форму
    ОткрытьФорму("Документ.ЭтапПроизводства2_2.ФормаВыбора", ПараметрыОткрытия, Элемент);     

КонецПроцедуры

Нюансы работы с отборами в динамических списках

При программном открытии форм выбора важно правильно указывать ключи структуры отбора. Давайте проанализируем, как правильно формировать структуру Отбор.

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

Частая ошибка: попытка использовать путь через точку в имени ключа структуры.


// Так делать НЕЛЬЗЯ, если в списке нет колонки с таким псевдонимом:
ЗначениеОтбора = Новый Структура("Объект.Распоряжение.ДокументОснование", СсылкаНаЗаказ);

Динамический список формы выбора, как правило, имеет простые реквизиты: Ссылка, Дата, Номер, Контрагент, ЗаказКлиента. Если вам нужно отобрать документы по реквизиту шапки, используйте прямое имя реквизита.

Полный пример реализации с обработкой выбора

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


&НаКлиенте
Процедура ЭтапПроизводства1НачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Подготовка отбора
    // Предположим, мы хотим отобрать этапы только по конкретному заказу
    СтруктураОтбора = Новый Структура;
    СтруктураОтбора.Вставить("ЗаказКлиента", Объект.ЗаказКлиента);
    
    // 2. Подготовка параметров открытия формы
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", СтруктураОтбора);
    // Если нужно разрешить выбор нескольких элементов:
    // ПараметрыФормы.Вставить("РежимВыбора", Истина);
    // ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
    
    // 3. Создание описания оповещения для обработки результата
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораЭтапа", ЭтотОбъект);
    
    // 4. Открытие формы
    // Третий параметр "Элемент" указывает владельца формы, 
    // что важно для блокировки интерфейса (если нужно)
    ОткрытьФорму("Документ.ЭтапПроизводства2_2.ФормаВыбора", 
                 ПараметрыФормы, 
                 Элемент, 
                 , 
                 , 
                 , 
                 Оповещение);
                 
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЭтапа(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    // Если пользователь нажал "Отмена" или закрыл окно
    Если РезультатВыбора = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Обработка результата (РезультатВыбора содержит ссылку или массив ссылок)
    Объект.ЭтапПроизводства = РезультатВыбора;
    // Можно вызвать серверный метод для дозаполнения данных
    ОбработатьВыборНаСервере(РезультатВыбора);

КонецПроцедуры

Альтернативный способ: Связи параметров выбора

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

Давайте рассмотрим, когда лучше использовать этот метод:

  1. Откройте свойства элемента формы (поля ввода), в котором происходит выбор.
  2. Найдите свойство Связи параметров выбора.
  3. Добавьте новую связь:
    • Параметр выбора: Отбор.ЗаказКлиента (имя поля в форме выбора, куда передаем значение).
    • Реквизит формы: Объект.ЗаказКлиента (откуда берем значение).

В этом случае платформа сама отследит изменение поля ЗаказКлиента и при открытии формы выбора этапа автоматически наложит нужный фильтр. Это «clean code» подход, который уменьшает количество кода в модуле формы.

Выводы

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

← На главную