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