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

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

Разработчики в 1С часто сталкиваются с задачей: в зависимости от значения определенного реквизита документа (например, вида операции или статуса) открыть пользователю ту или иную форму. При попытке реализовать это через обработчик события выбора в динамическом списке списка документов возникает неприятная проблема — открываются сразу две формы (и стандартная, и специализированная), несмотря на то, что в коде явно прописано СтандартнаяОбработка = Ложь;.

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

Проанализируем ситуацию на конкретном примере. Допустим, у нас есть документ ИнвентаризацияТоваровНаСкладе. Если у документа вид операции равен «Спецодежда», нам необходимо открыть специализированную форму ФормаСпецодежды, во всех остальных случаях — стандартную ФормаДокумента.

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

Основная причина, по которой установленное свойство СтандартнаяОбработка = Ложь игнорируется платформой — это неправильное количество параметров в объявлении процедуры-обработчика.

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


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

Обратим внимание на сигнатуру процедуры СписокВыбор. Здесь объявлено всего три параметра. Однако системное событие таблицы динамического списка Выбор требует строго четыре параметра:

Выбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)

Платформа 1С передает параметры по порядку их следования. При трех параметрах в коде происходит следующее:

  1. В первый параметр Элемент передается сама таблица формы.
  2. Во второй параметр ВыбранноеЗначение передается идентификатор выбранной строки.
  3. В третий параметр, который разработчик назвал СтандартнаяОбработка, передается объект ПолеФормы (по которому кликнул пользователь).

Таким образом, строка кода СтандартнаяОбработка = Ложь; всего лишь перезаписывает локальную переменную, содержащую ссылку на поле формы, а реальный четвертый параметр, управляющий стандартной обработкой события на уровне платформы, остается незадействованным. Платформа считает, что стандартную обработку никто не отменял (флаг равен Истина), и параллельно с вашей формой открывает стандартную форму объекта.

Решение №1. Исправление обработчика в форме списка

Самый быстрый способ решить проблему непосредственно в форме списка — привести сигнатуру процедуры в соответствие со стандартами платформы, добавив пропущенный параметр Поле.

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


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

Важное примечание: При двойном клике по строке списка у таблицы также может срабатывать событие ПередНачаломИзменения. Если вы хотите полностью заблокировать стандартное поведение изменения строки, убедитесь, что в свойствах таблицы на это событие не завязана логика, способная вызвать открытие стандартного окна, или обработайте его, установив параметр Отказ = Истина.

Решение №2. Архитектурный подход через модуль менеджера (рекомендуемый)

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

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

Выполним следующие шаги для реализации этого подхода:

  1. Откроем модуль менеджера документа ИнвентаризацияТоваровНаСкладе.
  2. Добавим предопределенную процедуру ОбработкаПолученияФормы.

Разберем пример реализации кода:


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

Преимущества использования модуля менеджера:

Важные нюансы при работе с ОбработкаПолученияФормы:

← На главную