Почему при выборе документа «Перемещение товаров» открывается форма создания нового документа вместо списка?

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

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

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

Анализ причины проблемы: конфликт контекстов

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

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

Решение 1: Явное указание режима выбора

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


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

Использование параметра РежимВыбора в значении Истина принудительно сообщает системе, что форма открывается для подбора ссылки, а не для создания нового документа.

Решение 2: Реализация через подменю (командный интерфейс)

Рассмотрим более современный и удобный для пользователя подход, который часто применяется в типовых конфигурациях, таких как УТ 11 или ERP. Вместо открытия промежуточной формы с реквизитом составного типа, мы можем создать подменю непосредственно в командной панели формы.

  1. Создадим в командной панели группу кнопок с видом Подменю.
  2. Внутри этого подменю разместим отдельные команды для каждого типа документа: «Из реализации», «Из перемещения», «Из заказа».
  3. Для каждой команды пропишем вызов соответствующей формы выбора с использованием ОткрытьФорму.

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

Решение 3: Использование списка значений для выбора типа

Если нам необходимо программно определить, форму какого документа открывать, мы можем воспользоваться методом ПоказатьВыборИзСписка. Рассмотрим пример реализации:


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

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

Обработка результата: заполнение данных

После того как пользователь выбрал документ в открывшейся форме списка, срабатывает процедура оповещения. Выясним, как эффективно перенести данные из выбранного документа в наш текущий объект. Рассмотрим пример серверной процедуры, использующей запрос для работы с разными типами документов (универсальный подход через ОБЪЕДИНИТЬ ВСЕ):


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

Важный момент: при использовании запроса к разным таблицам документов, убедитесь, что псевдонимы полей совпадают. Это позволит использовать лаконичную конструкцию ЗаполнитьЗначенияСвойств внутри цикла обхода выборки.

Резюме по исправлению

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

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

← На главную