К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно выполнить команду объекта в 1С

Как программно выполнить команду объекта в 1С: ВыполнитьКоманду, обработчики формы, вызов стандартных команд, типичные ошибки и примеры кода.

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

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

Ниже разобраны основные подходы с примерами кода, ограничениями каждого метода и типичными ошибками, которые допускают разработчики при программном вызове команд.

Способы программного выполнения команды: что и когда применять

Под «командой объекта» в 1С обычно понимают три разные сущности: команду формы (элемент дерева команд формы, привязанный к кнопке), стандартную команду расширения формы (например, «Провести» у документа) и экспортный метод объекта данных. Способ вызова у них разный.

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

Если нужно выполнить не команду, а действие над данными (записать документ, провести его), правильнее вызывать методы объекта напрямую: ДокОбъект.Записать(РежимЗаписиДокумента.Проведение). Это работает вне формы, на сервере и не зависит от интерфейса.

Сравнение вариантов

ВыполнитьКоманду()

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

Прямой вызов процедуры-обработчика

Подходит, когда логика команды оформлена отдельной процедурой. Ограничение: обходится механизм команд, нужно самостоятельно следить за директивами &НаКлиенте/&НаСервере.

Методы объекта данных

Подходит для записи, проведения, пометки удаления вне формы. Ограничение: не выполняет обработчики формы, например проверки заполнения, добавленные в форме.

Метод ВыполнитьКоманду в модуле формы

Метод ВыполнитьКоманду() доступен у расширений формы (документов, справочников, динамических списков) и у самой управляемой формы. Вызов выглядит так:

&НаКлиенте

Процедура ПриОткрытии(Отказ)

ВыполнитьКоманду(ЭтаФорма.Команды.Найти("МояКоманда"));

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

Обратите внимание: в параметре передаётся не строка с именем, а объект команды, полученный из коллекции ЭтаФорма.Команды. Если передать строку, получите ошибку несоответствия типов. Чтобы не искать команду каждый раз, можно сохранить ссылку на неё в реквизите формы.

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

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

На практике чаще всего программно выполняют не саму команду, а процедуру, назначенную её обработчиком. Это прозрачнее и проще отлаживать. Рекомендуемый шаблон — вынести логику в отдельную процедуру, а обработчик команды сделать тонкой обёрткой:

&НаКлиенте

Процедура ПечатьНакладной(Команда)

ВыполнитьПечатьНакладной();

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

&НаКлиенте

Процедура ВыполнитьПечатьНакладной()

// логика команды

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

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

Главное ограничение — директивы компиляции. Если процедура объявлена &НаСервере, вызвать её с клиента можно только через серверный вызов, и она не увидит клиентский контекст (например, выбранный файл). Если обработчик команды клиентский, а вам нужна серверная логика, делите код на клиентскую и серверную части.

Программное выполнение стандартных действий объекта

Частая задача — программно «нажать» «Провести» или «Записать» у документа. Вне формы это делается через объект данных:

ДокОбъект = ДокументСсылка.ПолучитьОбъект();

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);

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

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

Вызов команды формы из другого модуля или обработки

Напрямую выполнить команду чужой формы нельзя — коллекция команд доступна только внутри её модуля. Стандартный приём: в модуле формы объявить экспортную процедуру, которая внутри вызывает нужную команду или логику, а извне получить объект формы и вызвать эту процедуру.

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

&НаКлиенте

Процедура ВыполнитьКомандуИзвне(ИмяКоманды) Экспорт

Если ИмяКоманды = "Печать" Тогда

ВыполнитьПечатьНакладной();

КонецЕсли;

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

// В вызывающем коде

ФормаДок = ПолучитьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта",

Новый Структура("Ключ", ДокументСсылка));

ФормаДок.ВыполнитьКомандуИзвне("Печать");

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

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

Порядок действий
  1. 1
    Определите, где должен выполняться код: внутри формы, на клиенте, на сервере или вне формы.
  2. 2
    Если внутри формы — используйте ВыполнитьКоманду или прямой вызов процедуры-обработчика.
  3. 3
    Если вне формы — вынесите логику в общий модуль или вызывайте методы объекта данных.
  4. 4
    Если нужен вызов команды чужой формы — добавьте в неё экспортную процедуру и обращайтесь через ПолучитьФорму.
  5. 5
    Проверьте результат: запись документа, отсутствие ошибок в журнале регистрации, корректное состояние формы.

Типичные ошибки и как их избежать

Самая частая ошибка — передача строки с именем команды в ВыполнитьКоманду() вместо объекта команды. Вторая по частоте — попытка вызвать клиентский обработчик из серверного контекста или наоборот, что приводит к ошибке компиляции или невидимости процедуры.

Ещё одна проблема — вызов команды до того, как форма полностью инициализирована. Например, в обработчике ПриСозданииНаСервере клиентские команды ещё недоступны. Выполняйте такие вызовы в ПриОткрытии или через ПодключитьОбработчикОжидания с короткой задержкой, если нужно дождаться полной загрузки.

Типичные ошибки
01
Передача строки вместо объекта команды в ВыполнитьКоманду — ошибка несоответствия типов. Используйте ЭтаФорма.Команды.Найти("Имя").
02
Вызов клиентской процедуры с сервера — процедура не видна. Разделяйте код директивами &НаКлиенте и &НаСервере.
03
Программная запись объекта в обход проверок формы — данные сохраняются без контроля, добавленного в форме.
04
Вызов команды в ПриСозданииНаСервере — форма ещё не готова. Переносите вызов в ПриОткрытии.
05
Обращение к форме после её закрытия — ошибка обращения к объекту. Проверяйте, что форма открыта.

Проверка результата выполнения команды

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

Контрольные точки

Как проверить результат

Документ после программного проведения
Норма

Свойство Проведен = Истина, движения появились в регистрах

Тревожный признак

Проведен = Ложь или движений нет — проверка не прошла, смотрите сообщения об ошибках

Вызов команды формы
Норма

Обработчик отработал без исключений, форма в ожидаемом состоянии

Тревожный признак

Ошибка «процедура не определена» или команда не найдена в коллекции

Массовая обработка
Норма

Все документы обработаны, в журнале регистрации нет ошибок

Тревожный признак

Часть документов пропущена — добавьте обработку исключений и протоколирование

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

Частые вопросы

Можно ли программно нажать кнопку командной панели, не зная её обработчика?

Да, если кнопка привязана к команде формы: найдите команду в коллекции ЭтаФорма.Команды и вызовите ВыполнитьКоманду. Искать саму кнопку среди элементов формы не требуется — важна именно команда, а не элемент интерфейса.

Как выполнить команду печати программно?

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

Почему ВыполнитьКоманду выдаёт ошибку «Команда не найдена»?

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

Можно ли вызвать команду формы списка из формы элемента?

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

Чем отличается ЭтаФорма.Записать() от Записать() у объекта?

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

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

Используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", 0.1, Истина) в обработчике ПриОткрытии. Однократный вызов с минимальным интервалом сработает после завершения инициализации формы. Не используйте циклы ожидания — они блокируют клиентский поток.

Итог

Что важно запомнить

Внутри формы команду выполняют через ВыполнитьКоманду с объектом команды или прямым вызовом процедуры-обработчика. Для действий с данными вне формы используйте методы объекта. Вызов команды чужой формы делается через экспортные процедуры или оповещения. Всегда проверяйте результат и помните про разделение клиентского и серверного контекста.