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

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

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

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

Почему прямая запись в базу данных из обработки — это опасный антипаттерн?

Рассмотрим типичную ошибку, которую совершают начинающие разработчики. В коде внешней обработки они получают объект документа по ссылке, вносят изменения в его табличную часть и принудительно записывают его в базу данных:


&НаСервере
Процедура ЗаполнитьТЧДокументНаСервере()
    // ПОДХОД С ОШИБКОЙ! ТАК ДЕЛАТЬ НЕЛЬЗЯ!
    ДокументОбъект = Объект.Документ.ПолучитьОбъект(); 
    ДокументОбъект.ДанныеОВремени.Загрузить(Объект.ДанныеОВремени.Выгрузить()); 
    ДокументОбъект.Записать();
КонецПроцедуры

Чем опасен этот подход на управляемых формах?

  1. Конфликт модификации данных (потеря работы пользователя): Представим ситуацию. Пользователь открыл документ, начал вносить в него изменения, но еще не нажал кнопку «Записать». В этот момент он запускает вашу обработку заполнения ТЧ. Обработка получает объект из базы данных, перезаписывает его и сохраняет. В базе данных версия объекта меняется. Когда пользователь возвращается к форме документа и пытается нажать «Записать», система выдает критическую ошибку: «Данные изменены или удалены другим пользователем». Вся ручная работа пользователя будет безвозвратно потеряна.
  2. Отсутствие автоматического обновления интерфейса: Поскольку изменения были записаны в базу данных «в обход» открытой формы документа, сам интерфейс (форма-владелец) ничего об этом не узнает. Пользователю придется закрывать документ и открывать его заново, чтобы увидеть обновленную табличную часть. Это крайне неудобно и вызывает вопросы у пользователей.

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

Архитектура по стандартам БСП: Создаем одну универсальную форму

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

Чтобы обработка была удобной для отладки (когда мы открываем ее через меню Файл -> Открыть) и корректно работала при вызове из документа в рабочем режиме, мы должны разделить логику в процедуре ПриСозданииНаСервере. Проанализируем, как это сделать:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, запущена ли обработка в контексте документа через механизм БСП
    Если Параметры.Свойство("ОбъектыНазначения") И Параметры.ОбъектыНазначения.Количество() > 0 Тогда
        // Рабочий режим: документ-владелец передан из БСП
        Объект.Документ = Параметры.ОбъектыНазначения[0];
        
        // Скрываем поле выбора документа на форме параметров, так как он уже определен
        Элементы.Документ.Видимость = Ложь;
    Иначе
        // Режим отладки: обработка открыта вручную через "Файл -> Открыть"
        Элементы.Документ.Видимость = Истина;
    КонецЕсли;
    
КонецПроцедуры

При регистрации обработки в справочнике «Дополнительные отчеты и обработки» необходимо указать тип команды ОткрытиеФормы. Тогда БСП автоматически передаст форму документа в качестве свойства ВладелецФормы открываемой обработки.

Способ 1. Использование метода КопироватьДанныеФормы (Рекомендуемый)

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

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

Для реализации этого способа добавим на форму внешней обработки реквизит с именем ДокументОбъект. Тип этого реквизита должен соответствовать типу заполняемого документа (например, ДокументОбъект.РеализацияТоваровУслуг).

Разберем по шагам код на форме внешней обработки:


&НаКлиенте
Процедура ЗагрузитьДанныеВДокумент(Команда)
    
    // Шаг 1. Проверяем, что форма открыта из документа-владельца
    Если ВладелецФормы = Неопределено Тогда
        Предупреждение("Обработка должна быть запущена из формы документа!");
        Возврат;
    КонецЕсли;
    
    // Шаг 2. Копируем текущие данные из формы-владельца в наш локальный реквизит формы обработки
    КопироватьДанныеФормы(ВладелецФормы.Объект, ДокументОбъект);
    
    // Шаг 3. Обрабатываем и заполняем табличную часть на сервере
    ЗаполнитьТабличнуюЧастьНаСервере();
    
    // Шаг 4. Копируем измененные данные из локального реквизита обратно в форму-владельца
    КопироватьДанныеФормы(ДокументОбъект, ВладелецФормы.Объект);
    
    // Шаг 5. Сигнализируем форме документа, что ее данные были изменены
    ВладелецФормы.Модифицированность = Истина;
    
    // Шаг 6. Закрываем форму параметров обработки
    Закрыть();
    
КонецПроцедуры

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

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

Способ 2. Универсальный механизм через Временное хранилище

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

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

При работе через БСП и стандартную команду заполнения этот механизм можно реализовать следующим образом на форме обработки:


&НаКлиенте
Процедура ВыполнитьЗаполнение(Команда)
    
    // Помещаем таблицу значений во временное хранилище на сервере
    АдресХранилища = ПоместитьДанныеВХранилищеНаСервере();
    
    // Оповещаем форму-владельца о готовности данных
    Оповестить("ЗаполнениеТабличнойЧастиЗавершено", АдресХранилища, ВладелецФормы);
    
    // Закрываем форму параметров
    Закрыть();
    
КонецПроцедуры

&НаСервере
Функция ПоместитьДанныеВХранилищеНаСервере()
    
    // Выгружаем данные ТЧ обработки в обычную Таблицу Значений
    ТаблицаДляПередачи = Объект.ДанныеОВремени.Выгрузить();
    
    // Помещаем в уникальное временное хранилище
    Возврат ПоместитьВоВременноеХранилище(ТаблицаДляПередачи, УникальныйИдентификатор);
    
КонецФункции

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

Критически важный нюанс: Пересчет цен, сумм и итогов

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

Дело в том, что при использовании метода КопироватьДанныеФормы интерактивные события элементов формы (такие как событие ПриИзменении у колонок «Количество», «Цена», «Номенклатура») автоматически не вызываются. Платформа воспринимает это как чисто программное присвоение.

Чтобы решить эту проблему, внутри процедуры ЗаполнитьТабличнуюЧастьНаСервере перед возвратом данных в форму-владелец обязательно вызовите процедуры пересчета из модуля объекта документа или общих модулей конфигурации. Посмотрим на типичный пример для конфигураций на БСП:


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

Изучите структуру вашего документа-цели: найдите в модуле его объекта или менеджера экспортные процедуры пересчета табличных частей и задействуйте их. Это гарантирует, что данные в форме документа будут не просто визуально заполнены, но и математически корректны.

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

← На главную