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

13.07.20

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

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

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

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

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

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

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

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

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

 

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

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

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

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

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

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

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

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

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

 

Вступайте в нашу телеграмм-группу Инфостарт

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

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    3286    Abysswalker    7    

44

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

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

14.05.2025    6121    DeerCven    15    

57

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    48034    dimanich70    83    

168

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

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

1 стартмани

18.03.2024    7242    6    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

12.02.2024    59821    atdonya    31    

69

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

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

30.11.2023    9021    ke.92@mail.ru    17    

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

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

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

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

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