В процессе разработки на платформе 1С:Предприятие 8.3 часто возникают задачи "на интерес", которые имеют под собой серьезное практическое обоснование. Одной из таких задач является программная инициация стандартного выбора значения. Представим ситуацию: пользователь нажимает на кнопку или выполняет определенное действие, и система должна открыть то же самое окно выбора, которое открывается при нажатии на кнопку с тремя точками (кнопка выбора) или клавишу F4.
Стандартными средствами встроенного языка метод типа Элементы.ИмяПоля.ВыполнитьВыбор() не предусмотрен. Однако существует несколько эффективных стратегий, которые позволяют добиться нужного результата. Разберем их подробно, двигаясь от простых "хакерских" методов к более архитектурно правильным подходам.
Проанализируем самый быстрый способ — программную эмуляцию действий пользователя. Платформа 1С во многих аспектах опирается на стандартные горячие клавиши операционной системы. Если мы "заставим" систему думать, что пользователь нажал F4, находясь в нужном поле, откроется стандартное окно выбора.
Для реализации этого метода нам понадобится COM-объект WScript.Shell. Рассмотрим пошагово, как это работает:
Посмотрим на пример кода:
&НаКлиенте
Процедура ВызватьВыборПрограммно()
// Устанавливаем фокус на нужный элемент
ЭтаФорма.ТекущийЭлемент = Элементы.ИмяВашегоРеквизита;
// Создаем объект для управления вводом ОС
Попытка
ОбъектWshShell = Новый COMОбъект("WScript.Shell");
// Отправляем нажатие клавиши F4
ОбъектWshShell.SendKeys("{F4}");
Исключение
Сообщить("Метод SendKeys не поддерживается в данной среде.");
КонецПопытки;
КонецПроцедуры
Важное ограничение: данный метод будет работать исключительно в тонком и толстом клиенте под управлением ОС Windows. Если ваш пользователь работает через веб-клиент (в браузере) или на Linux, этот код не сработает.
Разберем ситуацию, когда предыдущий метод не срабатывает из-за того, что платформа не успевает мгновенно переключить фокус на элемент до того, как будет отправлена команда нажатия клавиши. Выясним причину: установка ТекущийЭлемент в коде — это асинхронное пожелание платформе, а выполнение SendKeys происходит немедленно в операционной системе.
Чтобы гарантировать успех, применим "хитрость" с небольшим ожиданием:
&НаКлиенте
Процедура ЗапуститьВыборСЗадержкой()
// Сначала фокусируемся
ЭтаФорма.ТекущийЭлемент = Элементы.НужнаяКолонкаТаблицы;
// Подключаем обработчик, который сработает через 0.1 секунды
ПодключитьОбработчикОжидания("ВыполнитьНажатиеF4", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьНажатиеF4()
ОбъектWshShell = Новый COMОбъект("WScript.Shell");
ОбъектWshShell.SendKeys("{F4}");
КонецПроцедуры
Этот подход особенно полезен при работе с табличными частями, когда фокус нужно установить не только на колонку, но и на конкретную строку через Элементы.ИмяТаблицы.ТекущаяСтрока.
Теперь рассмотрим наиболее корректный с точки зрения архитектуры 1С способ. Если мы не хотим эмулировать клавиатуру, мы можем программно вызвать форму выбора, используя метод ОткрытьФорму. Основной секрет здесь заключается в параметре Владелец.
Если в качестве владельца формы выбора передать не саму ЭтаФорма, а конкретный элемент управления (поле ввода), то платформа автоматически сделает следующее:
ПриИзменении, ОбработкаВыбора).Проанализируем пример реализации:
&НаКлиенте
Процедура ОткрытьВыборПравильно()
// Определяем элемент-владелец
ЭлементВладелец = Элементы.Склад;
// Формируем параметры (если нужны фильтры)
ПараметрыВыбора = Новый Структура;
ПараметрыВыбора.Вставить("ЗакрыватьПриВыборе", Истина);
// Вызываем форму выбора, указывая владельцем сам ЭЛЕМЕНТ формы
ОткрытьФорму("Справочник.Склады.ФормаВыбора", ПараметрыВыбора, ЭлементВладелец);
КонецПроцедуры
Этот метод избавляет нас от ручного разбора типов данных, описанного в некоторых сообщениях на форумах, и корректно работает во всех типах клиентов (включая веб-клиент).
Если задача стоит в вызове выбора для ячейки в таблице, нужно учитывать, что элемент формы для всей колонки один, а данных в строках много. Чтобы платформа поняла, куда именно нужно вернуть значение, перед вызовом выбора убедитесь, что:
ТекущаяСтрока для таблицы.Владелец в ОткрытьФорму указывает на поле в этой колонке.Разберем пример для таблицы товаров:
&НаКлиенте
Процедура ВыборВТаблице()
// Убедимся, что строка выбрана
Если Элементы.Товары.ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Вызываем стандартную форму для поля Номенклатура в таблице
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , Элементы.ТоварыНоменклатура);
КонецПроцедуры
Мы рассмотрели различные варианты решения задачи. Использование SendKeys удобно для быстрой реализации "как есть", но привязывает решение к Windows. Программное открытие формы с указанием элемента-владельца является универсальным и надежным способом, который полностью имитирует поведение платформы, сохраняя все стандартные обработчики и проверки данных.
Выбор конкретного метода зависит от ваших требований к кроссплатформенности и необходимости жестко контролировать процесс выбора (например, накладывать сложные динамические фильтры перед открытием окна).