Имя: Пароль:
1C
1С v8
Как в УФ открыть форму существующего документа, изменить его и не записывая открыть
0 paxan
 
18.09.19
10:20
Здравствуйте.
С УФ не так плотно работаю, просьба подсказать...
У меня есть ссылка на уже записанный документ, мне нужно этот документ изменить (конкретно таб. часть) и открыть его не записывая. Пользователь уже сам должен решить нужно ли его записывать или нет.
В обычном интерфейсе все безумно просто - получаем объект от ссылки с помощью ПолучитьОбъект, потом изменяем его как нужно и через Объект.ПолучитьФорму().Открыть() открываем форму.
Для УФ оказывается довольно хитро все нужно делать, либо я что-то не понимаю. Сделал вот так из рекомендаций в инете, но почему-то документ открывается не в том виде, как при открытии его станданртно - таб. часть не заполнена как мининум.
Что делаю не так? может есть проще вообще способ это делать?

&НаКлиенте
СтруктураОткрытияФормы = Новый Структура("Ключ",СсылкаНаТабель);
ФормаТабеля= ПолучитьФорму("Документ.ТабельУчетаРабочегоВремени.Форма.ФормаДокумента",СтруктураОткрытияФормы);    
ДанныеФормыОбъектаТабеля = ФормаТабеля.Объект;

ИзменитьТабель(ДанныеФормыОбъектаТабеля ) // в этой процедуре на сервере меняю как мне нужно документ

КопироватьДанныеФормы(ДанныеФормыОбъектаТабеля, ФормаТабеля.Объект); // не очень понятно зачем нужно, но без этого измененные данные не прописываются
ФормаТабеля.Открыть();    

// сама процедура где изменяю документ
&НаСервере
Процедура ИзменитьТабель(ДанныеФормыОбъектаТабеля )

    ДокОбъект = ДанныеФормыВЗначение(ДанныеФормыОбъектаТабеля,Тип("ДокументОбъект.ТабельУчетаРабочегоВремени"));
  
   // далее что-то меняю в объекте..

    ЗначениеВДанныеФормы(ДокОбъект ,ДанныеФормыОбъектаТабеля);

КонецПроцедуры
1 Василий Алибабаевич
 
18.09.19
10:33
(0) Как-то все через задний проход. Никаких получитьФорму и прочего в УФ не нужно. Все делается в ОткрытьФорму + ПриСозданииНаСервере

Вариантов 2
1. В ОткрытьФорму вторым параметром передается структура. В которой "Ключ" - ссылка на твой документ и "Основание" - структура, которая упадет в ОбработкаЗаполнения. В ОбработкаЗаполнения выполнить код из твоего "ИзменитьТабель".

2. В ОткрытьФорму вторым параметром передается структура. В которой "Ключ" - ссылка на твой документ и еще один ключ (Например "ДанныеЗаполнения") с теми же данными, что и в варианте 1.
В ПриСозданииНаСервере примерно такой код :
Если Параметры.Свойство("ДанныеЗаполнения") Тогда
   ...
   Твой код из "ИзменитьТабель"
   ...
КонецЕсли;
2 paxan
 
18.09.19
10:37
(1) Спасибо, но в вашем случае необходимо изменять конфигурацию - либо модуль объекта либо формы, чего не хотелось бы делать. Все это делает внешняя обработка и таких обработок объекта может быть куча, не пихать же все в конфу.
3 polosov
 
18.09.19
10:46
(2)
1.Получил объект
2.Изменил данные ОБЪЕКТА
3.Открыл форму (код открытия через Ключ-Ссылку у тебя есть)
Попробуй так.
4 paxan
 
18.09.19
10:49
(3) Как в открытии при этом указать что должна открываться форма именно измененного ообъекта? Откроется просто форма документа в базе по ссылке и все..
5 Cyberhawk
 
18.09.19
11:18
Если нельзя изменять модуль формы, тогде через ПолучитьФорму, модификацию _Объекта_ (реквизита формы) и КопироватьДанныеФормы
6 Cyberhawk
 
18.09.19
11:18
Но поскольку никто не разрабатывает формы с расчетом на такую модификацию, могут быть артекакты
7 Cyberhawk
 
18.09.19
11:19
*артефакты
8 paxan
 
18.09.19
11:27
(7) А почему возникают такие артефакты? По другому говоря почему разработка формы должна влиять на такую модификацию? Могу только предоположить что возможно выполняются какие-то действия при создании формы на сервере в стандартной форме, которые зависят от данных объекта, а объект я уже изменил.. или что?
9 fisher
 
18.09.19
11:30
(0) Почти так же просто. Сначала ПолучитьФорму(), работаешь с полученной формой (ТЧ меняешь через основной реквизит формы - обычно "Объект"), потом вызываешь Открыть()
Только внимательно читай синтаксис ПолучитьФорму() для УФ.
10 fisher
 
18.09.19
11:31
Та ПолучитьФорму(), которая метод глобального контекста.
11 d4rkmesa
 
18.09.19
11:50
(0) Без записи, только внешней обработкой тяжело будет воспроизвести заполнение формы. Я, как правило, сейчас делаю расширение, где вызываю методы формы документа, чтобы заполнились все реквизиты формы.
12 d4rkmesa
 
18.09.19
11:53
Т.к. в ЗУП сейчас довольно сложно реализована работа табличных частей с формой, данные гоняются туда-сюда, воспроизвести точно заполнение, как в форме документа, с помощью внешней обработки невозможно.
13 fisher
 
18.09.19
11:55
У тебя в (0) получение формы правильно прописано.
Дальше просто в идеале все заполнение должно происходить с клиента - с использованием серверных вызовов, но не "передавая" данные формы на сервер. И в конце вызываешь Открыть() у формы.
Та часть, что вызывает проблемы - это как раз попытка сериализовать данные формы, передать их на сервер, обработать и потом "запинать" их обратно в форму. Если можно этого избежать - избегай :)
14 aleks_default
 
18.09.19
11:55
(8)Такие артефакты возникают из-за того что в процедуре ПриСозданииНаСервере могут создаваться/изменяться элементы формы в зависимости от данных объекта. Что довольно часто реализовано в типовых конфигурациях (например, отображение тех же доп. реквизитов). Соответственно ПриСозданииНаСервере происходит во время ПолучитьФорму() т. е. ДО твоего перезаполнения объекта, т.е. на основе исходного состояния объекта.
15 aleks_default
 
18.09.19
11:59
Иными словами ты должен воспроизвести все действия, которые прописаны в ПриСозданиинаСервере и которые изменяют отображение элементов формы, но уже после ПолучитьФорму() и того как ты изменил Объект.
16 fisher
 
18.09.19
12:11
Проблемы при попытке прямой передачи данных формы на сервер возникают насколько я понимаю из-за того, что они изначально не предполагались для явной сериализации, только для неявной при клиент-серверных вызовах из самой формы. У этих структур данных даже в СП не отмечено, что они сериализуются. Т.е. их явная сериализация недокументирована. А альтернативную "глубокую" сериализацию обычно лень писать ради такой фигни.
Хотя чисто логически код из (0) вполне корректен.
Данные формы передаются на сервер (предполагается их "отрыв" от формы и сериализация), на сервере они преобразуются в объект, меняется объект, данные объекта преобразовываются в данные формы (пока оторванные от конкретной формы), данные формы возвращаются на клиент и на клиенте они копируются уже в данные конкретной формы, которые часть контекста этой формы.
17 takefive
 
18.09.19
12:25
я проверил твой код. у меня все работает
18 paxan
 
18.09.19
12:30
(17) Спасибо за проверку! Я подозреваю что дело связано с самой формой документа, а именно Табеля из зупа (3.1), сейчас еще одно проверю..
19 paxan
 
18.09.19
12:57
хм.. интересное дело, попробовал для простоты переделать код чтобы работать не с ДокументОбъект а с документом как реквизитом формы (Данные формы коллекция).
Прошелся отладчиком по коду, выяснилось вот что (в комментариях написал):
&НаКлиенте
СтруктураОткрытияФормы = Новый Структура("Ключ",СсылкаНаТабель);
ФормаТабеля= ПолучитьФорму("Документ.ТабельУчетаРабочегоВремени.Форма.ФормаДокумента",СтруктураОткрытияФормы);    
ДанныеФормыОбъектаТабеля = ФормаТабеля.Объект; // изначально в документе в таб. части 10 строк, т.е. в ДанныеФормыОбъектаТабеля.ТЧ.Количество()=10

ИзменитьТабель(ДанныеФормыОбъектаТабеля ) // в этой процедуре на сервере меняю как мне нужно документ

// на момент открытия хотя мы в предыдущей обработке изменили количество строк в ТЧ документа
// количество в ФорматТабеля.Объект.ТЧ остается старым! т.е. не меняется.
ФормаТабеля.Открыть();    

// сама процедура где изменяю документ (уже не сам а через переданные данные формы)
&НаСервере
Процедура ИзменитьТабель(ДанныеФормыОбъектаТабеля )
//здесь работая напрямую с ДанныеФормыОбъектаТабеля
// т.е. делаю например ДанныеФормыОбъектаТабеля.ТЧ.Добавить() и тп..
// после этого количество строк например становится 20 в ДанныеФормыОбъектаТабеля.ТЧ

КонецПроцедуры
20 paxan
 
18.09.19
13:07
Добавлю.. Создал простую обработку, кинул на форму ссылку на документ.
Код формы ниже. Так вот при таком коде выходит ошибка при попытке вызова функции изменения документа "Нельзя изменять поле, содержащее объект данных формы".  Этот же код работает если предварительно перед вызовом присвоить ФормаДок.Объект какой-то переменной и ее уже передавать в процедуру изменения. Но при этом перед непосредственным открытим формы этих изменений в ТЧ нет, т.е. изменяется по факту копия, а не сам объект. Совсем запутался..

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


&НаСервере
Процедура ИзменитьДокумент(Док)
        
    НовСтр= Док.ДанныеОВремени.Добавить();
    
    
КонецПроцедуры
21 Cyberhawk
 
18.09.19
13:17
(8) И еще потому что модуль формы и ее элементы с реквизитами могут когда-нибудь поменяться, а ты по-прежнему в своем внешнем коде будешь рассчитывать на старую структуру и логику. В лучшем случае ты словишь явную программную ошибку типа "Поле объекта не обнаружено" или еще что-то такое, в худшем - логическую, т.е. незаметную.
22 MuxaH
 
18.09.19
13:31
(19) Дык тебе в (14) всё правильно описали. В табеле при создании на сервере дофига вспомогательных данных пишется именно в реквизиты формы (а не объекта) на основе твоего, ещё не измененного, объекта. Проще через расширение с обработкой заполнения нужное тебе поведение сделать всё-таки. Т.е. получаешь объект нужного тебе табеля, пишешь его данные в структуру, меняешь как нужно структуру, вызываешь

ОткрытьФорму("Документ.ТабельУчетаРабочегоВремени.Форма.ФормаДокумента", Новый Структура("ЗначенияЗаполнения", ТвояСтруктура));

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

Т.е. меняешь данные объекта, которые потом уже будут переданы в ПриСозданииНаСервере, заполнятся все вспомогательные реквизиты формы, а пользователь уже сам примет решение перезаписывать ему объект или нет. Только заморачиваться во внешней обработке придется с передачей некоторых данных с клиента на сервер, но ВременноеХранилище там в помощь.
23 paxan
 
18.09.19
13:44
(22) Это какой-то геморой.. Для простых вещей изменения объекта городить еще и расширение.
Прокомментируете пожалуйста, а почему тогда в посте 20 такое поведение "Этот же код работает если предварительно перед вызовом присвоить ФормаДок.Объект какой-то переменной и ее уже передавать в процедуру изменения. Но при этом перед непосредственным открытим формы этих изменений в ТЧ нет, т.е. изменяется по факту копия, а не сам объект. Совсем запутался..
". А именно почему сделанные изменения не видятся и не применяются? Т.е. допустим что форма документа простейшая, нет никаких сложных обработок заполнения формы на сервере при создании, но почему тогда так нельзя открыть форму чтобы были видны изменения?
24 dezss
 
18.09.19
13:55
(23) На это тебе в (16) ответили. На сервер передается именно значение, а не ссылка. При возврате он пытается изменения записать, но это не получается. Поэтому надо черед доп. переменную подобные вещи делать. Я подобное делал через КопироватьДанныеФормы, когда нельзя было делать контекстных серверных, но данные менять надо было.
25 dezss
 
18.09.19
13:56
(24) +
Вот такое делал. Информация - это ДанныеФормыКоллекция.
ИнформацияВрем = Информация;
ЗаполнитьИнформацию(перПрайсСсылкаТекущая,рекТекущийМагазин, ИнформацияВрем);
КопироватьДанныеФормы(ИнформацияВрем,Информация);
26 MuxaH
 
18.09.19
14:06
(23) Если форма документа простейшая и нет никаких сложных обработок ПриСозданиинаСервере, то тогда отработает и код из твоего первого поста, с простыми формами я так и делаю, но в ЗУП 3, к сожалению, простых форм раз-два и обчелся...
27 paxan
 
18.09.19
17:29
Спасибо большое всем что направили на путь истинный )) Да, дело было действительно в том, что при создании форму довольно хитрые вещи происходят в этом документе. Попытался я это наскоком съэмулировать, почти даже добился результата, но что-то гиблое это дело и пугают проблемы при дальнейшем обновлении конфы.
В общем, как и рекомендовали, пытаюсь сейчас сделать это через передачу параметра при открытии, чтобы в процедуре ОбработкаЗаполнения()в модуле объекта на основании наличия этой переданной структуры скорректировать открываемый объект. Саму обработку заполнения объекта планирую скорректировать в расширении. Но что-то есть проблема)
Делаю так:
            
СтруктураОткрытияФормы = Новый Структура("Ключ",СсылкаНаТабель);

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

Проблема - при таком открытии формы у меня не вызывается метод ОбработкаЗаполнения у объекта. Это так и должно происходить при открытии существующего объекта и нужно тогда отрабатывать это событие в самой форме? Хотел сделать это через объект, как наиболее железный способ...
28 ssh2006
 
18.09.19
17:40
(27) ОбработкаЗаполнения вызывать при интерактивном вводе нового или при явном вызове метода объекта Заполнить()
29 paxan
 
19.09.19
02:47
(28) Спасибо за замечание! Переделал через расширение, работаю с событием формы ПриЧтенииНаСервере, так как оказалось что именно в нем подготавливается форма табеля. Сейчас все отлично. Не думал конечно что вроде такая тривиальная задача решается таким способом)) Спасибо еще раз всем за помощь!
30 rphosts
 
19.09.19
03:54
(0) в ПриСозданииНаСервере спрятать дефолтовые кнопки Записать, Закрыть, Ок и вместо них вставить свои, которые начнут с вопроса а далее по ответу.