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

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

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

Разберем причину: магия кэширования представлений

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

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

Выясним, почему стандартные методы обновления не работают

Многие разработчики пытаются использовать метод ЭтаФорма.Прочитать(). Давайте проанализируем, почему это не помогает. Метод Прочитать() перечитывает данные самого документа (его реквизиты и строки табличных частей). Он обновляет ссылку (её внутренний идентификатор GUID), но если ссылка в документе осталась прежней (вы изменили только данные внутри объекта, на который она указывает), то для платформы данные в строке не изменились. Следовательно, перерисовывать представление ссылки она не будет, а возьмет его из того самого «устаревшего» кэша.

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

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

Рассмотрим пример кода, который необходимо выполнить на клиенте после того, как вы программно изменили серию на сервере:


// Предположим, мы изменили серию в серверной процедуре
// СсылкаНаСерию — это ссылка на объект СправочникСсылка.СерииНоменклатуры

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

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

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

Способ №2: Принудительное обновление через повторно используемые значения

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

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

Способ №3: «Программная хитрость» или Force Refresh ячейки

Иногда возникают ситуации, когда даже оповещение не заставляет форму немедленно перерисовать конкретную строку. В таком случае мы можем применить небольшую хитрость. Суть метода заключается в том, чтобы заставить форму «подумать», что ссылка в строке изменилась на другую, а потом вернуть её обратно.

Посмотрим на алгоритм реализации в коде формы:


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

Проанализируем специфику УТ 11.4 и фоновых заданий

В конфигурации УТ 11.4 многие процессы (например, проведение документов или сложные обработки) могут выполняться в фоновом режиме. Если серия была изменена фоновым заданием, то открытая форма документа у пользователя вообще не получит уведомления об этом.

В таких случаях рекомендуем использовать систему взаимодействия (если она настроена) или обработчик ожидания, который будет периодически проверять статус изменений. Но в большинстве случаев достаточно добавить вызов ОповеститьОбИзменении() в код завершения команды, которая инициировала правку серии.

Итоги и рекомендации

Подводя итог нашему разбору, выделим основные шаги для корректного обновления названия серии:

  1. Всегда вызывайте ОповеститьОбИзменении(Ссылка) на стороне клиента сразу после фиксации изменений в базе данных.
  2. Если вы используете динамические списки для выбора серий, убедитесь, что в свойствах справочника не включен слишком агрессивный режим «Быстрого выбора», который может кэшировать списки отдельно от представлений.
  3. В сложных случаях, когда форма «упрямится», используйте временную перезапись значения реквизита в табличной части (метод Force Refresh).
  4. Помните, что проблема «разных значений» на сервере и клиенте — это не ошибка базы данных, а штатное поведение платформы 1С для оптимизации трафика.

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

← На главную