РеквизитФормыВЗначение () и ДанныеФормыВзначение (). Описание и примеры использования.

Опубликовал Галина Курчавова (gvk2009) в раздел Программирование - Практика программирования

В Синтаксис-Помощнике очень скупо написано о процедуре ДанныеФормыВЗначение(), чуть побольше - о РеквизитФормыВЗначение(). И совсем нет примеров использования. Попробуем с этим разобраться.
 

РеквизитФормыВЗначение() является методом управляемой формы, компилируется только &НаСервере, контекст формы является для него необходимым, поэтому компиляция &НаСервереБезКонтекста недоступна. На клиенте не работает, поскольку в результате получаем прикладной объект.

Где и когда его нужно использовать?
Метод РеквизитФормыВЗначение() необходим, если требуется из модуля формы вызвать стандартный метод объекта или метод (процедуру, функцию) из модуля объекта, из общего модуля.
Этот метод будет отрабатывать с данными, взятыми из формы, т.е. еще не записанными в базу.

Для того, чтобы измененные данные вернуть на форму, используется метод ЗначениеВРеквизитФормы().

Вторым параметром метода РеквизитФормыВЗначение является тип значения. Это необязательный параметр. Если обрабатываемый реквизит не является составным типом, то тип будет автоматически получен из реквизита формы. Иначе генерируется исключение времени выполнения.

Примеры:
1)

&НаСервере
Процедура ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент)

            ДокОбъект = РеквизитФормыВЗначение("Объект");
            ДокОбъект.ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент);
            ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

2)

&НаСервере
Процедура ОчиститьСтрокиСПустойЦенойНаСервере()

         ДокОбъект = РеквизитФормыВЗначение("Объект");
         ДокОбъект.ОчиститьСтрокиСПустойЦеной();
         ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

3)

&НаСервере
Функция ОбъектЗаполнен()
         Возврат РеквизитФормыВЗначение("Объект").ПроверитьЗаполнение();
КонецФункции

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


ДанныеФормыВзначение()

В отличие от метода управляемой формы РеквизитФормыВЗначение(), процедура глобального контекста ДанныеФормыВЗначение() может работать без контекста формы, но именно поэтому, в частности, ей необходимо указывать тип конвертируемых данных.

Обратной процедурой является ЗначениеВДанныеФормы().

Примеры:
1)    &НаСервере

       // Инициализация набора констант
       НаборКонстантОбъект = ДанныеФормыВЗначение(НаборКонстант, Тип("КонстантыНабор"));
       НаборКонстантОбъект.Прочитать();
       ЗначениеВДанныеФормы(НаборКонстантОбъект, НаборКонстант);

2)   &НаСервере  

       НаборФорма = Объект.Движения.РегистрУправленческий;

       Набор = ДанныеФормыВЗначение(НаборФорма, Тип("РегистрБухгалтерииНаборЗаписей.РегистрУправленческий"));
       Если Набор.Количество()=0 Тогда
              Возврат;
       КонецЕсли;
       Набор.УстановитьАктивность(НЕ Набор[0].Активность);
       ЗначениеВДанныеФормы(Набор, НаборФорма);

В этом примере на форме отображен набор записей регистра бухгалтерии. При отработке процедуры, активность набора меняется только на форме, в базе при этом ничего не происходит. Активность у набора записей регистра в базе поменяется только после выполнения операции Записать.

3)
&НаКлиенте
Процедура Заполнить(Команда)

       ОснРеквизит = Объект;
       ВыполнитьНаСервереБезКонтекста(ОснРеквизит);
       КопироватьДанныеФормы(ОснРеквизит,Объект)

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

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервереБезКонтекста(ОснРеквизит)

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

       //...Выполнение операций с Объектом "ОбъектЗначение"

       ЗначениеВДанныеФормы(ОбъектЗначение, ОснРеквизит);

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

В этом примере на клиент возвращается ОснРеквизит, содержащий измененные данные. Но его еще нужно "запихать"  в отображаемую форму. Для этого используем процедуру глобального контекста КопироватьДанныеФормы().

 

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

В качестве иллюстрации взаимозаменяемости Пример 2 еще в двух вариантах:

ВАРИАНТ 1
&НаКлиенте
Процедура Активность(Команда)

       ОснРеквизитДвижения = Объект.Движения.РегистрУправленческий;
       АктивностьНаСервереБезКонтекста(ОснРеквизитДвижения);
       КопироватьДанныеФормы(ОснРеквизитДвижения,Объект.Движения.РегистрУправленческий);

КонецПроцедуры // Активность()

&НаСервереБезКонтекста
Процедура АктивностьНаСервереБезКонтекста(ОснРеквизитДвижения)

       Набор = ДанныеФормыВЗначение(ОснРеквизитДвижения, Тип("РегистрБухгалтерииНаборЗаписей.РегистрУправленческий"));
       Если Набор.Количество()=0 Тогда
              Возврат;
       КонецЕсли;
       Набор.УстановитьАктивность(НЕ Набор[0].Активность);
       ЗначениеВДанныеФормы(Набор, ОснРеквизитДвижения);

КонецПроцедуры // АктивностьНаСервереБезКонтекста()


ВАРИАНТ 2

&НаСервере
Процедура АктивностьНаСервере()

       НаборФорма = РеквизитФормыВЗначение("Объект");
       Набор = НаборФорма.Движения.РегистрУправленческий;

       Если Набор.Количество()=0 Тогда
              Возврат;
       КонецЕсли;

       Набор.УстановитьАктивность(НЕ Набор[0].Активность);
       ЗначениеВРеквизитФормы(НаборФорма, "Объект");

КонецПроцедуры // АктивностьНаСервере()

См. также

Добавить вознаграждение
Комментарии
1. Сергей Ожерельев (Поручик) 3469 26.09.12 13:06 Сейчас в теме
Щас набегут местные умники и начнут грабить корованы размахивать Хрусталёвой с Радченко.
2. no_registration no_registration (no_registration) 26.09.12 14:30 Сейчас в теме
Спасибо. Полезная статья.
3. Suliko Beridze (Daddysb) 02.10.12 10:39 Сейчас в теме
4. Евгений Федоров (FedorovEvg) 143 05.10.12 16:54 Сейчас в теме
5. Олег Осипов (plastilin) 8 07.10.12 00:25 Сейчас в теме
6. Дмитрий Медведев (ZeroDM) 10 08.10.12 08:37 Сейчас в теме
Тема хорошая, но раскрыта не до конца.

Во второй части, где описываются методы ДанныеФормыВзначение() и ЗначениеВДанныеФормы() не достаточно содержательно, описано:
- назначение процедур;
- почему или в каких случаях нужно использовать ДанныеФормыВзначение(), а не РеквизитФормыВЗначение() и в каких наоборот.
TeMochkiN; perepetulichka; +2 Ответить
7. Владимир (vladir) 105 10.10.12 14:16 Сейчас в теме
(0) Спасибо, полезная информация.
8. Андрей Киреев (FractonKireyev) 11.10.12 19:10 Сейчас в теме
Согласен с ZeroDM - тема раскрыта не полностью. Кроме того описание скомкано: то-ли автору лень писать, то-ли не до конца понял о чём пишет...
Serg_1C(M); +1 Ответить
9. Dimon (klel) 11.10.12 20:28 Сейчас в теме
Полезно и наглядно =) ОГРОМНЫЙ +
10. Сергей Маслов (LexSeIch) 180 21.03.13 05:47 Сейчас в теме
Мир этому дому.
Полезная статья для тех кто начинает программировать управляемые формы. Автору спасибо!
11. Алексей Карвацкий (AVK_Alex) 4 24.10.13 11:18 Сейчас в теме
Здравствуйте, коллеги!

Сначала немного лирики: у клиента (УТ11) скачет интернет (меняется IP / отключается). Пользователи дубасят документы (пусть будет РТУ). Кнопку "Записать" нажимать забывают (наверное, только на уровне Господа Бога этот вопрос еще не обсуждался). Работают тонким клиентом через веб-сервер (RDP нет). При отключении интернет клиент отваливается с потерей всего, что нажито непосильным трудом.

Задача: обеспечить минимальные потери данных при скачках интернета.

Решение выбрано такое:
1. При изменении ТЧ "Товары" сохранять объект целиком (документ РТУ) в регистре сведений. Записывать документ не подойдет, т.к. пользователь может отказаться от создания документа.
2. При записи / проведении / закрытии формы документа - удалять записи из регистра.
3. При старте 1С проверять, есть ли записи в регистре и восстанавливать их.

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

Варианты решения:
1. Заполнять на клиенте в цикле по одному реквизиту - как-то несерьезно.
2. Дорабатывать форму документа, чтобы при открытии она сама проверяла наличие записи в регистре - дополнительное изменение конфигурации (а такую практику восстановления планируется распространить и на прочие документы).
3. Сохранять непосредственно ТЧ "Товары" - проще восстанавливать, но шапка будет пустая...

Что посоветуете? Должен же быть какой-то встроенный заполнятор?

P.S. Кусок кода:

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

kostyaomsk; +1 Ответить 1
12. Галина Курчавова (gvk2009) 264 25.10.13 10:18 Сейчас в теме
(11) AVK_Alex, в качестве "заполнятора" используйте процедуру глобального контекста КопироватьДанныеФормы. В вашем коде будет примерно так (при условии, что структуры "ВосстановленныйОбъект" и "Фрм.Объект" совпадают):

...
КопироватьДанныеФормы(ВосстановленныйОбъект, Фрм.Объект);
Фрм.Открыть();
13. Алексей Карвацкий (AVK_Alex) 4 25.10.13 12:41 Сейчас в теме
(12) gvk2009, так уже пробовал:
{ОбщаяФорма.ПУРУМ_НесохраненныеОбъекты.Форма(37)}: Ошибка при вызове метода контекста (КопироватьДанныеФормы)
КопированиеВыполнено = КопироватьДанныеФормы(ВосстановленныйОбъект, Фрм.Объект);
по причине:
Несоответствие типов (параметр номер '1')

Тут должен быть не ДокументОбъект, а ДанныеФормыСтруктураСКоллекцией; ДанныеФормыКоллекция; ДанныеФормыСтруктура

Но все равно спасибо за участие. Посмотрю версионирование в БСП (но там-то все в контексте формы объекта) - может, натолкнет на какую мысль...
14. Галина Курчавова (gvk2009) 264 25.10.13 13:01 Сейчас в теме
(13) AVK_Alex, а какой тип данных у ВосстановленныйОбъект?
Делаете ли в процедуре ВосстановитьОбъектНаСервере() перед передачей на Клиента преобразование объекта с помощью
ЗначениеВДанныеФормы?
15. Виктор Лебедев (eeeio) 80 25.10.13 14:17 Сейчас в теме
Вызов процедуры &НаСервереБезКонтекста
Обработать(КакаятоТаблицаФормы)...
вываливается с ошибкой.
Нормально отрабатывается вот так: Обработать(ЗНАЧ КакаятоТаблицаФормы)
16. Алексей Карвацкий (AVK_Alex) 4 25.10.13 14:49 Сейчас в теме
(14) gvk2009, тип данных ДокументОбъект
Код теперь выглядит так:
&НаКлиенте
Процедура ВосстановитьОбъект (СсылкаНаОбъект, ИмяФормы)
	ВосстановленныйОбъект = ВосстановитьОбъектНаСервере (СсылкаНаОбъект);
	Фрм = ПолучитьФорму(ИмяФормы);
	ЗначениеВРеквизитФормыНаСервере(ВосстановленныйОбъект, Фрм.Объект);
	Фрм.Открыть();
КонецПроцедуры

&НаСервере
Процедура ЗначениеВРеквизитФормыНаСервере (ВосстановленныйОбъект, ФормаОбъект)
	ЗначениеВДанныеФормы(ВосстановленныйОбъект, ФормаОбъект);	
КонецПроцедуры //Прикольно, сюда дохожу отладчиком. Дальше F10 и ошибка
...Показать Скрыть


{ОбщаяФорма.ПУРУМ_НесохраненныеОбъекты.Форма(37)}: Ошибка при установке значения атрибута контекста (Объект)
ЗначениеВРеквизитФормыНаСервере(ВосстановленныйОбъект, Фрм.Объект);
по причине:
Нельзя изменять поле, содержащее объект данных формы
17. Алексей Карвацкий (AVK_Alex) 4 25.10.13 14:52 Сейчас в теме
(15) eeeio, возможно, не совсем понимаю - а разве в форме после этого что-то поменяется?
18. Виктор Лебедев (eeeio) 80 25.10.13 16:07 Сейчас в теме
19. Алексей Карвацкий (AVK_Alex) 4 25.10.13 17:23 Сейчас в теме
20. Галина Курчавова (gvk2009) 264 26.10.13 18:46 Сейчас в теме
(16) AVK_Alex, вот код для примера. Я создала внешнюю обработку с реквизитом ДокСсылка (тип - ДокументСсылка).

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

&НаСервереБезКонтекста
Процедура ЗаполнитьНаСервереБезКонтекста(ФрмОбъект, ДокСсылка)
	
	ВосстановленныйОбъект = ДокСсылка.ПолучитьОбъект();
	ЗначениеВДанныеФормы(ВосстановленныйОбъект, ФрмОбъект);
	
КонецПроцедуры // НаСервереБезКонтекста()

...Показать Скрыть
21. Алексей Карвацкий (AVK_Alex) 4 28.10.13 10:13 Сейчас в теме
(20) gvk2009, Спасибо!

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

&НаСервереБезКонтекста
Процедура ЗаполнитьНаСервереБезКонтекста(ФрмОбъект, ВосстановленныйОбъект)
    ЗначениеВДанныеФормы(ВосстановленныйОбъект, ФрмОбъект);
КонецПроцедуры // ЗаполнитьНаСервереБезКонтекста()
...Показать Скрыть
22. Сергей Толмачев (sss999) 36 19.09.14 12:15 Сейчас в теме
(20) gvk2009, че то мне вообще этот код не понравился,как то он не соответствует концепции разделения на сервер и клиент,например как это можно получать объект на клиенте а потом передавать его через параметр,все должно на сервере получаться имхо
23. Галина Курчавова (gvk2009) 264 23.09.14 13:21 Сейчас в теме
(22) sss999, если получать объект на сервере по ссылке (реквизит формы Объект.Ссылка), то для этого потребуется контекст формы - это как раз случай использования "РеквизитФормыВЗначение()". А в том коде, на который ссылаетесь вы, контекст формы не используется. С Клиента на Сервер передается форма документа и документ со всеми своими реквизитами, помещенный в переменную. Но его тип - не ДокументОбъект! Именно поэтому его можно использовать на Клиенте. Если обратиться с справке 1С, то читаем:"Важно заметить, что для типов прикладных объектов (таких, как СправочникОбъект, например) форма будет реально использовать не прикладные, а специализированные типы данных, состав которых будет автоматически наполняться из указанных типов".
Предпочтительнее использовать компиляцию НаСервереБезКонтекста, потому что в этом случае объем передаваемых данных между Клиентом и Сервером значительно меньше.
24. Надежда (user_2010) 124 10.04.15 12:11 Сейчас в теме
Спасибо - статья полезна!

Решаю такую задачу: на форму программно добавлен реквизит и его элемент.

Почему функция РеквизитФормыВЗначение не видит мой реквизит/элемент?
25. Николай Сигаев (arancar) 19 01.07.15 14:39 Сейчас в теме
Тема годная, только мне больше интересно насколько такие вызовы по переупаковке данных из одного типа в другой трудозатратны по времени исполнения?
Стоит ли при наличии двух форм документа (управляемой и обычной) помещать методы вида ПриИзмененииДоговора в модуль объекта и в управляемой форме шаманить во всех удобных и неудобных местах ДанныеФормыВЗначение -> ЗначениеВДанныеФормы? Или лучше продублировать тот де самый код в разных формах или придумать что-то более интересное?
26. Наталья Фанаскова (Afa_fil) 14.10.15 17:59 Сейчас в теме
Спасибо, полезная статья.
Я пыталась таким же образом преобразовывать не сам Объект формы, а его реквизиты.
Если у реквизита тип динамический список, то ни одна из этих процедур не срабатывает.
Если у реквизита тип таблица значений, то все хорошо получается.
27. Ирина progr-2008 Санкт-Петербург (progr-2008) 113 18.09.16 23:01 Сейчас в теме
28. Семён Щербаков (userGJ) 26.10.16 17:20 Сейчас в теме
Спасибо за статью, очень помогла.
29. Павел С (pavel_pss) 158 16.12.16 17:51 Сейчас в теме
Всем привет. Помогите. При работе в тонком клиенте.

Есть обработка, на ней табличная часть и ТЧ. реквизит Док.ПоступлениеТовУслуг.

по кнопке наформе:

&НаКлиенте
Процедура ВыполнитьЗагрузку(Команда)
	
	Сообщить("Выполняется загрузка документов, подождите ...", СтатусСообщения.Внимание);  
	ВыполнитьЗагрузкуНаСервере(Элементы.Страницы.ТекущаяСтраница.Имя);
	Сообщить("Загрузка документов, выполнена", СтатусСообщения.Информация);

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

&НаСервере
Процедура ВыполнитьЗагрузкуНаСервере(ИмяСтраницы)
	ФРМ = РеквизитФормыВЗначение("Объект");
	
	Если ИмяСтраницы = "ГруппаВыборТЧ" Тогда
	
		ФРМ.ЗагрузитьПТУ();
	КонецЕсли;
	
	ЗначениеВРеквизитФормы(ФРМ,"Объект");


...Показать Скрыть


процедура ЗагрузитьПТУ - объявленна в модуле объекта.

Там идет загрузка внешних данных и создание нового или изменение существующего документа ПоступлениеТоваровУслуг.

Вопрос, если новый док, то все нормально, но если док уже есть и у него например меняется дата и док. записывается док. То пока я на сервере то дата встает правильная,
но когда возвращается в Процедура ВыполнитьЗагрузку(Команда), то в колонке ТЧ, дата остается старая.

Подскажите в чем мой косяк.

Лучше куском кода. Спасибо.

В толстом клиенте такой проблемы нет.