Разработка и Конфигурация · 11 мин
Как программно выполнить команду объекта в 1С
Как программно выполнить команду объекта в 1С: ВыполнитьКоманду, обработчики формы, вызов стандартных команд, типичные ошибки и примеры кода.
В управляемых формах 1С команды объектов (кнопки «Провести», «Записать», команды печати, пользовательские кнопки) часто нужно вызвать не по нажатию пользователя, а из кода — например, при автоматизации документооборота, в обработчиках событий или при тестировании. Платформа предоставляет для этого несколько механизмов: метод формы ВыполнитьКоманду(), прямой вызов процедур обработчиков, а также программное выполнение стандартных действий через объект данных.
Выбор способа зависит от того, где находится код: внутри модуля формы, в общем модуле, на клиенте или на сервере. Неправильный выбор приводит к ошибкам «Процедура или функция с указанным именем не определена», потере контекста формы или обходу проверок, которые выполняются при интерактивном нажатии кнопки.
Ниже разобраны основные подходы с примерами кода, ограничениями каждого метода и типичными ошибками, которые допускают разработчики при программном вызове команд.
Способы программного выполнения команды: что и когда применять
Под «командой объекта» в 1С обычно понимают три разные сущности: команду формы (элемент дерева команд формы, привязанный к кнопке), стандартную команду расширения формы (например, «Провести» у документа) и экспортный метод объекта данных. Способ вызова у них разный.
Команду формы из модуля этой же формы выполняют методом ВыполнитьКоманду(Команда), передавая объект команды из коллекции ЭтаФорма.Команды или саму команду. Это равнозначно нажатию кнопки: сработает назначенный обработчик с учётом директив компиляции.
Если нужно выполнить не команду, а действие над данными (записать документ, провести его), правильнее вызывать методы объекта напрямую: ДокОбъект.Записать(РежимЗаписиДокумента.Проведение). Это работает вне формы, на сервере и не зависит от интерфейса.
Сравнение вариантов
Подходит внутри модуля формы для вызова команды формы со всеми её проверками. Ограничение: только в контексте формы, нельзя вызвать извне.
Подходит, когда логика команды оформлена отдельной процедурой. Ограничение: обходится механизм команд, нужно самостоятельно следить за директивами &НаКлиенте/&НаСервере.
Подходит для записи, проведения, пометки удаления вне формы. Ограничение: не выполняет обработчики формы, например проверки заполнения, добавленные в форме.
Метод ВыполнитьКоманду в модуле формы
Метод ВыполнитьКоманду() доступен у расширений формы (документов, справочников, динамических списков) и у самой управляемой формы. Вызов выглядит так:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ВыполнитьКоманду(ЭтаФорма.Команды.Найти("МояКоманда"));
КонецПроцедуры
Обратите внимание: в параметре передаётся не строка с именем, а объект команды, полученный из коллекции ЭтаФорма.Команды. Если передать строку, получите ошибку несоответствия типов. Чтобы не искать команду каждый раз, можно сохранить ссылку на неё в реквизите формы.
Для стандартных команд расширения формы (например, у документа есть команды «Записать», «Провести») вызов аналогичен — они тоже присутствуют в коллекции команд формы. Однако надёжнее для таких действий использовать методы объекта, потому что поведение стандартных команд может отличаться в зависимости от состояния формы (модифицированность, блокировки).
Прямой вызов процедуры-обработчика команды
На практике чаще всего программно выполняют не саму команду, а процедуру, назначенную её обработчиком. Это прозрачнее и проще отлаживать. Рекомендуемый шаблон — вынести логику в отдельную процедуру, а обработчик команды сделать тонкой обёрткой:
&НаКлиенте
Процедура ПечатьНакладной(Команда)
ВыполнитьПечатьНакладной();
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьПечатьНакладной()
// логика команды
КонецПроцедуры
Теперь из любого места модуля формы (например, из обработчика ПриОткрытии или после оповещения) можно вызвать ВыполнитьПечатьНакладной() без привязки к команде. Такой код проще тестировать и переиспользовать.
Главное ограничение — директивы компиляции. Если процедура объявлена &НаСервере, вызвать её с клиента можно только через серверный вызов, и она не увидит клиентский контекст (например, выбранный файл). Если обработчик команды клиентский, а вам нужна серверная логика, делите код на клиентскую и серверную части.
Программное выполнение стандартных действий объекта
Частая задача — программно «нажать» «Провести» или «Записать» у документа. Вне формы это делается через объект данных:
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);
Такой вызов выполнит обработчики событий объекта (ПередЗаписью, ОбработкаПроведения), но не выполнит обработчики формы, например ПередЗаписью формы с дополнительными проверками. Если бизнес-логика частично реализована в форме, программная запись объекта может её обойти — учитывайте это при проектировании.
Внутри формы документа для записи и проведения используют метод формы Записать() с параметрами: ЭтаФорма.Записать(Новый Структура("РежимЗаписи", РежимЗаписиДокумента.Проведение)). Это ближе к поведению кнопки «Провести», потому что проходит через механизмы формы.
Вызов команды формы из другого модуля или обработки
Напрямую выполнить команду чужой формы нельзя — коллекция команд доступна только внутри её модуля. Стандартный приём: в модуле формы объявить экспортную процедуру, которая внутри вызывает нужную команду или логику, а извне получить объект формы и вызвать эту процедуру.
// В модуле формы документа
&НаКлиенте
Процедура ВыполнитьКомандуИзвне(ИмяКоманды) Экспорт
Если ИмяКоманды = "Печать" Тогда
ВыполнитьПечатьНакладной();
КонецЕсли;
КонецПроцедуры
// В вызывающем коде
ФормаДок = ПолучитьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта",
Новый Структура("Ключ", ДокументСсылка));
ФормаДок.ВыполнитьКомандуИзвне("Печать");
Учтите: ПолучитьФорму() с указанным ключом вернёт уже открытую форму этого объекта, если она есть, или создаст новую. Обращение к экспортным клиентским процедурам формы возможно только на клиенте и только пока форма существует.
Если форма закрыта или её открытие нежелательно, перенесите логику в общий модуль или объект данных — это архитектурно правильнее, чем дёргать форму ради одного действия.
- 1Определите, где должен выполняться код: внутри формы, на клиенте, на сервере или вне формы.
- 2Если внутри формы — используйте ВыполнитьКоманду или прямой вызов процедуры-обработчика.
- 3Если вне формы — вынесите логику в общий модуль или вызывайте методы объекта данных.
- 4Если нужен вызов команды чужой формы — добавьте в неё экспортную процедуру и обращайтесь через ПолучитьФорму.
- 5Проверьте результат: запись документа, отсутствие ошибок в журнале регистрации, корректное состояние формы.
Типичные ошибки и как их избежать
Самая частая ошибка — передача строки с именем команды в ВыполнитьКоманду() вместо объекта команды. Вторая по частоте — попытка вызвать клиентский обработчик из серверного контекста или наоборот, что приводит к ошибке компиляции или невидимости процедуры.
Ещё одна проблема — вызов команды до того, как форма полностью инициализирована. Например, в обработчике ПриСозданииНаСервере клиентские команды ещё недоступны. Выполняйте такие вызовы в ПриОткрытии или через ПодключитьОбработчикОжидания с короткой задержкой, если нужно дождаться полной загрузки.
Проверка результата выполнения команды
После программного вызова команды убедитесь, что действие реально выполнилось. Для записи и проведения проверяйте признаки объекта: Проведен, ПометкаУдаления, дату изменения. Для команд формы — состояние элементов, сообщения пользователю и отсутствие исключений.
Как проверить результат
Свойство Проведен = Истина, движения появились в регистрах
Проведен = Ложь или движений нет — проверка не прошла, смотрите сообщения об ошибках
Обработчик отработал без исключений, форма в ожидаемом состоянии
Ошибка «процедура не определена» или команда не найдена в коллекции
Все документы обработаны, в журнале регистрации нет ошибок
Часть документов пропущена — добавьте обработку исключений и протоколирование
При отладке полезно временно выводить сообщения через Сообщить() или использовать точки останова в конфигураторе. Для серверного кода помните, что отладка на сервере должна быть включена в свойствах информационной базы.
Частые вопросы
Можно ли программно нажать кнопку командной панели, не зная её обработчика?
Да, если кнопка привязана к команде формы: найдите команду в коллекции ЭтаФорма.Команды и вызовите ВыполнитьКоманду. Искать саму кнопку среди элементов формы не требуется — важна именно команда, а не элемент интерфейса.
Как выполнить команду печати программно?
Команды печати в типовых конфигурациях реализованы через подсистему печати. Проще всего вызвать методы модуля менеджера печати объекта или сформировать табличный документ напрямую и вывести его, минуя команду формы. Точный вызов зависит от версии библиотеки стандартных подсистем в вашей конфигурации.
Почему ВыполнитьКоманду выдаёт ошибку «Команда не найдена»?
Команда с таким именем отсутствует в коллекции команд формы. Проверьте имя в редакторе формы (панель «Команды»), учтите регистр не важен, но важны точное написание и то, что команда принадлежит именно этой форме, а не глобальному командному интерфейсу.
Можно ли вызвать команду формы списка из формы элемента?
Напрямую — нет. Получите объект формы списка через ПолучитьФорму или через Оповестить с обработкой оповещения в форме списка. Второй способ предпочтительнее: формы остаются слабо связанными и не зависят от того, открыта ли другая форма.
Чем отличается ЭтаФорма.Записать() от Записать() у объекта?
ЭтаФорма.Записать() проходит через механизмы формы: выполняются обработчики формы ПередЗаписью и ПослеЗаписи, проверки заполнения, обновление интерфейса. Записать у объекта данных работает только с данными и обработчиками модуля объекта, проверки формы не выполняются.
Как выполнить команду с задержкой после открытия формы?
Используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", 0.1, Истина) в обработчике ПриОткрытии. Однократный вызов с минимальным интервалом сработает после завершения инициализации формы. Не используйте циклы ожидания — они блокируют клиентский поток.
Что важно запомнить
Внутри формы команду выполняют через ВыполнитьКоманду с объектом команды или прямым вызовом процедуры-обработчика. Для действий с данными вне формы используйте методы объекта. Вызов команды чужой формы делается через экспортные процедуры или оповещения. Всегда проверяйте результат и помните про разделение клиентского и серверного контекста.