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

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

1С: как обновить форму на сервере

Как обновить форму на сервере в 1С: методы Прочитать(), ОбновитьДанные, перечитывание объекта, работа с управляемой формой. Примеры кода и типичные ошибки.

Задача обновить форму на сервере в 1С возникает, когда данные объекта изменились вне текущего сеанса редактирования: другой пользователь записал документ, фоновое задание обновило регистры, регламентная операция изменила справочник. Клиентская форма при этом продолжает показывать устаревшие данные, потому что управляемая форма кэширует объект в своём контексте и не следит за изменениями в базе автоматически.

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

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

Почему форма не обновляется сама

Управляемая форма в 1С работает по модели «запросил — получил». При открытии формы платформа считывает объект из базы, помещает его данные в реквизиты формы и дальше не синхронизирует их с базой. Если в это время другой сеанс записал тот же документ, открытая форма об этом не узнает.

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

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

Обновление данных объекта через Прочитать()

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

&НаСервере

Процедура ОбновитьДанныеНаСервере()

ЭтотОбъект.Прочитать();

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

&НаКлиенте

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

ОбновитьДанныеНаСервере();

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

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

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

Обновление через РеквизитФормыВЗначение

Когда данные формы хранятся не в стандартном реквизите Объект, а в произвольных реквизитах формы (типично для внешних обработок и форм с ручной компоновкой), перечитывание выполняется через пару методов РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.

&НаСервере

Процедура ОбновитьОбъектНаСервере()

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

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

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

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

Здесь последовательность такая: реквизит формы преобразуется в прикладной объект, у объекта вызывается Прочитать(), затем объект преобразуется обратно в реквизит формы. Именно обратное преобразование заставляет форму отобразить новые данные — без ЗначениеВРеквизитФормы изменения останутся в серверной переменной и до интерфейса не дойдут.

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

Порядок действий
  1. 1
    Определите, где лежат данные: стандартный реквизит Объект или произвольный реквизит формы
  2. 2
    Создайте серверную процедуру с директивой &НаСервере
  3. 3
    Для стандартного реквизита вызовите ЭтотОбъект.Прочитать(), для произвольного — цепочку РеквизитФормыВЗначение / Прочитать / ЗначениеВРеквизитФормы
  4. 4
    Вызовите серверную процедуру из клиентской (кнопка, команда, обработчик ожидания)
  5. 5
    Проверьте, что элементы формы отобразили актуальные значения и несохранённые данные не потерялись

Обновление динамических списков и связанных данных

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

&НаКлиенте

Процедура ОбновитьСписок(Команда)

Элементы.СписокДокументов.Обновить();

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

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

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

Обновление отображения без перечитывания данных

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

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

&НаКлиенте

Процедура ПослеСерверногоИзменения()

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

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

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

Сравнение вариантов

Прочитать() у объекта

Полное перечитывание объекта из базы. Подходит для форм документов и справочников, но затирает несохранённые изменения

РеквизитФормыВЗначение + ЗначениеВРеквизитФормы

Для произвольных реквизитов формы и случаев, когда объект нужно изменить на сервере перед отображением

Элементы.Список.Обновить()

Только для динамических списков; данные объекта формы не затрагивает

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

Перерисовка элементов без обращения к базе; данные должны быть актуальны заранее

Закрыть и открыть форму заново

Гарантированно чистое состояние, но теряются настройки ввода и это заметно для пользователя

Типичные ошибки и ограничения

Наиболее частая ошибка — попытка вызвать Прочитать() в клиентской процедуре. Метод доступен только на сервере, и компилятор модуля формы сообщит об этом. Любое обращение к базе из управляемой формы оформляется серверной процедурой, вызываемой из клиентской.

Вторая ошибка — забыть ЗначениеВРеквизитФормы после изменений объекта на сервере. Код выполняется без ошибок, но форма показывает старые данные, и разработчик долго ищет причину. Третья типичная ситуация — перечитывание объекта без проверки модифицированности, из-за чего пользователи теряют введённые данные и перестают доверять кнопке «Обновить».

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

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

Проверка результата и FAQ

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

Итог

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

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

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

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

Почему после серверной процедуры форма показывает старые данные?

Чаще всего вы изменили объект, полученный через РеквизитФормыВЗначение, но не вернули его в форму через ЗначениеВРеквизитФормы. Без обратного преобразования изменения остаются в локальной серверной переменной и уничтожаются при завершении вызова.

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

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

Чем отличается ОбновитьОтображениеДанных() от Прочитать()?

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

Почему Прочитать() выдаёт ошибку конфликта блокировок?

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

Можно ли полностью пересоздать управляемую форму на сервере?

Нет, такого метода платформа не предоставляет. Рабочий вариант — закрыть текущую форму и открыть новую через ОткрытьФорму() с теми же параметрами. Для большинства задач это не требуется: достаточно перечитать данные и обновить отображение.