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

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

В процессе разработки прикладных решений на платформе «1С:Предприятие 8» часто возникает задача пакетного создания документов. Например, когда необходимо сформировать отдельные документы по каждой организации из определенного списка, заполнить их данными на основании запроса, а затем предоставить пользователю возможность визуально оценить результат работы алгоритма.

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

Анализ проблемы и базовое решение

Исходная попытка автора темы заключалась в том, чтобы вызывать серверный метод для создания каждого отдельного документа. Это классическая ошибка, которая приводит к избыточному числу клиент-серверных вызовов (так называемый «ping-pong» между клиентом и сервером). Если документов будет много, система начнет заметно зависать.

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

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


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

КонецФункции

Теперь на стороне клиента мы принимаем этот массив и открываем форму для каждого созданного документа. Обратите внимание, что вместо устаревшего и нерекомендуемого метода ОткрытьЗначение мы будем использовать современный метод ОткрытьФорму или универсальный метод ПоказатьЗначение.


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

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


Продвинутый уровень: Открытие новых (незаписанных) документов

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

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

Для открытия уникальных окон новых документов необходимо использовать специальный параметр — ключ уникальности формы. Давайте разберем по шагам, как это реализовать.

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


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

При таком подходе в самом модуле менеджера или модуле объекта создаваемого документа в предопределенной процедуре ОбработкаЗаполнения необходимо корректно принять переданные значения структуры ДанныеЗаполнения и присвоить их реквизитам объекта.


Отказ от устаревших синхронных вызовов

В коде автора темы фигурирует метод ОткрытьЗначение. Использование этого метода, так же как и модальных окон, крайне не рекомендуется в современных конфигурациях 1С. Это связано с тем, что в веб-клиенте (при работе через браузер) или в мобильном клиенте синхронные вызовы могут блокировать работу интерфейса или вообще не поддерживаться браузерами.

Вместо устаревших конструкций следует применять асинхронный метод ПоказатьЗначение. Давайте посмотрим, как будет выглядеть код с его использованием:


&НаКлиенте
Процедура ПоказатьСозданныеДокументы(МассивСсылок)
    
    Для Каждого СсылкаДокумента Из МассивСсылок Цикл
        // Метод выполняется асинхронно и не блокирует поток выполнения программы
        ПоказатьЗначение(, СсылкаДокумента);
    КонецЦикла;
    
КонецПроцедуры

Проблемы юзабилити (UX) и производительности при массовом открытии окон

Хотя технически открыть 10, 20 или 50 окон одновременно возможно, с точки зрения удобства интерфейса это считается плохой практикой разработки. Рассмотрим основные причины, почему стоит избегать массового открытия документов:

  1. Засорение экрана: Экран пользователя моментально заполняется вкладками. Разобраться в них становится невозможно, пользователю приходится вручную закрывать десятки окон, что вызывает раздражение.
  2. Высокая нагрузка на клиентскую машину: Каждое открытие формы инициализирует клиентские скрипты, требует отрисовки графических элементов и компоновки интерфейса. При открытии более 10 форм система может кратковременно зависнуть.

Альтернативное и более элегантное решение:

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


Применение механизмов БСП для длительных операций

Если алгоритм формирования документов по организациям включает сложные расчеты (например, распределение затрат, расчет себестоимости, анализ остатков), его выполнение на сервере в рамках обычного вызова команды может занять значительное время (более 10–15 секунд). Это приведет к временному «зависанию» интерфейса 1С и может вызвать ошибку превышения времени ожидания сервера.

В профессиональной разработке для этого применяют подсистему «Длительные операции» из Библиотеки Стандартных Подсистем (БСП). Схема работы выглядит следующим образом:

  1. Клиентская кнопка инициирует запуск фонового задания на сервере через БСП.
  2. Пользователю показывается симпатичное окно ожидания с индикатором хода выполнения.
  3. Фоновое задание на сервере выполняет расчеты, записывает документы, а результат (массив ссылок) сохраняет во временное хранилище.
  4. После завершения фонового задания клиентское приложение забирает массив ссылок из хранилища и выводит отчет о проделанной работе или открывает формы документов по желанию пользователя.

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

← На главную