Как правильно пометить на удаление элементы справочника в управляемых формах 1С

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

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

Разбор основной ошибки: Архитектура команд в УФ

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

В управляемом приложении 1С существует строгое разделение контекстов. Команда формы, инициированная пользователем (нажатие кнопки), всегда должна начинаться на клиенте. Платформа 1С спроектирована так, что обработчик команды — это клиентский метод. Если попытаться "перепрыгнуть" этот этап, логика приложения нарушается.

Правильная схема вызова выглядит так:

  1. Пользователь нажимает кнопку (Событие на клиенте).
  2. Вызывается клиентская процедура &НаКлиенте.
  3. Из клиентской процедуры происходит вызов серверной процедуры &НаСервере, где выполняется работа с базой данных.

Проанализируем исправленный вариант структуры кода:


&НаКлиенте
Процедура ПометитьЭлементыНаКлиенте(Команда)
    // Вызываем серверный контекст для работы с данными
    ПометитьЭлементыНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПометитьЭлементыНаСервере()
    // Здесь размещается логика запроса и изменения объектов
КонецПроцедуры

Программная установка пометки удаления: Запись объекта

Еще одна распространенная проблема — изменение свойства ПометкаУдаления без последующего сохранения. В отличие от некоторых других языков программирования, изменение свойства объекта в памяти 1С не означает автоматического изменения записи в таблице базы данных. Для фиксации изменений необходимо явно вызвать метод Записать().

Однако для установки пометки удаления существует более специализированный метод — УстановитьПометкуУдаления(). Рассмотрим разницу подробнее.

Вариант 1: Через свойство объекта

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


ОбъектСправочника = Выборка.Ссылка.ПолучитьОбъект();
ОбъектСправочника.ПометкаУдаления = Истина;
ОбъектСправочника.Записать();

Вариант 2: Через специализированный метод

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


ОбъектСправочника = Выборка.Ссылка.ПолучитьОбъект();
ОбъектСправочника.УстановитьПометкуУдаления(Истина);

Оптимизация массовой обработки данных

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

1. Использование транзакций

По умолчанию 1С открывает и закрывает транзакцию для каждого вызова Записать(). Это создает огромную нагрузку на дисковую подсистему. Обернем цикл в одну общую транзакцию, чтобы ускорить запись в десятки раз.


НачатьТранзакцию();
Попытка
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Объект = Выборка.Ссылка.ПолучитьОбъект();
        Объект.УстановитьПометкуУдаления(Истина);
    КонецЦикла;
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписатьЛогСобытий(ОписаниеОшибки());
КонецПопытки;

2. Свойство ОбменДанными.Загрузка

В типовых конфигурациях при записи объекта срабатывает множество проверок: проверяется, не занято ли подразделение, есть ли связанные сотрудники и так далее. Если ваша цель — гарантированная "очистка" справочника без учета бизнес-логики, используйте флаг Загрузка. Это позволит пропустить проверки в модулях объекта и подписках на события.


Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина;
Объект.УстановитьПометкуУдаления(Истина);

Работа с иерархией в справочнике СтруктураПредприятия

Справочник СтруктураПредприятия обычно является иерархическим. Если мы помечаем на удаление головное подразделение, логично пометить и все вложенные. Метод УстановитьПометкуУдаления имеет второй параметр — ВключаяПодчиненные.

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

Особенности отладки и вывода сообщений на сервере

Часто разработчики жалуются, что команда Сообщить() или точка останова не срабатывают в серверном коде. Выясним, почему это происходит.

Сообщения: На самом деле метод Сообщить() на сервере работает. Платформа собирает все сообщения, возникшие во время выполнения серверного вызова, и передает их на клиент "пакетом" сразу после завершения работы сервера. Если серверная процедура прервалась по ошибке или завершилась аварийно, сообщения могут не дойти.

Отладка: Если точка останова "не горит" (внутри нее нет красного кружка с галочкой), значит, в вашей базе не включена отладка на сервере. Для файловых баз это происходит автоматически, но для клиент-серверных вариантов (SQL) отладку нужно включать в параметрах запуска службы агента сервера 1С (ключ -debug).

Итоговый пример кода для массовой пометки

Объединим все полученные знания в одну эффективную процедуру для управляемой формы:


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

&НаКлиенте
Процедура КомандаПометитьВсе(Команда)
    // Подтверждение действия пользователем - хороший тон
    ТекстВопроса = "Вы уверены, что хотите пометить на удаление все подразделения?";
    Оповещение = Новый ОписаниеОповещения("ПослеВопроса", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

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

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

← На главную