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

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

При разработке внешних обработок заполнения табличных частей часто возникает неприятная особенность платформы 1С:Предприятие 8.3: реквизит ссылочного типа заполнен корректно, однако в пользовательском интерфейсе поле ячейки остается совершенно пустым. Особенно часто эта проблема проявляется, если для целевого ссылочного объекта программно переопределено стандартное представление, а сам документ-владелец еще не записан в базу данных. При этом запись документа в форме мгновенно возвращает правильные строки на экран, а стандартный вызов метода ОповеститьОбИзменении на клиенте не приносит результата.

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

Причины возникновения проблемы с кэшем представлений

Рассмотрим механизм формирования и передачи представлений данных на управляемых формах. В платформе 1С:Предприятие 8 строковые представления ссылок вычисляются на стороне сервера и передаются клиенту в оптимизированном виде, сохраняясь в специальном клиентском кэше представлений.

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

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

Способ 1. Обновление интерфейса формы через ОбновитьОтображениеДанных

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

Посмотрим, как правильно вызвать этот метод после завершения вставки строк:


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

// Принудительно заставляем форму перечитать визуальные свойства ячеек
ВладелецФормы.ОбновитьОтображениеДанных();

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

Способ 2. Перенос заполнения в серверный контекст формы владельца

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

  1. В форме внешней обработки считываем файл и упаковываем строки в структуру или массив структур.
  2. Передаем эти данные в форму документа через вызов экспортного метода или через механизм оповещений.
  3. В форме документа в процедуре с директивой &НаСервере заполняем табличную часть объекта.

Посмотрим на пример реализации передачи через оповещение:


&НаКлиенте
Процедура ЗавершитьЗаполнениеНаКлиенте()
    ПараметрыЗаполнения = Новый Структура("ТаблицаДанных", ПодготовленныеДанные);
    Оповестить("ЗаполнитьТабличнуюЧастьИзФайла", ПараметрыЗаполнения, ВладелецФормы);
    Закрыть();
КонецПроцедуры

В форме документа обрабатываем событие оповещения и уходим на сервер:


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

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

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

Способ 3. Проверка процедур модуля менеджера целевого объекта

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

Разберем код в модуле менеджера целевого документа:


Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Поля.Добавить("Номер");
    Поля.Добавить("Дата");
    Поля.Добавить("Организация");
КонецПроцедуры

Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Представление = СтрШаблон("Документ № %1 от %2 (%3)", Данные.Номер, Формат(Данные.Дата, "ДФ=dd.MM.yyyy"), Данные.Организация);
КонецПроцедуры

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

Способ 4. Интерфейсные обходные пути

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

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

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

← На главную