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