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

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

Почему возникает блокировка? Проанализируем ситуацию

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


Процедура ВыполнитьУдаление()
    Форма.Закрыть(0);
    Спр = СоздатьОбъект("Справочник.Сотрудники");
    Если Спр.НайтиЭлемент(ТекущийЭлемент()) = 1 Тогда
        Спр.Удалить(0); // Ошибка: Объект заблокирован!
    КонецЕсли;
КонецПроцедуры

Мы потерпим неудачу. Команда Форма.Закрыть() не закрывает форму мгновенно. Она лишь посылает системе сигнал о том, что форму нужно закрыть после завершения выполнения текущей процедуры. Таким образом, пока выполняется код Спр.Удалить(0), форма всё еще считается открытой, а объект — заблокированным.

Способ №1: Использование внешней обработки в качестве посредника

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

Разберем алгоритм по шагам:

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

Пример кода в форме элемента справочника:


Процедура УдалитьИзФормы()
    Параметры = СоздатьОбъект("СписокЗначений");
    Параметры.ДобавитьЗначение(Контекст, "КонтекстЭлемента");
    ОткрытьФорму("Отчет", Параметры, КаталогИБ() + "ExtForms\Удалятор.ert");
КонецПроцедуры

Код во внешней обработке (файл Удалятор.ert):


Перем ЭлементДляУдаления;
Перем ВидСпр;

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

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

Способ №2: Обработка ожидания (Метод отложенного действия)

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

Посмотрим на пример реализации:

  1. В Глобальном модуле создаем переменную и процедуру для удаления.
  2. В форме элемента заполняем переменную и запускаем таймер.
  3. Закрываем форму элемента.
  4. Таймер срабатывает в пустом контексте, когда объект уже свободен.

Код в Глобальном модуле:


Перем ГлОбъектДляУдаления Экспорт;

Процедура ГлВыполнитьУдалениеПомеченного() Экспорт
    // Останавливаем обработку ожидания, чтобы не зациклиться
    Сервис = СоздатьОбъект("Сервис"); // Если используется FormEx
    // Или просто стандартным методом:
    ИмяПроцедуры = "";
    Форма.ОбработкаОжидания(ИмяПроцедуры, 0); 
    
    Спр = СоздатьОбъект("Справочник." + ГлОбъектДляУдаления.Вид());
    Если Спр.НайтиЭлемент(ГлОбъектДляУдаления) = 1 Тогда
        Спр.Удалить(0);
    КонецЕсли;
КонецПроцедуры

Код в форме элемента справочника:


Процедура КнопкаУдалить()
    ГлОбъектДляУдаления = ТекущийЭлемент();
    Форма.Закрыть(0);
    // Запускаем процедуру через 1 секунду
    Форма.ОбработкаОжидания("ГлВыполнитьУдалениеПомеченного", 1);
КонецПроцедуры

Способ №3: Использование ложного закрытия и статус возврата

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

В форме списка в процедуре ПриПовторномОткрытии() или при возврате управления из ОткрытьФорму() можно проверить состояние объекта. Но этот метод сложен в реализации, если элемент открывался из разных мест системы.

Способ №4: Метод подмены формы («Показ копии»)

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

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

Алгоритм действий:

Важные замечания и рекомендации

Проанализировав все способы, важно отметить несколько критических моментов:

  1. Транзакции: Старайтесь не выполнять удаление внутри открытых транзакций, если используете метод с обработкой ожидания, так как это может привести к непредсказуемым блокировкам всей таблицы.
  2. Проверки: При программном удалении через Спр.Удалить(0) платформа 7.7 НЕ вызывает процедуру ПриУдаленииЭлемента(), если она прописана в модуле справочника. Если у вас там сложная логика проверок (например, запрет удаления сотрудников с долгами), её нужно вызвать вручную или продублировать в коде удаления.
  3. Права доступа: Помните, что метод Удалить(0) (пометка) требует наличия соответствующих прав у пользователя. Метод Удалить(1) (непосредственное удаление) — прав на интерактивное удаление, что в корпоративных базах часто запрещено.

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

← На главную