Как программно отменить проведение документа в управляемых формах 1С 8.3?

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

При работе с управляемыми формами в «1С:Предприятии 8.3» начинающие разработчики часто сталкиваются с ошибкой «Несоответствие типов» при попытке программно отменить проведение документа. Ситуация кажется стандартной: мы создаем кнопку, пишем команду и вызываем метод Записать, передавая в него режим отмены проведения. Однако платформа выдает ошибку. Давайте подробно разберем, почему это происходит, проанализируем механизмы работы формы и объекта, и рассмотрим два правильных способа решения этой задачи.

Выясним причину ошибки: форма vs объект

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

  1. Метод ДокументОбъект.Записать(): этот метод доступен только на сервере. Он принимает в качестве первого параметра значение перечисления РежимЗаписиДокумента (например, РежимЗаписиДокумента.ОтменаПроведения).
  2. Метод Расширение управляемой формы для документа.Записать(): этот метод доступен и на клиенте, и на сервере. Но, в отличие от метода объекта, он принимает в качестве параметра структуру, а не значение перечисления.

Когда вы пишете в модуле формы Записать(РежимЗаписиДокумента.ОтменаПроведения), система ожидает структуру параметров записи, а получает элемент перечисления. Именно это и вызывает ошибку «Несоответствие типов».

Решение 1: Программная отмена проведения через объект на сервере

Рассмотрим первый способ, который является наиболее «прозрачным» с точки зрения логики работы платформы. Суть его заключается в том, чтобы передать данные формы на сервер, преобразовать их в реальный объект документа, выполнить отмену проведения и вернуть обновленные данные обратно на форму. Проанализируем пример кода:


&НаКлиенте
Процедура РаспровестиДокумент(Команда)
    
    // Сначала проверим, проведен ли документ вообще
    Если НЕ Объект.Проведен Тогда
        Сообщить("Документ еще не проведен, отмена не требуется.");
        Возврат;
    КонецЕсли;

    // Вызываем серверную процедуру для работы с объектом
    РаспровестиДокументНаСервере();
    
КонецПроцедуры

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

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

Решение 2: Использование метода формы с параметрами (рекомендуемый способ)

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

Разберем, как правильно подготовить структуру параметров:


&НаКлиенте
Процедура ОтменитьПроведениеЭлегантно(Команда)

    // Подготавливаем структуру параметров записи
    ПараметрыЗаписи = Новый Структура;
    ПараметрыЗаписи.Вставить("РежимЗаписи", РежимЗаписиДокумента.ОтменаПроведения);
    
    // Вызываем метод Записать расширения формы
    // Платформа сама поймет, что нужно сделать, и обновит интерфейс
    Записать(ПараметрыЗаписи);

КонецПроцедуры

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

Передача дополнительных параметров и обработка на сервере

Иногда требуется не просто отменить проведение, но и передать на сервер какой-то признак (например, чтобы в модуле объекта пропустить определенные проверки). Поскольку метод Записать на форме принимает структуру, мы можем добавить туда любые свои данные.

Посмотрим на пример расширенного вызова:


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

На сервере в модуле формы мы сможем поймать этот параметр:


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

Важные нюансы при программной отмене проведения

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

Подводя итог, можно сказать: если ваша задача просто отменить проведение из формы, лучше всего использовать Решение №2 со структурой параметров. Это минимизирует количество кода и снижает риск возникновения ошибок синхронизации данных между клиентом и сервером.

← На главную