При разработке внешних обработок заполнения табличных частей управляемых форм 1С разработчики иногда сталкиваются с ситуацией: код запроса выполняется успешно, сообщения с заполненными строками выводятся на экран, но сама табличная часть документа на форме остается пустой. Рассмотрим по шагам причинно-следственные связи этой проблемы и выясним, как правильно передавать данные в форму документа.
Проанализируем распространенную ошибку в коде клиентского обработчика внешней обработки. Часто для обращения к документу пытаются программно получить его форму с помощью функции ПолучитьФорму() и параметра Ключ:
Процедура ПослеВводаЗначения(ВыбЗнач, Параметры) Экспорт
Если ВыбЗнач <> Неопределено Тогда
Для каждого Элемент из ОбъектыНазначения Цикл
// Ошибка: создается или получаются данные формы вне контекста текущего окна
ФормаОбъекта = ПолучитьФорму(ПолучитьПолноеИмяДокумента(Элемент) + ".Форма.ФормаДокумента", Новый Структура("Ключ", Элемент));
Если ФормаОбъекта = Неопределено Тогда
Сообщить("Не удалось заполнить документ!");
Возврат;
КонецЕсли;
ОбъектСсылки = ФормаОбъекта.Объект;
ЗаполнитьПоТерритории(ОбъектСсылки, ВыбЗнач);
ФормаОбъекта.ОбновитьОтображениеДанных();
КопироватьДанныеФормы(ОбъектСсылки, ФормаОбъекта.Объект);
ФормаОбъекта.Модифицированность = Истина;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
В приведенном примере вызов ПолучитьФорму() возвращает не то контекстное окно, из которого пользователь вызвал заполнение, а новый экземпляр формы или несвязанный контекст. Изменения вносятся в копию данных структуры Объект, в результате чего пользователь не видит результата в своем открытом документе.
Выясним, как правильно связать обработку с уже открытой формой документа. В контексте внешней обработки заполнения ТЧ ключевое значение имеет свойство ВладелецФормы. Именно в нем содержится ссылка на управляемую форму документа, из которой был произведен вызов обработки.
Разберем по шагам верный алгоритм внесения изменений:
ПолучитьФорму() обращаемся напрямую к ВладелецФормы.Сотрудники).Модифицированность = Истина, чтобы платформа знала об изменениях.Посмотрим на исправленный вариант клиентской процедуры:
Процедура ПослеВводаЗначения(ВыбЗнач, Параметры) Экспорт
Если ВыбЗнач <> Неопределено Тогда
// Получаем текущую открытую форму документа
ФормаОбъекта = ВладелецФормы;
Если ФормаОбъекта <> Неопределено Тогда
// Заполняем данные непосредственно в объекте формы владельца
ЗаполнитьПоТерритории(ФормаОбъекта.Объект, ВыбЗнач);
ФормаОбъекта.Модифицированность = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В серверной процедуре заполнения мы загружаем полученные данные запроса напрямую в табличную часть ДанныеФормыКоллекция:
&НаСервере
Процедура ЗаполнитьПоТерритории(ОбъектФормы, Территория)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КадроваяИсторияСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
| КадроваяИсторияСотрудниковСрезПоследних.ФизическоеЛицо КАК ФизическоеЛицо
|ИЗ
| РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних КАК КадроваяИсторияСотрудниковСрезПоследних
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ТерриторииСотрудников.СрезПоследних КАК ТерриторииСотрудниковСрезПоследних
| ПО КадроваяИсторияСотрудниковСрезПоследних.Сотрудник = ТерриторииСотрудниковСрезПоследних.Сотрудник
|ГДЕ
| КадроваяИсторияСотрудниковСрезПоследних.ВидСобытия <> ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение)
| И ТерриторииСотрудниковСрезПоследних.Территория = &Территория
|УПОРЯДОЧИТЬ ПО
| Сотрудник";
Запрос.УстановитьПараметр("Территория", Территория);
ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
// Загружаем данные в табличную часть формы документа
ОбъектФормы.Сотрудники.Загрузить(ТаблицаРезультата);
КонецПроцедуры
Рассмотрим дополнительные особенности, с которыми можно столкнуться при программном заполнении форм:
ЗаполнениеОбъекта. В модуле объекта внешней обработки создается экспортная процедура ЗаполнитьОбъект(), принимающая структуру Объект (данные формы). Платформа сама заботится о передаче контекста и обновлении элементов на клиенте.Загрузить() имена колонок в таблице значений должны строго совпадать с именами реквизитов табличной части формы.ДанныеФормыВЗначение() и ЗначениеВДанныеФормы():
ДокументОбъект = ДанныеФормыВЗначение(ФормаОбъекта.Объект, Тип("ДокументОбъект.ОтпускБезСохраненияОплатыСписком"));
// Выполнение процедур заполнения над прикладным объектом
...
ЗначениеВДанныеФормы(ДокументОбъект, ФормаОбъекта.Объект);
Таким образом, обращение через ВладелецФормы позволяет работать именно с открытым сеансом формы пользователя, моментально отображая все внесенные изменения в табличных частях.