Как обновить список регистра сведений в табличном поле на обычных формах 1С:Предприятие 8?

Программист 1С v8.3 (Обычные формы)
← На главную

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

1. Метод Обновить() самого объекта списка

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


// Вариант 1: Через элемент формы, если его свойство "Данные" ссылается на список
ЭлементыФормы.Информация.Значение.Обновить();

// Вариант 2: Непосредственно у самого объекта списка, если он доступен по имени переменной
РегистрСведенийСписок.Обновить();

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

2. Различие между Обновить() и ОбновитьСтроки()

Очень важно понимать техническую разницу между этими двумя методами, чтобы избежать распространенных ошибок:

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

Таким образом, когда вы сталкиваетесь с ситуацией, что ЭлементыФормы.Информация.ОбновитьСтроки() не помогает, почти всегда это означает, что вам нужен именно Обновить() для объекта-источника данных.

3. Принудительная перезапись отбора

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

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


// Пример из Сообщения 1, показывающий как установить отбор:
// Предположим, что Штрихкоды - это РегистрСведенийСписок
Штрихкоды.Отбор.Владелец.Установить(Ссылка);
ЭлементыФормы.Штрихкоды.НастройкаОтбора.Владелец.Доступность = Ложь;

// Универсальный прием "встряски" отбора для обновления списка:
// Допустим, у нас есть отбор по полю "Владелец"
Если РегистрСведенийСписок.Отбор.Владелец.Использование Тогда
    ЗначениеОтбора = РегистрСведенийСписок.Отбор.Владелец.Значение;
    РегистрСведенийСписок.Отбор.Владелец.Установить(ЗначениеОтбора); // Повторная установка того же значения
Иначе
    // Если отбор не используется, можно временно его включить и выключить,
    // или установить фиктивное значение, а затем вернуть прежнее.
    // Однако, лучше всего просто вызвать Обновить() в этом случае.
    РегистрСведенийСписок.Обновить(); 
КонецЕсли;

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

4. Использование метода ОбновитьДанные() для элементов формы

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


// Предположим, что мы вызвали РегистрСведенийСписок.Обновить();
// и хотим гарантировать, что табличное поле "Информация" обновится
РегистрСведенийСписок.Обновить();
ЭлементыФормы.Информация.ОбновитьДанные();

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

5. Свойство «Автообновление»

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

Однако, стоит помнить о некоторых нюансах:

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

Мы рекомендуем использовать автообновление с осторожностью и только при наличии реальной необходимости, выбирая разумный интервал (например, 30-60 секунд или более) и тестируя его влияние на производительность системы.

6. Проблема кэширования на стороне клиента

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

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

Нам важно понимать, что платформа 1С активно использует кэширование для оптимизации производительности. Принудительное обновление через Обновить() или "встряска" отбора являются основными инструментами для преодоления такого кэширования и получения актуальных данных.

7. Метод Прочитать() для наборов записей

Мы должны провести четкое разграничение между РегистрСведенийСписок и РегистрСведенийНаборЗаписей. Если в вашем табличном поле отображается не весь регистр в виде динамического списка (т.е. объект типа РегистрСведенийСписок), а конкретный РегистрСведенийНаборЗаписей (например, вы работаете с набором записей по одному регистратору, владельцу или на определенную дату), то для обновления данных нужно использовать метод НаборЗаписей.Прочитать().

Объект РегистрСведенийНаборЗаписей представляет собой коллекцию записей, которые загружаются в память по определенному отбору. Метод Прочитать() заставляет этот объект заново загрузить свои записи из базы данных в соответствии с текущими установками отбора и режима записи. После вызова НаборЗаписей.Прочитать() данные в табличном поле, привязанном к этому набору записей, обновятся автоматически, так как они напрямую связаны с этим объектом в памяти.


// Пример обновления набора записей
МойНаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
МойНаборЗаписей.Отбор.Владелец.Установить(СсылкаНаВладельца);
МойНаборЗаписей.Прочитать(); // Загружаем актуальные записи

// Если табличное поле "Информация" привязано к МойНаборЗаписей,
// оно автоматически отобразит обновленные данные.

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

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

← На главную