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

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

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

Рассмотрим подробно, почему это происходит и как правильно организовать получение актуальных данных.

Выясним причину проблемы

Когда мы выполняем запрос к Документ.ЗаказКлиента.Товары с отбором по ссылке, 1С обращается к таблицам СУБД. Если пользователь добавил товар в табличную часть формы, но еще не нажал кнопку «Записать» или «Провести», данных об этой строке в базе еще нет. Следовательно, запрос вернет результат без учета новой позиции.

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

Решение 1: Обработка коллекции в памяти (рекомендуемый способ)

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

Давайте разберем, как это реализовать:


// Пример функции для расчета веса в памяти
&НаСервере
Функция ПолучитьВесЗаказаВПамяти(Товары)
    ИтогоВес = 0;
    Для Каждого СтрокаТЧ Из Товары Цикл
        // Здесь мы получаем вес номенклатуры. 
        // Для оптимизации рекомендуется использовать заранее 
        // полученные данные или свойства номенклатуры
        ВесСтроки = ПолучитьВесНоменклатуры(СтрокаТЧ.Номенклатура, СтрокаТЧ.Количество);
        ИтогоВес = ИтогоВес + ВесСтроки;
    КонецЦикла;
    Возврат ИтогоВес;
КонецФункции

Этот способ позволяет мгновенно получать результат, так как данные уже загружены в память клиентского приложения. Мы избавляемся от лишних обращений к серверу и СУБД, а также решаем проблему «невидимых» незаписанных строк.

Решение 2: Использование табличной части как параметра запроса

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

  1. Выгрузите табличную часть в таблицу значений: ТЗ = Объект.Товары.Выгрузить();
  2. Передайте эту таблицу в запрос как параметр: Запрос.УстановитьПараметр("ТаблицаТоваров", ТЗ);
  3. В самом тексте запроса используйте параметр &ТаблицаТоваров как временную таблицу.

Этот подход позволяет использовать мощь Запрос, сохраняя при этом актуальность данных, так как мы передаем не ссылку на документ, а текущее состояние строк из памяти.

Оптимизация взаимодействия с пользователем

Не менее важным аспектом является то, как именно мы запускаем процесс пересчета:

Подводя итог, можно сказать, что ключ к корректной работе с данными формы — это использование коллекции объекта Объект.Товары вместо прямого обращения к БД. Это делает код более производительным, а поведение программы — предсказуемым и надежным в любых сценариях редактирования заказа.

← На главную