Как автоматически пересчитать колонки табличной части документа и обновить форму после внешней обработки в 1С:Предприятие 8.3?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Бухгалтерский учет Промышленность, строительство и АПК
← На главную

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

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

Особенности работы с табличными частями и клиент-серверным взаимодействием

Прежде чем перейти к решениям, давайте вспомним, что архитектура 1С:Предприятие 8.3 разделяет выполнение кода на клиентскую и серверную части. Клиент в основном отвечает за отображение интерфейса и взаимодействие с пользователем, тогда как сервер выполняет основную логику, работает с данными информационной базы. Взаимодействие между ними происходит через серверные вызовы. Это разделение важно учитывать при разработке, особенно когда речь идет о работе с данными документов.

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

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

В типовых конфигурациях 1С, таких как ERP, часто предусмотрены специальные служебные модули для работы с табличными частями. Они позволяют выполнять различные действия, включая пересчет сумм, НДС, заполнение ставок и другие операции. Мы рассмотрим, как использовать эти механизмы для автоматического пересчета. Для глубокого изучения подобных возможностей БСП рекомендуем использовать справочник по методам БСП с примерами использования, который поможет быстро найти нужный программный код.

Обратим внимание на общие модули ПакетнаяОбработкаТабличнойЧастиКлиентСервер и ПакетнаяОбработкаТабличнойЧастиСервер. Они предоставляют методы для обработки как всей табличной части, так и отдельных строк.

Шаг 1: Подготовка параметров пересчета.

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

Шаг 2: Формирование структуры действий.

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

Шаг 3: Вызов серверной процедуры обработки.

Для выполнения пакетной обработки всей табличной части мы используем метод ОбработатьТЧ из модуля ПакетнаяОбработкаТабличнойЧастиСервер. Этот метод принимает объект табличной части и структуру действий.

Посмотрим на пример кода, демонстрирующий этот подход:


// Предполагаем, что "об" - это объект документа, например, ЗаказКлиента
// и мы находимся в серверном контексте (&НаСервере)

// === Часть 1: Заполнение ставки НДС (если требуется) ===
// Получаем объект документа
// об = ссылкаРТУ.ПолучитьОбъект(); // Если мы работаем со ссылкой

СтруктураДействийЗаполнения = Новый Структура;
СтруктураДействийЗаполнения.Вставить("ЗаполнитьСтавкуНДС", ПакетнаяОбработкаТабличнойЧастиКлиентСервер.ПараметрыЗаполненияСтавкиНДС(об));
ПакетнаяОбработкаТабличнойЧастиСервер.ОбработатьТЧ(об.Товары, СтруктураДействийЗаполнения, Неопределено);

// === Часть 2: Пересчет сумм НДС и сумм с НДС ===
СтруктураПересчетаСуммы = ПакетнаяОбработкаТабличнойЧастиКлиентСервер.ПараметрыПересчетаСуммыНДСВТЧ(об);

СтруктураДействийПересчета = Новый Структура;
СтруктураДействийПересчета.Вставить("ПересчитатьСуммуНДС", СтруктураПересчетаСуммы);
СтруктураДействийПересчета.Вставить("ПересчитатьСуммуСНДС", СтруктураПересчетаСуммы);

ПакетнаяОбработкаТабличнойЧастиСервер.ОбработатьТЧ(об.Товары, СтруктураДействийПересчета, Неопределено);

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

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

Бывают ситуации, когда стандартных механизмов недостаточно. Например, если нам нужно выполнить сложный расчет на основе дополнительных реквизитов номенклатуры или реализовать универсальный механизм добавления табличных частей с помощью расширения для хранения специфических данных, а затем обновить определенные колонки. В таких случаях мы можем написать собственный код для построчного пересчета.

Давайте рассмотрим пример, где нам нужно рассчитать площадь на основе длины и ширины, хранящихся в дополнительных реквизитах номенклатуры, и затем обновить количество в табличной части, а также пересчитать суммы — для этого подойдёт автоматический расчет физических показателей в табличной части 1С.

Шаг 1: Создание серверной процедуры.

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


Процедура РасчитатьМ2(ДанныеФормы) Экспорт
    ТекстПодробно = "";
    // ... дальнейший код ...
КонецПроцедуры;

Шаг 2: Подготовка параметров для построчного пересчета.

Аналогично первому решению, мы можем использовать ПакетнаяОбработкаТабличнойЧастиКлиентСервер.ПараметрыПересчетаСуммыНДСВСтрокеТЧ для получения параметров пересчета конкретной строки.


СтруктураПересчетаСуммы = ПакетнаяОбработкаТабличнойЧастиКлиентСервер.ПараметрыПересчетаСуммыНДСВСтрокеТЧ(ДанныеФормы);
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ПересчитатьСуммуНДС",  СтруктураПересчетаСуммы);
СтруктураДействий.Вставить("ПересчитатьСуммуСНДС", СтруктураПересчетаСуммы);
СтруктураДействий.Вставить("ПересчитатьСуммуСУчетомРучнойСкидки", Новый Структура("Очищать", Ложь));
СтруктураДействий.Вставить("ПересчитатьСуммуСУчетомАвтоматическойСкидки", Новый Структура("Очищать", Истина));

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

Шаг 3: Оптимизация получения дополнительных реквизитов.

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


// Получаем ссылки на дополнительные реквизиты один раз до начала цикла
ДопСвойствоШирина = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Ширина");
ДопСвойствоДлина = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Длина");

КэшированныеЗначения = Неопределено; // Используется для оптимизации в типовых механизмах

Шаг 4: Перебор строк табличной части и выполнение расчетов.

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


Для Каждого Товар Из ДанныеФормы.Товары Цикл
    // Код получения свойств и расчет площади...
    Площадь = (Ширина / 1000) * (Длина / 1000) * КоличествоШтук;

    // Обновляем количество...
    // Вызываем построчную обработку типовым механизмом
    ПакетнаяОбработкаТабличнойЧастиСервер.ОбработатьСтрокуТЧ(Товар, СтруктураДействий, КэшированныеЗначения, ДанныеФормы.Товары);
    // ...
КонецЦикла;

Шаг 5: Обновление дополнительных полей формы.

Если в форме предусмотрены поля для вывода дополнительной информации, мы можем обновить их в конце процедуры.

Ключевой момент: Обновление отображения формы

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

Мы рассмотрим несколько методов, которые помогут нам обновить форму:

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

Лучшие практики и рекомендации

Чтобы ваша работа с табличными частями была эффективной и поддерживаемой, мы предлагаем придерживаться следующих рекомендаций:

  1. Выносите код в общие модули: Процедуры, которые выполняют типовые расчеты, лучше выносить в общие модули для повышения переиспользуемости.
  2. Используйте серверные вызовы для объемных операций: Если операция требует сложной логики, всегда выполняйте ее на сервере.
  3. Оптимизируйте доступ к данным в циклах: Выносите получение метаданных за пределы цикла перебора строк.
  4. Программно изменяйте управляемые формы: Для повышения гибкости часто используется программное изменение форм (для разработчиков), что позволяет динамически добавлять элементы и команды. Если же вы хотите упростить процесс, изучите добавление реквизитов и элементов формы на управляемые формы без написания громоздкого кода (поможет конструктор настройки поведения управляемых форм без программирования).
  5. Явно обновляйте форму: Всегда помните о необходимости явно обновлять отображение формы после программного изменения данных.

Мы проанализировали различные подходы к автоматическому пересчету колонок табличных частей и обновлению формы документа. Используя типовые механизмы пакетной обработки или разрабатывая собственные алгоритмы с учетом клиент-серверной архитектуры, вы сможете создавать эффективные и удобные решения в 1С:Предприятие 8.3.

← На главную