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