При программном создании нескольких документов из одной формы часто возникает конфликт блокировок. Платформа 1С воспринимает попытку открыть второй документ как редактирование того же самого объекта, так как при копировании данных формы в новую форму нередко переносятся внутренние идентификаторы и ссылки, которые уже заняты первым документом. Давайте разберем, как правильно реализовать этот процесс, чтобы избежать системных ошибок.
Основная причина кроется в механизме ДанныеФормы. Когда мы используем КопироватьДанныеФормы, мы копируем не только значения реквизитов, но и метаданные объекта. Если в составе этих данных остается «пустая» ссылка или идентификатор, который система уже ассоциирует с первой открытой формой, возникает конфликт. Платформа защищает данные от потери при параллельной записи, блокируя второй экземпляр формы.
Наиболее чистый и правильный способ передачи данных в новую форму — это использование параметра ЗначенияЗаполнения. Этот подход позволяет не вмешиваться в типовые модули объектов, а передавать данные «на лету» при открытии.
Рассмотрим, как это реализовать:
// В коде инициализации создания документа
ДанныеЗаполнения = Новый Структура("Реквизит1, Товары", Объект.Реквизит1, Объект.Товары.Выгрузить());
ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ДанныеЗаполнения);
ОткрытьФорму("Документ.ПеремещениеТоваров.ФормаОбъекта", ПараметрыФормы, ЭтаФорма, Истина);
Важным моментом здесь является четвертый параметр метода ОткрытьФорму — Уникальность. Установив его в значение Истина, мы гарантируем, что для новой формы будет создан отдельный контекст, который не будет конфликтовать с текущим документом.
Если документ содержит большую табличную часть, передача данных через структуру может быть ресурсозатратной. В таких случаях лучше использовать механизм ПоместитьВоВременноеХранилище. Это стандартный подход для 1С, который позволяет безопасно передать данные на сервер.
ПриСозданииНаСервере новой формы считываем данные по адресу.Этот метод исключает прямую зависимость форм друг от друга и позволяет платформе корректно обработать создание двух независимых новых объектов.
Если вы хотите сохранить текущую логику открытия формы, но избежать ошибки, попробуйте ограничить область копирования. Не копируйте объект целиком, если в этом нет необходимости. Вы можете вручную присвоить только нужные реквизиты, минуя системные поля.
Посмотрим на пример ручного заполнения свойств:
ФормаНовая = ПолучитьФорму("Документ.ПеремещениеТоваров.ФормаОбъекта",,, Истина);
НовыйОбъект = ФормаНовая.Объект;
ЗаполнитьЗначенияСвойств(НовыйОбъект, Объект, , "Ссылка, Номер, Проведен, Дата, Товары");
// Теперь заполняем табличные части отдельно, если это требуется
КопироватьДанныеФормы(Объект.Товары, НовыйОбъект.Товары);
ФормаНовая.Открыть();
Важное примечание: При использовании ЗаполнитьЗначенияСвойств обязательно указывайте список имен реквизитов, которые не нужно заполнять (например, Ссылка). Это предотвратит перенос идентификатора уже созданного документа в новый.
Чтобы успешно открывать два новых документа и не получать ошибку блокировки, следуйте этим рекомендациям:
Уникальность (четвертый аргумент в ОткрытьФорму или ПолучитьФорму), установив его в Истина.ДанныеФормы целиком, если это приводит к переносу нежелательных метаданных.ЗаполнитьЗначенияСвойств с исключением системных полей, если вам нужно перенести только часть информации из одного документа в другой.ПоместитьВоВременноеХранилище, чтобы передача данных происходила на уровне сервера, а не клиента.Эти методы помогут вам реализовать механизм разбиения документов, не затрагивая типовой код конфигурации, что значительно упростит дальнейшие обновления системы.