Открытие управляемой формы 1С 8.3 с измененным несохраненным объектом

13.07.20

Разработка - Универсальные функции

Как загрузить в управляемую форму программно изменённый несохранённый документ (или элемент справочника).

В обработках часто встречается следующая логика: загрузить объект (документ или элемент справочника), изменить его программно в соответствие с логикой обработки, и открыть форму с получившимся документом пользователю, который может сохранить изменения, добавить свои либо отвергнуть изменения, вернуть «как было». В 1С8.3 (Управляемое приложение) осуществить данную логику оказалось неожиданно сложно.

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

В итоге (в частности по советам в обсуждениях) сделал несколько по-другому:

поместить данные объекта во временное хранилище,

ОткрытьФорму, в параметрах передать адрес во временном хранилище,

Изменения в код формы вносить пришлось: В форме, перед ПриЧтенииНаСервере (у меня - через расширение) загрузить данные объекта.

Такого в Сети не нашёл, поэтому выкладываю:

 

//в общем модуле
&НаСервереБезКонтекста
Функция СохранитьОбъектВХранилище(знач Док) Экспорт
	СтруктРеквизиты = Новый Структура;
	Мтд = Док.Метаданные();
	Для каждого Рекв из Мтд.Реквизиты цикл
		СтруктРеквизиты.Вставить(Рекв.Имя);
	КонецЦикла;
	Для каждого Рекв из Мтд.СтандартныеРеквизиты цикл
		СтруктРеквизиты.Вставить(Рекв.Имя);
	КонецЦикла;
	ЗаполнитьЗначенияСвойств(СтруктРеквизиты, Док);
	
	ДанныеДок = Новый Структура;
	ДанныеДок.Вставить("Реквизиты", СтруктРеквизиты);
	ТабЧ = Новый Структура;
	Для каждого Рекв из Мтд.ТабличныеЧасти цикл
		ТабЧ.Вставить(Рекв.Имя, Док[Рекв.Имя].Выгрузить());	
	КонецЦикла;
	ДанныеДок.Вставить("ТабличныеЧасти",ТабЧ);
	Возврат ПоместитьВоВременноеХранилище(ДанныеДок);
КонецФункции

Процедура ВзятьОбъектИзХранилища(Объект, знач Хран) Экспорт
	ДанныеДок = ПолучитьИзВременногоХранилища(Хран);
	Рекв = ДанныеДок.Реквизиты;
	ЗаполнитьЗначенияСвойств(Объект, Рекв);
	Для каждого Стр из ДанныеДок.ТабличныеЧасти Цикл
		Объект[Стр.Ключ].Загрузить(Стр.Значение);
	КонецЦикла;
КонецПроцедуры

//в расширении в форме объекта
&НаСервере
Процедура Расш1_ПриЧтенииНаСервереПеред(ТекущийОбъект)
	Если Параметры.Свойство("НесохраненныйДокумент") Тогда
		МойМодуль.ВзятьОбъектИзХранилища(Объект, Параметры.НесохраненныйДокумент);
		Модифицированность = Истина;
	КонецЕсли;
КонецПроцедуры

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

&НаКлиенте
Процедура ВашеНазвание(Команда)
	//...
	ИзмДок = ОформитьНаСервере(Ссылка);
	П = Новый Структура;
	П.Вставить("НесохраненныйДокумент", ИзмДок);
	П.Вставить("Ключ", Ссылка);
	Форма = ОткрытьФорму("Документ.ВАШДОКУМЕНТ.ФормаОбъекта", П );
	//если справочник - аналогично
КонецПроцедуры

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

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

//в обработке
&НаСервереБезКонтекста
Функция ОформитьНаСервере()
	Док = Документы.ВАШДОКУМЕНТ.СоздатьДокумент();
	//Изменить документ
	//в соответствие с логикой обработки
	Возврат МойМодуль.СохранитьОбъектВХранилище(Док);
КонецФункции

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

 

форма документ загрузка

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

21.05.2024    20124    dimanich70    81    

144

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

1 стартмани

18.03.2024    4091    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    18059    atdonya    24    

56

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    5502    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14730    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3580    56    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18478    171    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. ltfriend 13.07.20 22:39 Сейчас в теме
Так и не понял, чем такой вариант не устроил?
Изменение документа
&НаКлиенте
Процедура ИзменитьДокументИОткрыть(ДокументСсылка)
	
	ПараметрыФормы = Новый Структура("Ключ", ДокументСсылка);
	ФормаДокумента = ПолучитьФорму("Документ.ПриобретениеТоваровУслуг.ФормаОбъекта", ПараметрыФормы);
	
	ОбъектФормы = ФормаДокумента.Объект;
	
	ИзменитьДокументНаСервере(ОбъектФормы);
	
	КопироватьДанныеФормы(ОбъектФормы, ФормаДокумента.Объект);
	
	ФормаДокумента.Открыть();
	
КонецПроцедуры

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


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

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

Сколько пользуюсь данным методом, проблем ни когда не было.
Vin1s; ra9000; MrFlanker; RocKeR_13; Dzenn; bulpi; Gorus; vvp117; plainer; +9 Ответить
2. plainer 21 14.07.20 14:23 Сейчас в теме
(1) Проверил, в моём случае работает, в большинстве других, думаю, тоже. И, несомненно, проще.
Тонкость, как я понял, в том, что здесь на сервере вы работаете с ОбъектФормы типа ДанныеФормыСтруктура, который хотя и дублирует по свойствам ДокументОбъект, но не полностью и не по методам. Поэтому если в обработке где-то требуется именно ДокументОбъект, то там будет ошибка.
(Например, у меня первоначально выдало ошибку на
Если ОбъектФормы.Модифицированность()
правда оно в моей обработке и не особо нужно)

УПД. Сейчас проверил внимательней. В вашем варианте у меня в форме не переустанавливается по умолчанию видимость одной из страниц (табличных частей).
8. soulner 461 24.07.20 16:58 Сейчас в теме
Единственно верным способом создать объект (справочник, документ и т.д.) и открыть его форму, является использование обработчика заполнения.
(1) так не правильно, потому, что обработчик формы ПриСозданииНаСервере оперирует пустым объектом, а потом вы перезаполняете объект, а форма уже создана и видимость элементов установлена. Попробуйте свой метод на сложной форме из тиражного решения и убедитесь насколько всё плохо.
Правильно будет создать структуру для заполнения и открыть форму передав в неё параметр ЗначениеЗаполнения с вашей структурой. Тогда будет создан объект, заполнен, как надо и уже из него создана и открыта форма с адекватной настройкой элементов.
10. ltfriend 25.07.20 10:04 Сейчас в теме
(8) То, что нужно заполнять документ в обработчике заполнения - это и так понятно. Но это в идеале. А что, если нужно, например, из внешней обработки создать типовой документ, находящийся на поддержке и реквизиты, которые не заполняются в обработчике? Единственное, что я не упомянул, то, что при таком способе заполнения документа необходимо самостоятельно заполнять и реквизиты самой формы (т.е. продублировать код ПриСоздании/ЧтенииНаСервере). Тогда всё корректно работает и со сложными формами.
В идеале да, нужно создавать как-то так:
ЗначенияЗаполнения = Новый Структура;
ЗначенияЗаполнения.Вставить("Организация", НашаОрганизация);
ЗначенияЗаполнения.Вставить("Склад", ГлавныйСклад);
ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ЗначенияЗаполнения);
ОткрытьФорму("Документы.НашДокумент.Форма.ФормаДокумента", ПараметрыФормы);

Но так не заполнить реквизиты, у которых не установлен флаг "Заполнять из данных заполнения". Без модификации документа не обойтись.
9. Dzenn 894 24.07.20 18:37 Сейчас в теме
(1) спасибо, добрый человек :-) Сколько программирую в 1С и в управляемых формах, а тут пробел был :-)
3. Hla 85 16.07.20 09:15 Сейчас в теме
Добрый день! А можно в этом куске
//в обработке
&НаСервереБезКонтекста
Функция ОформитьНаСервере(Ссылка)
	Док = Ссылка.ПолучитьОбъект();
	//Изменить документ
	//в соответствие с логикой обработки
	Возврат МойМодуль.СохранитьОбъектВХранилище(Док);
КонецФункции

добавить код, как изменить строки в одной из табличных частей.
6. plainer 21 16.07.20 16:52 Сейчас в теме
(3) Табличные части? Как обычно:
//в обработке
&НаСервереБезКонтекста
Функция ОформитьНаСервере(Ссылка)
	Док = Ссылка.ПолучитьОбъект();
	//Изменить документ
	//в соответствие с логикой обработки
	//Ну, к примеру
	Для каждого Стр из Док.Товары цикл
		Стр.Количество = Стр.Количество *2;
	КонецЦикла;

	НоваяСтрока = Док.Товары.Добавить;
	СтараяСтрока = Док.Товары[ВзятыйОткудатоНомерСтроки -1];
	ЗаполнитьЗначениеСвойств(НоваяСтрока, СтараяСтрока);
	НоваяСтрока.Количество = 1;
	СтараяСтрока.Количество = СтараяСтрока.Количество -1;

	Док.Товары.Удалить(ЕщеКакойтоНомерСтроки);
	//и т. п.
Возврат МойМодуль.СохранитьОбъектВХранилище(Док);
КонецФункции
Показать
4. Hla 85 16.07.20 09:52 Сейчас в теме
Сделала проверку во все ли добавленные функции и процедуры попадаю. Оказывается в
&НаСервере
Процедура Расш1_ПриЧтенииНаСервереПеред(ТекущийОбъект)
	Если Параметры.Свойство("НесохраненныйДокумент") Тогда
		МойМодуль.ВзятьОбъектИзХранилища(Объект, Параметры.НесохраненныйДокумент);
		Модифицированность = Истина;
	КонецЕсли;
КонецПроцедуры
сюда не попадаю. Можно в картинках показать как вы добавили это в расширение. Прикладываю свой скрин.
Прикрепленные файлы:
5. plainer 21 16.07.20 15:59 Сейчас в теме
(4) В зависимости от выбора на 2-й картинке у вас будет или 4я, или 5я. И далее вставить туда текст.
Прикрепленные файлы:
7. Hla 85 17.07.20 06:14 Сейчас в теме
11. German_Tagil 43 27.07.20 07:02 Сейчас в теме
Жаль - недели две назад делал запуск отчета из формы документа и запись данных из отчета
в документ - одним из вариантов была мысль о хранилище но не пошло...
сделал по другому
Но в заметки себе поставил - тема интересная ....
Оставьте свое сообщение