Поиск по блогу

среда, 18 февраля 2015 г.

Отличия функций РеквизитФормыВЗначение и ДанныеФормыВЗначение

Первые проблемы


Во времена толстого клиента вызов процедуры модуля объекта из модуля формы был прост. Достаточно было определить процедуру модуля как экспортируемую и вызвать её в модуле формы.
Вызов процедуры модуля в толстом клиенте обычное приложение


Времена меняются, платформу 1С оптимизируют и совершенствуют, толстый клиент забывают, всем подавай тонкий или web-клиент. Разработчики начинают переводить обычные формы на управляемые, но не все так просто, появляются некоторые сложности в связи с разделением выполнения программного кода на два контекста: сервер и клиент. Поэтому выше приведенный пример кода работать не будет в тонком клиенте.

Новые типы данных


Так же из-за управляемых форм появились новые типы данных. Имеется форма:
Управляемая форма
Запоминаем типы реквизитов и смотрим какие типы в отладке для этих реквизитов:

Новые типы данных формы
Делаем вывод, для отображения данных самого объекта используется тип ДанныеФормыСтруктура, для отображения дерева значений - ДанныеФормыДерево, для табличной части - ДанныеФормыКоллекция и т.д. То есть  в модуле формы на клиенте мы работаем не с самим объектом а с его представлением! Поэтому, методы, которые доступны, например, для табличной части в модуле объекта НЕ ДОСТУПНЫ в модуле формы.

Борьба с новыми типами


Разработчики платформы 1С предоставили две функции:

  1. РеквизитФормыВЗначение - преобразует указанный реквизит формы в объект прикладного типа.
  2. ДанныеФормыВЗначение - преобразует данные формы в объект прикладного типа.

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

СпрОбъект1 = РеквизитФормыВЗначение("Объект");
СпрОбъект1.ВывестиСообщение(Объект.Реквизит1);

СпрОбъект2 = ДанныеФормыВЗначение(Объект, Тип("СправочникОбъект.Справочник1"));
СпрОбъект2.ВывестиСообщение(Объект.Реквизит1);

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


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

ДеревоЗначений1 = РеквизитФормыВЗначение("Реквизит1");
ДеревоЗначений2 = ДанныеФормыВЗначение(ЭтаФорма.Реквизит1, Тип("ДеревоЗначений"));

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


ДеревоЗначений1 и ДеревоЗначений2 имеют одинаковый тип - ДеревоЗначений. Так в чем же разница этих функций???

ДанныеФормыВЗначение - функция глобального контекста. Производит преобразование типа объекта поддерживаемого формой в тип объекта базы данных: ДанныеФормыСтруктура --> СправочникОбъект.Справочник1.

РеквизитФормыВЗначение - функция модуля формы, то есть вызывается на сервере в контексте формы (&НаСервере). Если вы попытаетесь вызвать данную функцию вне контексте формы, то платформа сгенерирует исключительную ошибку:
&НаСервереБезКонтекста
Процедура ПреобразованиеТипа()

// Этот код неправильный, контекст формы не доступен, будет ошибка!
СпрОбъект2 = ДанныеФормыВЗначение(Объект, Тип("СправочникОбъект.Справочник1"));
СпрОбъект2.ВывестиСообщение(Объект.Реквизит1);

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


Вот и все отличия.

4 комментария:

  1. Добрый день!
    А есть ли аналог РеквизитФормыВЗначение() для обычного приложения?

    ОтветитьУдалить
    Ответы
    1. Для обычного приложения эти функции не имеют смысла существовать (нету разделения на контекст выполнения кода). Производите все операции в обычной форме через переменную ЭтотОбъект (обращение к реквизитам объекта и вызов процедур из модуля объекта)!

      Удалить
  2. В коде:
    "&НаСервереБезКонтекста
    Процедура ПреобразованиеТипа()

    // Этот код неправильный, контекст формы не доступен, будет ошибка!
    СпрОбъект2 = ДанныеФормыВЗначение(Объект, Тип("СправочникОбъект.Справочник1"));
    СпрОбъект2.ВывестиСообщение(Объект.Реквизит1);

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

    Возможно, вы имели ввиду &НаСервере? Т.к. у меня работает аналогичный код с &НаСервереБезКонтекста

    ОтветитьУдалить
    Ответы
    1. Да, код ошибочный, перемудрил. По-хорошему, процедуру надо было вынести в серверный общий модуль (без Вызов сервера!!!) где нет контекста формы и передать в эту процедуру Объект через параметр. Вот для таких маневров существует функция ДанныеФормыВЗначение.

      Удалить