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