Как программно изменить данные объекта в одной управляемой форме из другой и отобразить изменения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разбор типичной ошибки: почему не работает РеквизитФормыВЗначение

Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка вызвать РеквизитФормыВЗначение из контекста "чужой" формы приводит к ошибке "Недопустимое значение параметра". Выясним причину этого поведения. Данный метод предназначен для работы внутри серверного контекста конкретной формы. Он ищет реквизит именно в той форме, где исполняется код. Если вы пытаетесь программно изменить объект ДокЗагрузкиСсылка, находясь в форме обработки, платформа просто "не видит" реквизитов формы открытого документа.

Кроме того, важным моментом является точность именования. В примере автора использовалась строка "Об " с лишним пробелом. Платформа 1С крайне чувствительна к синтаксису: имя реквизита в строковом параметре должно строго соответствовать его имени в дереве объектов формы.

Метод 1: Использование механизмов ЗначениеВДанныеФормы и контекста формы

Если нам нужно обновить данные объекта, который является основным реквизитом формы, но мы находимся в другом контексте, стандартный подход через ЗначениеВРеквизитФормы может быть ограничен. Проанализируем более универсальный метод ЗначениеВДанныеФормы. Этот метод позволяет поместить прикладной объект (например, ДокументОбъект) непосредственно в структуру данных управляемой формы.

Однако стоит помнить, что для прямого использования этого метода нам нужен доступ к программному объекту формы. Если формы не связаны иерархически (например, "Владелец - Дочернее окно"), этот путь будет затруднен. Рассмотрим, как правильно выполнить преобразование, если у нас есть доступ к данным:


// Пример на сервере, если мы работаем внутри формы документа
ДокОбъект = РеквизитФормыВЗначение("Объект");
// Вносим изменения
ДокОбъект.Комментарий = "Изменено программно";
// Возвращаем данные обратно в форму
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

Метод 2: Механизм оповещений (Оповестить и ОбработкаОповещения)

Это самый рекомендуемый и "чистый" способ взаимодействия в управляемом приложении. Разберем его по шагам.

Шаг 1. Отправка оповещения. В форме, где производятся расчеты или изменения, мы вызываем процедуру Оповестить. Она работает на клиенте и рассылает сигнал всем открытым окнам приложения.


// В форме-источнике (на клиенте)
ПараметрыИзменения = Новый Структура;
ПараметрыИзменения.Вставить("НоваяСумма", 1500);
ПараметрыИзменения.Вставить("НовыйКомментарий", "Обновлено из подбора");

Оповестить("ОбновитьДанныеДокумента", ПараметрыИзменения, ЭтаФорма);

Шаг 2. Прием оповещения. В основной форме документа (которую нужно обновить) создаем стандартный обработчик ОбработкаОповещения.


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

Преимущество этого метода в том, что нам не нужно передавать тяжелые объекты между формами — мы передаем только конкретные измененные значения.

Метод 3: Использование ОписанияОповещения (Callback)

Если одна форма открывается из другой для выбора данных, правильно будет использовать ОписаниеОповещения. Рассмотрим ситуацию: мы открываем вспомогательную форму и хотим получить результат её работы после закрытия.

Проанализируем пример кода:


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

&НаКлиенте
Процедура ПослеЗакрытияФормыВыбора(Результат, ДополнительныеПараметры) Экспорт
    Если Результат <> Неопределено Тогда
        // Заполняем реквизиты формы данными из результата
        ЗаполнитьЗначенияСвойств(Объект, Результат);
    КонецЕсли;
КонецПроцедуры

В самой вспомогательной форме при закрытии мы должны передать данные:


&НаКлиенте
Процедура ЗавершитьРаботу(Команда)
    СтруктураРезультата = Новый Структура("Комментарий", "Текст из формы выбора");
    Закрыть(СтруктураРезультата);
КонецПроцедуры

Метод 4: ОповеститьОбИзменении (системный механизм)

Если изменения объекта происходят на сервере с записью в базу данных (например, через фоновое задание или другую форму, которая сразу фиксирует изменения), нам нужно заставить текущую форму перечитать данные. Вызов ОповеститьОбИзменении(Ссылка) — это сигнал платформе о том, что объект в базе изменился. 1С автоматически обновит динамические списки и открытые формы, связанные с этой ссылкой.

Важно: Этот метод работает только для уже записанных объектов. Если ваш документ еще находится в стадии заполнения и не имеет ссылки в БД, этот метод не поможет.

Метод 5: Метод ОбновитьОтображениеДанных()

Часто программисты путают обновление данных и обновление отображения. Выясним разницу. Метод ЭтаФорма.ОбновитьОтображениеДанных() не ходит на сервер и не меняет значения в Объект. Он лишь заставляет визуальные элементы (поля ввода, таблицы) перерисоваться в соответствии с текущим состоянием реквизитов формы. Его следует вызывать тогда, когда вы программно изменили реквизит на клиенте, но связанные с ним элементы (например, вычисляемые поля или условное оформление) не успели среагировать.

Рекомендации по выбору решения

  1. Если формы не связаны родством: Оптимально использовать Оповестить() и ОбработкаОповещения. Это обеспечивает слабую связность кода и высокую стабильность.
  2. Если одна форма открывает другую для выбора: Однозначно используйте ОписаниеОповещения.
  3. Если изменения касаются структуры данных (например, всей таблицы): На сервере можно использовать КопироватьДанныеФормы(Источник, Приемник), что работает значительно быстрее ручного перебора строк.
  4. Если вы программно изменили объект в БД: Используйте ОповеститьОбИзменении(Ссылка).

Таким образом, успех программного изменения данных из другой формы зависит от правильного понимания контекста и выбора соответствующего метода передачи информации между клиентскими окнами управляемого приложения.

← На главную