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

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

При разработке в среде 1С:Предприятие 8 часто возникает задача: открыть форму нового документа из внешней обработки или другой формы, при этом предварительно заполнив её данными. Если с обычными реквизитами (дата, контрагент, сумма) механизм ЗначенияЗаполнения справляется отлично, то при попытке передать данные в табличную часть разработчики часто сталкиваются с трудностями и ошибками типа "Нельзя изменять поле, содержащее объект данных формы". Рассмотрим детально, как правильно решать эту задачу, разберем типичные ошибки и изучим несколько эффективных способов реализации.

Причина возникновения ошибок при заполнении ТЧ

Разберем ситуацию, с которой столкнулся автор темы. Попытка передать табличную часть как массив структур напрямую в ЗначенияЗаполнения или использование метода Загрузить() в неподходящем контексте — основные причины неудач. В управляемом приложении табличная часть на форме представлена типом ДанныеФормыКоллекция. Мы не можем просто заменить одну коллекцию другой (через оператор присваивания =), так как это нарушает связь формы с данными. Также важно помнить, что метод Загрузить() доступен только на стороне сервера, а манипуляции с открытой формой часто происходят в клиентском контексте.

Способ 1: Прямое заполнение через объект формы (Клиент)

Проанализируем самый простой и быстрый способ, который подходит для небольшого объема данных. Суть заключается в том, чтобы получить форму, а затем программно добавить строки в её коллекцию данных. Этот метод хорош тем, что не требует изменения модуля самого документа.

Рассмотрим пример кода, где мы сначала подготавливаем структуру данных, а затем заполняем форму:


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

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

Способ 2: Использование стандартного механизма ОбработкаЗаполнения

Выясним, как сделать решение более архитектурно правильным. В 1С предусмотрено событие модуля объекта ОбработкаЗаполнения. Если мы передаем в метод ОткрытьФорму структуру ЗначенияЗаполнения, платформа автоматически вызывает этот обработчик в модуле документа.

Посмотрим на алгоритм реализации по шагам:

  1. В вызывающем коде: помещаем массив структур ТЧ в параметр ЗначенияЗаполнения под ключом, совпадающим с именем табличной части.
  2. В модуле объекта документа: описываем логику разбора этого параметра.

Пример кода в модуле документа:


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

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

Способ 3: Передача данных через Временное хранилище

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

В этом случае эффективнее будет следующий алгоритм:

  1. Сформировать таблицу значений на сервере.
  2. Поместить её во Временное хранилище и получить адрес.
  3. Передать этот адрес (строку) в параметры формы.
  4. В модуле формы в обработчике ПриСозданииНаСервере извлечь данные и загрузить их в ТЧ.

Пример реализации в форме документа:


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

Метод Загрузить() идеально подходит здесь, так как мы находимся на сервере и работаем с коллекцией Объект.Товары, которая в серверном контексте формы ведет себя как полноценная таблица.

Выводы и рекомендации

Подведем итог нашего анализа. Выбор метода зависит от ваших условий:

Главное правило: никогда не пытайтесь присвоить коллекцию ДанныеФормыКоллекция целиком. Всегда используйте либо метод Добавить() в цикле, либо метод Загрузить(), но строго в серверном контексте.

← На главную