Как обработать выделенные строки в таблице значений после асинхронного вызова вопроса в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В современных версиях платформы 1С:Предприятие 8.3 работа с диалоговыми окнами, такими как вопросы пользователю, стала асинхронной. Это означает, что программа не останавливает выполнение кода в ожидании ответа пользователя, а продолжает работу. Для обработки выбора пользователя используется специальный механизм оповещений. Рассмотрим подробнее, как правильно передать массив выделенных строк из таблицы в процедуру-обработчик и избежать типичных ошибок.

Проблема передачи контекста между процедурами

Когда мы вызываем метод ПоказатьВопрос, выполнение текущей процедуры завершается. Ответ пользователя будет обработан в отдельной экспортной процедуре, которую мы указываем в объекте ОписаниеОповещения. Основная сложность заключается в том, что в эту новую процедуру нужно как-то передать данные о том, какие именно строки были выделены в момент нажатия кнопки. Разберем по шагам, как это реализовать.

Проанализируем типичную ситуацию: пользователь выделил несколько строк в динамическом списке или таблице значений на форме и нажал кнопку "Удалить". Нам нужно спросить подтверждение, и если пользователь ответит "Да", выполнить действие именно с этими строками.

Использование дополнительных параметров в Описании Оповещения

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

Рассмотрим пример кода, где мы собираем выделенные строки и передаем их в обработчик:


&НаКлиенте
Процедура ПроцессУбить(Команда)
    
    // Получаем массив идентификаторов выделенных строк
    МассивСтрок = Элементы.ТабДиспетчерЗадач.ВыделенныеСтроки;
    
    Если МассивСтрок.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Не выбрано ни одной строки!");
        Возврат;
    КонецЕсли;

    // Формируем структуру с дополнительными параметрами
    ДопПараметры = Новый Структура;
    ДопПараметры.Вставить("МассивИдентификаторов", МассивСтрок);
    
    ТекстВопроса = СтрШаблон("Вы уверены, что хотите обработать %1 строк?", МассивСтрок.Количество());
    
    // Создаем оповещение, передавая в него наши параметры
    Оповещение = Новый ОписаниеОповещения("ПослеВопросаОбУдалении", ЭтотОбъект, ДопПараметры);
    
    ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    
КонецПроцедуры

В данном примере мы упаковали массив выделенных строк в структуру ДопПараметры. Теперь выясним, как принять эти данные в процедуре обработки.

Обработка результата в процедуре оповещения

Процедура, указанная в оповещении, должна иметь определенную сигнатуру. Вторым параметром в нее придут те самые ДополнительныеПараметры, которые мы создали ранее.


&НаКлиенте
Процедура ПослеВопросаОбУдалении(РезультатВопроса, ДополнительныеПараметры) Экспорт
    
    Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
        
        // Извлекаем переданный массив из структуры
        МассивИдентификаторов = ДополнительныеПараметры.МассивИдентификаторов;
        
        // Выполняем действия со строками
        Для Каждого Идентификатор Из МассивИдентификаторов Цикл
            // ВАЖНО: Работаем через поиск по идентификатору
            СтрокаТаблицы = ТабДиспетчерЗадач.НайтиПоИдентификатору(Идентификатор);
            
            Если СтрокаТаблицы <> Неопределено Тогда
                Сообщить("Обработка строки: " + СтрокаТаблицы.СтрИмя);
                // Здесь логика удаления или изменения
            КонецЕсли;
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры

Критическая ошибка: Индекс vs Идентификатор

Разберем важный технический нюанс, на котором часто ошибаются начинающие разработчики. Свойство ВыделенныеСтроки элемента формы (таблицы) содержит массив идентификаторов строк, а не их индексов в коллекции.

Почему это важно:

  1. Индекс — это порядковый номер строки в массиве (0, 1, 2...). При удалении строк индексы остальных строк меняются.
  2. Идентификатор — это уникальный номер строки в рамках текущего сеанса работы формы. Он остается неизменным, даже если строки выше были удалены или отсортированы.

Поэтому в коде выше мы используем метод НайтиПоИдентификатору(). Попытка обратиться к таблице по индексу, используя идентификатор (например, ТабДиспетчерЗадач[Идентификатор]), приведет к ошибке выполнения или обращению не к той строке.

Оптимизация: Вопрос в цикле или один на всех?

Проанализируем ситуацию, когда разработчик хочет задавать вопрос по каждой строке отдельно. Реализовать это через простой цикл Для Каждого внутри клиентской процедуры невозможно, так как ПоказатьВопрос не останавливает цикл, и пользователь увидит сразу стек из нескольких окон (или получит ошибку).

Существует два правильных подхода:

  1. Групповой вопрос: Спросить один раз ("Выполнить действие для 5 строк?"), как показано в примере выше. Это лучший вариант с точки зрения UX (удобства пользователя).
  2. Рекурсивный вызов: Создать процедуру, которая берет первую строку, задает вопрос, а в обработчике ответа вызывает саму себя для следующей строки, пока массив не станет пустым.

Современный подход: Async/Await (1С 8.3.18+)

Если ваша платформа версии 8.3.18 и выше, мы можем использовать асинхронные функции. Это позволяет писать код "линейно", не разрывая его на разные процедуры. Выясним, как это выглядит:


&НаКлиенте
Асинхрон Процедура ПроцессУбитьАсинхрон(Команда)
    
    МассивСтрок = Элементы.ТабДиспетчерЗадач.ВыделенныеСтроки;
    
    // Вместо ПоказатьВопрос используем ВопросАсинх
    Результат = Ждать ВопросАсинх("Выполнить обработку?", РежимДиалогаВопрос.ДаНет);
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        Для Каждого Идентификатор Из МассивСтрок Цикл
            // Весь контекст процедуры нам доступен здесь напрямую
            Стр = ТабДиспетчерЗадач.НайтиПоИдентификатору(Идентификатор);
            // Обработка...
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Использование ключевых слов Асинхрон и Ждать значительно упрощает разработку, так как отпадает необходимость в создании ОписанияОповещения и передаче ДополнительныхПараметров вручную. Весь контекст (переменные процедуры) сохраняется автоматически.

Проблема «протухания» данных

Важно помнить о безопасности данных. Между моментом появления вопроса на экране и моментом, когда пользователь нажмет кнопку, может пройти много времени. За эти минуты другой пользователь может удалить эти же строки в базе данных.

Рекомендация: Внутри процедуры-обработчика (или после оператора Ждать) всегда делайте дополнительную проверку на существование данных на сервере перед их изменением или удалением.

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

← На главную