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

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

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

Особенности работы с метаданными и контекстом управляемой формы

В управляемом приложении коллекция Метаданные доступна только на стороне сервера. Попытка обратиться к ней из клиентских процедур (с директивой &НаКлиенте) вызовет ошибку компиляции или выполнения. Поэтому цикл обхода метаданных обязательно выносится в серверную процедуру.

Важно помнить об ограничении платформы: объекты типа ОбъектМетаданных не сериализуются и не могут передаваться с сервера на клиент. Если попытаться записать в качестве значения элемента списка значений сам объект метаданных, платформа выдаст ошибку передачи контекста при возврате управления на форму. В качестве значения необходимо сохранять строковое имя объекта (Имя), а в пользовательское представление передавать его синоним (Синоним).

Если на управляемой форме уже создан реквизит типа СписокЗначений (например, с именем Результат), то внутри серверной контекстной процедуры &НаСервере к нему можно обращаться напрямую по имени. Использовать дополнительные методы ЗначениеВРеквизитФормы или РеквизитФормыВЗначение в данном случае не требуется, так как контекст формы синхронизируется платформой автоматически.

Шаг 1. Заполнение списка видов документов на форме

Рассмотрим реализацию команды заполнения списка. На форме создается команда Заполнить, связанная с клиентским обработчиком, который вызывает серверный контекст.


&НаКлиенте
Процедура Заполнить(Команда)
    ЗаполнитьНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьНаСервере()
    
    // Очищаем реквизит формы перед новым заполнением
    Результат.Очистить();
    
    // Обходим метаданные документов
    Для Каждого МДДокумент Из Метаданные.Документы Цикл
        // Проверяем доступность чтения для текущего пользователя
        Если ПравоДоступа("Чтение", МДДокумент) Тогда
            Результат.Добавить(МДДокумент.Имя, МДДокумент.Синоним);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Шаг 2. Обработка выбранных документов на сервере

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

Вариант 1. Использование менеджера документа и выборки

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


&НаКлиенте
Процедура ВыполнитьОбработку(Команда)
    ВыполнитьНаСервере();
КонецПроцедуры

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

Вариант 2. Использование динамического запроса

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


&НаСервере
Процедура ВыполнитьОбработкуЧерезЗапрос()
    
    ШаблонЗапроса = 
        "ВЫБРАТЬ
        |   Таб.Ссылка КАК Ссылка
        |ИЗ
        |   Документ.%ИмяТаблицы% КАК Таб
        |ГДЕ
        |   НЕ Таб.ПометкаУдаления";
    
    Для Каждого ЭлементСписка Из Результат Цикл
        
        Если ЭлементСписка.Пометка Тогда
            
            ИмяДокумента = ЭлементСписка.Значение;
            
            Запрос = Новый Запрос;
            Запрос.Текст = СтрЗаменить(ШаблонЗапроса, "%ИмяТаблицы%", ИмяДокумента);
            
            Выборка = Запрос.Выполнить().Выбрать();
            Пока Выборка.Следующий() Цикл
                
                ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
                ДокОбъект.УстановитьПометкуУдаления(Истина);
                
            КонецЦикла;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Важные нюансы и рекомендации

  1. Различие между УстановитьПометкуУдаления и прямой записью свойства: метод ДокОбъект.УстановитьПометкуУдаления(Истина) для проведенного документа автоматически снимает его с проведения и очищает все движения по регистрам. Если же просто присвоить ДокОбъект.ПометкаУдаления = Истина и вызвать метод Записать(РежимЗаписиДокумента.Запись), документ будет помечен на удаление без отмены движений, что приведет к рассогласованию регистров и остатков в базе.
  2. Проверка прав доступа: перед изменением данных всегда проверяйте права текущего пользователя с помощью функции ПравоДоступа("ИнтерактивноеУдалениеПометки", Метаданные.Документы[ИмяДокумента]) или ПравоДоступа("Изменение", ...), чтобы избежать прерывания работы по системной ошибке нарушения прав.
  3. Производительность и большие объемы данных: выполнение длительных циклов в контексте клиент-серверного вызова блокирует интерфейс пользователя. При обработке сотен тысяч документов операцию рекомендуется выносить в фоновое задание или разделять транзакции порциями с включением режима ДокОбъект.ОбменДанными.Загрузка = Истина (когда отключение проверок допустимо регламентом).
← На главную