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