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

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

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

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

Основной принцип: вызов процедуры, а не команды

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

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

Шаг 1: Идентификация процедуры, связанной с командой

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

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

  2. Найдем элемент формы, связанный с командой. Обычно это кнопка. На вкладке «Элементы» формы в конфигураторе найдем эту кнопку. Если команда является стандартной (например, из командной панели), то ее может не быть в виде отдельной кнопки, но она все равно будет присутствовать в списке команд формы.

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

    Для быстрого перехода к коду, можно кликнуть правой кнопкой мыши на элементе формы (кнопке) в палитре элементов формы или на самой команде в списке команд и выбрать пункт «Перейти к обработчику» или «Перейти к определению».

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

    • Параметры процедуры: Есть ли у процедуры входные параметры? Обычно обработчики команд формы не принимают прямых параметров, но процедура, которую они вызывают, может их требовать.
    • Внутренние вызовы: Часто бывает, что процедура обработчика команды вызывает другую, более низкоуровневую процедуру (возможно, экспортную из общего модуля) для выполнения основной логики. Важно понять всю цепочку вызовов — для этого подойдёт инструмент для архитектурного анализа конфигураций.
    • Зависимости: От каких реквизитов формы или объекта зависит работа этой процедуры? Она может полагаться на то, что определенные поля формы уже заполнены.

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

Например, мы обнаружили, что команда «Перезаполнить из ВСД» вызывает процедуру с именем ПерезаполнитьИзВСДНаКлиенте в модуле формы.


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

Шаг 2: Учет контекста выполнения (Клиент/Сервер)

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

  1. Создание формы: Программное создание формы может происходить как на клиенте, так и на сервере. Если вы открываете форму с сервера (например, в фоновом задании или серверной процедуре), вам необходимо будет передать управление на клиент для выполнения команд, связанных с интерактивным интерфейсом.

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

Как правило, все действия по заполнению реквизитов формы и вызову процедур, изменяющих ее состояние и внешний вид, выполняются в клиентском контексте, после того как форма уже открыта.

Шаг 3: Подготовка данных и программный вызов процедуры

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

  1. Получим ссылку на открытую форму. После программного создания или получения формы, у нас должна быть переменная, ссылающаяся на объект формы.

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

    В этом примере ПеременнаяФормы.Методы.Найти("ПерезаполнитьИзВСДНаКлиенте") является более надежным способом проверить наличие метода, чем ПеременнаяФормы.ЕстьРеквизит(), хотя последний также может сработать для публичных процедур/функций формы.

  2. Передача параметров (если требуется): Как мы выяснили, сама процедура, выполняющая логику команды, может принимать параметры. Если наша процедура ПерезаполнитьИзВСДНаКлиенте() была бы определена, например, как ПерезаполнитьИзВСДНаКлиенте(ИсточникДанных), то при вызове мы должны были бы передать соответствующее значение:

    
    ПеременнаяФормы.ПерезаполнитьИзВСДНаКлиенте(ПеременнаяФормы.Объект);
    

    Обычно, процедуры модуля формы работают с ее собственными реквизитами через ЭтотОбъект или напрямую обращаясь к реквизитам формы (например, Объект.ВСД), поэтому явная передача параметров для них может и не потребоваться.

Важные аспекты и потенциальные проблемы

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

  1. Доступность и видимость команды: В конфигураторе для команд могут быть установлены условия доступности (Доступность) или видимости (Видимость), которые зависят от состояния реквизитов формы. При прямом программном вызове процедуры, эти условия игнорируются. То есть, вы можете вызвать процедуру, даже если кнопка была бы неактивна или невидима для пользователя. Это может привести к ошибкам, если логика процедуры полагается на то, что кнопка доступна только при определенных условиях. Перед вызовом процедуры, вам необходимо самостоятельно проверять все условия, которые обеспечивают корректную работу логики, если это критично.

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

  3. Модифицированность формы: Некоторые команды могут изменять данные формы. После программного вызова такой процедуры, форма может оказаться модифицированной. Если вы хотите сохранить изменения, вам потребуется вызвать метод Записать() или ЗаписатьВФорме() для формы или ее объекта.

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

Лучшая практика: Декомпозиция логики

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

Преимущества такого подхода:

Пример декомпозиции:

Предположим, у нас есть общий модуль РаботаСВСДСервер.


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

Теперь в модуле формы мы можем вызывать эту экспортную процедуру:


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

// Обработчик команды формы (Клиент)
&НаКлиенте
Процедура КомандаПерезаполнитьИзВСД(Команда)
    ПерезаполнитьИзВСДНаКлиенте();
КонецПроцедуры

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


&НаКлиенте
Процедура ПрограммноСоздатьИЗаполнитьФорму()

    ПеременнаяФормы = ПолучитьФорму("Документ.ИмяДокумента.ФормаДокумента"); 

    Если ПеременнаяФормы Тогда
        ПеременнаяФормы.Активизировать();
        ПеременнаяФормы.Объект.ВСД = "ПримерЗначенияВСД002"; 
        
        // Теперь мы можем вызвать клиентскую процедуру, которая уже содержит логику
        Если ПеременнаяФормы.Методы.Найти("ПерезаполнитьИзВСДНаКлиенте") <> Неопределено Тогда
            ПеременнаяФормы.ПерезаполнитьИзВСДНаКлиенте();
            Сообщить("Команда 'Перезаполнить из ВСД' выполнена программно через клиентскую процедуру.");
        Иначе
            Сообщить("Процедура 'ПерезаполнитьИзВСДНаКлиенте' не найдена или недоступна в форме.");
        КонецЕсли;

    Иначе
        Сообщить("Не удалось получить форму.");
    КонецЕсли;

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

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

Заключение

Программный вызов команды при создании формы в 1С:Предприятие 8.3 — это стандартная задача, которая эффективно решается путем идентификации и прямого вызова процедуры, лежащей в основе команды. Мы рассмотрели шаги по поиску этой процедуры в конфигураторе, анализу ее зависимостей и параметров, а также учету контекста выполнения (клиент/сервер). Придерживаясь этих рекомендаций и применяя лучшие практики декомпозиции кода, вы сможете надежно автоматизировать необходимые действия в ваших решениях на платформе 1С. Для этой задачи есть сценарии для программной имитации действий пользователя.

← На главную