Как в расширении добавить новый элемент в список на форме?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← К списку

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

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

Решение для управляемых форм: используем перехват событий

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

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

Разберем по шагам, что нужно сделать:

  1. Добавьте нужную форму в ваше расширение.
  2. В расширении для этой формы создайте модуль.
  3. В модуле напишите процедуру-обработчик с аннотацией &После("ПриСозданииНаСервере"). Это означает, что ваш код выполнится сразу после основного обработчика ПриСозданииНаСервере в типовой конфигурации.
  4. Внутри этой процедуры получите доступ к элементу формы (вашему списку) и добавьте в него новое значение.

Посмотрим на пример кода:

Предположим, на форме есть реквизит СписокВыбора с типом СписокЗначений, и мы хотим добавить в него еще один элемент.


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

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

Решение для обычных форм: поиск подходящего обработчика

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

Выясним причину: в расширениях для обычных форм мы не можем напрямую перехватить событие ПриОткрытии. Поэтому наша задача — найти "обходной путь".

Разберем по шагам этот метод:

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

Посмотрим на гипотетический пример:

Допустим, мы выяснили, что при открытии формы документа вызывается процедура ЗаполнитьДополнительныеСвойства из общего модуля РаботаСФормами. Тогда наше решение будет выглядеть так:


&Вместо("ЗаполнитьДополнительныеСвойства")
Процедура Расш1_ЗаполнитьДополнительныеСвойства(Форма)

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

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

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

← К списку