Как создать документ на основании бизнес-процесса и перенести данные из табличной части

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

При разработке сложных систем на платформе 1С:Предприятие 8.3 часто возникает задача создания связанных объектов. Одной из типовых задач является генерация документа на основании бизнес-процесса. Особенную сложность у начинающих разработчиков вызывает перенос данных из табличных частей и корректное управление жизненным циклом нового объекта (нужно ли его записывать сразу или дать возможность пользователю проверить данные в форме).

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

Разбор проблемы: почему данные не переносятся автоматически

Когда мы используем стандартный конструктор «Ввод на основании», платформа 1С помогает связать простые реквизиты. Однако, если данные находятся внутри табличной части бизнес-процесса, конструктор может их «не видеть» или требовать ручного написания кода. Рассмотрим ситуацию: у нас есть бизнес-процесс СнижениеРисков с табличной частью Причины, и нам нужно создать документ ОценкаЗначимостиРиска, заполнив его реквизиты данными из этой таблицы.

Основная ошибка часто заключается в неправильной передаче контекста или попытке обратиться к переменной ДанныеЗаполнения там, где она не определена. Выясним, как это исправить.

Шаг 1. Настройка обработчика в модуле объекта документа

Логика заполнения нового документа всегда должна располагаться в Модуле объекта создаваемого документа в предопределенной процедуре ОбработкаЗаполнения. Рассмотрим, как правильно обратиться к данным бизнес-процесса-основания.

Проанализируем пример кода, который позволяет достать данные из первой строки табличной части бизнес-процесса:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
    
    // Проверяем, что основанием является именно наш бизнес-процесс
    Если ТипЗнч(ДанныеЗаполнения) = Тип("БизнесПроцессСсылка.СнижениеРисков") Тогда
        
        // Важно: проверяем, есть ли вообще строки в табличной части
        Если ДанныеЗаполнения.Причины.Количество() > 0 Тогда
            
            // Получаем доступ к первой строке (индекс 0)
            СтрокаИсточника = ДанныеЗаполнения.Причины[0];
            
            // Заполняем реквизиты документа из строки ТЧ бизнес-процесса
            Ответственный     = СтрокаИсточника.Ответственный;
            ВероятностьРиска  = СтрокаИсточника.планируемаяВероятностьриска;
            ЗначимостьРиска   = СтрокаИсточника.ПланируемаяЗначимостьРиска;
            ПоследствияРиска  = СтрокаИсточника.ПланируемыеПоследствияРиска;
            Риск              = СтрокаИсточника.Риск;
            
        КонецЕсли;
        
        // Можно также заполнить реквизиты из шапки бизнес-процесса, если нужно
        // Например: ДокументОснование = ДанныеЗаполнения;
        
    КонецЕсли;
    
КонецПроцедуры

Важный момент: обращение по индексу [0] допустимо только в том случае, если вы на 100% уверены, что в бизнес-процессе всегда ровно одна строка. Если строк может быть несколько, правильнее использовать цикл или метод Загрузить(), о которых мы поговорим ниже.

Шаг 2. Вызов создания документа из формы бизнес-процесса

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

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


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

Шаг 3. Работа с несколькими строками табличной части

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

Способ А: Перебор строк в цикле

Этот метод хорош, если имена колонок в бизнес-процессе и документе различаются.


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

Способ Б: Метод Загрузить

Если структуры таблиц идентичны, мы можем воспользоваться методом Выгрузить() у источника и Загрузить() у приемника. Это работает значительно быстрее.


ТаблицаДанных = ДанныеЗаполнения.Причины.Выгрузить();
ТабличнаяЧастьДокумента.Загрузить(ТаблицаДанных);

Шаг 4. Открытие формы нового документа без записи

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

Рассмотрим, как вызвать создание документа так, чтобы открылась форма, а процедура ОбработкаЗаполнения отработала автоматически:


&НаКлиенте
Процедура СоздатьБезЗаписи(Команда)
    
    // Формируем параметры для открытия формы
    // Ключ "Основание" автоматически инициирует механизм заполнения
    ПараметрыФормы = Новый Структура("Основание", Объект.Ссылка);
    
    // Открываем форму нового документа
    ОткрытьФорму("Документ.ОценкаЗначимостиРиска.ФормаОбъекта", ПараметрыФормы);
    
КонецПроцедуры

В этом случае документ не будет записан в базу данных до тех пор, пока пользователь не нажмет кнопку «Провести и закрыть». Это избавляет систему от появления «пустых» или ошибочных документов, если пользователь просто закрыл форму.

Рекомендации по надежности кода

При реализации механизма «Ввод на основании» всегда придерживайтесь следующих правил:

  1. Проверка типа: Всегда проверяйте ТипЗнч(ДанныеЗаполнения) в начале процедуры. Один и тот же документ может создаваться на основании разных объектов (например, из другого документа или из задачи).
  2. Проверка на пустую ссылку: Перед заполнением убедитесь, что ДанныеЗаполнения — это не пустая ссылка, иначе обращение к реквизитам через точку вызовет ошибку.
  3. Использование ЗаполнитьЗначенияСвойств: Чтобы не писать десятки строк кода вида А = Б, используйте функцию ЗаполнитьЗначенияСвойств(Приемник, Источник). Она автоматически копирует значения реквизитов с одинаковыми именами.
  4. Транзакции: Если вы создаете документ программно с записью, помните, что ОбработкаЗаполнения выполняется внутри транзакции записи. Ошибки в ней приведут к откату всей операции.

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

← На главную