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