В процессе разработки прикладных решений на платформе «1С:Предприятие 8» часто возникает задача пакетного создания документов. Например, когда необходимо сформировать отдельные документы по каждой организации из определенного списка, заполнить их данными на основании запроса, а затем предоставить пользователю возможность визуально оценить результат работы алгоритма.
Давайте подробно разберем, как правильно реализовать эту задачу. Мы рассмотрим как базовое решение, предложенное в ходе обсуждения на форуме, так и профессиональные подходы, учитывающие производительность системы, стандарты разработки фирмы «1С» и удобство конечного пользователя (UX).
Исходная попытка автора темы заключалась в том, чтобы вызывать серверный метод для создания каждого отдельного документа. Это классическая ошибка, которая приводит к избыточному числу клиент-серверных вызовов (так называемый «ping-pong» между клиентом и сервером). Если документов будет много, система начнет заметно зависать.
Правильный архитектурный подход заключается в следующем: мы должны выполнить всю тяжелую работу на сервере за один вызов, собрать результаты в массив и вернуть этот массив на клиент для последующего интерактивного открытия форм.
Рассмотрим базовый пример реализации этого механизма. Создадим на сервере функцию, которая формирует документы и возвращает массив созданных ссылок:
&НаСервере
Функция СоздатьДокументыНаСервере()
МассивСсылок = Новый Массив;
// Получаем список организаций, по которым нужно создать документы
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Организации.Ссылка КАК Организация
|ИЗ
| Справочник.Организации КАК Организации
|ГДЕ
| НЕ Организации.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем новый документ в памяти сервера
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДатаСеанса();
НовыйДокумент.Организация = Выборка.Организация;
// Здесь выполняется логика автоматического заполнения (табличные части, реквизиты)
// ЗаполнитьПараметрыДокумента(НовыйДокумент);
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
// Добавляем успешно записанную ссылку в массив
МассивСсылок.Добавить(НовыйДокумент.Ссылка);
Исключение
ЗаписьЖурналаРегистрации("СозданиеДокументов",
УровеньЖурналаРегистрации.Ошибка,
,
,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЦикла;
Возврат МассивСсылок;
КонецФункции
Теперь на стороне клиента мы принимаем этот массив и открываем форму для каждого созданного документа. Обратите внимание, что вместо устаревшего и нерекомендуемого метода ОткрытьЗначение мы будем использовать современный метод ОткрытьФорму или универсальный метод ПоказатьЗначение.
&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
// Выполняем один серверный вызов для создания всех объектов
СозданныеДокументы = СоздатьДокументыНаСервере();
Если СозданныеДокументы.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Не было создано ни одного документа.");
Возврат;
КонецЕсли;
// Перебираем массив на клиенте и открываем формы документов
Для Каждого СсылкаДок Из СозданныеДокументы Цикл
ПараметрыФормы = Новый Структура("Ключ", СсылкаДок);
ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);
КонецЦикла;
EndПроцедуры
Этот код отлично работает для уже записанных документов. Платформа самостоятельно определяет, что документы сохранены в базе данных, сопоставляет их по ссылке и открывает индивидуальное окно для каждого объекта.
Очень часто бизнес-логика требует, чтобы документы открывались перед пользователем новыми и незаписанными. Это позволяет пользователю проверить данные, внести ручные корректировки и самостоятельно нажать кнопку «Провести и закрыть». Если же документ не подошел, пользователь может просто закрыть его форму без засорения базы данных «мусорными» записями.
При реализации такого сценария мы сталкиваемся с важной особенностью платформы 1С. Если мы просто вызовем метод ОткрытьФорму для нового документа несколько раз подряд, платформа по умолчанию откроет только одно окно. Все последующие вызовы будут лишь активировать эту уже открытую форму. Выясним, почему это происходит и как решить данную проблему.
Для открытия уникальных окон новых документов необходимо использовать специальный параметр — ключ уникальности формы. Давайте разберем по шагам, как это реализовать.
Передадим на клиент структуру данных для заполнения и используем уникальный идентификатор при инициализации каждого нового окна:
&НаКлиенте
Процедура ОткрытьНовыеНезаписанныеДокументы()
// Получаем массив структур с данными для заполнения на сервере
МассивДанныхЗаполнения = ПолучитьДанныеДляНовыхДокументовНаСервере();
Для Каждого ДанныеЗаполнения Из МассивДанныхЗаполнения Цикл
ПараметрыФормы = Новый Структура;
// Передаем параметры заполнения, которые будут обработаны в "ОбработкеЗаполнения" документа
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ДанныеЗаполнения);
// Генерируем уникальный идентификатор для обеспечения открытия новой формы в отдельном окне
КлючУникальности = Новый УникальныйИдентификатор();
ОткрытьФорму(
"Документ.РеализацияТоваровУслуг.ФормаОбъекта",
ПараметрыФормы,
ЭтотОбъект,
КлючУникальности
);
КонецЦикла;
КонецПроцедуры
При таком подходе в самом модуле менеджера или модуле объекта создаваемого документа в предопределенной процедуре ОбработкаЗаполнения необходимо корректно принять переданные значения структуры ДанныеЗаполнения и присвоить их реквизитам объекта.
В коде автора темы фигурирует метод ОткрытьЗначение. Использование этого метода, так же как и модальных окон, крайне не рекомендуется в современных конфигурациях 1С. Это связано с тем, что в веб-клиенте (при работе через браузер) или в мобильном клиенте синхронные вызовы могут блокировать работу интерфейса или вообще не поддерживаться браузерами.
Вместо устаревших конструкций следует применять асинхронный метод ПоказатьЗначение. Давайте посмотрим, как будет выглядеть код с его использованием:
&НаКлиенте
Процедура ПоказатьСозданныеДокументы(МассивСсылок)
Для Каждого СсылкаДокумента Из МассивСсылок Цикл
// Метод выполняется асинхронно и не блокирует поток выполнения программы
ПоказатьЗначение(, СсылкаДокумента);
КонецЦикла;
КонецПроцедуры
Хотя технически открыть 10, 20 или 50 окон одновременно возможно, с точки зрения удобства интерфейса это считается плохой практикой разработки. Рассмотрим основные причины, почему стоит избегать массового открытия документов:
Альтернативное и более элегантное решение:
Вместо автоматического открытия всех форм создайте промежуточное рабочее место (АРМ) или форму-помощник. Выведите список созданных документов во временную таблицу прямо на текущей форме, из которой пользователь сможет сам точечно кликнуть на нужную строку и открыть только те документы, которые действительно требуют его внимания и ручной проверки.
Если алгоритм формирования документов по организациям включает сложные расчеты (например, распределение затрат, расчет себестоимости, анализ остатков), его выполнение на сервере в рамках обычного вызова команды может занять значительное время (более 10–15 секунд). Это приведет к временному «зависанию» интерфейса 1С и может вызвать ошибку превышения времени ожидания сервера.
В профессиональной разработке для этого применяют подсистему «Длительные операции» из Библиотеки Стандартных Подсистем (БСП). Схема работы выглядит следующим образом:
Использование комплексного подхода к проектированию таких задач гарантирует высокую производительность системы, стабильность работы интерфейса и лояльность конечных пользователей программных продуктов на платформе «1С:Предприятие».