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