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