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

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

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

Различие между данными и элементами отображения

Для начала разберем фундаментальный принцип управляемого приложения: разделение данных и их представления. В управляемой форме у нас есть Реквизиты (содержат данные) и Элементы (визуализируют данные).

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

  1. Метод Элементы.Гарниры.ДобавитьСтроку() предназначен для имитации действий пользователя. Он переводит фокус на таблицу, создает пустую строку и активирует поле для ввода.
  2. Этот метод является интерактивным и не предназначен для использования в циклах при обработке данных на сервере.
  3. При попытке вызвать его как функцию в коде может возникнуть ошибка "Обращение к процедуре как к функции".

Правильный подход — обращаться напрямую к данным, которые хранятся в реквизите Объект (если это форма документа/справочника/обработки) или напрямую в реквизите формы типа ТабличнаяЧасть или ТаблицаЗначений.

Правильный способ добавления строк в цикле

Рассмотрим исправленный код, который должен выполняться в процедуре с директивой компиляции &НаСервере. Вместо обращения к Элементам, мы будем использовать коллекцию данных Объект.Гарниры.


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

КонецПроцедуры

Обратите внимание на важный нюанс типизации: если колонка Номенклатура имеет тип СправочникСсылка.Номенклатура, то записывать в нее нужно именно ссылку (Выборка.Ссылка), а не строковое представление (Выборка.Наименование). Это одна из причин, по которой новички часто видят пустые строки после выполнения кода.

Оптимизация заполнения через метод Загрузить

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

Этот метод позволяет одним действием заменить содержимое табличной части данными из таблицы значений. Единственное условие — имена колонок в таблице значений должны полностью совпадать с именами реквизитов табличной части.


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

Этот способ является наиболее предпочтительным с точки зрения производительности 1С, так как минимизирует количество обращений к коллекции данных.

Программное создание колонок в таблице формы

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

Процесс состоит из двух шагов: создание самого реквизита (данных) и создание элемента формы (визуального поля).


&НаСервере
Процедура ДобавитьКолонкуПрограммно()
    
    // Шаг 1: Добавляем новый реквизит в структуру формы
    МассивДобавляемыхРеквизитов = Новый Массив;
    НовыйРеквизит = Новый РеквизитФормы("ДополнительнаяИнфо", Новый ОписаниеТипов("Строка"), "Объект.Гарниры", "Доп. инфо");
    МассивДобавляемыхРеквизитов.Добавить(НовыйРеквизит);
    
    ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
    
    // Шаг 2: Создаем элемент интерфейса для отображения этого реквизита
    НовоеПоле = Элементы.Добавить("ГарнирыДополнительнаяИнфо", Тип("ПолеФормы"), Элементы.Гарниры);
    НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
    НовоеПоле.ПутьКДанным = "Объект.Гарниры.ДополнительнаяИнфо";
    
КонецПроцедуры

Важный момент: метод ИзменитьРеквизиты() является довольно "тяжелым", так как приводит к полной перерисовке формы. Старайтесь использовать его только в тех случаях, когда колонки действительно невозможно определить заранее в конфигураторе (например, в универсальных отчетах или обработках).

Особенности работы с Динамическими списками

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

Однако помните, что в динамический список нельзя просто "добавить строку" методом Добавить(). Чтобы в нем появилась новая запись, она должна быть физически записана в базу данных (в соответствующий справочник или регистр), после чего список обновится автоматически или командой Элементы.Список.Обновить().

Подведем итоги

Для успешной работы с табличными частями в управляемом интерфейсе 1С придерживайтесь следующих правил:

Соблюдение этих принципов позволит вам писать чистый, быстрый и отказоустойчивый код для управляемого приложения 1С.

← На главную