Как получить и обработать табличную часть объекта через РеквизитФормыВЗначение?

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

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

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

Понимание проблемы: Типы данных в управляемой форме

В первом сообщении темы автор столкнулся с классической ситуацией: попытка получить табличную часть отдельно от объекта.

Важно понимать архитектуру платформы:

  1. На форме (Клиент/Сервер): Табличная часть представлена типом ДанныеФормыКоллекция. Это облегченная структура, предназначенная для отображения данных интерфейсе. У нее нет методов прикладного объекта (например, методов модуля объекта), и она не является полноценной ТабличнойЧастью.
  2. В объекте (Сервер): Тип ТабличнаяЧасть существует только как свойство прикладного объекта (ДокументОбъект, СправочникОбъект). Она не может существовать "сама по себе", в отрыве от родителя.
  3. Универсальная коллекция: ТаблицаЗначений — это отдельный тип, в который можно выгрузить данные для произвольной обработки.

Поэтому вызов РеквизитФормыВЗначение("Объект.Товары") вернет вам не табличную часть объекта, а коллекцию данных формы, либо вызовет ошибку, если платформа не сможет интерпретировать путь.

Решение 1: Конвертация всего объекта

Самый надежный и "классический" способ получить доступ к "настоящей" табличной части — это восстановить весь прикладной объект из данных формы. Это позволяет работать с методами объекта и его метаданными.

Рассмотрим алгоритм действий:

  1. Конвертируем реквизит формы (обычно это основной реквизит "Объект") в прикладной объект.
  2. Обращаемся к табличной части через точку (как к свойству объекта).
  3. Выполняем необходимые действия.
  4. Возвращаем измененные данные обратно в форму.

Пример кода:


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

Решение 2: Использование Таблицы Значений (ТЗ)

В ходе обсуждения (сообщения 5, 9, 14) был предложен и использован метод выгрузки данных в ТаблицуЗначений. Это удобно, если вам нужно использовать специфические методы ТЗ (например, сложные свертки, поиск строк или выгрузка в другую подсистему), которые недоступны в табличной части напрямую, или если вы хотите избежать передачи всего "тяжелого" объекта.

Разберем этот подход:


&НаСервере
Процедура УдалитьНулевыеЦеныЧерезТЗ()

    // Вариант А: Через объект (как обсуждалось в теме)
    ТекущийОбъект = РеквизитФормыВЗначение("Объект");
    
    // Выгружаем ТЧ в Таблицу Значений
    ТаблицаТоваров = ТекущийОбъект.Товары.Выгрузить();
    
    // ... здесь проводим манипуляции с ТЗ ...
    
    // Загружаем обратно
    ТекущийОбъект.Товары.Загрузить(ТаблицаТоваров);
    
    // Возвращаем на форму
    ЗначениеВРеквизитФормы(ТекущийОбъект, "Объект");

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

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

Практическая задача: Удаление строк с ценой 0

Автор темы обозначил конкретную задачу: удалить из списка товары, у которых цена не заполнена (равна нулю). Разберем, как это сделать правильно, не выгружая данные в ТЗ, а работая напрямую с объектом. Это часто бывает оптимальнее по производительности.

При удалении строк из коллекции в цикле нужно помнить главное правило: удалять следует при обходе с конца. Если идти с начала, индексы строк смещаются после удаления, и цикл "перепрыгивает" через строки.

Рассмотрим правильный код решения задачи автора:


&НаСервере
Процедура ОчиститьСтрокиСНезаполненнойЦенойНаСервере()
    
    // Конвертируем данные формы в объект
    ДокументОбъект = РеквизитФормыВЗначение("Объект");
    
    // Получаем ссылку на табличную часть для удобства
    ТЧТовары = ДокументОбъект.Товары;
    
    // Обходим коллекцию с конца к началу
    // Индексы в 1С начинаются с 0, поэтому верхняя граница: Количество() - 1
    Индекс = ТЧТовары.Количество() - 1;
    
    Пока Индекс >= 0 Цикл
        
        СтрокаТЧ = ТЧТовары.Получить(Индекс);
        
        // Проверяем условие
        Если СтрокаТЧ.Цена = 0 Тогда
            ТЧТовары.Удалить(Индекс);
        КонецЕсли;
        
        Индекс = Индекс - 1;
        
    КонецЦикла;
    
    // Возвращаем измененный объект на форму
    ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

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

Альтернатива: Использование НайтиСтроки

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


ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Цена", 0);

// Находим все строки, подходящие под условие
НайденныеСтроки = ДокументОбъект.Товары.НайтиСтроки(ПараметрыОтбора);

// Удаляем их
Для Каждого УдаляемаяСтрока Из НайденныеСтроки Цикл
    ДокументОбъект.Товары.Удалить(УдаляемаяСтрока);
КонецЦикла;

Ключевые выводы

  1. Метод РеквизитФормыВЗначение("Объект") создает серверный прикладной объект. Обращение к его табличным частям (Объект.Товары) дает тип ТабличнаяЧасть.
  2. Нельзя получить ТабличнуюЧасть отдельно от объекта. Если вам нужно передать только таблицу в процедуру общего модуля, используйте выгрузку в ТаблицаЗначений.
  3. Для изменения данных на форме после манипуляций с объектом обязательно используйте ЗначениеВРеквизитФормы.
  4. Будьте осторожны с методом Загрузить() при работе с формами — он полностью обновляет коллекцию, что может повлиять на пользовательский опыт (сброс выделения, прокрутки).
← На главную