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