Вопрос, ввод, выбор файла и своя форма: диалоги в управляемом приложении
Содержание
Чтобы открыть диалоговое окно в 1С 8.3, на клиенте вызывают один из немодальных методов: ПоказатьВопрос, ПоказатьПредупреждение, ПоказатьВводЗначения или ОткрытьФорму с режимом РежимОткрытияОкнаФормы.БлокироватьОкноВладельца. Результат приходит не в следующую строку кода, а в процедуру-обработчик, которую передают через ОписаниеОповещения. На платформе 8.3.18 и выше то же самое пишут короче: Ждать ВопросАсинх(...) внутри процедуры с модификатором Асинх.
Типичная ситуация: разработчик переносит обработку из старой конфигурации, где стояло Если Вопрос("Удалить?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да, и при запуске получает Использование модальных окон в данном режиме запрещено!. Ниже разобраны все виды диалогов, как получить из них значение и чем веб-клиент отличается от тонкого.
Почему диалоги в 1С 8.3 открываются иначе, чем в 8.2
В обычном приложении и ранних управляемых конфигурациях диалог был модальным: код останавливался на вызове Вопрос() или ОткрытьФормуМодально() и ждал, пока пользователь нажмёт кнопку. Браузеры такую остановку скрипта не поддерживают, а 1С должна одинаково работать в тонком клиенте, веб-клиенте и мобильном приложении.
Поэтому с платформы 8.3.3 у конфигурации появилось свойство «Режим использования модальности». Оно стоит в палитре свойств корня конфигурации, в группе «Совместимость». Значения:
| Значение | Что происходит при вызове Вопрос(), ОткрытьФормуМодально() |
|---|---|
| Использовать | Работает как в 8.2, окно модальное |
| Использовать с предупреждениями | Работает, но при проверке модулей выдаются предупреждения |
| Не использовать | Исключение «Использование модальных окон в данном режиме запрещено!» |
Типовые конфигурации на БСП давно переведены в режим «Не использовать». В новых разработках модальные вызовы не пишут вообще.
Как устроен немодальный диалог:
- 🧩 Процедура вызывает метод показа окна и сразу идёт дальше.
- 🪟 Окно блокирует форму-владельца, но платформа и другие окна живут.
- 📨 Когда пользователь закрыл окно, платформа вызывает процедуру из
ОписаниеОповещенияи передаёт ей результат.
Код, который должен выполниться после ответа пользователя, обязан стоять в обработчике оповещения, а не после вызова ПоказатьВопрос. Это главная ловушка при переходе.
Вопрос и предупреждение: самые частые диалоговые окна
ПоказатьВопрос с кнопками «Да» и «Нет»
Синтаксис: ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, Кнопки, Таймаут, КнопкаПоУмолчанию, Заголовок, КнопкаТаймаута). Обязательны первые три параметра.
&НаКлиенте
Процедура УдалитьСтроки(Команда)
Оповещение = Новый ОписаниеОповещения("УдалитьСтрокиЗавершение", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Удалить выделенные строки?", РежимДиалогаВопрос.ДаНет, ,
КодВозвратаДиалога.Нет, "Подтверждение");
КонецПроцедуры
&НаКлиенте
Процедура УдалитьСтрокиЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
Для Каждого Идентификатор Из Элементы.Товары.ВыделенныеСтроки Цикл
// собираем идентификаторы и удаляем строки
КонецЦикла;
КонецПроцедуры
Варианты кнопок задаёт перечисление РежимДиалогаВопрос: ДаНет, ДаНетОтмена, ОК, ОКОтмена, ПовторитьОтмена, ПрерватьПовторитьПропустить. Если нужны свои подписи, передайте вместо перечисления СписокЗначений: значение — то, что вернётся в обработчик, представление — текст на кнопке.
Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Перезаписать", "Перезаписать");
Кнопки.Добавить("Пропустить", "Пропустить");
Кнопки.Добавить(КодВозвратаДиалога.Отмена, "Отмена");
ПоказатьВопрос(Оповещение, "Файл уже загружен. Что сделать?", Кнопки);
Таймаут задают в секундах. Если пользователь не ответил, в обработчик придёт КодВозвратаДиалога.Таймаут. Удобно для служебных сообщений, которые не должны висеть на экране весь день.
ПоказатьПредупреждение
Окно с одной кнопкой «ОК». Оповещение можно не передавать, если после закрытия ничего делать не нужно:
ПоказатьПредупреждение(, "Выгрузка завершена: 148 документов.", 10, "Обмен");
Здесь 10 — таймаут в секундах. Для подсказок, которые не требуют реакции, лучше ПоказатьОповещениеПользователя — всплывающее окно в углу, оно вообще не блокирует работу.
Окна ввода значения, числа, строки и даты
Когда нужно спросить у пользователя одно значение, отдельная форма не нужна. Платформа даёт готовые диалоги ввода:
| Метод | Что спрашивает | Что придёт в обработчик |
|---|---|---|
ПоказатьВводЗначения | Значение любого типа, включая ссылку на справочник | Значение или Неопределено при отмене |
ПоказатьВводЧисла | Число с заданной длиной и точностью | Число или Неопределено |
ПоказатьВводСтроки | Строку, в том числе многострочную | Строка или Неопределено |
ПоказатьВводДаты | Дату, время или дату со временем | Дата или Неопределено |
Пример: спросить склад и подставить его во все строки документа.
&НаКлиенте
Процедура ЗаполнитьСклад(Команда)
Оповещение = Новый ОписаниеОповещения("ЗаполнитьСкладЗавершение", ЭтотОбъект);
ПоказатьВводЗначения(Оповещение, , "Выберите склад", Тип("СправочникСсылка.Склады"));
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьСкладЗавершение(Значение, ДополнительныеПараметры) Экспорт
Если Не ЗначениеЗаполнено(Значение) Тогда
Возврат;
КонецЕсли;
Для Каждого Строка Из Объект.Товары Цикл
Строка.Склад = Значение;
КонецЦикла;
КонецПроцедуры
Для ссылочного типа ПоказатьВводЗначения открывает форму выбора справочника, для примитивного — небольшое поле ввода. Если тип не указан и значение не задано, платформа сначала предложит выбрать тип — пользователей это обычно путает, поэтому тип лучше передавать всегда.
Через ДополнительныеПараметры в обработчик передают всё, что нужно для продолжения: идентификатор строки, имя реквизита. Третий параметр конструктора ОписаниеОповещения — как раз эта структура.
Как открыть свою форму как диалоговое окно
Если вопрос сложнее одного поля — нужна своя форма. Её открывают ОткрытьФорму:
ОткрытьФорму(ИмяФормы, Параметры, Владелец, Уникальность, Окно,
НавигационнаяСсылка, ОписаниеОповещенияОЗакрытии, РежимОткрытияОкна)
Чтобы форма вела себя как диалог, заполните последние два параметра:
&НаКлиенте
Процедура НастроитьСкидку(Команда)
ПараметрыФормы = Новый Структура("Контрагент", Объект.Контрагент);
Оповещение = Новый ОписаниеОповещения("НастроитьСкидкуЗавершение", ЭтотОбъект);
ОткрытьФорму("Обработка.ПодборСкидки.Форма.Форма", ПараметрыФормы, ЭтаФорма, , , ,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
Режимы открытия окна:
- 🔓
Независимый— обычное окно, владелец остаётся доступным; - 🔒
БлокироватьОкноВладельца— блокируется только форма-владелец, остальной интерфейс работает. Это стандарт для диалога; - ⛔
БлокироватьВесьИнтерфейс— блокируется всё приложение. Нужен редко: подтверждение критичной операции, ввод пароля.
Режим можно задать и в самой форме: свойство формы «Режим открытия окна» в конфигураторе. Тогда параметр в ОткрытьФорму можно опустить.
Как передать параметры в открываемую форму
Ключи структуры Параметры должны совпадать с параметрами, созданными на закладке «Параметры» открываемой формы. Иначе значение просто не дойдёт. Читают их в ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ЗначениеЗаполнено(Параметры.Контрагент) Тогда
Контрагент = Параметры.Контрагент;
КонецЕсли;
КонецПроцедуры
Исключение — стандартные параметры вроде Ключ, РежимВыбора, Отбор: их у форм объектов и списков объявлять не нужно.
Выбор файла и каталога через ДиалогВыбораФайла
Для загрузки прайса или выгрузки отчёта нужен системный диалог выбора файла. Объект создаётся с одним из режимов РежимДиалогаВыбораФайла: Открытие, Сохранение, ВыборКаталога.
&НаКлиенте
Процедура ВыбратьФайлПрайса(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите прайс-лист";
Диалог.Фильтр = "Книга Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
Диалог.МножественныйВыбор = Ложь;
Оповещение = Новый ОписаниеОповещения("ВыбратьФайлПрайсаЗавершение", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ВыбратьФайлПрайсаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы = Неопределено Тогда
Возврат; // пользователь нажал «Отмена»
КонецЕсли;
ПутьКФайлу = ВыбранныеФайлы[0];
КонецПроцедуры
Что полезно знать:
- 📁
ВыбранныеФайлы— массив полных путей, даже если выбран один файл; - 🔤 фильтр пишется парами «описание|маска», пары разделяются той же вертикальной чертой;
- 📂 начальную папку задаёт свойство
Каталог, имя по умолчанию —ПолноеИмяФайла; - 🧾 для режима
Сохранениеудобно включитьПроверятьСуществованиеФайла, чтобы пользователь не перетёр нужный файл молча.
Старый вызов Диалог.Выбрать() модальный и в режиме «Не использовать» упадёт с той же ошибкой, что и Вопрос().
Сравнение способов открыть диалоговое окно
| Задача | Немодальный метод | Асинхронный аналог (8.3.18+) | Устаревший модальный |
|---|---|---|---|
| Да/Нет | ПоказатьВопрос | ВопросАсинх | Вопрос |
| Сообщение с «ОК» | ПоказатьПредупреждение | ПредупреждениеАсинх | Предупреждение |
| Одно значение | ПоказатьВводЗначения | ВвестиЗначениеАсинх | ВвестиЗначение |
| Число / строка / дата | ПоказатьВводЧисла, ПоказатьВводСтроки, ПоказатьВводДаты | ВвестиЧислоАсинх, ВвестиСтрокуАсинх, ВвестиДатуАсинх | ВвестиЧисло, ВвестиСтроку, ВвестиДату |
| Файл, каталог | ДиалогВыбораФайла.Показать | ДиалогВыбораФайла.ВыбратьАсинх | ДиалогВыбораФайла.Выбрать |
| Своя форма | ОткрытьФорму с оповещением | ОткрытьФорму + ожидание закрытия через оповещение | ОткрытьФормуМодально |
Иногда в описаниях встречается «ПоказатьМодально» — метода с таким именем в платформе нет. Модальное открытие своей формы делается через ОткрытьФормуМодально или метод формы ОткрытьМодально(), и оба варианта в новом коде не используют.
Тот же вопрос через Асинх и Ждать
На платформе с номером не ниже 8.3.18 и режиме совместимости не ниже этой версии код можно писать «сверху вниз», без отдельной процедуры-обработчика:
&НаКлиенте
Асинх Процедура УдалитьСтроки(Команда)
Ответ = Ждать ВопросАсинх("Удалить выделенные строки?", РежимДиалогаВопрос.ДаНет);
Если Ответ <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
// удаляем строки
КонецПроцедуры
Внешне похоже на модальный вызов, но окно немодальное и в веб-клиенте работает. Ждать допустим только внутри процедуры или функции с модификатором Асинх.
Как получить значение из диалога обратно
Результат собственной формы возвращают двумя способами.
Закрыть(Значение) и ОписаниеОповещенияОЗакрытии
В открытой форме по кнопке «ОК» вызывают Закрыть() с параметром:
&НаКлиенте
Процедура ОК(Команда)
Результат = Новый Структура("Процент, ДатаОкончания", Процент, ДатаОкончания);
Закрыть(Результат);
КонецПроцедуры
Эта структура придёт первым параметром в обработчик, указанный в ОткрытьФорму. Если пользователь закрыл окно крестиком, придёт Неопределено — проверяйте это первой строкой обработчика.
ОповеститьОВыборе и ОбработкаВыбора
Второй способ — для форм выбора. Форму открывают с владельцем, а в ней вызывают ОповеститьОВыборе(Значение). Значение попадает в событие ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) формы-владельца. Так работают формы подбора: окно может отправить несколько значений подряд и не закрываться, если у него выключено свойство «Закрывать при выборе».
| Способ | Когда подходит |
|---|---|
Закрыть(Значение) | Диалог настроек, ввод нескольких полей, одно итоговое значение |
ОповеститьОВыборе | Подбор: пользователь выбирает несколько позиций, окно остаётся открытым |
Особенности веб-клиента и тонкого клиента
Немодальные методы работают одинаково в тонком и веб-клиенте. Различия начинаются там, где нужен доступ к файлам компьютера пользователя.
- 🌐 Всплывающие окна браузера. Веб-клиент открывает формы внутри своей страницы, поэтому блокировщик всплывающих окон им не мешает. Но отдельные окна, например при открытии внешней ссылки, браузер может заблокировать.
- 📎 Выбор файла в веб-клиенте.
ДиалогВыбораФайлас полным путём к файлу требует расширения для работы с файлами. Подключают его черезНачатьПодключениеРасширенияРаботыСФайлами, а при отказе предлагают установку. - ⬆️ Без расширения. Если нужно только загрузить файл на сервер, используйте
НачатьПомещениеФайловилиПоместитьФайлАсинх. Браузер покажет свой диалог выбора, файл ляжет во временное хранилище, путь на диске пользователя вы не получите. - 🖥️ Тонкий клиент. Доступ к файловой системе есть сразу, расширение не нужно.
Свойство «Режим использования синхронных вызовов расширений платформы и внешних компонент» работает так же, как режим модальности. При значении «Не использовать» синхронные вызовы работы с файлами и внешними компонентами вызывают исключение, нужны их Начать… или …Асинх версии.