Почему не обновляется реквизит табличной части, выведенный через точку, и как это исправить?

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

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

Проанализируем причину: почему платформа «молчит» об изменениях?

Для начала разберем внутренний механизм работы платформы. Когда мы выводим данные в колонку табличной части через путь к данным вида Объект.Товары.СсылкаНаРеализацию.ВремяОтгрузки, платформа 1С применяет механизмы оптимизации. Чтобы не запрашивать базу данных при каждой перерисовке формы, значения, полученные по ссылке, сохраняются в так называемом кэше представлений объектов на стороне клиента.

Когда вы программно изменяете связанный документ (Реализацию) на сервере через ПолучитьОбъект().Записать(), база данных обновляется корректно. Но клиентское приложение (Тонкий или Толстый клиент) ничего не знает о том, что данные по этой конкретной ссылке в его локальном кэше стали неактуальными. В результате пользователь видит старое значение, которое «застряло» в памяти сеанса. Это объясняет, почему помогает только полный перезапуск программы — при новом входе кэш очищается и формируется заново.

Способ 1. Использование метода ОповеститьОбИзменении()

Это стандартный и наиболее правильный способ сообщить платформе, что данные объекта по определенной ссылке изменились. Метод ОповеститьОбИзменении() принудительно очищает закэшированные данные для указанного объекта на клиенте.

Рассмотрим пример кода. Если мы меняем данные в серверном контексте, нам необходимо передать ссылку на измененный объект обратно на клиент и там вызвать оповещение:


// Код на клиенте
&НаКлиенте
Процедура ИзменитьДанныеРеализаций()
    
    // Вызываем серверную процедуру для изменения данных в БД
    ИзменитьДанныеНаСервере();
    
    // Оповещаем систему, что ссылки изменились, чтобы обновить кэш в форме
    Для Каждого СтрокаТЧ Из Объект.ВашаТабличнаяЧасть Цикл
        ОповеститьОбИзменении(СтрокаТЧ.Реализация);
    КонецЦикла;

КонецПроцедуры

Важный нюанс: метод ОповеститьОбИзменении() доступен только в клиентском контексте. Если вы вносите изменения внутри серверной процедуры формы, вызов оповещения нужно делать сразу после возврата управления на клиент.

Способ 2. Массовое оповещение по типу объекта

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


// Сброс кэша для всех объектов типа "РеализацияТоваровУслуг"
ОповеститьОбИзменении(Тип("ДокументСсылка.РеализацияТоваровУслуг"));

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

Способ 3. Решение для фоновых заданий и HTTP-сервисов

Выясним, как быть в ситуации, когда данные меняются «извне» (например, регламентным заданием или через внешнее API), и метод ОповеститьОбИзменении() вызвать физически невозможно, так как нет активного клиентского контекста, связанного с этим процессом.

В этом случае можно использовать следующие подходы:

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

Рекомендации по архитектуре данных

Если вы понимаете, что актуальность данных «через точку» является критически важной и данные меняются часто, проанализируем альтернативные варианты проектирования:

1. Дублирование данных в реквизиты ТЧ. Если ВремяОтгрузки должно быть зафиксировано на момент работы с документом, целесообразно создать физический реквизит в табличной части вашего документа и записывать значение туда. Это избавит от проблем с кэшированием и повысит скорость формирования отчетов.

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

3. Метод ОбновитьОтображениеДанных(). Не путайте его с обновлением кэша. Этот метод просто заставляет форму перерисовать элементы, используя уже имеющиеся в памяти данные. В случае проблемы с кэшем «через точку» он, как правило, не помогает, так как данные в памяти клиента остаются старыми.

Подведем итог: магическое «необновление» данных — это не глюк платформы, а следствие работы механизма кэширования представлений. Используйте ОповеститьОбИзменении() для точечного обновления и пересматривайте архитектуру в пользу хранения данных в самой ТЧ, если работа требует высокой оперативности изменений.

← На главную