В современных версиях платформы 1С:Предприятие 8.3 работа с диалоговыми окнами, такими как вопросы пользователю, стала асинхронной. Это означает, что программа не останавливает выполнение кода в ожидании ответа пользователя, а продолжает работу. Для обработки выбора пользователя используется специальный механизм оповещений. Рассмотрим подробнее, как правильно передать массив выделенных строк из таблицы в процедуру-обработчик и избежать типичных ошибок.
Когда мы вызываем метод ПоказатьВопрос, выполнение текущей процедуры завершается. Ответ пользователя будет обработан в отдельной экспортной процедуре, которую мы указываем в объекте ОписаниеОповещения. Основная сложность заключается в том, что в эту новую процедуру нужно как-то передать данные о том, какие именно строки были выделены в момент нажатия кнопки. Разберем по шагам, как это реализовать.
Проанализируем типичную ситуацию: пользователь выделил несколько строк в динамическом списке или таблице значений на форме и нажал кнопку "Удалить". Нам нужно спросить подтверждение, и если пользователь ответит "Да", выполнить действие именно с этими строками.
Самый эффективный способ передать данные — использовать третий параметр конструктора ОписаниеОповещения. Этот параметр называется ДополнительныеПараметры. Туда можно поместить любую структуру, массив или значение, которое будет доступно в процедуре обработки ответа.
Рассмотрим пример кода, где мы собираем выделенные строки и передаем их в обработчик:
&НаКлиенте
Процедура ПроцессУбить(Команда)
// Получаем массив идентификаторов выделенных строк
МассивСтрок = Элементы.ТабДиспетчерЗадач.ВыделенныеСтроки;
Если МассивСтрок.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Не выбрано ни одной строки!");
Возврат;
КонецЕсли;
// Формируем структуру с дополнительными параметрами
ДопПараметры = Новый Структура;
ДопПараметры.Вставить("МассивИдентификаторов", МассивСтрок);
ТекстВопроса = СтрШаблон("Вы уверены, что хотите обработать %1 строк?", МассивСтрок.Количество());
// Создаем оповещение, передавая в него наши параметры
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОбУдалении", ЭтотОбъект, ДопПараметры);
ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
В данном примере мы упаковали массив выделенных строк в структуру ДопПараметры. Теперь выясним, как принять эти данные в процедуре обработки.
Процедура, указанная в оповещении, должна иметь определенную сигнатуру. Вторым параметром в нее придут те самые ДополнительныеПараметры, которые мы создали ранее.
&НаКлиенте
Процедура ПослеВопросаОбУдалении(РезультатВопроса, ДополнительныеПараметры) Экспорт
Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
// Извлекаем переданный массив из структуры
МассивИдентификаторов = ДополнительныеПараметры.МассивИдентификаторов;
// Выполняем действия со строками
Для Каждого Идентификатор Из МассивИдентификаторов Цикл
// ВАЖНО: Работаем через поиск по идентификатору
СтрокаТаблицы = ТабДиспетчерЗадач.НайтиПоИдентификатору(Идентификатор);
Если СтрокаТаблицы <> Неопределено Тогда
Сообщить("Обработка строки: " + СтрокаТаблицы.СтрИмя);
// Здесь логика удаления или изменения
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Разберем важный технический нюанс, на котором часто ошибаются начинающие разработчики. Свойство ВыделенныеСтроки элемента формы (таблицы) содержит массив идентификаторов строк, а не их индексов в коллекции.
Почему это важно:
Поэтому в коде выше мы используем метод НайтиПоИдентификатору(). Попытка обратиться к таблице по индексу, используя идентификатор (например, ТабДиспетчерЗадач[Идентификатор]), приведет к ошибке выполнения или обращению не к той строке.
Проанализируем ситуацию, когда разработчик хочет задавать вопрос по каждой строке отдельно. Реализовать это через простой цикл Для Каждого внутри клиентской процедуры невозможно, так как ПоказатьВопрос не останавливает цикл, и пользователь увидит сразу стек из нескольких окон (или получит ошибку).
Существует два правильных подхода:
Если ваша платформа версии 8.3.18 и выше, мы можем использовать асинхронные функции. Это позволяет писать код "линейно", не разрывая его на разные процедуры. Выясним, как это выглядит:
&НаКлиенте
Асинхрон Процедура ПроцессУбитьАсинхрон(Команда)
МассивСтрок = Элементы.ТабДиспетчерЗадач.ВыделенныеСтроки;
// Вместо ПоказатьВопрос используем ВопросАсинх
Результат = Ждать ВопросАсинх("Выполнить обработку?", РежимДиалогаВопрос.ДаНет);
Если Результат = КодВозвратаДиалога.Да Тогда
Для Каждого Идентификатор Из МассивСтрок Цикл
// Весь контекст процедуры нам доступен здесь напрямую
Стр = ТабДиспетчерЗадач.НайтиПоИдентификатору(Идентификатор);
// Обработка...
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Использование ключевых слов Асинхрон и Ждать значительно упрощает разработку, так как отпадает необходимость в создании ОписанияОповещения и передаче ДополнительныхПараметров вручную. Весь контекст (переменные процедуры) сохраняется автоматически.
Важно помнить о безопасности данных. Между моментом появления вопроса на экране и моментом, когда пользователь нажмет кнопку, может пройти много времени. За эти минуты другой пользователь может удалить эти же строки в базе данных.
Рекомендация: Внутри процедуры-обработчика (или после оператора Ждать) всегда делайте дополнительную проверку на существование данных на сервере перед их изменением или удалением.
Подведем итог: для обработки выделенных строк в асинхронном режиме необходимо передавать массив идентификаторов через структуру дополнительных параметров оповещения, использовать поиск строк по идентификатору и стремиться к групповой обработке данных вместо бесконечных диалоговых окон для каждой строки.