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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализируем причину проблемы

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

Рассмотрим основные методы, которые позволяют заставить интерфейс отобразить актуальную информацию.

Способ 1. Использование метода Прочитать()

Самый простой и быстрый способ, к которому пришел автор темы, — это метод ЭтаФорма.Прочитать(). Рассмотрим пример его использования:


&НаСервере
Процедура ЗагрузитьДанныеИзЭксельНаСервере()
    // Логика загрузки данных и записи объекта в базу
    ОбъектЗаписать(); 
    // Обновляем данные формы из базы данных
    ЭтаФорма.Прочитать();
КонецПроцедуры

Разберем, что происходит в этот момент. Метод Прочитать() полностью перечитывает данные текущего основного реквизита (документа) из базы данных. Это гарантирует, что табличная часть на экране станет идентичной той, что сохранена в БД.

Важный нюанс: У этого метода есть существенный недостаток. Если пользователь до нажатия кнопки загрузки изменил какие-то другие поля на форме (например, комментарий или дату) и не нажал кнопку «Записать», то после вызова Прочитать() все эти ручные изменения будут стерты, так как форма вернется к состоянию, зафиксированному в базе данных.

Способ 2. Преобразование РеквизитФормыВЗначение и обратно

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

Проанализируем шаги в коде:


&НаСервере
Процедура ОбновитьТабличнуюЧастьНаСервере()
    // 1. Преобразуем данные формы в реальный объект документа
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // 2. Выполняем загрузку в табличную часть документа
    // (например, добавление строк из загруженного файла)
    НоваяСтрока = ДокОбъект.Товары.Добавить();
    НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар из Excel");
    
    // 3. Важнейший шаг: возвращаем изменения обратно в реквизит формы
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

Метод ЗначениеВРеквизитФормы синхронизирует состояние ДокОбъект с экранной формой. Это позволяет избежать полной перезаписи из БД (как в первом способе) и сохранить те данные, которые пользователь ввел в другие поля, но еще не записал.

Способ 3. Прямая работа с данными формы (рекомендуемый)

Наиболее современный и правильный подход для управляемых форм — это работа напрямую с коллекциями Объект.ИмяТабличнойЧасти. Поскольку Объект на форме является типом ДанныеФормыСтруктура, изменения в нем в контекстной серверной процедуре (&НаСервере) автоматически передаются на клиент по завершении вызова.

Посмотрим на пример:


&НаСервере
Процедура ЗагрузитьНапрямуюНаСервере(МассивДанных)
    // Очищаем текущую таблицу на форме
    Объект.Товары.Очистить();
    
    Для Каждого СтрокаДанных Из МассивДанных Цикл
        НоваяСтрока = Объект.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
    КонецЦикла;
    
    // В конце можно пометить форму как измененную
    ЭтаФорма.Модифицированность = Истина;
КонецПроцедуры

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

Способ 4. Метод ОбновитьОтображениеДанных()

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

Рассмотрим вызов:


&НаКлиенте
Процедура ПослеЗагрузки()
    // Вызываем серверную загрузку
    ЗагрузитьДанныеНаСервере();
    
    // Принудительно заставляем элементы формы перечитать данные из реквизитов
    ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры

Этот метод не обращается к серверу за данными, он лишь перерисовывает уже имеющиеся в памяти клиента данные в элементах управления.

Способ 5. Оповещение об изменениях

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

Разберем алгоритм:

  1. В процедуре записи данных вызываем ОповеститьОбИзменении(ТипЗнч(СсылкаНаОбъект)) или передаем конкретную ссылку.
  2. Платформа сама найдет все открытые формы, отображающие этот объект, и предложит им обновиться.
  3. Для динамических списков это основной способ заставить их «увидеть» новые строки без перезапуска формы.

Типичные ошибки при обновлении

Проанализируем, почему обновление может не срабатывать даже при использовании вышеописанных методов:

Подводя итог, для большинства задач оптимальным решением является либо прямая работа с Объект.ТабличнаяЧасть в контекстной серверной процедуре, либо связка РеквизитФормыВЗначение / ЗначениеВРеквизитФормы, если требуется сложная бизнес-логика из модуля объекта.

← На главную