К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как обновить табличную часть формы

Как обновить табличную часть формы в 1С: ОбновитьОтображениеДанных, Прочитать, модифицированность, работа с управляемыми и обычными формами.

Табличная часть формы в 1С не всегда отображает актуальные данные автоматически. Если строки изменены программно — обработкой, регламентным заданием, обменом данными или кодом в другой форме — пользователь может видеть устаревший состав строк, пока форму не переоткроют. В таких ситуациях требуется принудительно обновить данные табличной части, и способ зависит от того, где именно произошло изменение: на клиенте, на сервере или вне текущего сеанса.

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

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

Что значит «обновить табличную часть»: перерисовка или перечитывание

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

Перерисовка безопасна: она не трогает данные, только обновляет отображение. Перечитывание заменяет содержимое объекта данными из базы, поэтому все несохранённые изменения пользователя будут потеряны. Если документ открыт и в нём уже введены строки, вызов Прочитать() без предупреждения приведёт к их исчезновению.

Обновление отображения таблицы на управляемой форме

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

&НаКлиенте

Процедура ОбновитьТаблицу(Команда)

Элементы.Товары.Обновить();

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

Альтернатива — метод формы ОбновитьОтображениеДанных(), который обновляет отображение всех элементов формы или конкретного элемента, переданного параметром. Он полезен, когда после программных манипуляций нужно «освежить» сразу несколько элементов:

&НаКлиенте

Процедура ПослеЗагрузкиДанных()

ОбновитьОтображениеДанных(Элементы.Товары);

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

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

Перечитывание табличной части из базы данных

Когда табличная часть изменена вне текущей формы — другим пользователем, обменом или фоновым заданием — объект нужно перечитать. В управляемой форме это делается на сервере вызовом Прочитать() у реквизита формы или через преобразование в объект:

&НаСервере

Процедура ПеречитатьДокумент()

ОбъектДокумента = РеквизитФормыВЗначение("Объект");

ОбъектДокумента.Прочитать();

ЗначениеВРеквизитФормы(ОбъектДокумента, "Объект");

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

Более простой вариант для основного реквизита формы — вызов метода Прочитать() самой формы (доступен в модуле формы объекта): он перечитывает объект из базы и обновляет реквизит. После перечитывания табличная часть автоматически отобразит новый состав строк.

Перед перечитыванием проверяйте свойство Модифицированность формы. Если оно истинно, у пользователя есть несохранённые изменения, и корректное поведение — задать вопрос:

&НаКлиенте

Процедура ОбновитьИзБазы(Команда)

Если Модифицированность Тогда

ПоказатьВопрос(Новый ОписаниеОповещения("ОбновитьИзБазыЗавершение", ЭтотОбъект),

"Несохранённые изменения будут потеряны. Продолжить?",

РежимДиалогаВопрос.ДаНет);

Иначе

ПеречитатьДокумент();

КонецЕсли;

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

bsl
// Перечитывание объекта с проверкой модифицированности
&НаКлиенте
Процедура ОбновитьИзБазыЗавершение(Результат, Доп) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ПеречитатьДокумент(); // серверный вызов Прочитать()
        Модифицированность = Ложь;
    КонецЕсли;
КонецПроцедуры

Обновление через оповещения между формами

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

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "Запись_РеализацияТоваровУслуг"

И Параметр = Объект.Ссылка Тогда

ПеречитатьДокумент();

КонецЕсли;

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

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

Плюс подхода — обновление происходит только при реальном изменении, без лишних обращений к базе. Минус — нужно контролировать, что все места изменения объекта действительно отправляют оповещение; типовые механизмы записи документа делают это автоматически через событие записи.

Порядок настройки обновления через оповещения
  1. 1
    В форме, изменяющей данные, после записи вызовите ОповеститьОбИзменении(Ссылка) или Оповестить() со своим именем события
  2. 2
    В форме с табличной частью добавьте обработчик ОбработкаОповещения
  3. 3
    В обработчике проверьте имя события и соответствие ссылки
  4. 4
    Вызовите серверную процедуру перечитывания объекта
  5. 5
    Проверьте: откройте документ, измените его из другой формы, убедитесь, что строки обновились

Программное изменение строк и обновление на сервере

Частая задача — массово изменить строки табличной части (заполнить цены, пересчитать суммы, добавить строки по остаткам) и сразу показать результат. В управляемой форме изменения выполняются в серверной процедуре напрямую в реквизите Объект:

&НаСервере

Процедура ЗаполнитьЦеныНаСервере()

Для Каждого СтрокаТовары Из Объект.Товары Цикл

СтрокаТовары.Цена = ПолучитьЦену(СтрокаТовары.Номенклатура);

СтрокаТовары.Сумма = СтрокаТовары.Цена * СтрокаТовары.Количество;

КонецЦикла;

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

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

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

Сравнение способов обновления

Элементы.Таблица.Обновить()

Перерисовывает таблицу на клиенте. Подходит, когда данные в реквизите уже актуальны. Не читает базу.

Прочитать() на сервере

Загружает объект из базы заново. Нужен при изменениях извне. Уничтожает несохранённые изменения.

Оповещения (ОповеститьОбИзменении)

Автоматическая реакция на запись объекта в других формах. Требует реализации ОбработкаОповещения.

ОбновитьОтображениеДанных()

Обновляет отображение элементов формы. Помогает при косвенных изменениях, не перечитывает данные.

Частые ошибки и как их избежать

Самая распространённая ошибка — вызов Прочитать() без проверки модифицированности. Пользователь вводит строки, срабатывает таймер или оповещение, объект перечитывается — и введённые данные пропадают. Всегда проверяйте Модифицированность и спрашивайте подтверждение.

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

Третья ошибка — обновление в цикле или слишком частое перечитывание по таймеру. Каждый Прочитать() — обращение к базе; при частых вызовах это создаёт лишнюю нагрузку и мерцание формы. Если нужна периодическая актуализация, используйте ПодключитьОбработчикОжидания с разумным интервалом и обновляйте только при реальной необходимости.

Типичные ошибки
01
Прочитать() без проверки Модифицированности — потеря несохранённых строк, введённых пользователем
02
Элементы.Таблица.Обновить() вместо перечитывания — данные в базе изменились, а форма показывает старое
03
Перечитывание по таймеру каждые секунды — лишняя нагрузка на базу и мерцание таблицы
04
Обновление на клиенте данных, изменённых только на сервере, без возврата результата серверной процедуры
05
Отсутствие ОбработкаОповещения — форма не реагирует на запись документа из других окон

Проверка результата и границы самостоятельной работы

Проверить корректность обновления просто: откройте документ в двух окнах (или у двух пользователей), измените табличную часть в одном и запишите. Во втором окне после оповещения или ручного обновления строки должны соответствовать записанным. Дополнительно проверьте сценарий с несохранёнными изменениями: при попытке перечитать должен появиться вопрос, а не молчаливая потеря данных.

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

Контрольные точки

Как проверить результат

Состав строк после обновления
Норма

Строки совпадают с данными в базе (проверить через запись в другом окне)

Тревожный признак

Таблица показывает прежние строки — перерисовка вместо перечитывания

Несохранённые изменения
Норма

Перед перечитыванием задаётся вопрос о потере изменений

Тревожный признак

Данные пользователя пропадают без предупреждения

Реакция на запись из другой формы
Норма

ОбработкаОповещения срабатывает, таблица обновляется автоматически

Тревожный признак

Форма не реагирует — не настроено оповещение

FAQ

Чем отличается Обновить() у таблицы от Прочитать() у объекта?

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

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

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

Как обновить табличную часть по таймеру без мерцания?

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

Работает ли ОбновитьОтображениеДанных() для динамического списка?

Для динамического списка правильнее вызывать Элементы.ИмяСписка.Обновить() — тогда список выполнит запрос заново и покажет актуальные данные из базы. ОбновитьОтображениеДанных() лишь перерисует текущее состояние без нового запроса.

Как обновить табличную часть в обычной форме (толстый клиент)?

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

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

Да, если изменение известно — например, передано через параметры оповещения. Тогда в обработчике находите нужную строку по ключевому полю и меняете её значения напрямую в реквизите Объект. Это быстрее и не затирает остальные несохранённые правки пользователя.

Итог

Что важно запомнить

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