Как правильно передать данные в форму и заполнить ее реквизиты перед открытием?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача: при открытии одной формы из другой необходимо передать в нее определенные данные (например, ссылку на документ, структуру настроек или таблицу). Одной из классических ошибок начинающих разработчиков является попытка сначала получить форму, затем программно заполнить ее реквизиты и только после этого вызвать метод Открыть. Рассмотрим подробнее, почему такой подход приводит к ошибкам и как сделать это правильно в соответствии со стандартами разработки.

Анализ проблемы: почему возникает ошибка «Элемент не выбран»

Разберем ситуацию на примере кода, который часто вызывает затруднения. Предположим, разработчик пишет следующий фрагмент в модуле основной формы:


Форма = ПолучитьФорму("Обработка.РабочийСтолПреподавателя.Форма.Анкета");
Форма.Источник = Док.Ссылка;
Форма.Открыть();

В вызываемой форме в обработчике ПриСозданииНаСервере прописано получение данных из этого реквизита:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЭтаФорма.Элементы.Название.Заголовок = ЭтаФорма.Источник.ПолучитьОбъект().Наименование;
КонецПроцедуры

При выполнении этого кода система выдает ошибку: «Ошибка при вызове метода контекста (ПолучитьОбъект). Элемент не выбран!». Выясним причину такого поведения. Все дело в жизненном цикле формы и порядке вызова событий. Когда исполняется метод ПолучитьФорму, платформа немедленно инициирует создание формы на сервере. Это означает, что процедура ПриСозданииНаСервере выполняется внутри вызова ПолучитьФорму.

Следовательно, на тот момент, когда код в ПриСозданииНаСервере пытается обратиться к реквизиту Источник, управление еще не вернулось в вызывающий код, и строка Форма.Источник = Док.Ссылка; еще не выполнилась. Реквизит пуст, и попытка вызвать ПолучитьОбъект() от пустой ссылки приводит к логичной ошибке.

Решение №1: Использование параметров формы (рекомендуемый способ)

Проанализируем наиболее правильный подход — использование структуры параметров. В платформе 1С реализован механизм автоматической инициализации: если имя ключа в структуре параметров совпадает с именем реквизита формы, значение будет присвоено реквизиту автоматически до начала выполнения ПриСозданииНаСервере.

Рассмотрим, как изменить вызывающий код (используем более современный метод ОткрытьФорму):


ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("Источник", Док.Ссылка);
// Если нужно передать дополнительные данные, добавляем их в структуру
ПараметрыОткрытия.Вставить("ЗаголовокОкна", "Анкета слушателя");

ОткрытьФорму("Обработка.РабочийСтолПреподавателя.Форма.Анкета", ПараметрыОткрытия);

В модуле открываемой формы теперь мы можем безопасно обращаться к этим данным через коллекцию Параметры:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли параметр
    Если Параметры.Свойство("Источник") И ЗначениеЗаполнено(Параметры.Источник) Тогда
        // Реквизит формы "Источник" уже будет заполнен платформой автоматически,
        // если его имя совпадает с ключом в структуре параметров.
        // Но для надежности можно обратиться напрямую к параметрам.
        
        ЗаголовокФормы = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Параметры.Источник, "Наименование");
        Элементы.Название.Заголовок = ЗаголовокФормы;
    КонецЕсли;

КонецПроцедуры

Решение №2: Оптимизация получения данных

Посмотрим на код из примера автора: использование ПолучитьОбъект() только для того, чтобы узнать наименование документа, является крайне неэффективным. Метод ПолучитьОбъект() считывает из базы данных абсолютно все поля объекта, включая все табличные части, что создает избыточную нагрузку на сервер и сеть.

Проанализируем лучшие практики:

  1. Использование функций общего модуля: Если вы работаете в типовой конфигурации (например, БП, УТ или ERP), используйте функцию ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "ИмяРеквизита").
  2. Легкий запрос: Если конфигурация самописная, напишите небольшой запрос, который выберет только нужные поля по ссылке.
  3. Передача готового значения: Еще более эффективно подготовить заголовок или другие строковые данные в вызывающей форме и передать их уже готовыми через те же параметры. Это избавит открываемую форму от лишнего обращения к базе данных.

Решение №3: Передача сложных данных через временное хранилище

Иногда требуется передать не просто ссылку, а, например, таблицу значений, сформированную «на лету». Такие данные нельзя передать напрямую через параметры, если они не являются примитивными типами. В этом случае мы воспользуемся механизмом временного хранилища.

Разберем алгоритм по шагам:

  1. В вызывающей форме помещаем данные в хранилище и получаем уникальный адрес (строку).
  2. Передаем этот адрес как параметр при открытии новой формы.
  3. В новой форме в событии ПриСозданииНаСервере извлекаем данные по адресу.

Пример кода вызывающей формы:


АдресДанных = ПоместитьВоВременноеХранилище(МояТаблицаЗначений, ЭтаФорма.УникальныйИдентификатор);

ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("АдресТаблицы", АдресДанных);

ОткрытьФорму("Обработка.МояОбработка.Форма.Результат", ПараметрыФормы);

Пример кода открываемой формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("АдресТаблицы") Тогда
        ТаблицаИзХранилища = ПолучитьИзВременногоХранилища(Параметры.АдресТаблицы);
        // Заполняем реквизит формы типа "ДанныеФормыКоллекция"
        ЗначениеВРеквизитФормы(ТаблицаИзХранилища, "РезультатПоиска");
    КонецЕсли;
КонецПроцедуры

Важные замечания по стилю кода

В процессе решения задачи важно помнить о стандартах разработки 1С. В сообщениях форума упоминается важное правило: не рекомендуется использовать ключевое слово ЭтаФорма в модуле управляемой формы без явной необходимости. Платформа и так понимает контекст формы, поэтому вместо ЭтаФорма.Элементы лучше писать просто Элементы.

Также стоит различать методы ОткрытьФорму и ПолучитьФорму. Метод ОткрытьФорму является более универсальным и предпочтительным, так как он минимизирует количество серверных вызовов. Используйте ПолучитьФорму только в тех редких случаях, когда вам действительно нужно выполнить сложную программную донастройку объекта формы на клиенте до ее фактического вывода на экран (хотя в 99% случаев это можно решить через параметры и логику ПриСозданииНаСервере).

Подведем итог: Чтобы избежать ошибки «Элемент не выбран», никогда не полагайтесь на ручное присвоение реквизитов после ПолучитьФорму. Используйте структуру параметров — это надежно, быстро и соответствует стандартам «1С:Предприятие 8».

← На главную