Первая часть проблемы в том, что сам Объект (ДокументОбъект, СправочникОбъект, ОбработкаОбъект) живет на сервере, а на клиент передается только его копия с воссозданной структурой. Поэтому периодически приходится прибегать к методам вроде «РеквизитФормыВЗначение». В случае с основной формой объекта проблем почти нет. Реквизиты формы заполняются, реквизиты объекта тоже.
Но вторая часть проблемы наступает тогда, когда нам нужно вывести дополнительную форму и часть реквизитов заполнить в ней. Тогда выясняется, что реквизиты на дополнительной форме не заполняются и обратно тоже не передаются. Хотя форма не произвольная, а принадлежит обработке, и реквизит Объект – основной, и структура объекта на ней тоже воссоздается. Но данных почему-то нет… Для тех, кто с управляемыми формами работает не очень долго или не очень плотно, это становится проблемой, как я выяснил, начитавшись форумов с подобными запросами. А вся соль в том, что у этой дополнительной формы реквизит Объект – свой. И он не имеет отношения к Объекту основной формы. Воссоздается только структура объекта, без данных. Такова суровая реальность тонкого клиента )))
Вот и я не так давно столкнулся с этой проблемой и потратил пару часов на «курение» различных форумов. Мне нужно было сделать внешнюю обработку, у которой есть несколько дополнительных форм, в которых вводятся дополнительные данные, в том числе табличные. В этом случае все реквизиты должны храниться в реквизитах и табличных частях обработки и выводиться фрагментарно на различных формах. Этакая замкнутая мини-система. Данные из обработки потом сохраняются во внешнюю БД, но это уже отдельная история.
В основном на что я наткнулся при поисках, это просьба о помощи и куча стёба без дельных предложений.
Несколько решений, правда, предложено было, но все они выглядели достаточно громоздко. В основном это либо метод ПолучитьФорму(), потом заполнение реквизитов полученной формы и ее модальное открытие, а затем выполнение операций после ее закрытия. Но в случае отказа от модальности 1С постоянно на это ругается. Другой вариант – создание структуры, занесение в нее значений всех необходимых реквизитов из основной формы, а потом передача этой структуры в качестве входящего параметра при открытии дополнительной формы. А при закрытии дополнительной формы нужно снова создать структуру и передать ее обратно в основную форму. При этом в обеих формах нужно прописать чтение этих параметров и заполнение реквизитов у получателя. На одном из форумов, где предлагали подобный метод, кто-то справедливо возразил, что при передаче сотни реквизитов и десятка таблиц это становится проблемой. В итоге все чувствуют, что решение должно быть проще, но никто его так и не озвучил. Так много лишнего кода мне прописывать очень не хотелось, поэтому я продолжил копать в поисках идеального решения. Пара высказанных мыслей подсказали мне в каком направлении копать, и… Решение оказалось простым, как всё гениальное!
Итак.
Поскольку структура объектов в обеих формах у нас идентична, различается только перечень реквизитов, которые видны на форме, ничто не мешает нам передать целиком весь Объект и заполнить его копию, а потом просто вернуть его обратно. Главное – правильно это сделать.
Допустим, нам нужно по кнопке открыть дополнительную форму с парой реквизитов и табличной частью обработки, заполнить ее, а потом вернуть назад, при этом таблица на основной форме не отображается.
На стороне основной формы мы пишем:
&НаКлиенте
Процедура ОткрытиеСправочника(Команда)
ОповещениеОВыборе = Новый ОписаниеОповещения("ОткрытиеСправочникаПослеВыбора", ЭтаФорма, Новый Структура("ИмяКоманды", Команда.Имя));
ОткрытьФорму("ПолноеИмяФормы",, ЭтаФорма,,,, ОповещениеОВыборе, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
На стороне дополнительной формы мы пишем так:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
КопироватьДанныеФормы(ВладелецФормы.Объект, Объект);
КонецПроцедуры
После этого дополнительная форма будет заполнена. Затем мы делаем необходимые махинации с реквизитами и таблицами и хотим передать результат обратно. для этого мы прописываем событие у дополнительной формы:
&НаКлиенте
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Закрыть(Объект);
КонецПроцедуры
И, соответственно, снова на стороне основной формы нам нужно принять результат:
&НаКлиенте
Процедура ОткрытиеСправочникаПослеВыбора(РезультатВыбора, ДопПараметры) Экспорт
КопироватьДанныеФормы(РезультатВыбора, Объект);
// все данные объекта заполнились
Если ДопПараметры.ИмяКоманды = "ТутБылоПереданоИмяКоманды" Тогда
// выполняем дополнительные процедуры, если они нужны
КонецЕсли;
КонецПроцедуры
Возможно, для кого-то это решение покажется очевидным и он давно именно так и делает, но мне раньше подобного делать не приходилось, а при чтении форумов я подобного решения не нашел. Надеюсь, кому-то мое изыскание пригодится.
Кстати, с полным именем формы тоже могут возникнуть некоторые неудобства, ведь полное имя задается как «ВнешняяОбработка.ИмяОбработки.Форма.ИмяФормы». И если обработку переименовать, то вызов доп. форм тоже придется исправить. Одно, что у нас в таком случае не меняется — это свойство ИмяФормы. Таким образом, получив полное имя основной и подменив последний фрагмент на имя доп. формы, мы получим полное имя доп. формы. И для этого можно использовать вот такую небольшую функцию:
&НаКлиенте
Функция ПолноеИмяФормы(НужноеИмя) Экспорт
НекийМассив = СтрРазделить(ИмяФормы, ".", Ложь);
НекийМассив[НекийМассив.ВГраница()] = НужноеИмя;
Возврат СтрСоединить(НекийМассив, ".");
КонецФункции
Для решения этой задачи нужно использовать хранилище значения. Посмотрите как сделан механизм подбора для табличных частей документов.
(1) TODD22, несомненно, можно использовать и хранилище значения. где-то этот вариант даже предлагался. но в моем случае меньше кода и всё работает. поскольку открытие всех форм происходит по сути в рамках одного объекта, меня такой вариант на данном этапе вполне устроил.
но если Вы объясните, почему именно «нужно», буду признателен за ликбез.
«Мы все учились понемногу,
Чему-нибудь и как-нибудь…»
(2)
С хранилищем кода будет столько же….
Почему именно хранилище значения не знаю. Но на спеца по платформе есть задача в которой нужно организовать функцию подбора товаров в таб часть документа. Она решается через хранилище значения.
(3) TODD22, так то подбор — из другой формы другого объекта ИБ. Автор же манипулирует формами и данными внутри ОДНОГО объекта. Так что решение ТС мне кажется более изящным.
Тоже пришлось сталкиваться с подобной задачей для мобильного решения, но реквизитов было немного. Поэтому решение было связано с передачей заполненной структуры.
Беру на заметку вашу статью! спасибо!
Там все просто, могу привести пример если актуально
Вот как формируется АдресВХ:
Показать
На открываемой форме ПриСозданииНаСервере читаешь эти параметры.
(7) Тильчик, спасибо за пример, наверняка кому-нибудь тоже пригодится. может, даже и мне )))
но это имеет смысл при передаче в другие объекты либо при передаче произвольных данных. в моем случае я бы не стал так делать. у меня и таблиц в обработке с десяток, и реквизитов в них хватает…
(8)
Таблица.Выгрузить() и Таблица.Загрузить()
Мне кажется, я участвовал в одном из обсуждений, где было выработано такое решение. Не помню, кто именно его предложил 🙂
Помню, что метод глобального контекста КопироватьДанныеФормы(), к моему стыду, стал для меня открытием.
Так что статье плюс.
я в ЗУП 3.0 добавлял новые формы к документу. для того чтоб форма была связана с текущим объектом в параметрах открытия нужно добавить поле «Ключ» и записать туда «Объект.Ссылка». прекрасно работает. хотя некоторые и жалуются на производительность… типовая конфигурация не брезгует таким способом открытия форм.
(11) biimmap, да, про ключ я тоже читал. и был не прочь его использовать. но у внешней обработки нет ссылки, а у ее доп. форм параметра «ключ»
(9) TODD22, каждую? а смысл, если можно оптом?
(11) biimmap, В статье речь о другом.
я обратил внимание на ссылочные типы… для обработки только хранилище значения. пример использования есть в ЗУПе 3-м. работа формы справочника штатного расписания.
А если записывать объект из дополнительной формы, то в базе будет перезаписан исходный объект, или будет создан новый как копия исходного?
(17) sigmov, круто у вас настроен шаблон вставки кода автора изменения ))
(17) sigmov, не приходило в голову проверить запись. спасибо, взял на заметку.
нечто подобное Вашему решению у меня тоже в мыслях было. пока не наткнулся на описанное в статье. сэкономило много времени.
благодарю, думаю многим будет полезно
Делал редактирование зависимой табличной части документа в диалоге, где редактируемая табличная часть открывается с отбором по значению первой табличной части.
Реализовал через передачу таблицы значений в доп форму, но описанный метод позволяет сделать все гораздо проще…
Как у этот метода с производительностью?
Документ самописный и достаточно объемный — 4 таб. части, десятки реквизитов…
(21) тормозов не наблюдал. использую его в своей внешней обработке для открытия доп. форм, передачи данных в них и обратно. у объекта «Обработка» чуть меньше десятка своих реквизитов, полтора десятка табличных частей, в каждой из которых от 5-ти до 15-ти реквизитов. передаётся мнгновенно
Столкнулся с такой проблемой — команда Закрыть(Объект) возвращает значение по умолчанию(неопределенно) в процедуру обработку(РезультатВыбора).
Форма родитель:
Показать
Форма приёмник:
Показать
(23) а обе формы относятся к одной и той же обработке? обработка встроенная или внешняя?
(24) к одной обработке, обработка встроенная.
сделал в итоге через оповещение формы
(25) несколько раз перечитал ваш код, сравнил с рабочим у меня. всё должно работать. значит, где-то идёт переназначение или ещё что-нибудь. если предоставите cf или хотя бы обработку, попробую найти проблему
(26)
Может дело в том, что конфигурация в режиме совместимости интерфейса 8.2 и режиме совместимости 8.3.2 работает?
Конфигурация самописная
(27) режим совместимости, похоже, ни при чем. у меня она тоже не сработала.
а вот новая, там же добавленная — сработала. возможно, вы при создании доп. форм указывали «произвольная», а не «форма обработки»?
во вложении с моей добавленной формой
Не приходилось решать подобную задачу в далеком 2015-м. Сегодня, в 2018 на 8.3.11 у меня кода получилось значительно меньше, просто вызываю КопироватьДанныеФормы() для передачи данных в обе стороны.
Родительская форма:
Дочерняя форма:
Показать