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

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

В этой статье мы подробно рассмотрим, как эффективно и корректно программно удалять помеченные элементы справочника, например, «Номенклатура», а также все связанные с ними записи из регистров сведений, таких как «ШтрихкодыНоменклатуры». Мы проанализируем распространенные ошибки и предложим рабочие решения, основанные на лучших практиках разработки на платформе 1С:Предприятие 8.3.

Постановка проблемы и анализ исходного кода

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

  1. Процедура для заполнения табличной части обработки помеченной номенклатурой.
  2. Процедура для удаления записей из регистра сведений и самого элемента номенклатуры.

Давайте посмотрим на первоначальную логику, предложенную в исходном сообщении:


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

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

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

&НаСервере
Процедура УдалитьНаСервере
    для каждого строка из Объект.Товары цикл
        ЗаписьРС = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьМенеджерЗаписи;
        ЗаписьРС.Номенклатура = Строка.Номенклатура;
        ЗаписьРС.Штрихкод = Строка.Штрихкод;
        ЗаписьРС.Характеристика = Строка.Характеристика;
        ЗаписьРС.Партия = Строка.Партия;
        ЗаписьРС.ЕдиницаИзмерения = Строка.ЕдиницаИзмерения;
        ЗаписьРС.Прочитать;
        ЗаписьРС.Удалить;
    конеццикла;

    Номенклатура = Справочники.Номенклатура.Выбрать;
    Если Номенклатура.ПометкаУдаления = Истина Тогда
        НоменклатураОбъект = Номенклатура.ПолучитьОбъект;
        НоменклатураОбъект.Удалить;
    КонецЕсли;
КонецПроцедуры

В этом коде мы сразу обнаруживаем несколько критических проблем, которые приводят к тому, что удаление не работает:

  1. Неправильное заполнение табличной части: В процедуре УдалитьНоменклатуруНаСервере в табличную часть Объект.Товары для колонки Номенклатура записывается Выборка.Наименование, то есть строковое представление, а не Выборка.Номенклатура (ссылка на сам элемент справочника). Аналогичная проблема, предположительно, происходит и с колонкой Характеристика. Это критично, так как для поиска записей в регистре сведений и для последующего удаления элемента справочника требуются именно ссылки.
  2. Некорректное удаление записей регистра сведений: В процедуре УдалитьНаСервере, при попытке удалить записи из регистра сведений через МенеджерЗаписи, поля Номенклатура и Характеристика менеджера записи заполняются строками (наименованиями) вместо ссылок. В результате метод Прочитать(), скорее всего, не находит нужную запись в регистре, и, соответственно, метод Удалить() не выполняет никаких действий.
  3. Ошибка при удалении элемента справочника: Блок кода для удаления самой номенклатуры после цикла ошибочен. Выражение Справочники.Номенклатура.Выбрать возвращает объект типа ВыборкаИзСправочника, а не отдельный элемент справочника. Проверка Номенклатура.ПометкаУдаления и вызов ПолучитьОбъект() на такой выборке приведут к ошибке выполнения.

Из-за этих ошибок, при нажатии на кнопку "удалить", как отмечает автор, "ничего не происходит".

Структура регистра сведений "ШтрихкодыНоменклатуры"

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

  1. Штрихкод (тип Строка)
  2. Номенклатура (тип СправочникСсылка.Номенклатура)
  3. Характеристика (тип СправочникСсылка.ХарактеристикиНоменклатуры или аналогичный)
  4. Партия (тип СправочникСсылка.Партии или аналогичный)
  5. ЕдиницаИзмерения (тип СправочникСсылка.ЕдиницыИзмерения или аналогичный)

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

Решение 1: Автоматическое удаление записей регистра с помощью свойства "Ведущее"

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

Чтобы настроить свойство "Ведущее", выполним следующие шаги:

  1. Откроем конфигурацию в режиме "Конфигуратор".
  2. Перейдем в раздел "Регистры сведений" и найдем ваш регистр (в нашем случае "ШтрихкодыНоменклатуры").
  3. Развернем ветку "Измерения" и найдем измерение, которое ссылается на справочник "Номенклатура" (скорее всего, это измерение Номенклатура).
  4. Установим для этого измерения флажок "Ведущее" (в свойствах измерения).
  5. Обновим конфигурацию базы данных (меню "Конфигурация" -> "Обновить конфигурацию базы данных").

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

Решение 2: Программное удаление записей регистра и номенклатуры с использованием НабораЗаписей

Если механизм "Ведущего" измерения не используется или его применение нецелесообразно (например, если регистр должен быть независим от удаления основного объекта в некоторых сценариях, или если требуется более сложная логика удаления), мы можем реализовать программное удаление. Мы будем использовать объект НаборЗаписей для эффективного удаления группы записей регистра сведений, а затем удалим саму номенклатуру.

Шаг 1: Корректное заполнение табличной части обработки

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

Мы рассмотрим два варианта заполнения. Первый — более явный, где мы вручную присваиваем значения колонкам табличной части:


&НаСервере
Процедура ЗаполнитьТаблицуПомеченнойНоменклатуройНаСервере()
    Объект.Товары.Очистить(); // Очищаем табличную часть перед заполнением

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | СправочникНоменклатура.Ссылка КАК НоменклатураСсылка,
    | СправочникНоменклатура.Наименование КАК НоменклатураНаименование,
    | ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод,
    | ШтрихкодыНоменклатуры.Характеристика КАК ХарактеристикаСсылка,
    | ШтрихкодыНоменклатуры.Характеристика.Наименование КАК ХарактеристикаНаименование,
    | СправочникНоменклатура.Весовой КАК Весовой,
    | ШтрихкодыНоменклатуры.Партия КАК Партия,
    | ШтрихкодыНоменклатуры.ЕдиницаИзмерения КАК ЕдиницаИзмерения
    |ИЗ
    | Справочник.Номенклатура КАК СправочникНоменклатура
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
    | ПО СправочникНоменклатура.Ссылка = ШтрихкодыНоменклатуры.Номенклатура
    |ГДЕ
    | СправочникНоменклатура.ПометкаУдаления = ИСТИНА";

    РезультатЗапроса = Запрос.Выполнить();
    ВыгрузкаТаблицы = РезультатЗапроса.Выгрузить();

    // Загружаем данные в табличную часть обработки, присваивая ссылки соответствующим колонкам
    // Предполагаем, что у табличной части обработки есть колонки:
    // Номенклатура (тип СправочникСсылка.Номенклатура),
    // НаименованиеНоменклатуры (тип Строка),
    // Штрихкод (тип Строка),
    // Характеристика (тип СправочникСсылка.ХарактеристикиНоменклатуры),
    // НаименованиеХарактеристики (тип Строка),
    // Весовой (тип Булево),
    // Партия (тип СправочникСсылка.Партии),
    // ЕдиницаИзмерения (тип СправочникСсылка.ЕдиницыИзмерения).
    Для Каждого СтрокаВыгрузки Из ВыгрузкаТаблицы Цикл
        СтрокаТЧ = Объект.Товары.Добавить();
        СтрокаТЧ.Номенклатура = СтрокаВыгрузки.НоменклатураСсылка;
        СтрокаТЧ.НаименованиеНоменклатуры = СтрокаВыгрузки.НоменклатураНаименование;
        СтрокаТЧ.Штрихкод = СтрокаВыгрузки.Штрихкод;
        СтрокаТЧ.Характеристика = СтрокаВыгрузки.ХарактеристикаСсылка;
        СтрокаТЧ.НаименованиеХарактеристики = СтрокаВыгрузки.ХарактеристикаНаименование;
        СтрокаТЧ.Весовой = СтрокаВыгрузки.Весовой;
        СтрокаТЧ.Партия = СтрокаВыгрузки.Партия;
        СтрокаТЧ.ЕдиницаИзмерения = СтрокаВыгрузки.ЕдиницаИзмерения;
    КонецЦикла;
КонецПроцедуры

Второй вариант, более компактный, предложенный в обсуждении, если имена колонок запроса точно совпадают с именами колонок табличной части обработки:


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

    // Загружаем результат запроса напрямую в табличную часть.
    // Это работает эффективно, если имена полей запроса соответствуют именам колонок табличной части.
    Объект.Товары.Загрузить(Запрос.Выполнить().Выгрузить());
КонецПроцедуры

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

Шаг 2: Удаление записей регистра сведений и элементов справочника

Для удаления записей регистра мы будем использовать объект НаборЗаписей. Это наиболее эффективный и рекомендуемый способ удаления группы записей по определенному отбору. Затем мы удалим саму номенклатуру.


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

    // Создаем коллекцию уникальных ссылок на номенклатуру
    // Это позволит избежать повторных операций удаления для одной и той же номенклатуры,
    // если она встречается в табличной части несколько раз (например, с разными штрихкодами).
    УникальнаяНоменклатураКУдалению = Новый Соответствие;
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        Если СтрокаТЧ.Номенклатура <> Неопределено Тогда
            УникальнаяНоменклатураКУдалению.Вставить(СтрокаТЧ.Номенклатура, Истина);
        КонецЕсли;
    КонецЦикла;

    // Начинаем процесс удаления для каждой уникальной номенклатуры
    Для Каждого ЭлементСоответствия Из УникальнаяНоменклатураКУдалению Цикл
        НоменклатураСсылка = ЭлементСоответствия.Ключ; // Получаем ссылку на номенклатуру

        // Используем транзакцию для каждой номенклатуры,
        // чтобы обеспечить целостность данных в случае ошибки
        НачатьТранзакцию();
        Попытка
            // 1. Удаляем все записи из регистра сведений "ШтрихкодыНоменклатуры",
            // связанные с данной номенклатурой
            НаборЗаписейРС = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьНаборЗаписей();
            // Устанавливаем отбор по измерению "Номенклатура"
            // Отбор НабораЗаписей всегда устанавливается на равенство.
            НаборЗаписейРС.Отбор.Номенклатура.Установить(НоменклатураСсылка);
            // Вызов метода Записать() для пустого набора записей с установленным отбором
            // приведет к удалению всех записей, соответствующих этому отбору.
            НаборЗаписейРС.Записать();
            Сообщить("Удалены записи регистра 'ШтрихкодыНоменклатуры' для номенклатуры: " + НоменклатураСсылка, СтатусСообщения.Информация);

            // 2. Удаляем саму номенклатуру из справочника
            НоменклатураОбъект = НоменклатураСсылка.ПолучитьОбъект();
            Если НоменклатураОбъект <> Неопределено Тогда
                // Дополнительно проверяем пометку на удаление, хотя мы уже отбирали только помеченные.
                // Это добавляет устойчивости, если в промежутке пометка была снята.
                Если НоменклатураОбъект.ПометкаУдаления Тогда
                    НоменклатураОбъект.Удалить();
                    Сообщить("Удалена номенклатура: " + НоменклатураСсылка, СтатусСообщения.Информация);
                Иначе
                    Сообщить("Номенклатура " + НоменклатураСсылка + " не помечена на удаление и не будет удалена.", СтатусСообщения.Предупреждение);
                КонецЕсли;
            Иначе
                Сообщить("Объект номенклатуры не найден по ссылке: " + НоменклатураСсылка, СтатусСообщения.Предупреждение);
            КонецЕсли;

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

    // После завершения всех операций очищаем табличную часть обработки
    Объект.Товары.Очистить();
КонецПроцедуры

// Пример вызова процедуры удаления на клиенте (например, по кнопке)
&НаКлиенте
Процедура Удалить(Команда)
    УдалитьНоменклатуруИШтрихкодыНаСервере();
    // Возможно, здесь потребуется обновить табличную часть, если пользователь
    // ожидает увидеть список оставшейся помеченной номенклатуры
    // ЗаполнитьТаблицуПомеченнойНоменклатуройНаСервере();
КонецПроцедуры

// Пример вызова процедуры заполнения на клиенте (например, по кнопке или при открытии формы)
&НаКлиенте
Процедура Заполнить(Команда)
    ЗаполнитьТаблицуПомеченнойНоменклатуройНаСервере();
КонецПроцедуры

Разберем ключевые моменты этого решения:

  1. Мы используем объект Соответствие для сбора уникальных ссылок на номенклатуру из табличной части. Это гарантирует, что каждая номенклатура будет обработана только один раз, даже если в табличной части она присутствует несколько раз (например, с разными штрихкодами).
  2. Мы создаем объект НаборЗаписейРС = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьНаборЗаписей(). Это объект, который управляет коллекцией записей регистра.
  3. Мы устанавливаем отбор по измерению Номенклатура: НаборЗаписейРС.Отбор.Номенклатура.Установить(НоменклатураСсылка). Это означает, что все операции с этим набором записей будут ограничены только теми записями регистра, у которых измерение Номенклатура равно нашей удаляемой ссылке.
  4. Вызов метода НаборЗаписейРС.Записать() для пустого набора записей (мы не считывали и не добавляли записи в набор после создания) приводит к тому, что все записи регистра, соответствующие установленному отбору, будут удалены. Это очень эффективный способ массового удаления записей.
  5. После удаления связанных записей из регистра сведений, мы получаем объект справочника по ссылке НоменклатураСсылка.ПолучитьОбъект() и вызываем его метод Удалить().
  6. Для лучшей диагностики и устойчивости кода, мы оборачиваем операции удаления в блоки Попытка...Исключение и выводим сообщения пользователю о ходе выполнения и возможных ошибках.
  7. Использование транзакций (НачатьТранзакцию(), ЗафиксироватьТранзакцию(), ОтменитьТранзакцию()) для каждой номенклатуры обеспечивает атомарность операции: либо все связанные записи регистра и сам элемент справочника удаляются успешно, либо все изменения отменяются, предотвращая частичное удаление и сохраняя целостность данных.

Решение 3: Удаление записей регистра сведений по одной с использованием МенеджераЗаписи

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


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

        Попытка
            ЗаписьРС = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьМенеджерЗаписи();
            // Важно: необходимо заполнить ВСЕ ключевые измерения регистра для уникальной идентификации записи
            ЗаписьРС.Номенклатура = СтрокаТЧ.Номенклатура;
            ЗаписьРС.Штрихкод = СтрокаТЧ.Штрихкод;
            ЗаписьРС.Характеристика = СтрокаТЧ.Характеристика;
            ЗаписьРС.Партия = СтрокаТЧ.Партия; // Убедитесь, что это измерение всегда заполнено или может быть Неопределено
            ЗаписьРС.ЕдиницаИзмерения = СтрокаТЧ.ЕдиницаИзмерения; // Убедитесь, что это измерение всегда заполнено или может быть Неопределено

            // Прочитать запись перед удалением. Если запись не найдена, метод Прочитать()
            // не изменит состояние менеджера записи (Модифицированность останется Ложь).
            ЗаписьРС.Прочитать();

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

Этот подход требует точного заполнения всех измерений, которые формируют ключ записи регистра сведений. Если хоть одно из ключевых измерений заполнено неверно или отсутствует, метод Прочитать() не найдет запись, и Удалить() не сработает. Поэтому для массового удаления НаборЗаписей является более предпочтительным.

Важные рекомендации и лучшие практики

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

  1. Контроль ссылочной целостности: Платформа 1С имеет встроенный механизм контроля ссылочной целостности. Если на объект существуют ссылки в других местах (документах, других регистрах, справочниках), его прямое удаление (даже помеченного) может быть заблокировано. Стандартная обработка "Удаление помеченных объектов" сначала проверяет такие ссылки и предлагает варианты решения (например, замену ссылок или принудительное удаление). При программном удалении мы должны быть уверены, что все зависимые данные либо удалены, либо изменены так, чтобы не ссылаться на удаляемый объект. Если объект не удаляется, вы получите исключение, которое необходимо корректно обрабатывать.
  2. Использование транзакций: При выполнении сложных операций удаления, включающих несколько объектов или регистров, мы настоятельно рекомендуем использовать транзакции. Это позволит отменить все изменения, если в процессе удаления возникнет ошибка, и сохранить целостность данных. Пример использования транзакции мы уже рассмотрели в Решении 2.
  3. 
    НачатьТранзакцию();
    Попытка
        // Ваш код удаления здесь:
        // Например, удаление записей регистра сведений
        // и удаление самого элемента справочника.
        // ...
        ЗафиксироватьТранзакцию();
        Сообщить("Операция удаления успешно завершена.", СтатусСообщения.Информация);
    Исключение
        ОтменитьТранзакцию();
        Сообщить("Ошибка при выполнении операции удаления. Изменения отменены: " + ОписаниеОшибки(), СтатусСообщения.Ошибка);
    КонецПопытки;
    
  4. Резервное копирование: Перед выполнением любых массовых операций по удалению данных, особенно программных, критически важно создать резервную копию информационной базы. Это позволит восстановить данные в случае непредвиденных ошибок или некорректной работы алгоритма.
  5. Пользовательский интерфейс: При разработке обработок для удаления данных, всегда предусматривайте подтверждение от пользователя перед выполнением необратимых операций. Отображайте список объектов, которые будут удалены, чтобы пользователь мог еще раз убедиться в правильности своих действий. Предоставляйте подробные сообщения о ходе выполнения и возможных ошибках.
  6. Свойство "Ведущее" и его ограничения: Помните, что "Ведущее" измерение работает только для удаления *самого* объекта справочника. Если вы удаляете записи регистра сведений вручную (например, через НаборЗаписей), а *затем* пытаетесь удалить объект, который всё ещё имеет ссылки в других местах (не связанных с "ведущим" измерением), платформа может не дать его удалить, даже если связанные записи из "ведущего" регистра уже были удалены. Поэтому всегда важно комплексно оценивать все ссылки на удаляемый объект.

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

← На главную