В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача открытия формы обработки или документа таким образом, чтобы в открывшейся форме сразу отображались данные из уже существующего объекта, включая его табличные части и реквизиты. Эта задача может вызвать вопросы, особенно при работе с обработками, поскольку их объекты не всегда имеют прямое соответствие с базой данных, как у документов. Рассмотрим различные подходы к решению этой проблемы, начиная от простых и заканчивая рекомендованными практиками.
При открытии формы и необходимости отображения в ней данных из существующего объекта, нам нужно передать эти данные в новую форму. Существует несколько способов реализации этой задачи, каждый из которых имеет свои особенности и области применения.
ПараметрыОткрытия и их обработка в процедуре ПриСозданииНаСервере. Это наиболее гибкий и рекомендуемый подход в управляемом приложении, позволяющий тонко настраивать процесс инициализации формы.Давайте разберем каждый из этих методов подробнее.
Этот способ позволяет передать все данные объекта (или его части) в основной реквизит открываемой формы. Это особенно актуально для обработок, когда форма обработки содержит основной реквизит типа ОбработкаОбъект.<ИмяОбработки>.
Ситуация: У нас есть существующий объект обработки (или документа), и мы хотим открыть новую форму обработки (или документа), в которой сразу будут отображены все данные этого объекта, включая табличные части.
Пример кода для вызывающей стороны:
&НаСервере
Функция ОткрытьФормуОбработкиСДаннымиНаСервере(ИмяОбработки, ОбъектИсточник)
Форма = ПолучитьФорму("Обработка." + ИмяОбработки + ".Форма.ФормаОбработки", , ОбъектИсточник); // ОбъектИсточник может быть передачей ключевого объекта
// Если объект формы (ОсновнойРеквизитФормы) совпадает по типу с ОбъектИсточник,
// мы можем скопировать данные напрямую.
Если Форма.Объект <> Неопределено Тогда
КопироватьДанныеФормы(ОбъектИсточник, Форма.Объект);
КонецЕсли;
Возврат Форма;
КонецФункции
&НаКлиенте
Процедура ОткрытьФормуОбработкиНаКлиенте()
// Предположим, у нас уже есть ОбъектМоейОбработки, который нужно отобразить
// Например, это может быть Объект текущей формы, или ранее прочитанный объект
ОбъектДляПередачи = РеквизитФормыВЗначение("Объект"); // Получаем текущий объект формы или другой
Если ОбъектДляПередачи = Неопределено Тогда
// Создадим новый объект обработки для примера
ОбъектДляПередачи = РеквизитыОбъекта(); // Предположим, что это функция, которая возвращает объект
КонецЕсли;
// ... здесь заполняем ОбъектДляПередачи данными, например, его табличную часть
// ОбъектДляПередачи.МояТабличнаяЧасть.Добавить().Поле1 = "Значение1";
// ОбъектДляПередачи.МояТабличнаяЧасть.Добавить().Поле1 = "Значение2";
ФормаДляОткрытия = ОткрытьФормуОбработкиСДаннымиНаСервере("МояОбработка", ОбъектДляПередачи);
ФормаДляОткрытия.Открыть(); // Открываем форму, полученную с сервера
КонецПроцедуры
Объяснение:
ПолучитьФорму() возвращает экземпляр формы, не открывая ее сразу. Это позволяет нам выполнить предварительные действия с формой.КопироватьДанныеФормы(). Она предназначена для копирования данных между объектами ДанныеФормы. В нашем случае мы копируем данные из ОбъектИсточник (который может быть как объектом базы данных, так и программно созданным объектом) в основной реквизит формы Форма.Объект. Это обеспечивает, что все реквизиты и табличные части объекта будут перенесены в форму.Форма.Открыть(), чтобы отобразить форму пользователю.Этот подход хорошо работает, когда структура данных открываемой формы совпадает со структурой передаваемого объекта. Например, если основная форма обработки имеет реквизит типа ОбъектОбработки.<ИмяОбработки>, а мы передаем объект именно этого типа.
Иногда нет необходимости передавать весь объект, а достаточно инициализировать лишь несколько конкретных реквизитов открываемой формы. В этом случае мы можем получить форму, а затем напрямую присвоить значения ее реквизитам перед открытием.
Ситуация: Нужно открыть форму документа и установить значение одного из его реквизитов, например, для фильтрации данных или предзаполнения.
Пример кода для вызывающей стороны:
&НаКлиенте
Процедура ОткрытьФормуДокументаСПараметром()
// Предположим, что "СвойДокумент" имеет реквизит "НужныйРеквизит"
// и табличную часть "ТабличнаяЧастьДокумента"
МояФорма = ПолучитьФорму("Документ.СвойДокумент.Форма.ФормаТЧ");
// Присваиваем значение конкретному реквизиту формы.
// Если "НужныйРеквизит" является реквизитом формы, доступ к нему прямой.
// Если же это реквизит объекта формы, то доступ через МояФорма.Объект.НужныйРеквизит
МояФорма.Объект.НужныйРеквизит = "ПредзаполненноеЗначение";
// Если нужно предзаполнить табличную часть, то делаем это по аналогии
// с МояФорма.Объект.ТабличнаяЧастьДокумента
// Например, если ТабличнаяЧастьДокумента - это коллекция формы,
// МояФорма.ТабличнаяЧастьДокумента.Очистить();
// НоваяСтрока = МояФорма.ТабличнаяЧастьДокумента.Добавить();
// НоваяСтрока.Поле1 = "ЗначениеТЧ1";
// НоваяСтрока.Поле2 = "ЗначениеТЧ2";
МояФорма.Открыть();
КонецПроцедуры
Объяснение:
ПолучитьФорму() для получения экземпляра формы.МояФорма.Открыть() отображает форму пользователю с уже установленными данными.Этот подход прост и эффективен для небольшого количества реквизитов. Однако он менее гибок, чем передача параметров, поскольку требует непосредственного знания структуры открываемой формы и может привести к нежелательным зависимостям.
ПараметрыОткрытия и обработка в ПриСозданииНаСервереВ управляемом приложении 1С:Предприятие 8.3 этот метод является наиболее правильным, гибким и рекомендованным для передачи данных в открываемую форму. Он позволяет четко определить, какие данные и каким образом должны быть переданы и обработаны.
Ситуация: Необходимо передать в форму обработки или документа ссылку на существующий объект, структуру с произвольными данными или идентификатор, чтобы форма могла самостоятельно загрузить и отобразить нужные данные.
Пример кода для вызывающей стороны:
&НаКлиенте
Процедура ОткрытьФормуСПараметрами()
// 1. Создаем структуру с параметрами, которые хотим передать в открываемую форму.
// Ключ может быть ссылкой на объект, который нужно открыть, или произвольной строкой.
// Например, передадим ссылку на существующий документ или обработку.
// А также дополнительные данные, например, для фильтрации или предзаполнения.
ПараметрыДляФормы = Новый Структура;
ПараметрыДляФормы.Вставить("Ключ", ОбъектСуществующегоДокументаИлиОбработки); // Ссылка на документ/обработку
ПараметрыДляФормы.Вставить("ДополнительныйПараметр", "НекоеЗначение");
ПараметрыДляФормы.Вставить("ДанныеДляТЧ", МассивДанныхДляТабличнойЧасти); // Например, массив структур
// 2. Открываем форму, передавая структуру с параметрами.
// Имя формы указываем полностью: "ВидОбъекта.ИмяОбъекта.Форма.ИмяФормы".
ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаСТабличнойЧастью", ПараметрыДляФормы);
// Для документов:
// ОткрытьФорму("Документ.СвойДокумент.Форма.ФормаТЧ", ПараметрыДляФормы);
КонецПроцедуры
Пример кода для открываемой формы (в модуле формы, процедура ПриСозданииНаСервере):
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Проверяем наличие переданных параметров.
Если Параметры.Свойство("Ключ") Тогда
СсылкаНаОбъект = Параметры.Ключ;
// 2. Загружаем данные объекта в основной реквизит формы.
Если ТипЗнч(СсылкаНаОбъект) = Тип("ДокументСсылка.СвойДокумент") Тогда
ОбъектДокумента = СсылкаНаОбъект.ПолучитьОбъект();
КопироватьДанныеФормы(ОбъектДокумента, Объект); // Объект - это основной реквизит формы
ИначеЕсли ТипЗнч(СсылкаНаОбъект) = Тип("ОбработкаСсылка.МояОбработка") Тогда
// Для обработок ссылка может быть фиктивной, но ее можно использовать
// как идентификатор для получения нужных данных.
// Если форма обработки имеет основной реквизит, то:
// ОбъектОбработки = РеквизитФормыВЗначение("Объект"); // Получаем текущий объект формы
// ЗаполнитьОбъектОбработкиПоДанным(ОбъектОбработки, СсылкаНаОбъект); // Наша функция для заполнения
// Или, если форма сама должна создать объект и заполнить его
// Например, если основной реквизит формы имеет тип ДанныеФормыСтруктура
// или ДанныеФормыКоллекция, то нужно заполнять его вручную.
// Пример заполнения табличной части:
// Допустим, в Параметрах мы передали МассивДанныхДляТабличнойЧасти
Если Параметры.Свойство("ДанныеДляТЧ") Тогда
МассивДанных = Параметры.ДанныеДляТЧ;
Для Каждого СтрокаДанных Из МассивДанных Цикл
НоваяСтрока = Объект.МояТабличнаяЧасть.Добавить(); // Объект.МояТабличнаяЧасть - реквизит формы
НоваяСтрока.Поле1 = СтрокаДанных.Поле1;
НоваяСтрока.Поле2 = СтрокаДанных.Поле2;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// 3. Обрабатываем другие переданные параметры.
Если Параметры.Свойство("ДополнительныйПараметр") Тогда
ЗначениеДополнительногоПараметра = Параметры.ДополнительныйПараметр;
// Используем его для инициализации других реквизитов формы
// Например, РеквизитФормы1 = ЗначениеДополнительногоПараметра;
КонецЕсли;
// Важно: если передан ключевой параметр, его можно объявить явно в свойствах формы
// на закладке "Параметры". Тогда проверка Параметры.Свойство("Ключ") не требуется,
// и к параметру можно будет обратиться напрямую как Ключ.
КонецПроцедуры
Объяснение:
ОткрытьФорму() позволяет передать вторым аргументом структуру ПараметрыОткрытия. Эта структура может содержать любые данные, которые вы хотите передать в новую форму. Рекомендуется использовать ключ "Ключ" для ссылки на основной объект, который должна открыть форма (например, ДокументСсылка или ОбработкаСсылка).ПриСозданииНаСервере: В открываемой форме эти параметры становятся доступны в коллекции Параметры в процедуре ПриСозданииНаСервере. Эта процедура выполняется на сервере в момент создания экземпляра формы.ПолучитьОбъект() и скопировать его данные в основной реквизит формы с помощью КопироватьДанныеФормы(). Для обработок, если основной реквизит формы не является объектом, связанным с БД, мы можем вручную заполнить его реквизиты и табличные части, используя данные, переданные в Параметры.Параметры без дополнительной проверки на наличие свойства.Ключ, который часто содержит ссылку на объект) влияют на уникальность формы (предотвращая открытие нескольких одинаковых форм для одного и того же объекта) и сохраняются на протяжении всей жизни формы. Обычные параметры существуют только в момент создания формы. Если обычные параметры необходимы для дальнейшей работы формы, их следует сохранить в реквизитах формы.Этот подход обеспечивает наилучшую архитектуру, разделяя логику вызова формы от логики ее инициализации, и делает код более поддерживаемым.
Часто данные для табличной части нужно не просто передать, а загрузить из базы данных на основе переданных параметров. Это можно сделать также в процедуре ПриСозданииНаСервере.
Ситуация: В форму обработки передается ссылка на документ, и нам нужно отобразить в табличной части обработки данные из табличной части этого документа, но с какой-то дополнительной фильтрацией или преобразованием.
Пример кода в открываемой форме (в модуле формы, процедура ПриСозданииНаСервере):
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ДокументОснование") Тогда
СсылкаНаДокумент = Параметры.ДокументОснование;
// Очищаем существующую табличную часть формы, если она уже содержит данные
Объект.ТабличнаяЧастьФормы.Очистить(); // Объект - основной реквизит формы, ТабличнаяЧастьФормы - его реквизит
// Создаем запрос для получения данных из табличной части документа-основания
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокументОснованиеТовары.Номенклатура,
| ДокументОснованиеТовары.Количество,
| ДокументОснованиеТовары.Цена
|ИЗ
| Документ.МойДокумент.Товары КАК ДокументОснованиеТовары
|ГДЕ
| ДокументОснованиеТовары.Ссылка = &СсылкаНаДокумент
| И ДокументОснованиеТовары.Количество > 0";
Запрос.УстановитьПараметр("СсылкаНаДокумент", СсылкаНаДокумент);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Заполняем табличную часть формы на основе результата запроса
Для Каждого СтрокаРезультата Из РезультатЗапроса Цикл
НоваяСтрокаТЧ = Объект.ТабличнаяЧастьФормы.Добавить();
НоваяСтрокаТЧ.Номенклатура = СтрокаРезультата.Номенклатура;
НоваяСтрокаТЧ.Количество = СтрокаРезультата.Количество;
НоваяСтрокаТЧ.Цена = СтрокаРезультата.Цена;
// ... другие поля табличной части формы
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Объяснение:
ТаблицаЗначений) итерируется, и для каждой строки результата создается новая строка в табличной части формы, которая затем заполняется соответствующими значениями.Этот метод очень мощный и гибок, так как позволяет формировать данные для табличной части формы практически произвольным образом.
ОткрытьФорму() и ПолучитьФорму()На форуме часто обсуждается разница между этими двумя методами, и важно понимать, когда какой использовать.
Метод ОткрытьФорму():
ПараметрыОткрытия для инициализации формы.ОткрытьФорму(), продолжает выполняться немедленно. Для обработки результата работы с формой (например, выбора элемента) необходимо использовать механизм оповещений (ОписаниеОповещения).ПолучитьФорму() + Открыть().Метод ПолучитьФорму():
Открыть() или ОткрытьМодально().Мы рекомендуем использовать ОткрытьФорму() с передачей параметров через ПараметрыОткрытия в большинстве случаев, поскольку это соответствует современным подходам управляемого приложения и позволяет избежать излишних серверных вызовов.
ОткрытьМодально() против Открыть() / ОткрытьФорму()Понимание отличий между модальным и немодальным открытием форм критически важно для корректной работы приложения и обеспечения удобства пользователя.
Форма.ОткрытьМодально():
ОткрытьМодально(), приостанавливается до закрытия модального окна и получает возвращаемое значение (если оно было задано в закрываемой форме методом Закрыть(Значение)).ОткрытьМодально() может привести к открытию нового всплывающего окна браузера, которое может быть заблокировано браузером как "всплывающее", или которое блокирует весь интерфейс браузера. Это негативно сказывается на пользовательском опыте.Форма.Открыть() (после ПолучитьФорму()) и ОткрытьФорму():
ОписаниеОповещения), который позволяет выполнить код после закрытия формы или после выполнения определенного действия в ней.Мы рекомендуем использовать немодальные подходы (ОткрытьФорму() или ПолучитьФорму() с последующим Открыть()) и механизм оповещений для обработки результатов. Метод ОткрытьМодально() следует применять только в случаях, когда это строго необходимо для сохранения логики работы или совместимости с очень старым кодом, и при этом необходимо учитывать его ограничения в веб-клиенте.
Мы рассмотрели различные способы открытия форм обработок и документов в 1С:Предприятии 8.3 с передачей данных, включая табличные части и реквизиты. Выяснили, что наиболее гибким и соответствующим лучшим практикам является подход с использованием ОткрытьФорму() и передачей параметров через структуру ПараметрыОткрытия, которые затем обрабатываются в процедуре ПриСозданииНаСервере открываемой формы.
Помните, что выбор конкретного метода зависит от вашей задачи и сложности передаваемых данных. Однако, всегда стремитесь к использованию рекомендованных механизмов платформы для создания поддерживаемого и эффективного кода.