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