Вопрос, ввод, выбор файла и своя форма: диалоги в управляемом приложении

· 9 мин

Содержание

Чтобы открыть диалоговое окно в 1С 8.3, на клиенте вызывают один из немодальных методов: ПоказатьВопрос, ПоказатьПредупреждение, ПоказатьВводЗначения или ОткрытьФорму с режимом РежимОткрытияОкнаФормы.БлокироватьОкноВладельца. Результат приходит не в следующую строку кода, а в процедуру-обработчик, которую передают через ОписаниеОповещения. На платформе 8.3.18 и выше то же самое пишут короче: Ждать ВопросАсинх(...) внутри процедуры с модификатором Асинх.

Типичная ситуация: разработчик переносит обработку из старой конфигурации, где стояло Если Вопрос("Удалить?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да, и при запуске получает Использование модальных окон в данном режиме запрещено!. Ниже разобраны все виды диалогов, как получить из них значение и чем веб-клиент отличается от тонкого.

Почему диалоги в 1С 8.3 открываются иначе, чем в 8.2

В обычном приложении и ранних управляемых конфигурациях диалог был модальным: код останавливался на вызове Вопрос() или ОткрытьФормуМодально() и ждал, пока пользователь нажмёт кнопку. Браузеры такую остановку скрипта не поддерживают, а 1С должна одинаково работать в тонком клиенте, веб-клиенте и мобильном приложении.

Поэтому с платформы 8.3.3 у конфигурации появилось свойство «Режим использования модальности». Оно стоит в палитре свойств корня конфигурации, в группе «Совместимость». Значения:

ЗначениеЧто происходит при вызове Вопрос(), ОткрытьФормуМодально()
ИспользоватьРаботает как в 8.2, окно модальное
Использовать с предупреждениямиРаботает, но при проверке модулей выдаются предупреждения
Не использоватьИсключение «Использование модальных окон в данном режиме запрещено!»

Типовые конфигурации на БСП давно переведены в режим «Не использовать». В новых разработках модальные вызовы не пишут вообще.

Как устроен немодальный диалог:

  1. 🧩 Процедура вызывает метод показа окна и сразу идёт дальше.
  2. 🪟 Окно блокирует форму-владельца, но платформа и другие окна живут.
  3. 📨 Когда пользователь закрыл окно, платформа вызывает процедуру из ОписаниеОповещения и передаёт ей результат.

Код, который должен выполниться после ответа пользователя, обязан стоять в обработчике оповещения, а не после вызова ПоказатьВопрос. Это главная ловушка при переходе.

Вопрос и предупреждение: самые частые диалоговые окна

ПоказатьВопрос с кнопками «Да» и «Нет»

Синтаксис: ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, Кнопки, Таймаут, КнопкаПоУмолчанию, Заголовок, КнопкаТаймаута). Обязательны первые три параметра.

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

&НаКлиенте
Процедура УдалитьСтрокиЗавершение(Результат, ДополнительныеПараметры) Экспорт
	Если Результат <> КодВозвратаДиалога.Да Тогда
		Возврат;
	КонецЕсли;
	Для Каждого Идентификатор Из Элементы.Товары.ВыделенныеСтроки Цикл
		// собираем идентификаторы и удаляем строки
	КонецЦикла;
КонецПроцедуры

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

Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Перезаписать", "Перезаписать");
Кнопки.Добавить("Пропустить", "Пропустить");
Кнопки.Добавить(КодВозвратаДиалога.Отмена, "Отмена");
ПоказатьВопрос(Оповещение, "Файл уже загружен. Что сделать?", Кнопки);

Таймаут задают в секундах. Если пользователь не ответил, в обработчик придёт КодВозвратаДиалога.Таймаут. Удобно для служебных сообщений, которые не должны висеть на экране весь день.

ПоказатьПредупреждение

Окно с одной кнопкой «ОК». Оповещение можно не передавать, если после закрытия ничего делать не нужно:

ПоказатьПредупреждение(, "Выгрузка завершена: 148 документов.", 10, "Обмен");

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

Окна ввода значения, числа, строки и даты

Когда нужно спросить у пользователя одно значение, отдельная форма не нужна. Платформа даёт готовые диалоги ввода:

МетодЧто спрашиваетЧто придёт в обработчик
ПоказатьВводЗначенияЗначение любого типа, включая ссылку на справочникЗначение или Неопределено при отмене
ПоказатьВводЧислаЧисло с заданной длиной и точностьюЧисло или Неопределено
ПоказатьВводСтрокиСтроку, в том числе многострочнуюСтрока или Неопределено
ПоказатьВводДатыДату, время или дату со временемДата или Неопределено

Пример: спросить склад и подставить его во все строки документа.

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

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

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

Через ДополнительныеПараметры в обработчик передают всё, что нужно для продолжения: идентификатор строки, имя реквизита. Третий параметр конструктора ОписаниеОповещения — как раз эта структура.

Как открыть свою форму как диалоговое окно

Если вопрос сложнее одного поля — нужна своя форма. Её открывают ОткрытьФорму:

ОткрытьФорму(ИмяФормы, Параметры, Владелец, Уникальность, Окно,
	НавигационнаяСсылка, ОписаниеОповещенияОЗакрытии, РежимОткрытияОкна)

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

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

Режимы открытия окна:

  • 🔓 Независимый — обычное окно, владелец остаётся доступным;
  • 🔒 БлокироватьОкноВладельца — блокируется только форма-владелец, остальной интерфейс работает. Это стандарт для диалога;
  • ⛔ БлокироватьВесьИнтерфейс — блокируется всё приложение. Нужен редко: подтверждение критичной операции, ввод пароля.

Режим можно задать и в самой форме: свойство формы «Режим открытия окна» в конфигураторе. Тогда параметр в ОткрытьФорму можно опустить.

Как передать параметры в открываемую форму

Ключи структуры Параметры должны совпадать с параметрами, созданными на закладке «Параметры» открываемой формы. Иначе значение просто не дойдёт. Читают их в ПриСозданииНаСервере:

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

Исключение — стандартные параметры вроде Ключ, РежимВыбора, Отбор: их у форм объектов и списков объявлять не нужно.

Выбор файла и каталога через ДиалогВыбораФайла

Для загрузки прайса или выгрузки отчёта нужен системный диалог выбора файла. Объект создаётся с одним из режимов РежимДиалогаВыбораФайла: Открытие, Сохранение, ВыборКаталога.

&НаКлиенте
Процедура ВыбратьФайлПрайса(Команда)
	Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	Диалог.Заголовок = "Выберите прайс-лист";
	Диалог.Фильтр = "Книга Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
	Диалог.МножественныйВыбор = Ложь;
	Оповещение = Новый ОписаниеОповещения("ВыбратьФайлПрайсаЗавершение", ЭтотОбъект);
	Диалог.Показать(Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьФайлПрайсаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
	Если ВыбранныеФайлы = Неопределено Тогда
		Возврат; // пользователь нажал «Отмена»
	КонецЕсли;
	ПутьКФайлу = ВыбранныеФайлы[0];
КонецПроцедуры

Что полезно знать:

  • 📁 ВыбранныеФайлы — массив полных путей, даже если выбран один файл;
  • 🔤 фильтр пишется парами «описание|маска», пары разделяются той же вертикальной чертой;
  • 📂 начальную папку задаёт свойство Каталог, имя по умолчанию — ПолноеИмяФайла;
  • 🧾 для режима Сохранение удобно включить ПроверятьСуществованиеФайла, чтобы пользователь не перетёр нужный файл молча.

Старый вызов Диалог.Выбрать() модальный и в режиме «Не использовать» упадёт с той же ошибкой, что и Вопрос().

Сравнение способов открыть диалоговое окно

ЗадачаНемодальный методАсинхронный аналог (8.3.18+)Устаревший модальный
Да/НетПоказатьВопросВопросАсинхВопрос
Сообщение с «ОК»ПоказатьПредупреждениеПредупреждениеАсинхПредупреждение
Одно значениеПоказатьВводЗначенияВвестиЗначениеАсинхВвестиЗначение
Число / строка / датаПоказатьВводЧисла, ПоказатьВводСтроки, ПоказатьВводДатыВвестиЧислоАсинх, ВвестиСтрокуАсинх, ВвестиДатуАсинхВвестиЧисло, ВвестиСтроку, ВвестиДату
Файл, каталогДиалогВыбораФайла.ПоказатьДиалогВыбораФайла.ВыбратьАсинхДиалогВыбораФайла.Выбрать
Своя формаОткрытьФорму с оповещениемОткрытьФорму + ожидание закрытия через оповещениеОткрытьФормуМодально

Иногда в описаниях встречается «ПоказатьМодально» — метода с таким именем в платформе нет. Модальное открытие своей формы делается через ОткрытьФормуМодально или метод формы ОткрытьМодально(), и оба варианта в новом коде не используют.

Тот же вопрос через Асинх и Ждать

На платформе с номером не ниже 8.3.18 и режиме совместимости не ниже этой версии код можно писать «сверху вниз», без отдельной процедуры-обработчика:

&НаКлиенте
Асинх Процедура УдалитьСтроки(Команда)
	Ответ = Ждать ВопросАсинх("Удалить выделенные строки?", РежимДиалогаВопрос.ДаНет);
	Если Ответ <> КодВозвратаДиалога.Да Тогда
		Возврат;
	КонецЕсли;
	// удаляем строки
КонецПроцедуры

Внешне похоже на модальный вызов, но окно немодальное и в веб-клиенте работает. Ждать допустим только внутри процедуры или функции с модификатором Асинх.

Как получить значение из диалога обратно

Результат собственной формы возвращают двумя способами.

Закрыть(Значение) и ОписаниеОповещенияОЗакрытии

В открытой форме по кнопке «ОК» вызывают Закрыть() с параметром:

&НаКлиенте
Процедура ОК(Команда)
	Результат = Новый Структура("Процент, ДатаОкончания", Процент, ДатаОкончания);
	Закрыть(Результат);
КонецПроцедуры

Эта структура придёт первым параметром в обработчик, указанный в ОткрытьФорму. Если пользователь закрыл окно крестиком, придёт Неопределено — проверяйте это первой строкой обработчика.

ОповеститьОВыборе и ОбработкаВыбора

Второй способ — для форм выбора. Форму открывают с владельцем, а в ней вызывают ОповеститьОВыборе(Значение). Значение попадает в событие ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) формы-владельца. Так работают формы подбора: окно может отправить несколько значений подряд и не закрываться, если у него выключено свойство «Закрывать при выборе».

СпособКогда подходит
Закрыть(Значение)Диалог настроек, ввод нескольких полей, одно итоговое значение
ОповеститьОВыбореПодбор: пользователь выбирает несколько позиций, окно остаётся открытым

Особенности веб-клиента и тонкого клиента

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

  • 🌐 Всплывающие окна браузера. Веб-клиент открывает формы внутри своей страницы, поэтому блокировщик всплывающих окон им не мешает. Но отдельные окна, например при открытии внешней ссылки, браузер может заблокировать.
  • 📎 Выбор файла в веб-клиенте. ДиалогВыбораФайла с полным путём к файлу требует расширения для работы с файлами. Подключают его через НачатьПодключениеРасширенияРаботыСФайлами, а при отказе предлагают установку.
  • ⬆️ Без расширения. Если нужно только загрузить файл на сервер, используйте НачатьПомещениеФайлов или ПоместитьФайлАсинх. Браузер покажет свой диалог выбора, файл ляжет во временное хранилище, путь на диске пользователя вы не получите.
  • 🖥️ Тонкий клиент. Доступ к файловой системе есть сразу, расширение не нужно.

Свойство «Режим использования синхронных вызовов расширений платформы и внешних компонент» работает так же, как режим модальности. При значении «Не использовать» синхронные вызовы работы с файлами и внешними компонентами вызывают исключение, нужны их Начать… или …Асинх версии.

Ошибки при открытии диалоговых окон

Диагностика: выберите симптом

Частые вопросы

Можно ли открыть диалог из общего модуля?
Да, если модуль клиентский. Вторым параметром ОписаниеОповещения передайте сам общий модуль, например ОбщийМодуль.МойМодульКлиент, а обработчик объявите в нём экспортной процедурой.
Как открыть форму во всплывающем окне поверх текущей, а не во вкладке?
Задайте форме режим «Блокировать окно владельца» — платформа покажет её отдельным окном поверх владельца. Независимые формы в интерфейсе «Такси» открываются во вкладке рабочей области.
Как показать диалог при открытии формы?
Не вызывайте его прямо в ПриОткрытии: форма ещё не отрисована. Обычный приём — ПодключитьОбработчикОжидания с интервалом 0,1 секунды и однократным вызовом, а уже в обработчике ожидания показывать вопрос.
Как задать ширину и высоту окна диалога?
Размер своей формы задают в конфигураторе свойствами формы «Ширина» и «Высота». У стандартных окон вопроса и ввода размер подбирается под текст автоматически.
Можно ли задать вопрос при закрытии формы?
В ПередЗакрытием установите Отказ = Истина, покажите ПоказатьВопрос, а в обработчике при согласии вызовите Закрыть(). Чтобы не зациклиться, перед повторным закрытием поставьте флаг-реквизит, который пропустит вопрос.