Почему не заполняется табличная часть документа внешней обработкой в 1С

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

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

Анализ проблемы: получение не той формы

Проанализируем распространенную ошибку в коде клиентского обработчика внешней обработки. Часто для обращения к документу пытаются программно получить его форму с помощью функции ПолучитьФорму() и параметра Ключ:


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

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

Решение проблемы: обращение к ВладелецФормы

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

Разберем по шагам верный алгоритм внесения изменений:

  1. Вместо функции ПолучитьФорму() обращаемся напрямую к ВладелецФормы.
  2. Изменяем реквизиты объекта формы (например, табличную часть Сотрудники).
  3. При необходимости устанавливаем флаг Модифицированность = Истина, чтобы платформа знала об изменениях.

Посмотрим на исправленный вариант клиентской процедуры:


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

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


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

Альтернативные подходы и важные нюансы

Рассмотрим дополнительные особенности, с которыми можно столкнуться при программном заполнении форм:

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

Таким образом, обращение через ВладелецФормы позволяет работать именно с открытым сеансом формы пользователя, моментально отображая все внесенные изменения в табличных частях.

← На главную