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