При разработке внешних обработок заполнения табличных частей для конфигураций на Обычных формах (ОФ) программисты часто сталкиваются с необходимостью запросить у пользователя дополнительные параметры перед выполнением алгоритма. Для этого создается вспомогательная форма ввода. Однако после того, как пользователь заполнил реквизиты на этой форме и нажал кнопку «ОК», возникает задача: как правильно передать эти данные назад в обработку и корректно заполнить строки табличной части документа, не нарушив при этом внутреннюю логику пересчета цен, скидок и сумм.
В данной статье мы подробно разберем, как реализовать этот процесс шаг за шагом. Мы рассмотрим два основных сценария передачи данных, проанализируем частые ошибки (такие как отсутствие автоматического пересчета колонок после программного изменения данных) и выясним, как правильно использовать механизмы типовых конфигураций 1С для автоматического обновления сумм.
Этот способ является классическим для обычных форм. Вспомогательная форма открывается модально, блокируя основной интерфейс. После ввода данных форма закрывается, возвращая структуру с заполненными значениями в вызывающий код внешней обработки.
Рассмотрим подробнее реализацию этого механизма.
Шаг 1. Реализация логики на вспомогательной форме параметров
На форме нашей обработки (назовем ее ФормаНастройки) разместим необходимые реквизиты, например: ПроцентСкидки и НоваяЦена. Также добавим кнопку «ОК» (или «Выполнить»). В обработчике нажатия этой кнопки мы сформируем структуру данных и передадим ее в качестве параметра закрытия формы:
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Создаем структуру, в которую помещаем значения реквизитов формы
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("ПроцентСкидкиВИнвойс", ПроцентСкидки);
ПараметрыЗаполнения.Вставить("Цена", НоваяЦена);
// Закрываем форму и возвращаем структуру как результат работы модального окна
Закрыть(ПараметрыЗаполнения);
КонецПроцедуры
Также можно применить более универсальный подход, предложенный участниками форума, — автоматический сбор данных со всех полей ввода формы без жесткого прописывания имен реквизитов в коде:
Процедура КнопкаВыполнитьНажатиеУниверсальная(Кнопка)
ПараметрыЗаполнения = Новый Структура;
Для Индекс = 0 По ЭтаФорма.ЭлементыФормы.Количество() - 1 Цикл
Элемент = ЭтаФорма.ЭлементыФормы.Получить(Индекс);
// Проверяем тип элемента управления, чтобы собирать данные только из полей ввода
Если ТипЗнч(Элемент) = Тип("ПолеВвода") Тогда
ПараметрыЗаполнения.Вставить(Элемент.Имя, Элемент.Значение);
КонецЕсли;
КонецЦикла;
Закрыть(ПараметрыЗаполнения);
КонецПроцедуры
Шаг 2. Вызов вспомогательной формы и заполнение табличной части
В модуле внешней обработки в процедуре Инициализировать (которая является стандартной точкой входа для внешних обработок заполнения ТЧ в обычных формах) мы открываем форму параметров модально, проверяем результат и переносим данные в строки документа:
Процедура Инициализировать(Объект, ИмяТабЧасти, ТабличноеПолеОбъекта) Экспорт
// Получаем вспомогательную форму параметров из этой же обработки
ФормаПараметров = ЭтотОбъект.ПолучитьФорму("ФормаНастройки");
// Открываем форму модально и ожидаем возврата структуры
Результат = ФормаПараметров.ОткрытьМодально();
// Если пользователь закрыл форму крестиком или нажал Cancel, возвращается Неопределено
Если ТипЗнч(Результат) <> Тип("Структура") Тогда
Возврат;
КонецЕсли;
// Получаем саму табличную часть документа
ТабличнаяЧасть = Объект[ИмяТабЧасти];
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
// Быстро копируем значения совпадающих реквизитов из структуры в строку табличной части
ЗаполнитьЗначенияСвойств(СтрокаТЧ, Результат);
КонецЦикла;
КонецПроцедуры
Если вы хотите избежать использования модальных окон (которые блокируют работу всей программы), или вам требуется динамически изменять документ прямо из формы настройки, вы можете передать ссылку на сам изменяемый объект 1С непосредственно во вспомогательную форму в качестве контекста.
Проанализируем этот метод по шагам.
Шаг 1. Передача контекста документа при открытии формы
В процедуре Инициализировать модуля обработки мы не просто открываем форму, а передаем ей ссылку на изменяемый документ через свойства или параметры формы:
Процедура Инициализировать(Объект, ИмяТабЧасти, ТабличноеПолеОбъекта) Экспорт
ФормаПараметров = ЭтотОбъект.ПолучитьФорму("ФормаНастройки");
// Передаем объект документа во вспомогательное свойство формы параметров
ФормаПараметров.ДокументОбъект = Объект;
ФормаПараметров.ИмяТекущейТабЧасти = ИмяТабЧасти;
// Открываем форму в обычном (немодальном) режиме
ФормаПараметров.Открыть();
КонецПроцедуры
Шаг 2. Прямое изменение строк документа из формы параметров
На вспомогательной форме создадим реквизиты объекта ДокументОбъект и ИмяТекущейТабЧасти с типом "Произвольный". При нажатии кнопки заполнения на форме параметров мы можем напрямую работать с табличной частью переданного документа:
Процедура КнопкаЗаполнитьНажатие(Кнопка)
Если ДокументОбъект = Неопределено Тогда
Возврат;
КонецЕсли;
ТабличнаяЧасть = ДокументОбъект[ИмяТекущейТабЧасти];
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
СтрокаТЧ.ПроцентСкидкиВИнвойс = ПроцентСкидки;
СтрокаТЧ.Цена = НоваяЦена;
КонецЦикла;
// Закрываем форму параметров после завершения работы
Закрыть();
КонецПроцедуры
Очень частая и неприятная проблема, с которой столкнулся автор темы на форуме, — после программного заполнения колонок табличной части (например, цены или скидки) формулы расчета сумм, НДС и итогов «не срабатывают». В интерфейсе пользователя колонки заполняются новыми значениями, но итоговые суммы остаются прежними.
Почему это происходит?
При интерактивном вводе данных пользователем на форме документа срабатывают события элементов управления, такие как ПриИзменении у поля ввода или самой табличной части. При программном изменении реквизитов объекта в коде внешней обработки эти интерактивные события не вызываются автоматически платформой 1С.
Как правильно решить эту проблему:
Способ 1. Использование общего модуля конфигурации (рекомендуемый)
В большинстве типовых конфигураций 1С на обычных формах (Управление торговлей 10.3, Управление производственным предприятием 1.3, Комплексная автоматизация 1.1) есть специализированные общие модули для работы с табличными частями документов. Обычно они называются ОбработкаТабличныхЧастей.
Вместо того чтобы вручную прописывать формулы расчета суммы и НДС, вызовем соответствующие процедуры общего модуля прямо внутри цикла перебора строк:
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
СтрокаТЧ.Цена = НоваяЦена;
// Вызываем типовой пересчет суммы строки документа
ОбработкаТабличныхЧастей.РассчитатьСуммуТабЧасти(СтрокаТЧ, Объект);
// Вызываем типовой пересчет суммы НДС строки документа
ОбработкаТабличныхЧастей.РассчитатьСуммуНДСТабЧасти(СтрокаТЧ, Объект);
КонецЦикла;
Использование этого метода гарантирует, что расчет будет произведен по точно таким же правилам и формулам, которые заложены разработчиками вашей конфигурации, с учетом всех ставок НДС и настроек учетной политики.
Способ 2. Вызов экспортных процедур формы документа
Если алгоритм расчета суммы уникален для конкретного документа и не вынесен в общие модули, вы можете сделать процедуру пересчета строки в модуле формы документа экспортной (добавив ключевое слово Экспорт в объявлении процедуры, например: Процедура РассчитатьСуммуСтрокиТЧ(СтрокаТЧ) Экспорт).
В таком случае из внешней обработки мы можем получить доступ к форме документа через переданное табличное поле и вызвать нужный метод:
// Получаем форму документа через свойство табличного поля
ФормаДокумента = ТабличноеПолеОбъекта.ВладелецФормы;
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
СтрокаТЧ.Цена = НоваяЦена;
// Вызываем экспортную процедуру пересчета непосредственно на форме документа
ФормаДокумента.РассчитатьСуммуСтрокиТЧ(СтрокаТЧ);
КонецЦикла;
Мы подробно разобрали, как организовать взаимодействие между основной формой документа и вспомогательной формой внешней обработки в среде Обычных форм 1С. Использование возвращаемой структуры при модальном открытии окна является простым и надежным решением, в то время как прямая передача контекста объекта открывает больше возможностей для немодальной и динамической работы с данными. При заполнении реквизитов всегда помните о необходимости вызова стандартных процедур пересчета из общих модулей типа ОбработкаТабличныхЧастей, чтобы избежать расхождения сумм в документе.