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