Почему при открытии формы в ОбработкеЗаполнения значение параметра ДанныеЗаполнения становится Неопределено?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача создания нового объекта на основании существующих данных. Мы используем метод ОткрытьФорму, передаем структуру параметров, но внезапно сталкиваемся с тем, что в модуле объекта процедура ОбработкаЗаполнения получает Неопределено вместо ожидаемой ссылки или структуры. Разберем подробно, как работает этот механизм, и выясним, в чем заключаются неочевидные правила платформы.

Механика взаимодействия формы и модуля объекта

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

  1. Вызов ОткрытьФорму на клиенте с передачей параметров.
  2. Инициализация нового экземпляра объекта на сервере.
  3. Вызов события ОбработкаЗаполнения в модуле объекта.
  4. Создание самой формы.
  5. Вызов события ПриСозданииНаСервере в модуле формы.

Ключевой момент здесь заключается в том, что процедура ОбработкаЗаполнения "не видит" все параметры, которые вы передали в ОткрытьФорму. Она получает только те данные, которые платформа посчитала системно значимыми для заполнения. Проанализируем, какие именно ключи в структуре параметров являются "магическими" для 1С.

Различия между параметрами Основание и ЗначенияЗаполнения

Платформа жестко регламентирует использование определенных ключей в структуре параметров. Если мы назовем параметр произвольно, например "ЯЛюблю1С", он будет доступен в форме (через Параметры.ЯЛюблю1С), но в ОбработкуЗаполнения он не попадет никогда.

Рассмотрим основные системные параметры:

  1. Основание — это универсальный параметр. Платформа спроектирована так, что значение, переданное с этим ключом, напрямую транслируется в параметр ДанныеЗаполнения процедуры ОбработкаЗаполнения. Важной особенностью является то, что Основание может принимать практически любой тип: ссылку, строку, число или даже структуру.
  2. ЗначенияЗаполнения — этот параметр имеет более строгое назначение. Платформа ожидает, что в нем будет передана исключительно Структура. Ключи этой структуры должны совпадать с именами реквизитов объекта.

Проанализируем ситуацию автора вопроса. При попытке передать ссылку напрямую в ЗначенияЗаполнения, вот так:


ОткрытьФорму("Справочник.КарточкаСотрудника.Форма.ФормаЭлемента", 
    Новый Структура("ЗначенияЗаполнения", Строка)); // Здесь Строка — это ссылка

Платформа видит, что в ЗначенияЗаполнения передана не Структура, а другой тип данных. В этот момент встроенные механизмы автоматического маппинга дают сбой, и в модуль объекта в качестве ДанныеЗаполнения приходит Неопределено. Однако, если мы используем ключ Основание, всё работает корректно, так как для него тип значения не критичен.

Правильное использование параметра ЗначенияЗаполнения

Параметр ЗначенияЗаполнения тесно связан со свойством реквизитов в конфигураторе — "Заполнять из данных заполнения". Если у реквизита установлена эта галочка, платформа автоматически запишет в него значение из одноименного ключа структуры, переданной в ЗначенияЗаполнения, даже без написания программного кода в модуле объекта.

Для корректной передачи данных через этот механизм рассмотрим следующий пример:


// На клиенте
ДанныеДляЗаполнения = Новый Структура;
ДанныеДляЗаполнения.Вставить("Подразделение", СсылкаНаПодразделение);
ДанныеДляЗаполнения.Вставить("Должность", СсылкаНаДолжность);

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

В этом случае в ОбработкаЗаполнения придет структура ДанныеДляЗаполнения, и вы сможете с ней работать. Если же вы хотите передать только один объект-основание (например, ссылку на документ-основание), правильнее использовать ключ Основание.

Нюансы с ТекущейСтрокой и типами данных

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

Проанализируем пример правильного получения ссылки перед открытием формы:


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

Обработка данных в модуле объекта

Теперь рассмотрим, как правильно принять эти данные на стороне объекта. Процедура ОбработкаЗаполнения должна быть готова к разным типам входящих данных. Хорошим тоном считается проверка типа параметра ДанныеЗаполнения.


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("СправочникСсылка.КарточкаСотрудника") Тогда
        // Вариант 1: Передана ссылка через "Основание"
        ЭтотОбъект.ФизическоеЛицо = ДанныеЗаполнения.ФизическоеЛицо;
        
    ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
        // Вариант 2: Передана структура через "ЗначенияЗаполнения" или "Основание"
        ЗаполнитьЗначенияСвойств(ЭтотОбъект, ДанныеЗаполнения);
        
    КонецЕсли;

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

Почему ОбработкаЗаполнения находится в модуле объекта, а не формы?

Этот вопрос часто сбивает с толку начинающих разработчиков. Логика платформы здесь такова: объект должен уметь заполняться независимо от того, есть у него форма или нет. Например, если вы создаете документ программно в фоновом задании или через COM-соединение, форма не создается, но вызов Объект.Заполнить(Основание) все равно должен отработать. Именно поэтому ОбработкаЗаполнения — это событие прикладного объекта, а не интерфейсного.

Если же вам нужно выполнить действия, специфичные именно для интерактивного открытия (например, изменить видимость кнопок в зависимости от параметров), это нужно делать в процедуре ПриСозданииНаСервере модуля формы, используя коллекцию Параметры.

Выводы и рекомендации

Подводя итог нашему анализу, сформулируем правила успешной передачи параметров:

Рассмотренные механизмы позволяют создавать гибкие и надежные системы ввода на основании, минимизируя количество ошибок "Неопределено" в самых ответственных участках кода.

← На главную