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