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