Как автоматически провести документ при открытии его формы в 1С:Предприятие 8.3

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

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

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

Причина ошибки «Несоответствие типов» при попытке записи

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

Чтобы провести документ, нам нужно работать либо непосредственно с объектом базы данных на сервере, либо использовать специализированные методы формы на клиенте. Рассмотрим основные способы реализации этой задачи.

Способ 1. Создание и проведение на сервере до открытия формы (Рекомендуемый)

Наиболее правильный и стабильный подход — полностью подготовить документ (создать, заполнить, провести) на сервере и только после этого передать ссылку на уже готовый документ для открытия его формы. В этом случае пользователь открывает форму уже проведенного документа и не сталкивается с задержками или ошибками транзакций.

Рассмотрим пример реализации команды создания документа «Установка цен номенклатуры» на основании «Приобретения товаров и услуг»:


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

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

Преимущества: исключаются ошибки интерфейса, документ гарантированно записывается в базу до визуализации, легко обрабатывать ошибки проведения через блок Попытка...Исключение.

Способ 2. Программное заполнение данных формы с конвертацией в объект

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

Посмотрим на алгоритм действий:

  1. Получаем форму документа программно через ПолучитьФорму.
  2. Передаем данные формы на сервер.
  3. Преобразуем ДанныеФормы в реальный ДокументОбъект.
  4. Выполняем заполнение и команду Записать(РежимЗаписиДокумента.Проведение).
  5. Возвращаем измененные данные (уже с ссылкой и статусом проведения) обратно в форму и открываем её.

&НаКлиенте
Процедура СоздатьСПреобразованием(Команда)
    Форма = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.ФормаОбъекта");
    ДанныеФормы = Форма.Объект;
    
    ВыполнитьПроведениеНаСервере(ДанныеФормы, Объект.Ссылка);
    
    КопироватьДанныеФормы(ДанныеФормы, Форма.Объект);
    Форма.Открыть();
КонецПроцедуры

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

Способ 3. Использование обработчика ожидания в форме

Иногда логика требует, чтобы проведение инициировала именно сама форма после того, как она была полностью инициализирована и отображена пользователю. Напрямую вызывать проведение в ПриОткрытии нельзя, так как это может привести к конфликтам блокировок или некорректному поведению элементов управления.

Проанализируем ситуацию: мы можем передать в форму параметр «Автопроведение» и использовать ПодключитьОбработчикОжидания. Это позволит системе «дорисовать» интерфейс и через долю секунды запустить процедуру записи.

В модуле формы документа:


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

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

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

Важные нюансы и рекомендации

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

Подводя итог, отметим, что выбор метода зависит от конкретной бизнес-логики. Если документ должен быть проведен «тихо» и быстро — используйте Способ 1. Если же нужно показать пользователю процесс и дать возможность вмешаться в случае ошибки проведения — используйте Способ 3.

← На главную