Как заполнить документ на основании другого документа во внешней обработке 1С

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

При разработке внешних обработок в современных конфигурациях на базе 1С:ERP, таких как 1С:Комплексная автоматизация 2.5 (КА 2.5), разработчики часто сталкиваются с необходимостью автоматизировать создание документов. Типовой сценарий: создание документа ЗаказПоставщику на основании ЗаказКлиента. Основная сложность заключается в том, что логика подготовки данных часто скрыта внутри модулей форм, которые недоступны для вызова извне.

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

Анализ проблемы: почему нельзя просто вызвать функцию формы

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

Выясняется, что функция СтруктураДокументаОснованияНаСервере, которая готовит эти данные, находится в модуле формы ЗаказКлиента и не помечена ключевым словом Экспорт. Поскольку программный доступ к контексту формы другого документа невозможен без её открытия, мы не можем вызвать эту функцию напрямую из нашей обработки.

Решение 1: Перенос и адаптация логики во внешнюю обработку

Самый надежный и распространенный способ — это дублирование или перенос логики формирования структуры во внешнюю обработку. Разберем по шагам, как это реализовать.

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

Посмотрим на пример кода во внешней обработке, который подготавливает данные для заполнения:


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

КонецФункции

Решение 2: Использование стандартного механизма заполнения объекта

После того как структура подготовлена, нам необходимо программно создать новый документ и вызвать метод Заполнить(). Этот метод автоматически вызывает процедуру ОбработкаЗаполнения в модуле объекта создаваемого документа.

Разберем, как это выглядит в коде:


Процедура СоздатьЗаказПоставщикуНаСервере(ЗаказКлиентаСсылка)
    
    // 1. Получаем структуру данных
    ДанныеДляЗаполнения = СформироватьДанныеДляЗаказаПоставщику(ЗаказКлиентаСсылка);
    
    // 2. Создаем новый объект документа Заказ поставщику
    НовыйЗаказ = Документы.ЗаказПоставщику.СоздатьДокумент();
    
    // 3. Вызываем стандартный механизм заполнения
    // В ДанныеЗаполнения передаем нашу структуру
    НовыйЗаказ.Заполнить(ДанныеДляЗаполнения);
    
    // 4. Дозаполняем специфичные реквизиты, если нужно
    НовыйЗаказ.Дата = ТекущаяДатаСеанса();
    
    // 5. Записываем документ
    Попытка
        НовыйЗаказ.Записать(РежимЗаписиДокумента.Запись);
        Сообщить("Создан документ: " + НовыйЗаказ.Ссылка);
    Исключение
        Сообщить("Ошибка при записи: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Важные нюансы конфигурации КА 2.5 и ERP

Выясним причину, по которой в КА 2.5 часто недостаточно просто передать ссылку. В крупных конфигурациях процедура ОбработкаЗаполнения документа ЗаказПоставщику часто содержит сложную логику, зависящую от типа входящих данных. Рассмотрим типичный фрагмент модуля объекта:


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

Важный момент: если вы решите просто скопировать код из модуля формы типовой конфигурации, обязательно проверьте наличие вызовов функций из общих модулей. В КА 2.5 активно используются модули типа ЗаказПоставщикуЛогикаСервер или ПродажиВызовСервера. Эти вызовы должны работать и в вашей внешней обработке, так как они обычно являются экспортными.

Рекомендации по разработке

Для создания качественной внешней обработки придерживайтесь следующих правил:

  1. Не пытайтесь взломать контекст формы: Если функция не экспортная и находится в форме — забудьте о ней. Реализуйте получение данных самостоятельно через запрос к базе данных.
  2. Используйте менеджер документа: Проверьте, нет ли в МодулеМенеджера документа ЗаказКлиента экспортной функции для подготовки данных. Иногда разработчики 1С выносят логику туда для возможности использования в фоновых заданиях.
  3. Минимизируйте дублирование кода: Если логика формирования данных слишком велика, постарайтесь вычленить только необходимые поля (Товары, Партнер, Договор).
  4. Учитывайте безопасный режим: Внешние обработки часто запускаются в безопасном режиме, что накладывает ограничения на работу с файловой системой или COM-объектами, но работа с запросами и документами внутри базы остается доступной.

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

← На главную