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

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

При разработке дополнительных внешних обработок заполнения табличных частей часто возникает задача предоставить пользователю интерактивный интерфейс. Например, для выбора файла Excel, предварительного просмотра и сопоставления номенклатуры перед непосредственной загрузкой в документ. Разберем типичные ошибки, возникающие при попытке передать данные через метод КопироватьДанныеФормы, и рассмотрим рабочий способ реализации загрузки.

Анализ проблемы: почему не работает КопироватьДанныеФормы при вызове из команды

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


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    Для каждого ОбъектНазначение из ОбъектыНазначения Цикл
        ПараметрыФормы = Новый Структура("Ключ", ОбъектНазначение);
        ФормаОткрытогоДок = ПолучитьФорму("Документ.ПриобретениеТоваровУслуг.Форма.ФормаДокумента", ПараметрыФормы);
        
        Рез = КопироватьДанныеФормы(ФормаОткрытогоДок.Объект, ЭтотОбъект.ДокОбСсылка);
        
        Сообщить("Результат копирования: " + СокрЛП(Рез) + " | Номер: " + СокрЛП(ЭтотОбъект.ДокОбСсылка.Номер));
    КонецЦикла;
КонецПроцедуры

В такой ситуации метод КопироватьДанныеФормы возвращает Истина, однако реквизиты объекта-приемника (например, Номер) остаются пустыми. Выясним основные причины такого поведения:

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

Решение 1: Заполнение табличной части через контекст владельца формы

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

Разберем по шагам регистрацию и реализацию этого подхода.

Шаг 1. Регистрация команды с типом «ОткрытиеФормы»

В модуле объекта внешней обработки в функции СведенияОВнешнейОбработке укажем вариант запуска команды как ОткрытиеФормы:


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

Шаг 2. Перенос данных в форму документа-владельца

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


&НаКлиенте
Процедура ВыполнитьЗагрузкуВТЧДокумента(Команда)
    // Получаем доступ к табличной части открытого документа
    ТоварыТЧ = ВладелецФормы.Объект.Товары;
    ТоварыТЧ.Очистить();
    
    Для Каждого СтрокаТЧ Из Объект.ДанныеДляЗагрузки Цикл
        НовСтрока = ТоварыТЧ.Добавить();
        ЗаполнитьЗначенияСвойств(НовСтрока, СтрокаТЧ);
        
        НовСтрока.КоличествоУпаковок = НовСтрока.Количество;
        НовСтрока.Цена = ?(НовСтрока.Количество <> 0, НовСтрока.Сумма / НовСтрока.Количество, 0);
    КонецЦикла;
    
    // Закрываем форму обработки после завершения загрузки
    ЭтаФорма.Закрыть();
КонецПроцедуры

Решение 2: Передача данных через механизм оповещений формы

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

  1. В форме внешней обработки формируем массив или таблицу подготовленных структур с номенклатурой, количеством и ценами.
  2. Вызываем платформенную процедуру ОповеститьОВыборе(ТаблицаЗагруженныхДанных) и закрываем форму обработки.
  3. В форме документа в событии ОбработкаВыбора перехватываем переданные данные и вызываем типовые серверные процедуры пересчета строк, что гарантирует корректность всех связанных полей документа.

Решение 3: Заполнение на сервере без создания интерактивной формы

Если для загрузки не требуется окно сопоставления номенклатуры, оптимально использовать вариант команды ЗаполнениеФормы. В этом случае БСП передает данные формы на сервер:

  1. В модуле объекта обработки объявляем процедуру ИсполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения).
  2. В ПараметрыВыполнения.ЭтаФорма передается контекст документа. Преобразуем ДанныеФормыСтруктураСКоллекцией в реальный прикладной объект через ДанныеФормыВЗначение.
  3. Заполняем табличные части, рассчитываем суммы штатным кодом объекта и возвращаем измененные данные обратно в форму с помощью функции ЗначениеВДанныеФормы.
← На главную