Как реализовать поочередное открытие документов в 1С на обычных формах?

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

При разработке в среде 1С:Предприятие 8.3 на обычных (неуправляемых) формах программисты часто сталкиваются с задачей организовать последовательную работу пользователя с выборкой документов. Типичный сценарий: пользователю нужно проверить или дозаполнить список документов, при этом система должна открывать следующий документ только после того, как будет закрыт предыдущий. Попытки перенести механизмы из управляемого приложения, такие как ОписаниеОповещения, в старый интерфейс заканчиваются неудачей. Разберем, почему это происходит и как правильно решить задачу в «толстом» клиенте.

Проблема: Смешение контекстов управляемых и обычных форм

Рассмотрим типичную ошибку начинающего разработчика. В управляемых формах для реализации асинхронности используется объект ОписаниеОповещения. Однако в обычном приложении этот механизм не работает так, как ожидается. Директивы компиляции &НаКлиенте и &НаСервере в модулях обычных форм игнорируются, так как весь код по умолчанию выполняется на клиенте в контексте толстого клиента. Процедура-обратный вызов (callback) попросту не срабатывает, потому что метод ОткрытьФорму в обычном приложении не поддерживает параметр описания оповещения для немодальных окон в том виде, в котором это реализовано в такси-интерфейсе.

Проанализируем ситуацию: если мы просто запустим цикл по массиву ссылок и будем вызывать ОткрытьФорму(), система мгновенно создаст десятки окон, которые перекроют друг друга, что сделает работу пользователя невозможной. Нам же требуется дождаться закрытия конкретного окна.

Решение 1: Использование модального открытия (Классический подход)

Самый простой и надежный способ для обычных форм — это использование метода ОткрытьМодально(). В отличие от управляемого приложения, где модальность считается «злом» и зачастую запрещена в настройках конфигурации, в обычном приложении это стандартный инструмент. Метод ОткрытьМодально() полностью останавливает выполнение программного кода в точке вызова до тех пор, пока пользователь не закроет открытую форму.

Разберем по шагам, как реализовать этот алгоритм:

  1. Формируем массив или список значений с нужными ссылками на документы.
  2. Запускаем цикл Для Каждого по этому массиву.
  3. Внутри цикла получаем форму документа через метод ПолучитьФорму().
  4. Вызываем метод ОткрытьМодально() для полученной формы.

Пример программного кода для реализации этого метода:


Процедура ОткрытьДокументыПоОчереди(МассивСсылок)
    
    Для Каждого ДокСсылка Из МассивСсылок Цикл
        
        // Получаем основную форму объекта
        ФормаДокумента = ДокСсылка.ПолучитьФорму();
        
        Если ФормаДокумента <> Неопределено Тогда
            // Программа остановится на этой строке, пока форма не закроется
            ФормаДокумента.ОткрытьМодально();
        КонецЕсли;
        
    КонецЦикла;
    
    Предупреждение("Обработка всех документов завершена!");
    
КонецПроцедуры

Важный нюанс: при модальном открытии весь интерфейс 1С блокируется. Пользователь не сможет переключиться на другое окно внутри программы (например, чтобы посмотреть отчет или справочник), пока не закроет текущий документ. Если такая блокировка критична, следует рассмотреть второй вариант.

Решение 2: Использование обработчика ожидания (Неблокирующий подход)

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

Для реализации нам понадобятся переменные в модуле формы, которые будут сохранять состояние между вызовами обработчика. Выясним, как это работает на практике:


Перем мМассивСсылок;
Перем мТекущаяФорма;

Процедура СтартОчереди()
    // Инициализируем массив ссылок (например, результатом запроса)
    мМассивСсылок = ПолучитьМассивСсылокНаСервере(); 
    
    // Запускаем процесс
    ОткрытьСледующийДокументИзСписка();
    
    // Подключаем проверку каждые 2 секунды
    ПодключитьОбработчикОжидания("ПроверитьСостояниеФормы", 2);
КонецПроцедуры

Процедура ПроверитьСостояниеФормы()
    // Если форма еще открыта, ничего не делаем
    Если мТекущаяФорма <> Неопределено и мТекущаяФорма.Открыта() Тогда
        Возврат;
    КонецЕсли;
    
    // Если мы здесь, значит форма закрыта или еще не открывалась
    ОткрытьСледующийДокументИзСписка();
КонецПроцедуры

Процедура ОткрытьСледующийДокументИзСписка()
    Если мМассивСсылок.Количество() = 0 Тогда
        ОтключитьОбработчикОжидания("ПроверитьСостояниеФормы");
        Предупреждение("Все документы обработаны.");
        Возврат;
    КонецЕсли;
    
    // Берем первый элемент и удаляем его из очереди
    СсылкаНаДок = мМассивСсылок[0];
    мМассивСсылок.Удалить(0);
    
    мТекущаяФорма = СсылкаНаДок.ПолучитьФорму();
    Если мТекущаяФорма <> Неопределено Тогда
        мТекущаяФорма.Открыть();
    Иначе
        // Если форму получить не удалось, пробуем следующий
        ОткрытьСледующийДокументИзСписка();
    КонецЕсли;
КонецПроцедуры

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

Решение 3: Событийный метод через Оповестить()

Существует еще более элегантный способ, который требует минимального вмешательства в открываемый документ (или использования внешней формы). Мы можем передать в открываемую форму владельца, а в процедуре ПриЗакрытии формы документа вызывать Оповестить().

Проанализируем алгоритм:

  1. В основной форме (обработке) подписываемся на событие ОбработкаОповещения.
  2. При открытии формы документа устанавливаем владельцем нашу форму.
  3. В обработке оповещения проверяем имя события (например, "ДокументЗакрыт") и запускаем открытие следующего элемента.

Такой подход минимизирует нагрузку на систему, так как нам не нужно постоянно запускать проверку по таймеру через ПодключитьОбработчикОжидания.

Рекомендации по реализации

При работе с большим количеством документов (более 50-100 штук) помните о потреблении ресурсов. В обычном приложении длительные циклы с объектами могут приводить к накоплению данных в оперативной памяти. Поэтому, если вы используете модальный режим, старайтесь после закрытия формы явно очищать переменные или использовать ЗавершитьРаботуСистемы(Ложь) в крайне редких случаях для очистки кэша, хотя для обычной поочередной работы достаточно простого цикла.

Резюме: Если вам нужна жесткая последовательность и не пугает блокировка интерфейса — используйте ОткрытьМодально(). Если важна многозадачность пользователя — используйте ПодключитьОбработчикОжидания с проверкой метода Открыта(). Забудьте про ОписаниеОповещения в обычных формах, этот инструмент предназначен для других задач в управляемом интерфейсе.

← На главную