Как вызвать процедуру пересчета при добавлении строки в табличную часть через подбор в 1С 8.3 (Обычные формы)

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

При разработке и кастомизации конфигураций на обычных формах (например, «Управление торговлей 10.3», «Управление производственным предприятием 1.3» или «Комплексная автоматизация 1.1») программисты часто сталкиваются с неприятной особенностью: логика, которая отлично работает при ручном вводе строк в табличную часть, напрочь отказывается выполняться при использовании механизма подбора товаров. Выясним причину этой проблемы, детально разберем механизм работы подбора и рассмотрим правильное архитектурное решение, которое позволит избежать дублирования кода.

В чем суть проблемы и почему не работают стандартные события?

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

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

Однако, когда пользователь нажимает кнопку «Подбор», открывается специализированное диалоговое окно (форма подбора). При выборе товаров в этом окне данные передаются в документ программно. В коде это выглядит как прямой вызов метода Добавить() у коллекции строк табличной части. Программное изменение коллекции данных не вызывает интерактивные события элементов управления формы. Именно поэтому процедура ПослеОкончанияРедактирования при подборе просто игнорируется системой.

Как устроен механизм подбора в УТ 10.3?

Проанализируем, как возвращаются данные из формы подбора в документ. В типовых конфигурациях на обычных формах этот процесс состоит из следующих шагов:

  1. Из документа открывается форма подбора (например, обработка ПодборНоменклатуры) с указанием владельца формы. Владельцем может выступать либо сама форма документа, либо непосредственно табличное поле.
  2. Пользователь осуществляет выбор товаров в форме подбора.
  3. При выборе номенклатуры форма подбора вызывает метод платформы ОповеститьОВыборе(ЗначениеВыбора).
  4. Платформа ловит это оповещение и передает управление в форму владельца, вызывая предопределенное событие ОбработкаВыбора(ЗначениеВыбора, Источник).

Если при открытии подбора владельцем была указана форма документа, то обрабатывать выбор нужно именно в модуле формы документа. В типовой УТ 10.3 стандартный маршрут обработки выбора выглядит следующим образом:


Процедура ОбработкаВыбора(ЗначениеВыбора, Источник)
    // Проверяем, что вернулась структура с данными подбора
    Если ТипЗнч(ЗначениеВыбора) = Тип("Структура") Тогда
        // Перенаправляем обработку в специализированную процедуру
        ОбработкаПодбора(Товары, ЗначениеВыбора);
    КонецЕсли;
КонецПроцедуры

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

Пошаговое решение проблемы: Рефакторинг кода

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

Выполним задачу по шагам.

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

Вынесем всю бизнес-логику заполнения и расчета строки табличной части в отдельную неэкспортную процедуру модуля формы документа. Назовем её, например, РассчитатьИЗаполнитьСтрокуТаблицы. В качестве параметра процедура должна принимать строку табличной части (строку коллекции):


Процедура РассчитатьИЗаполнитьСтрокуТаблицы(СтрокаТЧ)
    
    // 1. Заполнение значений по умолчанию, если они не заполнены
    Если Не ЗначениеЗаполнено(СтрокаТЧ.СтавкаНДС) Тогда
        СтрокаТЧ.СтавкаНДС = СтрокаТЧ.Номенклатура.СтавкаНДС;
    КонецЕсли;
    
    // 2. Расчет производных показателей
    СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
    
    // Расчет НДС
    НДС_Процент = Ценообразование.ПолучитьСтавкуНДС(СтрокаТЧ.СтавкаНДС);
    СтрокаТЧ.СуммаНДС = (СтрокаТЧ.Сумма * НДС_Процент) / (100 + ?(СтрокаТЧ.ДокументОбъект.УчитыватьНДС, НДС_Процент, 0));
    
КонецПроцедуры

Шаг 2. Подключение процедуры к интерактивным событиям

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


Процедура ТоварыКоличествоПриИзменении(Элемент)
    // Получаем текущую строку, которую редактирует пользователь
    СтрокаТЧ = ЭлементыФормы.Товары.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        РассчитатьИЗаполнитьСтрокуТаблицы(СтрокаТЧ);
    КонецЕсли;
КонецПроцедуры

Процедура ТоварыЦенаПриИзменении(Элемент)
    СтрокаТЧ = ЭлементыФормы.Товары.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        РассчитатьИЗаполнитьСтрокуТаблицы(СтрокаТЧ);
    КонецЕсли;
КонецПроцедуры

Шаг 3. Подключение процедуры к механизму подбора

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


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

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

Как быстро найти нужный обработчик с помощью замера производительности?

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

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

  1. В конфигураторе откроем модуль формы интересующего нас документа.
  2. Запустим сеанс «1С:Предприятие» в режиме отладки.
  3. Откроем нужный документ, нажмите кнопку «Подбор» и подготовьте форму подбора к выбору товара (но пока не выбирайте его).
  4. Вернемся в Конфигуратор и включим замер производительности, выбрав в главном меню: Отладка -> Замер производительности (или нажав соответствующую кнопку на панели инструментов).
  5. Переключимся обратно в режим предприятия и выполним выбор товара в форме подбора (так, чтобы строка добавилась в документ).
  6. Сразу же вернемся в конфигуратор и выключим замер производительности тем же способом.

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

← На главную