В процессе разработки в среде 1С:Предприятие 8.3 часто возникает задача обработки данных, которые пользователь уже ввел в форму документа, но еще не нажал кнопку «Записать». Типичный пример — необходимость свернуть строки в табличной части, проверить уникальность позиций или рассчитать промежуточные итоги «на лету», чтобы пользователь увидел результат до окончательной фиксации документа в базе данных.
Многие начинающие разработчики сталкиваются с трудностями, полагая, что если объекта еще нет в базе данных (нет ссылки), то и данные получить невозможно. Однако в управляемых формах работа идет не с данными базы, а с данными формы. Рассмотрим подробнее, как правильно извлечь эту информацию и обработать её.
Прежде чем переходить к коду, проанализируем, где хранятся данные в открытой форме. В управляемом приложении форма документа содержит основной реквизит Объект. Этот реквизит имеет тип ДанныеФормыСтруктура, а его табличные части — тип ДанныеФормыКоллекция.
Важный момент: ДанныеФормыКоллекция — это не ТаблицаЗначений. Несмотря на внешнее сходство, у этой коллекции отсутствуют такие методы, как Свернуть(), ЗаполнитьЗначения() или возможность использования запросов к ней. Поэтому для сложной обработки нам обязательно потребуется преобразование данных.
Если нам нужно просто перебрать строки или найти конкретное значение без обращения к серверу, мы можем работать напрямую с объектом формы. Это работает даже для нового, ни разу не записанного документа.
Рассмотрим пример простого обхода строк в процедуре на клиенте:
&НаКлиенте
Процедура ОбработатьСтрокиНаКлиенте(Команда)
// Обращаемся напрямую к коллекции данных формы
Для Каждого СтрокаПродукции Из Объект.Продукция Цикл
Если СтрокаПродукции.Количество > 100 Тогда
Сообщить("В строке " + СтрокаПродукции.НомерСтроки + " превышен лимит!");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Для выгрузки в простую структуру на клиенте можно использовать методы поиска, но полноценная ТаблицаЗначений на стороне клиента недоступна.
Чтобы выполнить такие операции, как Свернуть(), нам необходимо передать данные на сервер. Выясним, как это сделать правильно. Мы можем использовать метод Выгрузить(), который доступен у коллекции ДанныеФормыКоллекция на сервере.
Разберем по шагам реализацию команды по сворачиванию строк:
&НаКлиенте
Процедура КомандаСвернутьТЧ(Команда)
СвернутьТЧНаСервере();
КонецПроцедуры
&НаСервере
Процедура СвернутьТЧНаСервере()
// 1. Выгружаем данные из формы в полноценную Таблицу Значений
ТЗ = Объект.Продукция.Выгрузить();
// 2. Теперь нам доступны все методы ТЗ
// Например, свернем по Номенклатуре и суммируем Количество
ТЗ.Свернуть("Номенклатура", "Количество");
// 3. Загружаем обработанные данные обратно в форму
Объект.Продукция.Загрузить(ТЗ);
КонецПроцедуры
В этом примере Объект.Продукция.Выгрузить() создает копию данных из памяти формы и помещает их в объект типа ТаблицаЗначений. Обратите внимание, что это происходит мгновенно, так как данные уже находятся в оперативной памяти серверного вызова (если используется контекстный вызов &НаСервере).
Проанализируем ситуацию, когда код кажется верным, но данные «не находятся» или коллекция пуста:
Элементы.Продукция — это визуальный контрол (таблица на экране), а Объект.Продукция — это данные. Выгружать нужно данные.Товары, а программист обращается к Продукция). Всегда проверяйте путь к данным в свойствах элемента формы.Объект. Чтобы принудительно зафиксировать текущую строку перед выгрузкой, на клиенте можно использовать переключение фокуса или метод ЭтаФорма.ТекущийЭлемент = ....&НаСервереБезКонтекста, то Объект будет недоступен. В этом случае данные табличной части нужно передавать в процедуру как параметр.Если вам нужно не просто выгрузить таблицу, а выполнить методы самого документа (например, пересчитать итоги по правилам, описанным в модуле объекта), используйте преобразование коллекции в объект целиком:
&НаСервере
Процедура ПересчитатьДокументНаСервере()
// Преобразуем данные формы в реальный объект документа (без записи в БД)
ДокОбъект = ДанныеФормыВЗначение(Объект, Тип("ДокументОбъект.ПланПроизводства"));
// Вызываем экспортные процедуры из модуля объекта
ДокОбъект.РассчитатьЦены();
// Возвращаем измененные данные назад в форму
ЗначениеВДанныеФормы(ДокОбъект, Объект);
КонецПроцедуры
Этот метод ДанныеФормыВЗначение является наиболее мощным, так как он создает в памяти сервера полноценный экземпляр ДокументОбъект, со всеми его свойствами и табличными частями, полностью идентичный тому, что видит пользователь на экране, даже если документ еще не существует в базе.
Резюмируем: Для выгрузки данных из незаписанного документа используйте Объект.ИмяВашейТаблицы.Выгрузить() в серверном контексте. Это позволит вам получить ТаблицуЗначений, выполнить с ней любые манипуляции и вернуть результат пользователю с помощью метода Загрузить().