При разработке обработок загрузки данных в конфигурацию 1С:Управление нашей фирмой (УНФ) программисты часто сталкиваются с проблемой: данные в табличную часть загружаются, но автоматические расчеты (цены, суммы, НДС, скидки), привязанные к событию ПриИзменении на форме, не срабатывают. Это происходит потому, что событие ПриИзменении является клиентским и интерактивным, а программная загрузка выполняется на сервере.
В этой статье мы подробно разберем, как правильно организовать вызов логики пересчета строк, избегая дублирования огромных массивов кода и типичных ошибок при работе с управляемыми формами.
Рассмотрим ситуацию: в форме документа логика заполнения строки (например, подстановка цены при выборе номенклатуры) прописана непосредственно в обработчике НоменклатураПриИзменении. Когда пользователь выбирает товар руками, платформа вызывает этот код. Однако при программном заполнении коллекции Объект.Товары на сервере никакие события формы не генерируются.
Попытки «нажать на кнопку» программно или имитировать выбор строки через ТекущаяСтрока часто приводят к исключению «Ошибка изменения значения» или «Метод не доступен на сервере». Выясним, как решить эту задачу правильно.
Конфигурация УНФ достаточно технологична, и большинство расчетов в ней уже вынесено в общие модули. Вместо того чтобы пытаться вызвать событие формы, мы можем использовать серверные методы, которые делают ту же работу. Проанализируем состав конфигурации и выделим ключевые модули:
Рассмотрим пример программного заполнения строки на сервере с вызовом стандартной логики:
// Пример заполнения строки заказа покупателя на сервере
НоваяСтрока = Объект.Запасы.Добавить();
НоваяСтрока.Номенклатура = ВыбранныйТовар;
// Вызываем типовой механизм заполнения реквизитов по номенклатуре
ПараметрыЗаполнения = Новый Структура("ДокументОбъект, ИмяТабличнойЧасти", Объект, "Запасы");
ЗаполнениеДокументов.ЗаполнитьСтрокуТабличнойЧасти(Объект, НоваяСтрока, ПараметрыЗаполнения);
// Принудительно вызываем расчет цен и сумм, если это предусмотрено в модуле менеджера или объекта
Объект.РассчитатьЦеныИСуммы(НоваяСтрока);
Если в вашей форме УНФ в событии ПриИзменении действительно содержится «100500 строк кода», которые уникальны для этого документа, лучшим архитектурным решением будет рефакторинг. Нам нужно исключить дублирование кода (принцип DRY — Don't Repeat Yourself).
Разберем этот процесс по шагам:
РассчитатьПараметрыСтроки(СтрокаТЧ).ПриИзменении заменим старый код на вызов этой новой процедуры.Посмотрим на пример кода в модуле объекта:
// В модуле объекта
Процедура РассчитатьПараметрыСтроки(ТекущаяСтрока) Экспорт
// Здесь размещаем всю логику: цены, скидки, НДС
ТекущаяСтрока.Сумма = ТекущаяСтрока.Количество * ТекущаяСтрока.Цена;
// ... и так далее
КонецПроцедуры
Теперь на форме вызов будет выглядеть крайне лаконично:
&НаКлиенте
Процедура ЗапасыНоменклатураПриИзменении(Элемент)
СтрокаТЧ = Элементы.Запасы.ТекущиеДанные;
// Вызываем серверный метод объекта для расчета
РассчитатьПараметрыСтрокиНаСервере(СтрокаТЧ.ПолучитьИдентификатор());
КонецПроцедуры
&НаСервере
Процедура РассчитатьПараметрыСтрокиНаСервере(ИдентификаторСтроки)
ДокОбъект = РеквизитФормыВЗначение("Объект");
СтрокаТЧ = ДокОбъект.Запасы.НайтиПоИдентификатору(ИдентификаторСтроки);
ДокОбъект.РассчитатьПараметрыСтроки(СтрокаТЧ);
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Автор темы на форуме столкнулся с ошибкой при попытке программно менять текущую строку в форме. Важно помнить: в управляемом приложении ТекущаяСтрока — это не индекс массива и не сам объект данных, а Идентификатор строки (число).
Если вам все же необходимо программно «пройтись» по строкам в контексте формы и вызвать для каждой некий клиентский код, делайте это так:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
// Устанавливаем фокус на строку, используя её уникальный идентификатор
Элементы.Товары.ТекущаяСтрока = СтрокаТЧ.ПолучитьИдентификатор();
// Теперь можно вызывать клиентские процедуры, которые опираются на ТекущиеДанные
ТоварыНоменклатураПриИзменении(Элементы.Товары);
КонецЦикла;
Внимание: Этот метод работает только на клиенте. Однако помните, что вызывать ПриИзменении в цикле — это «костыль». Правильнее использовать подходы, описанные в первом и втором пунктах.
Если заполнение происходит внутри формы (например, по кнопке «Загрузить» в самой форме заказа), самым эффективным способом будет временная конвертация данных формы в прикладной объект. Это позволит использовать все методы модуля объекта, включая те, что отвечают за расчеты.
Проанализируем алгоритм:
ДанныеФормыСтруктура в полноценный ДокументОбъект через РеквизитФормыВЗначение.ЗначениеВРеквизитФормы.Этот подход гарантирует, что все связанные поля будут рассчитаны корректно, а пользователь сразу увидит результат на экране после завершения серверного вызова.
Для качественного решения задачи в 1С:УНФ следует придерживаться следующих правил:
ЗаполнитьСтрокуТабличнойЧасти и методы расчета сумм в ПродажиСервер.ПолучитьИдентификатор().Соблюдение этих принципов позволит вам создавать надежные механизмы загрузки данных, которые не ломаются при обновлении конфигурации и сохраняют всю бизнес-логику документа.