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

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

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

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

Понимание различных типов команд в 1С 8.3

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

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

Наша цель — собрать максимально полный список всех этих команд для заданного объекта.

Пошаговое решение: программное получение команд

Для программного получения списка команд мы разработаем универсальную функцию. Эта функция будет последовательно собирать команды из различных источников, используя информер по метаданным или системные объекты 1С.

Представим себе следующую функцию, которую мы можем использовать на стороне сервера или в общем модуле (быстро подготовить каркас кода поможет ИИ-помощник):


Функция ПолучитьВсеКомандыОбъекта(ПолноеИмяОбъектаМетаданных) Экспорт
    Результат = Новый Массив;

    // 1. Получение команд, определенных непосредственно в объекте метаданных
    // Это стандартные команды, которые являются частью структуры самого объекта.
    ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъектаМетаданных);
    Если ОбъектМетаданных <> Неопределено Тогда
        Для Каждого КомандаМетаданных Из ОбъектМетаданных.Команды Цикл
            // Добавляем к результату имя команды, обеспечивая уникальность
            Если Результат.Найти(КомандаМетаданных.Имя) = Неопределено Тогда
                Результат.Добавить(КомандаМетаданных.Имя);
            КонецЕсли;
        КонецЦикла;
    Иначе
        Возврат Результат; // Объект не найден, нет смысла продолжать
    КонецЕсли;

    // 2. Получение команд, определенных в основных формах объекта
    // Для этого нам нужно определить имена основных форм (объекта и списка) и найти их в метаданных.
    ИменаФормДляПроверки = Новый Массив;
    Если ОбъектМетаданных.ОсновнаяФормаОбъекта <> Неопределено Тогда
        ИменаФормДляПроверки.Добавить(ОбъектМетаданных.ОсновнаяФормаОбъекта.Имя);
    КонецЕсли;
    Если ОбъектМетаданных.ОсновнаяФормаСписка <> Неопределено Тогда
        ИменаФормДляПроверки.Добавить(ОбъектМетаданных.ОсновнаяФормаСписка.Имя);
    КонецЕсли;

    Для Каждого ИмяФормы Из ИменаФормДляПроверки Цикл
        // Формируем полное имя формы, например "Справочник.Номенклатура.Формы.ФормаЭлемента"
        ПолноеИмяФормы = ПолноеИмяОбъектаМетаданных + ".Формы." + ИмяФормы;
        ФормаМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяФормы);

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

// Пример использования функции:
// СписокКомандНоменклатуры = ПолучитьВсеКомандыОбъекта("Справочник.Номенклатура");
// Для Каждого Команда Из СписокКомандНоменклатуры Цикл
//     Сообщить(Команда);
// КонецЦикла;

// СписокКомандРеализации = ПолучитьВсеКомандыОбъекта("Документ.РеализацияТоваровУслуг");
// Для Каждого Команда Из СписокКомандРеализации Цикл
//     Сообщить(Команда);
// КонецЦикла;

Теперь давайте подробнее разберем каждый блок нашей функции.

Разбор функции: получение команд объекта метаданных

Первым шагом в нашей функции является получение команд, которые определены непосредственно в самом объекте метаданных. Мы начинаем с получения объекта метаданных по его полному имени, используя метод Метаданные.НайтиПоПолномуИмени().

  1. Поиск объекта метаданных:

    
    ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъектаМетаданных);
    Если ОбъектМетаданных <> Неопределено Тогда
        // ...
    Иначе
        Возврат Результат; 
    КонецЕсли;
    

    Мы используем полное имя объекта, например, "Справочник.Номенклатура" или "Документ.РеализацияТоваровУслуг". Если объект не найден (например, имя указано неверно), функция сразу завершает работу, возвращая пустой массив.

  2. Перебор команд объекта:

    
    Для Каждого КомандаМетаданных Из ОбъектМетаданных.Команды Цикл
        Если Результат.Найти(КомандаМетаданных.Имя) = Неопределено Тогда
            Результат.Добавить(КомандаМетаданных.Имя);
        КонецЕсли;
    КонецЦикла;
    

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

Получение команд форм

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

  1. Определение имен основных форм:

    
    ИменаФормДляПроверки = Новый Массив;
    Если ОбъектМетаданных.ОсновнаяФормаОбъекта <> Неопределено Тогда
        ИменаФормДляПроверки.Добавить(ОбъектМетаданных.ОсновнаяФормаОбъекта.Имя);
    КонецЕсли;
    Если ОбъектМетаданных.ОсновнаяФормаСписка <> Неопределено Тогда
        ИменаФормДляПроверки.Добавить(ОбъектМетаданных.ОсновнаяФормаСписка.Имя);
    КонецЕсли;
    

    Мы сначала собираем имена этих форм, если они заданы для объекта метаданных.

  2. Поиск и перебор команд форм:

    
    Для Каждого ИмяФормы Из ИменаФормДляПроверки Цикл
        ПолноеИмяФормы = ПолноеИмяОбъектаМетаданных + ".Формы." + ИмяФормы;
        ФормаМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяФормы);
    
        Если ФормаМетаданных <> Неопределено Тогда
            Для Каждого КомандаФормы Из ФормаМетаданных.Команды Цикл
                Если Результат.Найти(КомандаФормы.Имя) = Неопределено Тогда
                    Результат.Добавить(КомандаФормы.Имя);
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    

    Для каждой найденной основной формы мы формируем ее полное имя (например, "Справочник.Номенклатура.Формы.ФормаЭлемента") и также получаем ее объект метаданных. Затем мы перебираем коллекцию ФормаМетаданных.Команды и добавляем уникальные имена команд в наш итоговый массив.

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

Выявление общих команд, привязанных к объекту

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

  1. Перебор всех общих команд:

    
    Для Каждого ОбщаяКомандаМетаданных Из Метаданные.ОбщиеКоманды Цикл
        // ...
    КонецЦикла;
    

    Мы итерируемся по всей коллекции общих команд, доступных в конфигурации.

  2. Проверка назначения команды:

    
    Для Каждого ПараметрНазначения Из ОбщаяКомандаМетаданных.Назначение Цикл
        Если ПараметрНазначения.ПолноеИмя = ПолноеИмяОбъектаМетаданных Тогда
            Если Результат.Найти(ОбщаяКомандаМетаданных.Имя) = Неопределено Тогда
                Результат.Добавить(ОбщаяКомандаМетаданных.Имя);
            КонецЕсли;
            Прервать; 
        КонецЦикла;
    

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

Расширение и доработка решения

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

Учет команд из расширений

Если в конфигурации используются расширения, то они могут добавлять собственные команды или модифицировать существующие. Стандартный объект Метаданные платформы 1С предоставляет доступ только к метаданным основной конфигурации. Для работы с метаданными расширений существует отдельная коллекция Метаданные.Расширения. Чтобы учесть команды из расширений, нам потребуется дополнительно анализировать эту коллекцию:

  1. Перебираем все элементы Метаданные.Расширения.
  2. Для каждого расширения получаем его объект метаданных.
  3. Внутри расширения аналогично ищем объекты метаданных, которые могут быть связаны с нашим целевым объектом, и проверяем их команды, а также общие команды, определенные в расширении.

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

Команды подсистем (отчеты, обработки)

Некоторые подсистемы, например, Библиотека стандартных подсистем (БСП), реализуют механизмы динамического формирования команд. Примером могут служить команды вызова отчетов или обработок, которые появляются в стандартных формах объектов в разделах "Отчеты" или "Дополнительные обработки". Эти команды, как правило, не хранятся явно в метаданных объектов или форм, а формируются программно в зависимости от настроек подсистем (например, через регистры сведений типа "ДополнительныеОтчетыИОбработки").

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

Клиентский анализ командной панели формы

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

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

Объект ИнтерфейсКоманд

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

Применение полученного списка команд

Собранный список команд может быть использован в различных сценариях:

  1. Динамическое формирование меню: Мы можем использовать этот список для создания пользовательских меню или панелей, где будут отображаться только те команды, которые действительно относятся к текущему объекту или контексту.
  2. Проверка прав доступа: Список команд может быть полезен для анализа прав доступа пользователей. Мы можем проверить, к каким командам у пользователя есть доступ, и на основе этого формировать специализированные интерфейсы или отчеты по безопасности.
  3. Анализ функционала: Разработчики могут использовать этот список для быстрого изучения функционала объекта, понимания, какие операции с ним связаны, даже если эти команды скрыты в интерфейсе или вызываются косвенно.
  4. Автоматизированное тестирование: В сценариях автоматизированного тестирования можно использовать этот список для проверки наличия ожидаемых команд или для их программного вызова.

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

← На главную