При разработке в среде 1С:Предприятие 8 (особенно в конфигурациях на обычных формах, таких как Управление торговлей 10.3) часто возникает ситуация, когда данные в регистре сведений изменяются внешней обработкой или другим программным кодом, в то время как форма этой записи уже открыта у пользователя на экране. В этом случае пользователь видит старые данные, пока не нажмет кнопку «Перечитать» или не переоткроет форму. Рассмотрим подробнее, как автоматизировать этот процесс и заставить форму актуализировать данные программно.
Прежде всего, проанализируем разницу между двумя похожими методами, которые часто путают начинающие разработчики. Выясним причину, почему один из них может не сработать в вашей ситуации:
ЭтаФорма.Обновить() — этот метод отвечает исключительно за визуальную перерисовку элементов управления на форме. Он полезен, если вы программно изменили видимость кнопок или цвет текста, но он абсолютно бесполезен для получения новых данных из базы данных. Если данные в таблице физически изменились, Обновить() не подтянет их в объект формы.ЭтаФорма.Прочитать() — это именно тот инструмент, который нам нужен для работы с формой записи регистра. Он принудительно считывает текущее состояние записи из базы данных по значениям ключевых полей (измерений), которые установлены в объекте РегистрСведенийМенеджерЗаписи.Если код выполняется непосредственно внутри модуля формы записи, решение оказывается максимально простым. Достаточно вызвать метод Прочитать(). Это действие полностью аналогично нажатию стандартной кнопки «Перечитать» в командной панели формы.
Посмотрим на пример кода, который можно разместить, например, в обработчике какого-либо события или в вашей процедуре:
Процедура ОбновитьДанныеНаФорме()
// Считываем актуальные данные из БД для текущей записи
ЭтаФорма.Прочитать();
// Опционально можно перерисовать форму
ЭтаФорма.Обновить();
КонецПроцедуры
Ситуация усложняется, когда данные меняются «извне» — например, из внешней обработки. Форма записи «не знает», что где-то в недрах системы ее данные были перезаписаны. Для решения этой задачи разберем по шагам механизм глобальных оповещений.
Шаг 1. В коде обработки, которая записывает данные в регистр, после метода Записать() добавим вызов оповещения:
// Программное изменение записи регистра
НоваяЗапись = РегистрыСведений.ЗаявкиНаСборку.СоздатьМенеджерЗаписи();
// ... заполнение измерений и ресурсов ...
НоваяЗапись.Записать();
// Посылаем сигнал всем открытым окнам, что данные регистра изменились
Оповестить("ЗаписьРегистраИзменена", НоваяЗапись.ЗаказПокупателя, "ЗаявкиНаСборку");
Шаг 2. В модуле формы записи регистра сведений необходимо создать (если его нет) обработчик события ОбработкаОповещения. В нем мы проверим, касается ли это событие нашей записи, и если да — обновим форму.
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
// Проверяем имя события и источник
Если ИмяСобытия = "ЗаписьРегистраИзменена" И Источник = "ЗаявкиНаСборку" Тогда
// Проверяем, совпадает ли измененный объект с тем, что открыт в форме
// (Параметр в данном случае содержит ссылку на ЗаказПокупателя)
Если Параметр = РегистрСведенийМенеджерЗаписи.ЗаказПокупателя Тогда
ЭтаФорма.Прочитать();
Сообщить("Данные формы были автоматически обновлены!");
КонецЕсли;
КонецПроцедуры
Рассмотрим ситуацию, описанную в одном из сообщений форума: автор использует ОткрытьМодально для выбора документа. Важно понимать, что при модальном открытии выполнение кода основной обработки останавливается до момента закрытия модального окна. Если вы пытаетесь обновить форму записи из этого же кода, убедитесь, что вызовы методов идут строго в правильном порядке.
Проанализируем пример исправленной процедуры:
Процедура ОсновныеДействияФормыДействие(Кнопка)
ФормаВыбора = Документы.ЗаказПокупателя.ПолучитьФормуВыбора();
// Настройка отбора...
ВыбДокумент = ФормаВыбора.ОткрытьМодально();
Если ЗначениеЗаполнено(ВыбДокумент) Тогда
ИсходнаяЗапись = РегистрыСведений.ЗаявкиНаСборку.СоздатьМенеджерЗаписи();
ИсходнаяЗапись.ЗаказПокупателя = ВыбДокумент;
ИсходнаяЗапись.Прочитать();
Если ИсходнаяЗапись.Выбран() Тогда
// Код модификации данных...
// После записи данных во внешней процедуре,
// если форма записи этого регистра открыта,
// она должна вызвать ЭтаФорма.Прочитать()
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Иногда возникают задачи, когда нужно обновлять форму записи через определенные промежутки времени (например, если это монитор заказов). Для обычных форм в 1С нет свойства АвтоОбновление у самой формы записи (оно есть только у списков). Однако мы можем имитировать этот процесс. Разберем, как это сделать:
В обработчике ПриОткрытии формы записи подключим ожидание:
Процедура ПриОткрытии()
// Подключаем обновление каждые 10 секунд
ПодключитьОбработчикОжидания("ПринудительноеОбновлениеДанных", 10);
КонецПроцедуры
Процедура ПринудительноеОбновлениеДанных() Экспорт
Если ЭтаФорма.Модифицированность Тогда
// Если пользователь начал что-то вводить, лучше не прерывать его
Возврат;
КонецЕсли;
ЭтаФорма.Прочитать();
КонецПроцедуры
При использовании метода Прочитать() следует помнить о нескольких критически важных моментах:
Модифицированность), вызов Прочитать() затрет все невнесенные изменения данными из базы. Всегда проверяйте свойство Модифицированность перед обновлением.Прочитать() очистит поля объекта в форме, а метод Выбран() начнет возвращать Ложь.Прочитать() доступен только для объектов, имеющих связь с данными (например, РегистрСведенийМенеджерЗаписи). Если ваша форма построена на произвольных переменных, вам придется перечитывать данные запросом и присваивать их переменным вручную.Таким образом, мы выяснили, что наиболее надежным и "чистым" способом является комбинация метода Прочитать() и механизма оповещений Оповестить() / ОбработкаОповещения. Это позволяет избежать лишней нагрузки на систему (в отличие от обработчика ожидания) и гарантирует актуальность данных на экране пользователя.