Программное создание элементов интерфейса в управляемых формах 1С — это мощный инструмент, позволяющий адаптировать систему под конкретные нужды пользователя «на лету». Однако разработчики часто сталкиваются с досадной ошибкой: «Ошибка при вызове метода контекста (Добавить): Имя не уникально». Чаще всего это происходит при попытке добавить новую команду в коллекцию формы. В этой статье мы подробно разберем, почему возникает эта ситуация, как правильно организовать код и какие нюансы следует учитывать при динамическом управлении интерфейсом.
Рассмотрим классический пример кода, который часто приводит к ошибке. Представим, что в процедуре ПриСозданииНаСервере мы пытаемся создать команду и кнопку, которая будет ее вызывать:
// Создадим команду формы
НоваяКоманда = Команды.Добавить("НоваяКомандаНомер1");
НоваяКоманда.Заголовок = "Hello world!";
НоваяКоманда.Действие = "ВыполнитьДействиеНовойКоманды";
// Создадим кнопку и привяжем ее к команде
НовыйЭлемент = Элементы.Добавить(
"НоваяКнопкаНаФорме",
Тип("КнопкаФормы"),
Элементы.ГруппаКнопка
);
НовыйЭлемент.Вид = ВидКнопкиФормы.КнопкаКоманднойПанели;
НовыйЭлемент.ИмяКоманды = "НоваяКомандаНомер1";
Проанализируем ситуацию: если этот код отрабатывает один раз, кнопка успешно появляется на форме. Но если система пытается выполнить этот фрагмент повторно, метод Команды.Добавить() вызывает исключение, так как команда с идентификатором НоваяКомандаНомер1 уже существует в коллекции Команды этой формы.
Выясним причину, почему код может вызываться дважды. В контексте управляемого приложения событие ПриСозданииНаСервере выполняется один раз при открытии формы. Однако ошибка может возникнуть, если:
ПриСозданииНаСервере, и в ПриЧтенииНаСервере).Самый надежный способ избежать ошибки — всегда проверять, нет ли уже в коллекции элемента с таким именем. Рассмотрим, как правильно реализовать такую проверку для команд и элементов формы. Используем метод Найти(), который возвращает Неопределено, если объект не найден.
ИмяКоманды = "НоваяКомандаНомер1";
// Проверяем наличие команды
Если Команды.Найти(ИмяКоманды) = Неопределено Тогда
НоваяКоманда = Команды.Добавить(ИмяКоманды);
НоваяКоманда.Заголовок = "Выполнить операцию";
НоваяКоманда.Действие = "ОбработатьНажатиеКнопки";
КонецЕсли;
ИмяКнопки = "КнопкаВыполнитьОперацию";
// Проверяем наличие элемента (кнопки)
Если Элементы.Найти(ИмяКнопки) = Неопределено Тогда
// Определяем родителя для кнопки (например, командная панель формы)
Родитель = Элементы.КоманднаяПанельФормы;
НоваяКнопка = Элементы.Добавить(ИмяКнопки, Тип("КнопкаФормы"), Родитель);
НоваяКнопка.ИмяКоманды = ИмяКоманды;
КонецЕсли;
Такой подход гарантирует, что даже при многократном вызове процедуры инициализации ваш код не «упадет» с ошибкой. Это правило «хорошего тона» при динамическом создании любых объектов метаданных или элементов интерфейса.
Часто нам нужно не просто добавить кнопку в конец списка, а поместить её в определенное место командной панели. Для этого проанализируем метод Вставить(). В отличие от Добавить(), он принимает четвертый параметр — элемент, перед которым нужно вставить новый объект.
// Вставляем кнопку перед кнопкой "Справка"
ЭлементПередКоторымВставить = Элементы.Справка;
НоваяКнопка = Элементы.Вставить("МояКнопка", Тип("КнопкаФормы"), Родитель, ЭлементПередКоторымВставить);
Важно помнить, что если параметр ЭлементПередКоторымВставить равен Неопределено, кнопка будет добавлена в самый конец группы, аналогично методу Добавить().
Рассмотрим несколько критических моментов, о которых часто забывают начинающие разработчики при программном создании интерфейса:
Действие должно содержать имя процедуры, которая обязательно определена в модуле формы с директивой &НаКлиенте. Если процедура будет находиться только на сервере, при нажатии на кнопку в режиме «1С:Предприятие» ничего не произойдет или система выдаст ошибку о недоступности метода.КомандаФормы. Вы можете создать одну команду и привязать её к нескольким кнопкам в разных частях формы. Главное — правильно указать ИмяКоманды.Автоматическую командную панель, убедитесь, что свойство ТолькоВоВсехДействиях установлено в значение Ложь (если хотите видеть кнопку сразу) или Истина (если кнопка должна спрятаться в подменю «Еще»).Элементы обязательно указывайте правильный тип. Для кнопок это Тип("КнопкаФормы"). Ошибка в типе приведет к невозможности использования специфических свойств, таких как ИмяКоманды.Разберем более сложный пример, когда нам нужно добавить кнопку с иконкой из стандартной библиотеки картинок и задать ей отображение «Картинка и текст»:
Процедура ДобавитьКнопкуИмпортаНаСервере()
ИмяКоманды = "КомандаИмпортаДанных";
// 1. Создаем команду, если ее нет
Команда = Команды.Найти(ИмяКоманды);
Если Команда = Неопределено Тогда
Команда = Команды.Добавить(ИмяКоманды);
Команда.Заголовок = "Импорт из Excel";
Команда.Действие = "Подключаемый_ВыполнитьИмпорт";
Команда.Картинка = БиблиотекаКартинок.ЗагрузитьДанныеИзФайла;
КонецЕсли;
// 2. Создаем кнопку в командной панели
ИмяКнопки = "КнопкаИмпорта";
Если Элементы.Найти(ИмяКнопки) = Неопределено Тогда
ГруппаПанель = Элементы.КоманднаяПанельФормы;
НоваяКнопка = Элементы.Добавить(ИмяКнопки, Тип("КнопкаФормы"), ГруппаПанель);
НоваяКнопка.ИмяКоманды = ИмяКоманды;
НоваяКнопка.Отображение = ОтображениеКнопки.КартинкаИТекст;
НоваяКнопка.Пометка = Ложь;
КонецЕсли;
КонецПроцедуры
Посмотрим на этот код: мы использовали проверку на уникальность, привязали стандартную картинку и установили режим отображения. Такой код стабилен и не вызовет исключений при обновлении формы.
Мы выяснили, что ошибка «Имя не уникально» — это следствие отсутствия контроля за состоянием коллекции элементов формы. Проанализировав жизненный цикл формы и методы коллекций Команды и Элементы, мы пришли к выводу, что использование метода Найти() является обязательным стандартом при динамическом конструировании интерфейса. Соблюдение этих простых правил позволит вам создавать гибкие и отказоустойчивые решения в среде «1С:Предприятие 8.3».