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

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

В процессе разработки в среде 1С:Предприятие 8.3 часто возникает задача обработки данных, которые пользователь уже ввел в форму документа, но еще не нажал кнопку «Записать». Типичный пример — необходимость свернуть строки в табличной части, проверить уникальность позиций или рассчитать промежуточные итоги «на лету», чтобы пользователь увидел результат до окончательной фиксации документа в базе данных.

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

Понимание структуры данных управляемой формы

Прежде чем переходить к коду, проанализируем, где хранятся данные в открытой форме. В управляемом приложении форма документа содержит основной реквизит Объект. Этот реквизит имеет тип ДанныеФормыСтруктура, а его табличные части — тип ДанныеФормыКоллекция.

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

Способ 1. Выгрузка данных на клиенте

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

Рассмотрим пример простого обхода строк в процедуре на клиенте:


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

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

Способ 2. Выгрузка в Таблицу Значений на сервере

Чтобы выполнить такие операции, как Свернуть(), нам необходимо передать данные на сервер. Выясним, как это сделать правильно. Мы можем использовать метод Выгрузить(), который доступен у коллекции ДанныеФормыКоллекция на сервере.

Разберем по шагам реализацию команды по сворачиванию строк:


&НаКлиенте
Процедура КомандаСвернутьТЧ(Команда)
    СвернутьТЧНаСервере();
КонецПроцедуры

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

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

Типичные ошибки и подводные камни

Проанализируем ситуацию, когда код кажется верным, но данные «не находятся» или коллекция пуста:

  1. Обращение к элементам формы вместо реквизитов: Помните, что Элементы.Продукция — это визуальный контрол (таблица на экране), а Объект.Продукция — это данные. Выгружать нужно данные.
  2. Неправильное имя реквизита: Как показала практика обсуждений на форумах, часто разработчики просто путают имена таблиц (например, на форме отображается таблица Товары, а программист обращается к Продукция). Всегда проверяйте путь к данным в свойствах элемента формы.
  3. Буферизация ввода: Если пользователь ввел значение в ячейку и не нажал Enter (не покинул строку), данные могут еще не зафиксироваться в Объект. Чтобы принудительно зафиксировать текущую строку перед выгрузкой, на клиенте можно использовать переключение фокуса или метод ЭтаФорма.ТекущийЭлемент = ....
  4. Использование серверного вызова без контекста: Если вы используете &НаСервереБезКонтекста, то Объект будет недоступен. В этом случае данные табличной части нужно передавать в процедуру как параметр.

Продвинутый метод: Преобразование через ДанныеФормыВЗначение

Если вам нужно не просто выгрузить таблицу, а выполнить методы самого документа (например, пересчитать итоги по правилам, описанным в модуле объекта), используйте преобразование коллекции в объект целиком:


&НаСервере
Процедура ПересчитатьДокументНаСервере()
    // Преобразуем данные формы в реальный объект документа (без записи в БД)
    ДокОбъект = ДанныеФормыВЗначение(Объект, Тип("ДокументОбъект.ПланПроизводства"));
    
    // Вызываем экспортные процедуры из модуля объекта
    ДокОбъект.РассчитатьЦены();
    
    // Возвращаем измененные данные назад в форму
    ЗначениеВДанныеФормы(ДокОбъект, Объект);
КонецПроцедуры

Этот метод ДанныеФормыВЗначение является наиболее мощным, так как он создает в памяти сервера полноценный экземпляр ДокументОбъект, со всеми его свойствами и табличными частями, полностью идентичный тому, что видит пользователь на экране, даже если документ еще не существует в базе.

Резюмируем: Для выгрузки данных из незаписанного документа используйте Объект.ИмяВашейТаблицы.Выгрузить() в серверном контексте. Это позволит вам получить ТаблицуЗначений, выполнить с ней любые манипуляции и вернуть результат пользователю с помощью метода Загрузить().

← На главную