Как заполнить расширенные реквизиты управляемой формы в ЗУП 3.1 через внешнюю обработку заполнения

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке внешних обработок заполнения для конфигураций на базе 1С:Предприятие 8.3 (особенно в Зарплата и управление персоналом 3.1) программисты часто сталкиваются с ситуацией, когда табличная часть документа содержит так называемые «расширенные» реквизиты. В редакторе формы они отображаются красным пунктиром. Эти данные не хранятся в ДокументОбъект, а рассчитываются динамически при открытии или изменении данных формы. Рассмотрим, как правильно заполнить такие поля, используя штатные механизмы БСП (Библиотеки стандартных подсистем), не прибегая к сомнительным «костылям».

В чем заключается основная проблема

Проанализируем ситуацию на примере документа ВедомостьНаВыплатуЗарплатыВБанк. Когда мы работаем с обычной обработкой заполнения ТЧ (табличной части), платформа предоставляет нам объект документа. Мы можем легко заполнить стандартные колонки (Сотрудник, Подразделение, Выплачено), так как они являются частью метаданных объекта. Однако в ЗУП 3.1 ведомости имеют сложную структуру: суммы к выплате, НДФЛ и другие взаиморасчеты часто завязаны на внутренние механизмы формы, которые хранят данные в коллекциях ДанныеФормы, расширяющих физическую таблицу объекта.

Попытка вызвать серверную процедуру из модуля формы документа напрямую часто приводит к ошибке: Ошибка отображения типов: Отсутствует отображение для типа 'ДанныеФормыЭлементКоллекции'. Это происходит потому, что строка табличной части на клиенте является элементом ДанныеФормы, который нельзя просто так передать в произвольную серверную процедуру в отрыве от всей формы.

Решение №1: Использование типа команды «ЗаполнениеФормы»

Самый правильный и современный способ решить задачу — это использование правильного типа команды при регистрации внешней обработки в справочнике Дополнительные отчеты и обработки. Вместо привычного ВызовСерверногоМетода или ВызовКлиентскогоМетода, нам следует использовать тип ЗаполнениеФормы.

Разберем, почему это важно. При типе команды ЗаполнениеФормы, БСП передает в обработку не просто объект документа, а контекст самой формы. Это открывает нам доступ к экспортным методам формы и всем её реквизитам напрямую. Рассмотрим пример реализации функции СведенияОВнешнейОбработке в модуле объекта обработки:


Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
    
    НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
    НоваяКоманда.Представление = "Заполнить из документа Выплата бывшим сотрудникам (умное)";
    НоваяКоманда.Идентификатор = "ЗаполнитьВедомостьРасширенно";
    НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыЗаполнениеФормы();
    НоваяКоманда.ПоказыватьОповещение = Истина;
    
    Возврат ПараметрыРегистрации;
КонецФункции

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


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив, ПараметрыВыполнения) Экспорт
    
    // ПараметрыВыполнения.ЭтаФорма — это и есть форма документа Ведомость
    ФормаДокумента = ПараметрыВыполнения.ЭтаФорма;
    
    // Вызываем серверную процедуру обработки, передавая форму целиком
    ЗаполнитьДанныеНаСервере(ФормаДокумента);
    
    // Указываем форме, что она изменена
    ФормаДокумента.Модифицированность = Истина;
    
КонецПроцедуры

Решение №2: Работа с данными формы на сервере

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

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


&НаСервереБезКонтекста
Процедура ЗаполнитьДанныеНаСервере(ФормаДокумента)
    
    ОбъектДокумента = ФормаДокумента.Объект;
    
    // 1. Сначала заполняем физические данные ТЧ (Сотрудники, суммы)
    // Здесь может быть ваш алгоритм запроса к данным документа-основания
    Для Каждого СтрокаТЧ Из ОбъектДокумента.Состав Цикл
        // Например, заполняем основные реквизиты
        // СтрокаТЧ.Сотрудник = ...
    КонецЦикла;
    
    // 2. Теперь вызываем расчет расширенных реквизитов формы
    // Проходим по всем строкам данных формы (это уже не просто объект, а данные интерфейса)
    Для Каждого СтрокаСостава Из ОбъектДокумента.Состав Цикл
        
        // Вызываем типовой метод ЗУП, который обычно вызывается при изменении строки
        // Ему нужно передать форму и конкретную строку
        ВзаиморасчетыССотрудникамиФормыРасширенный.ВедомостьПриПолученииДанныхСтрокиСостава(
            ФормаДокумента, 
            СтрокаСостава
        );
        
    КонецЦикла;
    
    // 3. Крайне важно обновить итоги формы, иначе пользователь увидит старые суммы в подвале
    ВзаиморасчетыССотрудникамиФормыРасширенный.ВедомостьПриИзмененииСостава(ФормаДокумента);

КонецПроцедуры

Почему нельзя просто использовать «ЗначениеВДанныеФормы»

Рассмотрим распространенную ошибку. Программисты часто пытаются получить объект из данных формы через ДанныеФормыВЗначение, заполнить его на сервере и вернуть обратно через ЗначениеВДанныеФормы. Выясним причину, почему в случае с расширенными реквизитами это работает плохо:

  1. Метод ЗначениеВДанныеФормы обновляет только те поля, которые есть в метаданных объекта. Все расчетные колонки формы, не имеющие соответствия в объекте, будут очищены или сброшены в значения по умолчанию.
  2. При использовании этого метода не срабатывают обработчики событий формы, которые отвечают за динамические связи между колонками (например, автоматический расчет НДФЛ при изменении суммы выплаты).

Поэтому использование типа команды ЗаполнениеФормы является единственным верным путем, так как оно позволяет манипулировать данными формы напрямую, сохраняя состояние расширенных реквизитов.

Важные нюансы и рекомендации

Рассмотрим еще несколько технических моментов, которые помогут сделать вашу обработку надежной:

1. Отработка итогов. В сложных формах ЗУП 3.1 итоги документа (сумма к выплате, НДФЛ к удержанию) часто хранятся в отдельных реквизитах формы. После программного изменения строк таблицы обязательно ищите и вызывайте процедуры типа РассчитатьИтоги(), если они объявлены как экспортные в модуле формы документа, либо используйте соответствующие процедуры из расширенных модулей взаиморасчетов.

2. Модифицированность. Платформа не всегда понимает, что данные формы изменились, если вы меняли их напрямую на сервере через контекст формы в обработке. Всегда явно устанавливайте ФормаДокумента.Модифицированность = Истина; на клиенте после завершения работы серверного кода.

3. Использование структуры-«заглушки». Если по каким-то причинам вы не можете использовать ЗаполнениеФормы, вы можете попытаться обмануть типовой код, создав структуру, имитирующую форму. Рассмотрим этот прием (хотя он считается менее надежным):


// В серверном коде
ПараметрыИмитацииФормы = Новый Структура;
ПараметрыИмитацииФормы.Вставить("Объект", ДанныеФормыОбъект);
ПараметрыИмитацииФормы.Вставить("ХарактерВыплаты", ФормаДокумента.ХарактерВыплаты);

// Если типовая процедура обращается к Форма.Объект, она примет эту структуру
ТиповойМодуль.РассчитатьЧтоТо(ПараметрыИмитацииФормы, СтрокаТЧ);

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

Резюме

Мы выяснили, что для корректного заполнения сложных документов в ЗУП 3.1 необходимо работать не с объектом базы данных, а с контекстом управляемой формы. Использование правильного типа команды в регистрации обработки и прямая передача формы в серверные методы позволяют обойти ограничения платформы по передаче элементов коллекций и использовать всю мощь типовых механизмов конфигурации.

← На главную