Как программно воспроизвести интерактивное изменение реквизита в форме документа 1С

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Финансы и профессиональные услуги
← На главную

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

Анализ проблемы: почему прямой вызов процедуры не работает

В управляемом приложении логика форм жестко разделена между клиентом и сервером. Попытка вызвать процедуру КонтрагентПриИзмененииСервер напрямую из внешней обработки часто приводит к ошибке «Процедура или функция с указанным именем не определена». Это происходит по нескольким причинам:

  1. Область видимости: Процедуры в модуле формы обычно не имеют ключевого слова Экспорт. Даже если они экспортные, к ним нужно обращаться через контекст открытой формы.
  2. Контекст исполнения: Процедура может быть определена с директивой &НаСервере, а вызов происходит с тонкого клиента.
  3. Использование общих модулей: В современных конфигурациях на базе БСП (Библиотека стандартных подсистем) основная логика вынесена в специализированные общие модули с суффиксом Формы или КлиентСервер.

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

Шаг 1. Поиск правильного метода в общем модуле

В типовой конфигурации «Бухгалтерия предприятия 3.0» для документа «Приходный кассовый ордер» существует общий модуль ПриходныйКассовыйОрдерФормы. Именно в нем сосредоточена логика серверного пересчета при изменении ключевых реквизитов. Вместо того чтобы пытаться вызвать внутреннюю процедуру формы, нам следует обратиться к методу этого модуля.

Как правило, такой метод принимает в качестве параметра саму форму (контекст). Рассмотрим пример кода, который должен быть выполнен:


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

// Устанавливаем новое значение реквизита
Форма.Объект.Контрагент = НовыйКонтрагент;

// Вызываем обработку изменения контрагента из общего модуля
ПриходныйКассовыйОрдерФормы.КонтрагентПриИзмененииСервер(Форма);

Шаг 2. Решение проблемы «Переменная не определена»

Если при выполнении кода вы получаете ошибку Переменная не определена (ПриходныйКассовыйОрдерФормы), это означает, что вы пытаетесь обратиться к серверному общему модулю с тонкого клиента. У таких модулей в свойствах обычно включен флаг «Сервер», но выключен флаг «Клиент (управляемое приложение)».

Чтобы решить эту проблему, вызов логики необходимо обернуть в серверную процедуру вашей обработки. Разберем по шагам, как это реализовать:


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

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

Обратите внимание: при передаче ФормаДокумента с клиента на сервер передается весь контекст формы, что позволяет процедурам общего модуля изменять не только реквизиты объекта, но и элементы интерфейса (например, доступность полей или видимость закладок).

Шаг 3. Работа со стеком вызовов для поиска истины

Если вы не уверены, какой именно метод общего модуля вызывается, используйте Стек вызовов (Call Stack). Для этого выполните следующие действия:

  1. Откройте документ в режиме «1С:Предприятие» интерактивно.
  2. В конфигураторе установите точку останова в модуле формы документа внутри процедуры КонтрагентПриИзменении.
  3. Измените контрагента в форме вручную.
  4. Когда сработает отладка, посмотрите в окно «Стек вызовов». Вы увидите всю цепочку: от события формы до глубоких вызовов в общих модулях.
  5. Найдите наиболее «высокоуровневую» процедуру в общем модуле, которая принимает форму в качестве параметра. Это и будет ваша цель для программного вызова.

Альтернативный подход: Использование заполнения объекта

Иногда воспроизводить работу формы слишком сложно из-за «многокаскадности» вызовов. Если ваша задача — создать или обновить документ без обязательного открытия формы, проанализируем альтернативный путь через ОбработкаЗаполнения или методы модуля менеджера.

В типовых конфигурациях часто реализованы методы заполнения в модулях менеджеров документов. Посмотрим на пример вызова универсального заполнения:


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

Важный момент: Метод Заполнить() вызывает процедуру ОбработкаЗаполнения в модуле объекта. В БП 3.0 это основной механизм для подстановки счетов учета и договоров. Это гораздо надежнее, чем пытаться «прожать» кнопки на форме программно.

Резюме и рекомендации

Подведем итоги нашего исследования. Чтобы успешно имитировать интерактивные действия, следуйте этим правилам:

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

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

← На главную